aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/gspca
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-08-13 23:13:22 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-15 15:25:07 -0400
commit0c0d06cac63ee327ceaab4b5ffe2206574ab86bd (patch)
treee759f0dc3185d97f2a0c6b5cd5e32ea6faa74d40 /drivers/media/usb/gspca
parent84cfe9e79bd5ac11c963f4841158454fefa872f6 (diff)
[media] rename most media/video usb drivers to media/usb
Rename all USB drivers with their own directory under drivers/media/video into drivers/media/usb and update the building system. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/gspca')
-rw-r--r--drivers/media/usb/gspca/Kconfig425
-rw-r--r--drivers/media/usb/gspca/Makefile93
-rw-r--r--drivers/media/usb/gspca/autogain_functions.c178
-rw-r--r--drivers/media/usb/gspca/autogain_functions.h183
-rw-r--r--drivers/media/usb/gspca/benq.c289
-rw-r--r--drivers/media/usb/gspca/conex.c966
-rw-r--r--drivers/media/usb/gspca/cpia1.c1905
-rw-r--r--drivers/media/usb/gspca/etoms.c799
-rw-r--r--drivers/media/usb/gspca/finepix.c306
-rw-r--r--drivers/media/usb/gspca/gl860/Kconfig8
-rw-r--r--drivers/media/usb/gspca/gl860/Makefile10
-rw-r--r--drivers/media/usb/gspca/gl860/gl860-mi1320.c536
-rw-r--r--drivers/media/usb/gspca/gl860/gl860-mi2020.c733
-rw-r--r--drivers/media/usb/gspca/gl860/gl860-ov2640.c489
-rw-r--r--drivers/media/usb/gspca/gl860/gl860-ov9655.c336
-rw-r--r--drivers/media/usb/gspca/gl860/gl860.c725
-rw-r--r--drivers/media/usb/gspca/gl860/gl860.h105
-rw-r--r--drivers/media/usb/gspca/gspca.c2456
-rw-r--r--drivers/media/usb/gspca/gspca.h259
-rw-r--r--drivers/media/usb/gspca/jeilinj.c548
-rw-r--r--drivers/media/usb/gspca/jl2005bcd.c557
-rw-r--r--drivers/media/usb/gspca/jpeg.h168
-rw-r--r--drivers/media/usb/gspca/kinect.c408
-rw-r--r--drivers/media/usb/gspca/konica.c487
-rw-r--r--drivers/media/usb/gspca/m5602/Kconfig11
-rw-r--r--drivers/media/usb/gspca/m5602/Makefile11
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_bridge.h163
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_core.c424
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_mt9m111.c647
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_mt9m111.h271
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov7660.c488
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov7660.h260
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov9650.c881
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov9650.h307
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_po1030.c763
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_po1030.h272
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k4aa.c726
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k4aa.h283
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k83a.c605
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k83a.h193
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_sensor.h70
-rw-r--r--drivers/media/usb/gspca/mars.c439
-rw-r--r--drivers/media/usb/gspca/mr97310a.c1091
-rw-r--r--drivers/media/usb/gspca/nw80x.c2110
-rw-r--r--drivers/media/usb/gspca/ov519.c4991
-rw-r--r--drivers/media/usb/gspca/ov534.c1544
-rw-r--r--drivers/media/usb/gspca/ov534_9.c1500
-rw-r--r--drivers/media/usb/gspca/pac207.c469
-rw-r--r--drivers/media/usb/gspca/pac7302.c932
-rw-r--r--drivers/media/usb/gspca/pac7311.c701
-rw-r--r--drivers/media/usb/gspca/pac_common.h134
-rw-r--r--drivers/media/usb/gspca/se401.c739
-rw-r--r--drivers/media/usb/gspca/se401.h90
-rw-r--r--drivers/media/usb/gspca/sn9c2028.c735
-rw-r--r--drivers/media/usb/gspca/sn9c2028.h51
-rw-r--r--drivers/media/usb/gspca/sn9c20x.c2428
-rw-r--r--drivers/media/usb/gspca/sonixb.c1493
-rw-r--r--drivers/media/usb/gspca/sonixj.c3206
-rw-r--r--drivers/media/usb/gspca/spca1528.c444
-rw-r--r--drivers/media/usb/gspca/spca500.c990
-rw-r--r--drivers/media/usb/gspca/spca501.c2054
-rw-r--r--drivers/media/usb/gspca/spca505.c807
-rw-r--r--drivers/media/usb/gspca/spca506.c612
-rw-r--r--drivers/media/usb/gspca/spca508.c1540
-rw-r--r--drivers/media/usb/gspca/spca561.c936
-rw-r--r--drivers/media/usb/gspca/sq905.c440
-rw-r--r--drivers/media/usb/gspca/sq905c.c344
-rw-r--r--drivers/media/usb/gspca/sq930x.c1164
-rw-r--r--drivers/media/usb/gspca/stk014.c446
-rw-r--r--drivers/media/usb/gspca/stv0680.c353
-rw-r--r--drivers/media/usb/gspca/stv06xx/Kconfig9
-rw-r--r--drivers/media/usb/gspca/stv06xx/Makefile10
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx.c634
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx.h116
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c540
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h206
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c434
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h144
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h87
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c285
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h52
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c272
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h255
-rw-r--r--drivers/media/usb/gspca/sunplus.c1085
-rw-r--r--drivers/media/usb/gspca/t613.c1054
-rw-r--r--drivers/media/usb/gspca/topro.c4969
-rw-r--r--drivers/media/usb/gspca/tv8532.c378
-rw-r--r--drivers/media/usb/gspca/vc032x.c3850
-rw-r--r--drivers/media/usb/gspca/vicam.c365
-rw-r--r--drivers/media/usb/gspca/w996Xcf.c567
-rw-r--r--drivers/media/usb/gspca/xirlink_cit.c3145
-rw-r--r--drivers/media/usb/gspca/zc3xx-reg.h251
-rw-r--r--drivers/media/usb/gspca/zc3xx.c7024
93 files changed, 77859 insertions, 0 deletions
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
new file mode 100644
index 00000000000..6345f9331e7
--- /dev/null
+++ b/drivers/media/usb/gspca/Kconfig
@@ -0,0 +1,425 @@
1menuconfig USB_GSPCA
2 tristate "GSPCA based webcams"
3 depends on VIDEO_V4L2
4 default m
5 ---help---
6 Say Y here if you want to enable selecting webcams based
7 on the GSPCA framework.
8
9 See <file:Documentation/video4linux/gspca.txt> for more info.
10
11 This driver uses the Video For Linux API. You must say Y or M to
12 "Video For Linux" to use this driver.
13
14 To compile this driver as modules, choose M here: the
15 module will be called gspca_main.
16
17
18if USB_GSPCA && VIDEO_V4L2
19
20source "drivers/media/usb/gspca/m5602/Kconfig"
21source "drivers/media/usb/gspca/stv06xx/Kconfig"
22source "drivers/media/usb/gspca/gl860/Kconfig"
23
24config USB_GSPCA_BENQ
25 tristate "Benq USB Camera Driver"
26 depends on VIDEO_V4L2 && USB_GSPCA
27 help
28 Say Y here if you want support for the Benq DC E300 camera.
29
30 To compile this driver as a module, choose M here: the
31 module will be called gspca_benq.
32
33config USB_GSPCA_CONEX
34 tristate "Conexant Camera Driver"
35 depends on VIDEO_V4L2 && USB_GSPCA
36 help
37 Say Y here if you want support for cameras based on the Conexant chip.
38
39 To compile this driver as a module, choose M here: the
40 module will be called gspca_conex.
41
42config USB_GSPCA_CPIA1
43 tristate "cpia CPiA (version 1) Camera Driver"
44 depends on VIDEO_V4L2 && USB_GSPCA
45 help
46 Say Y here if you want support for USB cameras based on the cpia
47 CPiA chip. Note that you need atleast version 0.6.4 of libv4l for
48 applications to understand the videoformat generated by this driver.
49
50 To compile this driver as a module, choose M here: the
51 module will be called gspca_cpia1.
52
53config USB_GSPCA_ETOMS
54 tristate "Etoms USB Camera Driver"
55 depends on VIDEO_V4L2 && USB_GSPCA
56 help
57 Say Y here if you want support for cameras based on the Etoms chip.
58
59 To compile this driver as a module, choose M here: the
60 module will be called gspca_etoms.
61
62config USB_GSPCA_FINEPIX
63 tristate "Fujifilm FinePix USB V4L2 driver"
64 depends on VIDEO_V4L2 && USB_GSPCA
65 help
66 Say Y here if you want support for cameras based on the FinePix chip.
67
68 To compile this driver as a module, choose M here: the
69 module will be called gspca_finepix.
70
71config USB_GSPCA_JEILINJ
72 tristate "Jeilin JPEG USB V4L2 driver"
73 depends on VIDEO_V4L2 && USB_GSPCA
74 help
75 Say Y here if you want support for cameras based on this Jeilin chip.
76
77 To compile this driver as a module, choose M here: the
78 module will be called gspca_jeilinj.
79
80config USB_GSPCA_JL2005BCD
81 tristate "JL2005B/C/D USB V4L2 driver"
82 depends on VIDEO_V4L2 && USB_GSPCA
83 help
84 Say Y here if you want support for cameras based the
85 JL2005B, JL2005C, or JL2005D chip.
86
87 To compile this driver as a module, choose M here: the
88 module will be called gspca_jl2005bcd.
89
90config USB_GSPCA_KINECT
91 tristate "Kinect sensor device USB Camera Driver"
92 depends on VIDEO_V4L2 && USB_GSPCA
93 help
94 Say Y here if you want support for the Microsoft Kinect sensor device.
95
96 To compile this driver as a module, choose M here: the
97 module will be called gspca_kinect.
98
99config USB_GSPCA_KONICA
100 tristate "Konica USB Camera V4L2 driver"
101 depends on VIDEO_V4L2 && USB_GSPCA
102 help
103 Say Y here if you want support for cameras based on the Konica chip.
104
105 To compile this driver as a module, choose M here: the
106 module will be called gspca_konica.
107
108config USB_GSPCA_MARS
109 tristate "Mars USB Camera Driver"
110 depends on VIDEO_V4L2 && USB_GSPCA
111 help
112 Say Y here if you want support for cameras based on the Mars chip.
113
114 To compile this driver as a module, choose M here: the
115 module will be called gspca_mars.
116
117config USB_GSPCA_MR97310A
118 tristate "Mars-Semi MR97310A USB Camera Driver"
119 depends on VIDEO_V4L2 && USB_GSPCA
120 help
121 Say Y here if you want support for cameras based on the MR97310A chip.
122
123 To compile this driver as a module, choose M here: the
124 module will be called gspca_mr97310a.
125
126config USB_GSPCA_NW80X
127 tristate "Divio based (NW80x) USB Camera Driver"
128 depends on VIDEO_V4L2 && USB_GSPCA
129 help
130 Say Y here if you want support for cameras based on the NW80x chips.
131
132 To compile this driver as a module, choose M here: the
133 module will be called gspca_nw80x.
134
135config USB_GSPCA_OV519
136 tristate "OV51x / OVFX2 / W996xCF USB Camera Driver"
137 depends on VIDEO_V4L2 && USB_GSPCA
138 help
139 Say Y here if you want support for cameras based on one of these:
140 OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF
141
142 To compile this driver as a module, choose M here: the
143 module will be called gspca_ov519.
144
145config USB_GSPCA_OV534
146 tristate "OV534 OV772x USB Camera Driver"
147 depends on VIDEO_V4L2 && USB_GSPCA
148 help
149 Say Y here if you want support for cameras based on the OV534 chip
150 and sensor OV772x (e.g. Sony Playstation EYE)
151
152 To compile this driver as a module, choose M here: the
153 module will be called gspca_ov534.
154
155config USB_GSPCA_OV534_9
156 tristate "OV534 OV965x USB Camera Driver"
157 depends on VIDEO_V4L2 && USB_GSPCA
158 help
159 Say Y here if you want support for cameras based on the OV534 chip
160 and sensor OV965x (e.g. Hercules Dualpix)
161
162 To compile this driver as a module, choose M here: the
163 module will be called gspca_ov534_9.
164
165config USB_GSPCA_PAC207
166 tristate "Pixart PAC207 USB Camera Driver"
167 depends on VIDEO_V4L2 && USB_GSPCA
168 help
169 Say Y here if you want support for cameras based on the PAC207 chip.
170
171 To compile this driver as a module, choose M here: the
172 module will be called gspca_pac207.
173
174config USB_GSPCA_PAC7302
175 tristate "Pixart PAC7302 USB Camera Driver"
176 depends on VIDEO_V4L2 && USB_GSPCA
177 help
178 Say Y here if you want support for cameras based on the PAC7302 chip.
179
180 To compile this driver as a module, choose M here: the
181 module will be called gspca_pac7302.
182
183config USB_GSPCA_PAC7311
184 tristate "Pixart PAC7311 USB Camera Driver"
185 depends on VIDEO_V4L2 && USB_GSPCA
186 help
187 Say Y here if you want support for cameras based on the PAC7311 chip.
188
189 To compile this driver as a module, choose M here: the
190 module will be called gspca_pac7311.
191
192config USB_GSPCA_SE401
193 tristate "SE401 USB Camera Driver"
194 depends on VIDEO_V4L2 && USB_GSPCA
195 help
196 Say Y here if you want support for cameras based on the
197 Endpoints (formerly known as AOX) se401 chip.
198
199 To compile this driver as a module, choose M here: the
200 module will be called gspca_se401.
201
202config USB_GSPCA_SN9C2028
203 tristate "SONIX Dual-Mode USB Camera Driver"
204 depends on VIDEO_V4L2 && USB_GSPCA
205 help
206 Say Y here if you want streaming support for Sonix SN9C2028 cameras.
207 These are supported as stillcams in libgphoto2/camlibs/sonix.
208
209 To compile this driver as a module, choose M here: the
210 module will be called gspca_sn9c2028.
211
212config USB_GSPCA_SN9C20X
213 tristate "SN9C20X USB Camera Driver"
214 depends on VIDEO_V4L2 && USB_GSPCA
215 help
216 Say Y here if you want support for cameras based on the
217 sn9c20x chips (SN9C201 and SN9C202).
218
219 To compile this driver as a module, choose M here: the
220 module will be called gspca_sn9c20x.
221
222config USB_GSPCA_SONIXB
223 tristate "SONIX Bayer USB Camera Driver"
224 depends on VIDEO_V4L2 && USB_GSPCA
225 help
226 Say Y here if you want support for cameras based on the Sonix
227 chips with Bayer format (SN9C101, SN9C102 and SN9C103).
228
229 To compile this driver as a module, choose M here: the
230 module will be called gspca_sonixb.
231
232config USB_GSPCA_SONIXJ
233 tristate "SONIX JPEG USB Camera Driver"
234 depends on VIDEO_V4L2 && USB_GSPCA
235 help
236 Say Y here if you want support for cameras based on the Sonix
237 chips with JPEG format (SN9C102P, SN9C105 and >= SN9C110).
238
239 To compile this driver as a module, choose M here: the
240 module will be called gspca_sonixj
241
242config USB_GSPCA_SPCA500
243 tristate "SPCA500 USB Camera Driver"
244 depends on VIDEO_V4L2 && USB_GSPCA
245 help
246 Say Y here if you want support for cameras based on the SPCA500 chip.
247
248 To compile this driver as a module, choose M here: the
249 module will be called gspca_spca500.
250
251config USB_GSPCA_SPCA501
252 tristate "SPCA501 USB Camera Driver"
253 depends on VIDEO_V4L2 && USB_GSPCA
254 help
255 Say Y here if you want support for cameras based on the SPCA501 chip.
256
257 To compile this driver as a module, choose M here: the
258 module will be called gspca_spca501.
259
260config USB_GSPCA_SPCA505
261 tristate "SPCA505 USB Camera Driver"
262 depends on VIDEO_V4L2 && USB_GSPCA
263 help
264 Say Y here if you want support for cameras based on the SPCA505 chip.
265
266 To compile this driver as a module, choose M here: the
267 module will be called gspca_spca505.
268
269config USB_GSPCA_SPCA506
270 tristate "SPCA506 USB Camera Driver"
271 depends on VIDEO_V4L2 && USB_GSPCA
272 help
273 Say Y here if you want support for cameras based on the SPCA506 chip.
274
275 To compile this driver as a module, choose M here: the
276 module will be called gspca_spca506.
277
278config USB_GSPCA_SPCA508
279 tristate "SPCA508 USB Camera Driver"
280 depends on VIDEO_V4L2 && USB_GSPCA
281 help
282 Say Y here if you want support for cameras based on the SPCA508 chip.
283
284 To compile this driver as a module, choose M here: the
285 module will be called gspca_spca508.
286
287config USB_GSPCA_SPCA561
288 tristate "SPCA561 USB Camera Driver"
289 depends on VIDEO_V4L2 && USB_GSPCA
290 help
291 Say Y here if you want support for cameras based on the SPCA561 chip.
292
293 To compile this driver as a module, choose M here: the
294 module will be called gspca_spca561.
295
296config USB_GSPCA_SPCA1528
297 tristate "SPCA1528 USB Camera Driver"
298 depends on VIDEO_V4L2 && USB_GSPCA
299 help
300 Say Y here if you want support for cameras based on the SPCA1528 chip.
301
302 To compile this driver as a module, choose M here: the
303 module will be called gspca_spca1528.
304
305config USB_GSPCA_SQ905
306 tristate "SQ Technologies SQ905 based USB Camera Driver"
307 depends on VIDEO_V4L2 && USB_GSPCA
308 help
309 Say Y here if you want support for cameras based on the SQ905 chip.
310
311 To compile this driver as a module, choose M here: the
312 module will be called gspca_sq905.
313
314config USB_GSPCA_SQ905C
315 tristate "SQ Technologies SQ905C based USB Camera Driver"
316 depends on VIDEO_V4L2 && USB_GSPCA
317 help
318 Say Y here if you want support for cameras based on the SQ905C chip.
319
320 To compile this driver as a module, choose M here: the
321 module will be called gspca_sq905c.
322
323config USB_GSPCA_SQ930X
324 tristate "SQ Technologies SQ930X based USB Camera Driver"
325 depends on VIDEO_V4L2 && USB_GSPCA
326 help
327 Say Y here if you want support for cameras based on the SQ930X chip.
328
329 To compile this driver as a module, choose M here: the
330 module will be called gspca_sq930x.
331
332config USB_GSPCA_STK014
333 tristate "Syntek DV4000 (STK014) USB Camera Driver"
334 depends on VIDEO_V4L2 && USB_GSPCA
335 help
336 Say Y here if you want support for cameras based on the STK014 chip.
337
338 To compile this driver as a module, choose M here: the
339 module will be called gspca_stk014.
340
341config USB_GSPCA_STV0680
342 tristate "STV0680 USB Camera Driver"
343 depends on VIDEO_V4L2 && USB_GSPCA
344 help
345 Say Y here if you want support for cameras based on the STV0680 chip.
346
347 To compile this driver as a module, choose M here: the
348 module will be called gspca_stv0680.
349
350config USB_GSPCA_SUNPLUS
351 tristate "SUNPLUS USB Camera Driver"
352 depends on VIDEO_V4L2 && USB_GSPCA
353 help
354 Say Y here if you want support for cameras based on the Sunplus
355 SPCA504(abc) SPCA533 SPCA536 chips.
356
357 To compile this driver as a module, choose M here: the
358 module will be called gspca_sunplus.
359
360config USB_GSPCA_T613
361 tristate "T613 (JPEG Compliance) USB Camera Driver"
362 depends on VIDEO_V4L2 && USB_GSPCA
363 help
364 Say Y here if you want support for cameras based on the T613 chip.
365
366 To compile this driver as a module, choose M here: the
367 module will be called gspca_t613.
368
369config USB_GSPCA_TOPRO
370 tristate "TOPRO USB Camera Driver"
371 depends on VIDEO_V4L2 && USB_GSPCA
372 help
373 Say Y here if you want support for cameras based on the
374 TP6800 and TP6810 Topro chips.
375
376 To compile this driver as a module, choose M here: the
377 module will be called gspca_topro.
378
379config USB_GSPCA_TV8532
380 tristate "TV8532 USB Camera Driver"
381 depends on VIDEO_V4L2 && USB_GSPCA
382 help
383 Say Y here if you want support for cameras based on the TV8531 chip.
384
385 To compile this driver as a module, choose M here: the
386 module will be called gspca_tv8532.
387
388config USB_GSPCA_VC032X
389 tristate "VC032X USB Camera Driver"
390 depends on VIDEO_V4L2 && USB_GSPCA
391 help
392 Say Y here if you want support for cameras based on the VC032X chip.
393
394 To compile this driver as a module, choose M here: the
395 module will be called gspca_vc032x.
396
397config USB_GSPCA_VICAM
398 tristate "ViCam USB Camera Driver"
399 depends on VIDEO_V4L2 && USB_GSPCA
400 help
401 Say Y here if you want support for the 3com homeconnect camera
402 (vicam).
403
404 To compile this driver as a module, choose M here: the
405 module will be called gspca_vicam.
406
407config USB_GSPCA_XIRLINK_CIT
408 tristate "Xirlink C-It USB Camera Driver"
409 depends on VIDEO_V4L2 && USB_GSPCA
410 help
411 Say Y here if you want support for Xirlink C-It bases cameras.
412
413 To compile this driver as a module, choose M here: the
414 module will be called gspca_xirlink_cit.
415
416config USB_GSPCA_ZC3XX
417 tristate "ZC3XX USB Camera Driver"
418 depends on VIDEO_V4L2 && USB_GSPCA
419 help
420 Say Y here if you want support for cameras based on the ZC3XX chip.
421
422 To compile this driver as a module, choose M here: the
423 module will be called gspca_zc3xx.
424
425endif
diff --git a/drivers/media/usb/gspca/Makefile b/drivers/media/usb/gspca/Makefile
new file mode 100644
index 00000000000..c901da0bd65
--- /dev/null
+++ b/drivers/media/usb/gspca/Makefile
@@ -0,0 +1,93 @@
1obj-$(CONFIG_USB_GSPCA) += gspca_main.o
2obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o
3obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o
4obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o
5obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o
6obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o
7obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o
8obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o
9obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o
10obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o
11obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
12obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
13obj-$(CONFIG_USB_GSPCA_NW80X) += gspca_nw80x.o
14obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
15obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o
16obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o
17obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
18obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o
19obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
20obj-$(CONFIG_USB_GSPCA_SE401) += gspca_se401.o
21obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
22obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
23obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
24obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
25obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
26obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o
27obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o
28obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
29obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
30obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
31obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o
32obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o
33obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o
34obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o
35obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
36obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
37obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o
38obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
39obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o
40obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o
41obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
42obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o
43obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o
44obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o
45
46gspca_main-objs := gspca.o autogain_functions.o
47gspca_benq-objs := benq.o
48gspca_conex-objs := conex.o
49gspca_cpia1-objs := cpia1.o
50gspca_etoms-objs := etoms.o
51gspca_finepix-objs := finepix.o
52gspca_jeilinj-objs := jeilinj.o
53gspca_jl2005bcd-objs := jl2005bcd.o
54gspca_kinect-objs := kinect.o
55gspca_konica-objs := konica.o
56gspca_mars-objs := mars.o
57gspca_mr97310a-objs := mr97310a.o
58gspca_nw80x-objs := nw80x.o
59gspca_ov519-objs := ov519.o
60gspca_ov534-objs := ov534.o
61gspca_ov534_9-objs := ov534_9.o
62gspca_pac207-objs := pac207.o
63gspca_pac7302-objs := pac7302.o
64gspca_pac7311-objs := pac7311.o
65gspca_se401-objs := se401.o
66gspca_sn9c2028-objs := sn9c2028.o
67gspca_sn9c20x-objs := sn9c20x.o
68gspca_sonixb-objs := sonixb.o
69gspca_sonixj-objs := sonixj.o
70gspca_spca500-objs := spca500.o
71gspca_spca501-objs := spca501.o
72gspca_spca505-objs := spca505.o
73gspca_spca506-objs := spca506.o
74gspca_spca508-objs := spca508.o
75gspca_spca561-objs := spca561.o
76gspca_spca1528-objs := spca1528.o
77gspca_sq905-objs := sq905.o
78gspca_sq905c-objs := sq905c.o
79gspca_sq930x-objs := sq930x.o
80gspca_stk014-objs := stk014.o
81gspca_stv0680-objs := stv0680.o
82gspca_sunplus-objs := sunplus.o
83gspca_t613-objs := t613.o
84gspca_topro-objs := topro.o
85gspca_tv8532-objs := tv8532.o
86gspca_vc032x-objs := vc032x.o
87gspca_vicam-objs := vicam.o
88gspca_xirlink_cit-objs := xirlink_cit.o
89gspca_zc3xx-objs := zc3xx.o
90
91obj-$(CONFIG_USB_M5602) += m5602/
92obj-$(CONFIG_USB_STV06XX) += stv06xx/
93obj-$(CONFIG_USB_GL860) += gl860/
diff --git a/drivers/media/usb/gspca/autogain_functions.c b/drivers/media/usb/gspca/autogain_functions.c
new file mode 100644
index 00000000000..67db674bb04
--- /dev/null
+++ b/drivers/media/usb/gspca/autogain_functions.c
@@ -0,0 +1,178 @@
1/*
2 * Functions for auto gain.
3 *
4 * Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.com>
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 * (at your option) 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#include "gspca.h"
21
22/* auto gain and exposure algorithm based on the knee algorithm described here:
23 http://ytse.tricolour.net/docs/LowLightOptimization.html
24
25 Returns 0 if no changes were made, 1 if the gain and or exposure settings
26 where changed. */
27int gspca_expo_autogain(
28 struct gspca_dev *gspca_dev,
29 int avg_lum,
30 int desired_avg_lum,
31 int deadzone,
32 int gain_knee,
33 int exposure_knee)
34{
35 s32 gain, orig_gain, exposure, orig_exposure;
36 int i, steps, retval = 0;
37
38 if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
39 return 0;
40
41 orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
42 orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
43
44 /* If we are of a multiple of deadzone, do multiple steps to reach the
45 desired lumination fast (with the risc of a slight overshoot) */
46 steps = abs(desired_avg_lum - avg_lum) / deadzone;
47
48 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
49 avg_lum, desired_avg_lum, steps);
50
51 for (i = 0; i < steps; i++) {
52 if (avg_lum > desired_avg_lum) {
53 if (gain > gain_knee)
54 gain--;
55 else if (exposure > exposure_knee)
56 exposure--;
57 else if (gain > gspca_dev->gain->default_value)
58 gain--;
59 else if (exposure > gspca_dev->exposure->minimum)
60 exposure--;
61 else if (gain > gspca_dev->gain->minimum)
62 gain--;
63 else
64 break;
65 } else {
66 if (gain < gspca_dev->gain->default_value)
67 gain++;
68 else if (exposure < exposure_knee)
69 exposure++;
70 else if (gain < gain_knee)
71 gain++;
72 else if (exposure < gspca_dev->exposure->maximum)
73 exposure++;
74 else if (gain < gspca_dev->gain->maximum)
75 gain++;
76 else
77 break;
78 }
79 }
80
81 if (gain != orig_gain) {
82 v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
83 retval = 1;
84 }
85 if (exposure != orig_exposure) {
86 v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
87 retval = 1;
88 }
89
90 if (retval)
91 PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
92 gain, exposure);
93 return retval;
94}
95EXPORT_SYMBOL(gspca_expo_autogain);
96
97/* Autogain + exposure algorithm for cameras with a coarse exposure control
98 (usually this means we can only control the clockdiv to change exposure)
99 As changing the clockdiv so that the fps drops from 30 to 15 fps for
100 example, will lead to a huge exposure change (it effectively doubles),
101 this algorithm normally tries to only adjust the gain (between 40 and
102 80 %) and if that does not help, only then changes exposure. This leads
103 to a much more stable image then using the knee algorithm which at
104 certain points of the knee graph will only try to adjust exposure,
105 which leads to oscilating as one exposure step is huge.
106
107 Returns 0 if no changes were made, 1 if the gain and or exposure settings
108 where changed. */
109int gspca_coarse_grained_expo_autogain(
110 struct gspca_dev *gspca_dev,
111 int avg_lum,
112 int desired_avg_lum,
113 int deadzone)
114{
115 s32 gain_low, gain_high, gain, orig_gain, exposure, orig_exposure;
116 int steps, retval = 0;
117
118 if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
119 return 0;
120
121 orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
122 orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
123
124 gain_low = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
125 5 * 2 + gspca_dev->gain->minimum;
126 gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
127 5 * 4 + gspca_dev->gain->minimum;
128
129 /* If we are of a multiple of deadzone, do multiple steps to reach the
130 desired lumination fast (with the risc of a slight overshoot) */
131 steps = (desired_avg_lum - avg_lum) / deadzone;
132
133 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
134 avg_lum, desired_avg_lum, steps);
135
136 if ((gain + steps) > gain_high &&
137 exposure < gspca_dev->exposure->maximum) {
138 gain = gain_high;
139 gspca_dev->exp_too_low_cnt++;
140 gspca_dev->exp_too_high_cnt = 0;
141 } else if ((gain + steps) < gain_low &&
142 exposure > gspca_dev->exposure->minimum) {
143 gain = gain_low;
144 gspca_dev->exp_too_high_cnt++;
145 gspca_dev->exp_too_low_cnt = 0;
146 } else {
147 gain += steps;
148 if (gain > gspca_dev->gain->maximum)
149 gain = gspca_dev->gain->maximum;
150 else if (gain < gspca_dev->gain->minimum)
151 gain = gspca_dev->gain->minimum;
152 gspca_dev->exp_too_high_cnt = 0;
153 gspca_dev->exp_too_low_cnt = 0;
154 }
155
156 if (gspca_dev->exp_too_high_cnt > 3) {
157 exposure--;
158 gspca_dev->exp_too_high_cnt = 0;
159 } else if (gspca_dev->exp_too_low_cnt > 3) {
160 exposure++;
161 gspca_dev->exp_too_low_cnt = 0;
162 }
163
164 if (gain != orig_gain) {
165 v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
166 retval = 1;
167 }
168 if (exposure != orig_exposure) {
169 v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
170 retval = 1;
171 }
172
173 if (retval)
174 PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
175 gain, exposure);
176 return retval;
177}
178EXPORT_SYMBOL(gspca_coarse_grained_expo_autogain);
diff --git a/drivers/media/usb/gspca/autogain_functions.h b/drivers/media/usb/gspca/autogain_functions.h
new file mode 100644
index 00000000000..d625eafe63e
--- /dev/null
+++ b/drivers/media/usb/gspca/autogain_functions.h
@@ -0,0 +1,183 @@
1/*
2 * Functions for auto gain.
3 *
4 * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>
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 * (at your option) 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#ifdef WANT_REGULAR_AUTOGAIN
22/* auto gain and exposure algorithm based on the knee algorithm described here:
23 http://ytse.tricolour.net/docs/LowLightOptimization.html
24
25 Returns 0 if no changes were made, 1 if the gain and or exposure settings
26 where changed. */
27static inline int auto_gain_n_exposure(
28 struct gspca_dev *gspca_dev,
29 int avg_lum,
30 int desired_avg_lum,
31 int deadzone,
32 int gain_knee,
33 int exposure_knee)
34{
35 struct sd *sd = (struct sd *) gspca_dev;
36 int i, steps, gain, orig_gain, exposure, orig_exposure;
37 int retval = 0;
38
39 orig_gain = gain = sd->ctrls[GAIN].val;
40 orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
41
42 /* If we are of a multiple of deadzone, do multiple steps to reach the
43 desired lumination fast (with the risc of a slight overshoot) */
44 steps = abs(desired_avg_lum - avg_lum) / deadzone;
45
46 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
47 avg_lum, desired_avg_lum, steps);
48
49 for (i = 0; i < steps; i++) {
50 if (avg_lum > desired_avg_lum) {
51 if (gain > gain_knee)
52 gain--;
53 else if (exposure > exposure_knee)
54 exposure--;
55 else if (gain > sd->ctrls[GAIN].def)
56 gain--;
57 else if (exposure > sd->ctrls[EXPOSURE].min)
58 exposure--;
59 else if (gain > sd->ctrls[GAIN].min)
60 gain--;
61 else
62 break;
63 } else {
64 if (gain < sd->ctrls[GAIN].def)
65 gain++;
66 else if (exposure < exposure_knee)
67 exposure++;
68 else if (gain < gain_knee)
69 gain++;
70 else if (exposure < sd->ctrls[EXPOSURE].max)
71 exposure++;
72 else if (gain < sd->ctrls[GAIN].max)
73 gain++;
74 else
75 break;
76 }
77 }
78
79 if (gain != orig_gain) {
80 sd->ctrls[GAIN].val = gain;
81 setgain(gspca_dev);
82 retval = 1;
83 }
84 if (exposure != orig_exposure) {
85 sd->ctrls[EXPOSURE].val = exposure;
86 setexposure(gspca_dev);
87 retval = 1;
88 }
89
90 if (retval)
91 PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
92 gain, exposure);
93 return retval;
94}
95#endif
96
97#ifdef WANT_COARSE_EXPO_AUTOGAIN
98/* Autogain + exposure algorithm for cameras with a coarse exposure control
99 (usually this means we can only control the clockdiv to change exposure)
100 As changing the clockdiv so that the fps drops from 30 to 15 fps for
101 example, will lead to a huge exposure change (it effectively doubles),
102 this algorithm normally tries to only adjust the gain (between 40 and
103 80 %) and if that does not help, only then changes exposure. This leads
104 to a much more stable image then using the knee algorithm which at
105 certain points of the knee graph will only try to adjust exposure,
106 which leads to oscilating as one exposure step is huge.
107
108 Note this assumes that the sd struct for the cam in question has
109 exp_too_low_cnt and exp_too_high_cnt int members for use by this function.
110
111 Returns 0 if no changes were made, 1 if the gain and or exposure settings
112 where changed. */
113static inline int coarse_grained_expo_autogain(
114 struct gspca_dev *gspca_dev,
115 int avg_lum,
116 int desired_avg_lum,
117 int deadzone)
118{
119 struct sd *sd = (struct sd *) gspca_dev;
120 int steps, gain, orig_gain, exposure, orig_exposure;
121 int gain_low, gain_high;
122 int retval = 0;
123
124 orig_gain = gain = sd->ctrls[GAIN].val;
125 orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
126
127 gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2;
128 gain_low += sd->ctrls[GAIN].min;
129 gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4;
130 gain_high += sd->ctrls[GAIN].min;
131
132 /* If we are of a multiple of deadzone, do multiple steps to reach the
133 desired lumination fast (with the risc of a slight overshoot) */
134 steps = (desired_avg_lum - avg_lum) / deadzone;
135
136 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
137 avg_lum, desired_avg_lum, steps);
138
139 if ((gain + steps) > gain_high &&
140 exposure < sd->ctrls[EXPOSURE].max) {
141 gain = gain_high;
142 sd->exp_too_low_cnt++;
143 sd->exp_too_high_cnt = 0;
144 } else if ((gain + steps) < gain_low &&
145 exposure > sd->ctrls[EXPOSURE].min) {
146 gain = gain_low;
147 sd->exp_too_high_cnt++;
148 sd->exp_too_low_cnt = 0;
149 } else {
150 gain += steps;
151 if (gain > sd->ctrls[GAIN].max)
152 gain = sd->ctrls[GAIN].max;
153 else if (gain < sd->ctrls[GAIN].min)
154 gain = sd->ctrls[GAIN].min;
155 sd->exp_too_high_cnt = 0;
156 sd->exp_too_low_cnt = 0;
157 }
158
159 if (sd->exp_too_high_cnt > 3) {
160 exposure--;
161 sd->exp_too_high_cnt = 0;
162 } else if (sd->exp_too_low_cnt > 3) {
163 exposure++;
164 sd->exp_too_low_cnt = 0;
165 }
166
167 if (gain != orig_gain) {
168 sd->ctrls[GAIN].val = gain;
169 setgain(gspca_dev);
170 retval = 1;
171 }
172 if (exposure != orig_exposure) {
173 sd->ctrls[EXPOSURE].val = exposure;
174 setexposure(gspca_dev);
175 retval = 1;
176 }
177
178 if (retval)
179 PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
180 gain, exposure);
181 return retval;
182}
183#endif
diff --git a/drivers/media/usb/gspca/benq.c b/drivers/media/usb/gspca/benq.c
new file mode 100644
index 00000000000..352f32190e6
--- /dev/null
+++ b/drivers/media/usb/gspca/benq.c
@@ -0,0 +1,289 @@
1/*
2 * Benq DC E300 subdriver
3 *
4 * Copyright (C) 2009 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "benq"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
28MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34};
35
36static const struct v4l2_pix_format vga_mode[] = {
37 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
38 .bytesperline = 320,
39 .sizeimage = 320 * 240 * 3 / 8 + 590,
40 .colorspace = V4L2_COLORSPACE_JPEG},
41};
42
43static void sd_isoc_irq(struct urb *urb);
44
45/* -- write a register -- */
46static void reg_w(struct gspca_dev *gspca_dev,
47 u16 value, u16 index)
48{
49 struct usb_device *dev = gspca_dev->dev;
50 int ret;
51
52 if (gspca_dev->usb_err < 0)
53 return;
54 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
55 0x02,
56 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
57 value,
58 index,
59 NULL,
60 0,
61 500);
62 if (ret < 0) {
63 pr_err("reg_w err %d\n", ret);
64 gspca_dev->usb_err = ret;
65 }
66}
67
68/* this function is called at probe time */
69static int sd_config(struct gspca_dev *gspca_dev,
70 const struct usb_device_id *id)
71{
72 gspca_dev->cam.cam_mode = vga_mode;
73 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
74 gspca_dev->cam.no_urb_create = 1;
75 return 0;
76}
77
78/* this function is called at probe and resume time */
79static int sd_init(struct gspca_dev *gspca_dev)
80{
81 return 0;
82}
83
84/* -- start the camera -- */
85static int sd_start(struct gspca_dev *gspca_dev)
86{
87 struct urb *urb;
88 int i, n;
89
90 /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
91#if MAX_NURBS < 4
92#error "Not enough URBs in the gspca table"
93#endif
94#define SD_PKT_SZ 64
95#define SD_NPKT 32
96 for (n = 0; n < 4; n++) {
97 urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
98 if (!urb) {
99 pr_err("usb_alloc_urb failed\n");
100 return -ENOMEM;
101 }
102 gspca_dev->urb[n] = urb;
103 urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
104 SD_PKT_SZ * SD_NPKT,
105 GFP_KERNEL,
106 &urb->transfer_dma);
107
108 if (urb->transfer_buffer == NULL) {
109 pr_err("usb_alloc_coherent failed\n");
110 return -ENOMEM;
111 }
112 urb->dev = gspca_dev->dev;
113 urb->context = gspca_dev;
114 urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;
115 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
116 n & 1 ? 0x82 : 0x83);
117 urb->transfer_flags = URB_ISO_ASAP
118 | URB_NO_TRANSFER_DMA_MAP;
119 urb->interval = 1;
120 urb->complete = sd_isoc_irq;
121 urb->number_of_packets = SD_NPKT;
122 for (i = 0; i < SD_NPKT; i++) {
123 urb->iso_frame_desc[i].length = SD_PKT_SZ;
124 urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;
125 }
126 }
127
128 return gspca_dev->usb_err;
129}
130
131static void sd_stopN(struct gspca_dev *gspca_dev)
132{
133 struct usb_interface *intf;
134
135 reg_w(gspca_dev, 0x003c, 0x0003);
136 reg_w(gspca_dev, 0x003c, 0x0004);
137 reg_w(gspca_dev, 0x003c, 0x0005);
138 reg_w(gspca_dev, 0x003c, 0x0006);
139 reg_w(gspca_dev, 0x003c, 0x0007);
140
141 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
142 usb_set_interface(gspca_dev->dev, gspca_dev->iface,
143 intf->num_altsetting - 1);
144}
145
146static void sd_pkt_scan(struct gspca_dev *gspca_dev,
147 u8 *data, /* isoc packet */
148 int len) /* iso packet length */
149{
150 /* unused */
151}
152
153/* reception of an URB */
154static void sd_isoc_irq(struct urb *urb)
155{
156 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
157 struct urb *urb0;
158 u8 *data;
159 int i, st;
160
161 PDEBUG(D_PACK, "sd isoc irq");
162 if (!gspca_dev->streaming)
163 return;
164 if (urb->status != 0) {
165 if (urb->status == -ESHUTDOWN)
166 return; /* disconnection */
167#ifdef CONFIG_PM
168 if (gspca_dev->frozen)
169 return;
170#endif
171 pr_err("urb status: %d\n", urb->status);
172 return;
173 }
174
175 /* if this is a control URN (ep 0x83), wait */
176 if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])
177 return;
178
179 /* scan both received URBs */
180 if (urb == gspca_dev->urb[1])
181 urb0 = gspca_dev->urb[0];
182 else
183 urb0 = gspca_dev->urb[2];
184 for (i = 0; i < urb->number_of_packets; i++) {
185
186 /* check the packet status and length */
187 if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
188 || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
189 PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
190 urb0->iso_frame_desc[i].actual_length,
191 urb->iso_frame_desc[i].actual_length);
192 gspca_dev->last_packet_type = DISCARD_PACKET;
193 continue;
194 }
195 st = urb0->iso_frame_desc[i].status;
196 if (st == 0)
197 st = urb->iso_frame_desc[i].status;
198 if (st) {
199 pr_err("ISOC data error: [%d] status=%d\n",
200 i, st);
201 gspca_dev->last_packet_type = DISCARD_PACKET;
202 continue;
203 }
204
205 /*
206 * The images are received in URBs of different endpoints
207 * (0x83 and 0x82).
208 * Image pieces in URBs of ep 0x83 are continuated in URBs of
209 * ep 0x82 of the same index.
210 * The packets in the URBs of endpoint 0x83 start with:
211 * - 80 ba/bb 00 00 = start of image followed by 'ff d8'
212 * - 04 ba/bb oo oo = image piece
213 * where 'oo oo' is the image offset
214 (not cheked)
215 * - (other -> bad frame)
216 * The images are JPEG encoded with full header and
217 * normal ff escape.
218 * The end of image ('ff d9') may occur in any URB.
219 * (not cheked)
220 */
221 data = (u8 *) urb0->transfer_buffer
222 + urb0->iso_frame_desc[i].offset;
223 if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {
224
225 /* new image */
226 gspca_frame_add(gspca_dev, LAST_PACKET,
227 NULL, 0);
228 gspca_frame_add(gspca_dev, FIRST_PACKET,
229 data + 4, SD_PKT_SZ - 4);
230 } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {
231 gspca_frame_add(gspca_dev, INTER_PACKET,
232 data + 4, SD_PKT_SZ - 4);
233 } else {
234 gspca_dev->last_packet_type = DISCARD_PACKET;
235 continue;
236 }
237 data = (u8 *) urb->transfer_buffer
238 + urb->iso_frame_desc[i].offset;
239 gspca_frame_add(gspca_dev, INTER_PACKET,
240 data, SD_PKT_SZ);
241 }
242
243 /* resubmit the URBs */
244 st = usb_submit_urb(urb0, GFP_ATOMIC);
245 if (st < 0)
246 pr_err("usb_submit_urb(0) ret %d\n", st);
247 st = usb_submit_urb(urb, GFP_ATOMIC);
248 if (st < 0)
249 pr_err("usb_submit_urb() ret %d\n", st);
250}
251
252/* sub-driver description */
253static const struct sd_desc sd_desc = {
254 .name = MODULE_NAME,
255 .config = sd_config,
256 .init = sd_init,
257 .start = sd_start,
258 .stopN = sd_stopN,
259 .pkt_scan = sd_pkt_scan,
260};
261
262/* -- module initialisation -- */
263static const struct usb_device_id device_table[] = {
264 {USB_DEVICE(0x04a5, 0x3035)},
265 {}
266};
267MODULE_DEVICE_TABLE(usb, device_table);
268
269/* -- device connect -- */
270static int sd_probe(struct usb_interface *intf,
271 const struct usb_device_id *id)
272{
273 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
274 THIS_MODULE);
275}
276
277static struct usb_driver sd_driver = {
278 .name = MODULE_NAME,
279 .id_table = device_table,
280 .probe = sd_probe,
281 .disconnect = gspca_disconnect,
282#ifdef CONFIG_PM
283 .suspend = gspca_suspend,
284 .resume = gspca_resume,
285 .reset_resume = gspca_resume,
286#endif
287};
288
289module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
new file mode 100644
index 00000000000..c9052f20435
--- /dev/null
+++ b/drivers/media/usb/gspca/conex.c
@@ -0,0 +1,966 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "conex"
25
26#include "gspca.h"
27#define CONEX_CAM 1 /* special JPEG header */
28#include "jpeg.h"
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
32MODULE_LICENSE("GPL");
33
34#define QUALITY 50
35
36/* specific webcam descriptor */
37struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39 struct v4l2_ctrl *brightness;
40 struct v4l2_ctrl *contrast;
41 struct v4l2_ctrl *sat;
42
43 u8 jpeg_hdr[JPEG_HDR_SZ];
44};
45
46static const struct v4l2_pix_format vga_mode[] = {
47 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
48 .bytesperline = 176,
49 .sizeimage = 176 * 144 * 3 / 8 + 590,
50 .colorspace = V4L2_COLORSPACE_JPEG,
51 .priv = 3},
52 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
53 .bytesperline = 320,
54 .sizeimage = 320 * 240 * 3 / 8 + 590,
55 .colorspace = V4L2_COLORSPACE_JPEG,
56 .priv = 2},
57 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
58 .bytesperline = 352,
59 .sizeimage = 352 * 288 * 3 / 8 + 590,
60 .colorspace = V4L2_COLORSPACE_JPEG,
61 .priv = 1},
62 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
63 .bytesperline = 640,
64 .sizeimage = 640 * 480 * 3 / 8 + 590,
65 .colorspace = V4L2_COLORSPACE_JPEG,
66 .priv = 0},
67};
68
69/* the read bytes are found in gspca_dev->usb_buf */
70static void reg_r(struct gspca_dev *gspca_dev,
71 __u16 index,
72 __u16 len)
73{
74 struct usb_device *dev = gspca_dev->dev;
75
76#ifdef GSPCA_DEBUG
77 if (len > USB_BUF_SZ) {
78 pr_err("reg_r: buffer overflow\n");
79 return;
80 }
81#endif
82 usb_control_msg(dev,
83 usb_rcvctrlpipe(dev, 0),
84 0,
85 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
86 0,
87 index, gspca_dev->usb_buf, len,
88 500);
89 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
90 index, gspca_dev->usb_buf[0]);
91}
92
93/* the bytes to write are in gspca_dev->usb_buf */
94static void reg_w_val(struct gspca_dev *gspca_dev,
95 __u16 index,
96 __u8 val)
97{
98 struct usb_device *dev = gspca_dev->dev;
99
100 gspca_dev->usb_buf[0] = val;
101 usb_control_msg(dev,
102 usb_sndctrlpipe(dev, 0),
103 0,
104 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
105 0,
106 index, gspca_dev->usb_buf, 1, 500);
107}
108
109static void reg_w(struct gspca_dev *gspca_dev,
110 __u16 index,
111 const __u8 *buffer,
112 __u16 len)
113{
114 struct usb_device *dev = gspca_dev->dev;
115
116#ifdef GSPCA_DEBUG
117 if (len > USB_BUF_SZ) {
118 pr_err("reg_w: buffer overflow\n");
119 return;
120 }
121 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
122#endif
123 memcpy(gspca_dev->usb_buf, buffer, len);
124 usb_control_msg(dev,
125 usb_sndctrlpipe(dev, 0),
126 0,
127 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
128 0,
129 index, gspca_dev->usb_buf, len, 500);
130}
131
132static const __u8 cx_sensor_init[][4] = {
133 {0x88, 0x11, 0x01, 0x01},
134 {0x88, 0x12, 0x70, 0x01},
135 {0x88, 0x0f, 0x00, 0x01},
136 {0x88, 0x05, 0x01, 0x01},
137 {}
138};
139
140static const __u8 cx11646_fw1[][3] = {
141 {0x00, 0x02, 0x00},
142 {0x01, 0x43, 0x00},
143 {0x02, 0xA7, 0x00},
144 {0x03, 0x8B, 0x01},
145 {0x04, 0xE9, 0x02},
146 {0x05, 0x08, 0x04},
147 {0x06, 0x08, 0x05},
148 {0x07, 0x07, 0x06},
149 {0x08, 0xE7, 0x06},
150 {0x09, 0xC6, 0x07},
151 {0x0A, 0x86, 0x08},
152 {0x0B, 0x46, 0x09},
153 {0x0C, 0x05, 0x0A},
154 {0x0D, 0xA5, 0x0A},
155 {0x0E, 0x45, 0x0B},
156 {0x0F, 0xE5, 0x0B},
157 {0x10, 0x85, 0x0C},
158 {0x11, 0x25, 0x0D},
159 {0x12, 0xC4, 0x0D},
160 {0x13, 0x45, 0x0E},
161 {0x14, 0xE4, 0x0E},
162 {0x15, 0x64, 0x0F},
163 {0x16, 0xE4, 0x0F},
164 {0x17, 0x64, 0x10},
165 {0x18, 0xE4, 0x10},
166 {0x19, 0x64, 0x11},
167 {0x1A, 0xE4, 0x11},
168 {0x1B, 0x64, 0x12},
169 {0x1C, 0xE3, 0x12},
170 {0x1D, 0x44, 0x13},
171 {0x1E, 0xC3, 0x13},
172 {0x1F, 0x24, 0x14},
173 {0x20, 0xA3, 0x14},
174 {0x21, 0x04, 0x15},
175 {0x22, 0x83, 0x15},
176 {0x23, 0xE3, 0x15},
177 {0x24, 0x43, 0x16},
178 {0x25, 0xA4, 0x16},
179 {0x26, 0x23, 0x17},
180 {0x27, 0x83, 0x17},
181 {0x28, 0xE3, 0x17},
182 {0x29, 0x43, 0x18},
183 {0x2A, 0xA3, 0x18},
184 {0x2B, 0x03, 0x19},
185 {0x2C, 0x63, 0x19},
186 {0x2D, 0xC3, 0x19},
187 {0x2E, 0x22, 0x1A},
188 {0x2F, 0x63, 0x1A},
189 {0x30, 0xC3, 0x1A},
190 {0x31, 0x23, 0x1B},
191 {0x32, 0x83, 0x1B},
192 {0x33, 0xE2, 0x1B},
193 {0x34, 0x23, 0x1C},
194 {0x35, 0x83, 0x1C},
195 {0x36, 0xE2, 0x1C},
196 {0x37, 0x23, 0x1D},
197 {0x38, 0x83, 0x1D},
198 {0x39, 0xE2, 0x1D},
199 {0x3A, 0x23, 0x1E},
200 {0x3B, 0x82, 0x1E},
201 {0x3C, 0xC3, 0x1E},
202 {0x3D, 0x22, 0x1F},
203 {0x3E, 0x63, 0x1F},
204 {0x3F, 0xC1, 0x1F},
205 {}
206};
207static void cx11646_fw(struct gspca_dev*gspca_dev)
208{
209 int i = 0;
210
211 reg_w_val(gspca_dev, 0x006a, 0x02);
212 while (cx11646_fw1[i][1]) {
213 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
214 i++;
215 }
216 reg_w_val(gspca_dev, 0x006a, 0x00);
217}
218
219static const __u8 cxsensor[] = {
220 0x88, 0x12, 0x70, 0x01,
221 0x88, 0x0d, 0x02, 0x01,
222 0x88, 0x0f, 0x00, 0x01,
223 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
224 0x88, 0x02, 0x10, 0x01,
225 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
226 0x88, 0x0B, 0x00, 0x01,
227 0x88, 0x0A, 0x0A, 0x01,
228 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
229 0x88, 0x05, 0x01, 0x01,
230 0xA1, 0x18, 0x00, 0x01,
231 0x00
232};
233
234static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
235static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
236static const __u8 reg10[] = { 0xb1, 0xb1 };
237static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
238static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
239 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
240static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
241 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
242static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
243static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
244
245static void cx_sensor(struct gspca_dev*gspca_dev)
246{
247 int i = 0;
248 int length;
249 const __u8 *ptsensor = cxsensor;
250
251 reg_w(gspca_dev, 0x0020, reg20, 8);
252 reg_w(gspca_dev, 0x0028, reg28, 8);
253 reg_w(gspca_dev, 0x0010, reg10, 2);
254 reg_w_val(gspca_dev, 0x0092, 0x03);
255
256 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
257 case 0:
258 reg_w(gspca_dev, 0x0071, reg71a, 4);
259 break;
260 case 1:
261 reg_w(gspca_dev, 0x0071, reg71b, 4);
262 break;
263 default:
264/* case 2: */
265 reg_w(gspca_dev, 0x0071, reg71c, 4);
266 break;
267 case 3:
268 reg_w(gspca_dev, 0x0071, reg71d, 4);
269 break;
270 }
271 reg_w(gspca_dev, 0x007b, reg7b, 6);
272 reg_w_val(gspca_dev, 0x00f8, 0x00);
273 reg_w(gspca_dev, 0x0010, reg10, 2);
274 reg_w_val(gspca_dev, 0x0098, 0x41);
275 for (i = 0; i < 11; i++) {
276 if (i == 3 || i == 5 || i == 8)
277 length = 8;
278 else
279 length = 4;
280 reg_w(gspca_dev, 0x00e5, ptsensor, length);
281 if (length == 4)
282 reg_r(gspca_dev, 0x00e8, 1);
283 else
284 reg_r(gspca_dev, 0x00e8, length);
285 ptsensor += length;
286 }
287 reg_r(gspca_dev, 0x00e7, 8);
288}
289
290static const __u8 cx_inits_176[] = {
291 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
292 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
293 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
294 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
295 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
296 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
297 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
298};
299static const __u8 cx_inits_320[] = {
300 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
301 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
302 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
303 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
304 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
305 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
306 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
307};
308static const __u8 cx_inits_352[] = {
309 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
310 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
311 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
312 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
313 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
314 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
315 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
316};
317static const __u8 cx_inits_640[] = {
318 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
319 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
320 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
321 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
322 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
323 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
324 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
325};
326
327static void cx11646_initsize(struct gspca_dev *gspca_dev)
328{
329 const __u8 *cxinit;
330 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
331 static const __u8 reg17[] =
332 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
333
334 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
335 case 0:
336 cxinit = cx_inits_640;
337 break;
338 case 1:
339 cxinit = cx_inits_352;
340 break;
341 default:
342/* case 2: */
343 cxinit = cx_inits_320;
344 break;
345 case 3:
346 cxinit = cx_inits_176;
347 break;
348 }
349 reg_w_val(gspca_dev, 0x009a, 0x01);
350 reg_w_val(gspca_dev, 0x0010, 0x10);
351 reg_w(gspca_dev, 0x0012, reg12, 5);
352 reg_w(gspca_dev, 0x0017, reg17, 8);
353 reg_w_val(gspca_dev, 0x00c0, 0x00);
354 reg_w_val(gspca_dev, 0x00c1, 0x04);
355 reg_w_val(gspca_dev, 0x00c2, 0x04);
356
357 reg_w(gspca_dev, 0x0061, cxinit, 8);
358 cxinit += 8;
359 reg_w(gspca_dev, 0x00ca, cxinit, 8);
360 cxinit += 8;
361 reg_w(gspca_dev, 0x00d2, cxinit, 8);
362 cxinit += 8;
363 reg_w(gspca_dev, 0x00da, cxinit, 6);
364 cxinit += 8;
365 reg_w(gspca_dev, 0x0041, cxinit, 8);
366 cxinit += 8;
367 reg_w(gspca_dev, 0x0049, cxinit, 8);
368 cxinit += 8;
369 reg_w(gspca_dev, 0x0051, cxinit, 2);
370
371 reg_r(gspca_dev, 0x0010, 1);
372}
373
374static const __u8 cx_jpeg_init[][8] = {
375 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
376 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
377 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
378 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
379 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
380 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
381 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
382 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
383 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
384 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
385 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
386 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
387 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
388 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
389 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
390 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
391 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
392 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
393 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
394 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
395 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
396 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
397 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
398 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
399 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
400 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
401 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
402 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
403 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
404 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
405 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
406 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
407 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
408 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
409 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
410 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
411 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
412 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
413 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
414 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
415 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
416 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
417 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
418 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
419 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
420 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
421 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
422 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
423 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
424 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
425 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
426 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
427 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
428 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
429 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
430 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
431 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
432 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
433 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
434 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
435 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
436 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
437 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
438 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
439 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
440 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
441 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
442 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
443 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
444 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
445 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
446 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
447 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
448 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
449 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
450 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
451 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
452 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
453 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
454};
455
456
457static const __u8 cxjpeg_640[][8] = {
458 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
459 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
460 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
461 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
462 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
463 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
464 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
465 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
466 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
467 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
468 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
469 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
470 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
471 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
472 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
473 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
474 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
475 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
476 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
477 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
478 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
479 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
480 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
481 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
482 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
483 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
484 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
485};
486static const __u8 cxjpeg_352[][8] = {
487 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
488 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
489 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
490 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
491 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
492 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
493 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
494 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
495 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
496 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
497 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
498 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
499 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
500 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
501 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
502 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
503 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
504 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
505 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
506 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
507 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
508 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
509 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
510 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
511 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
512 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
513 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
514};
515static const __u8 cxjpeg_320[][8] = {
516 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
517 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
518 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
519 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
520 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
521 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
522 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
523 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
524 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
525 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
526 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
527 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
528 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
529 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
530 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
531 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
532 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
533 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
534 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
535 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
536 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
537 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
538 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
539 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
540 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
541 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
542 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
543};
544static const __u8 cxjpeg_176[][8] = {
545 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
546 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
547 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
548 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
549 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
550 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
551 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
552 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
553 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
554 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
555 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
556 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
557 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
558 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
559 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
560 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
561 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
562 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
563 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
564 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
565 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
566 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
567 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
568 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
569 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
570 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
571 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
572};
573/* 640 take with the zcx30x part */
574static const __u8 cxjpeg_qtable[][8] = {
575 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
576 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
577 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
578 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
579 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
580 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
581 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
582 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
583 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
584 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
585 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
586 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
587 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
588 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
589 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
590 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
591 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
592 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
593};
594
595
596static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
597{
598 int i;
599 int length;
600
601 reg_w_val(gspca_dev, 0x00c0, 0x01);
602 reg_w_val(gspca_dev, 0x00c3, 0x00);
603 reg_w_val(gspca_dev, 0x00c0, 0x00);
604 reg_r(gspca_dev, 0x0001, 1);
605 length = 8;
606 for (i = 0; i < 79; i++) {
607 if (i == 78)
608 length = 6;
609 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
610 }
611 reg_r(gspca_dev, 0x0002, 1);
612 reg_w_val(gspca_dev, 0x0055, 0x14);
613}
614
615static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
616static const __u8 regE5_8[] =
617 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
618static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
619static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
620static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
621static const __u8 reg51[] = { 0x77, 0x03 };
622#define reg70 0x03
623
624static void cx11646_jpeg(struct gspca_dev*gspca_dev)
625{
626 int i;
627 int length;
628 __u8 Reg55;
629 int retry;
630
631 reg_w_val(gspca_dev, 0x00c0, 0x01);
632 reg_w_val(gspca_dev, 0x00c3, 0x00);
633 reg_w_val(gspca_dev, 0x00c0, 0x00);
634 reg_r(gspca_dev, 0x0001, 1);
635 length = 8;
636 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
637 case 0:
638 for (i = 0; i < 27; i++) {
639 if (i == 26)
640 length = 2;
641 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
642 }
643 Reg55 = 0x28;
644 break;
645 case 1:
646 for (i = 0; i < 27; i++) {
647 if (i == 26)
648 length = 2;
649 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
650 }
651 Reg55 = 0x16;
652 break;
653 default:
654/* case 2: */
655 for (i = 0; i < 27; i++) {
656 if (i == 26)
657 length = 2;
658 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
659 }
660 Reg55 = 0x14;
661 break;
662 case 3:
663 for (i = 0; i < 27; i++) {
664 if (i == 26)
665 length = 2;
666 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
667 }
668 Reg55 = 0x0B;
669 break;
670 }
671
672 reg_r(gspca_dev, 0x0002, 1);
673 reg_w_val(gspca_dev, 0x0055, Reg55);
674 reg_r(gspca_dev, 0x0002, 1);
675 reg_w(gspca_dev, 0x0010, reg10, 2);
676 reg_w_val(gspca_dev, 0x0054, 0x02);
677 reg_w_val(gspca_dev, 0x0054, 0x01);
678 reg_w_val(gspca_dev, 0x0000, 0x94);
679 reg_w_val(gspca_dev, 0x0053, 0xc0);
680 reg_w_val(gspca_dev, 0x00fc, 0xe1);
681 reg_w_val(gspca_dev, 0x0000, 0x00);
682 /* wait for completion */
683 retry = 50;
684 do {
685 reg_r(gspca_dev, 0x0002, 1);
686 /* 0x07 until 0x00 */
687 if (gspca_dev->usb_buf[0] == 0x00)
688 break;
689 reg_w_val(gspca_dev, 0x0053, 0x00);
690 } while (--retry);
691 if (retry == 0)
692 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
693 /* send the qtable now */
694 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
695 length = 8;
696 for (i = 0; i < 18; i++) {
697 if (i == 17)
698 length = 2;
699 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
700
701 }
702 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
703 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
704 reg_w_val(gspca_dev, 0x0054, 0x02);
705 reg_w_val(gspca_dev, 0x0054, 0x01);
706 reg_w_val(gspca_dev, 0x0000, 0x94);
707 reg_w_val(gspca_dev, 0x0053, 0xc0);
708
709 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
710 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
711 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
712 reg_w(gspca_dev, 0x0012, reg12, 5);
713 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
714 reg_r(gspca_dev, 0x00e8, 8);
715 reg_w(gspca_dev, 0x00e5, regE5a, 4);
716 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
717 reg_w_val(gspca_dev, 0x009a, 0x01);
718 reg_w(gspca_dev, 0x00e5, regE5b, 4);
719 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
720 reg_w(gspca_dev, 0x00e5, regE5c, 4);
721 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
722
723 reg_w(gspca_dev, 0x0051, reg51, 2);
724 reg_w(gspca_dev, 0x0010, reg10, 2);
725 reg_w_val(gspca_dev, 0x0070, reg70);
726}
727
728static void cx11646_init1(struct gspca_dev *gspca_dev)
729{
730 int i = 0;
731
732 reg_w_val(gspca_dev, 0x0010, 0x00);
733 reg_w_val(gspca_dev, 0x0053, 0x00);
734 reg_w_val(gspca_dev, 0x0052, 0x00);
735 reg_w_val(gspca_dev, 0x009b, 0x2f);
736 reg_w_val(gspca_dev, 0x009c, 0x10);
737 reg_r(gspca_dev, 0x0098, 1);
738 reg_w_val(gspca_dev, 0x0098, 0x40);
739 reg_r(gspca_dev, 0x0099, 1);
740 reg_w_val(gspca_dev, 0x0099, 0x07);
741 reg_w_val(gspca_dev, 0x0039, 0x40);
742 reg_w_val(gspca_dev, 0x003c, 0xff);
743 reg_w_val(gspca_dev, 0x003f, 0x1f);
744 reg_w_val(gspca_dev, 0x003d, 0x40);
745/* reg_w_val(gspca_dev, 0x003d, 0x60); */
746 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
747
748 while (cx_sensor_init[i][0]) {
749 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
750 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
751 if (i == 1) {
752 reg_w_val(gspca_dev, 0x00ed, 0x01);
753 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
754 }
755 i++;
756 }
757 reg_w_val(gspca_dev, 0x00c3, 0x00);
758}
759
760/* this function is called at probe time */
761static int sd_config(struct gspca_dev *gspca_dev,
762 const struct usb_device_id *id)
763{
764 struct cam *cam;
765
766 cam = &gspca_dev->cam;
767 cam->cam_mode = vga_mode;
768 cam->nmodes = ARRAY_SIZE(vga_mode);
769 return 0;
770}
771
772/* this function is called at probe and resume time */
773static int sd_init(struct gspca_dev *gspca_dev)
774{
775 cx11646_init1(gspca_dev);
776 cx11646_initsize(gspca_dev);
777 cx11646_fw(gspca_dev);
778 cx_sensor(gspca_dev);
779 cx11646_jpegInit(gspca_dev);
780 return 0;
781}
782
783static int sd_start(struct gspca_dev *gspca_dev)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 /* create the JPEG header */
788 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
789 0x22); /* JPEG 411 */
790 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
791
792 cx11646_initsize(gspca_dev);
793 cx11646_fw(gspca_dev);
794 cx_sensor(gspca_dev);
795 cx11646_jpeg(gspca_dev);
796 return 0;
797}
798
799/* called on streamoff with alt 0 and on disconnect */
800static void sd_stop0(struct gspca_dev *gspca_dev)
801{
802 int retry = 50;
803
804 if (!gspca_dev->present)
805 return;
806 reg_w_val(gspca_dev, 0x0000, 0x00);
807 reg_r(gspca_dev, 0x0002, 1);
808 reg_w_val(gspca_dev, 0x0053, 0x00);
809
810 while (retry--) {
811/* reg_r(gspca_dev, 0x0002, 1);*/
812 reg_r(gspca_dev, 0x0053, 1);
813 if (gspca_dev->usb_buf[0] == 0)
814 break;
815 }
816 reg_w_val(gspca_dev, 0x0000, 0x00);
817 reg_r(gspca_dev, 0x0002, 1);
818
819 reg_w_val(gspca_dev, 0x0010, 0x00);
820 reg_r(gspca_dev, 0x0033, 1);
821 reg_w_val(gspca_dev, 0x00fc, 0xe0);
822}
823
824static void sd_pkt_scan(struct gspca_dev *gspca_dev,
825 u8 *data, /* isoc packet */
826 int len) /* iso packet length */
827{
828 struct sd *sd = (struct sd *) gspca_dev;
829
830 if (data[0] == 0xff && data[1] == 0xd8) {
831
832 /* start of frame */
833 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
834
835 /* put the JPEG header in the new frame */
836 gspca_frame_add(gspca_dev, FIRST_PACKET,
837 sd->jpeg_hdr, JPEG_HDR_SZ);
838 data += 2;
839 len -= 2;
840 }
841 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
842}
843
844static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
845{
846 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
847 __u8 reg51c[2];
848
849 regE5cbx[2] = val;
850 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
851 reg_r(gspca_dev, 0x00e8, 8);
852 reg_w(gspca_dev, 0x00e5, regE5c, 4);
853 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
854
855 reg51c[0] = 0x77;
856 reg51c[1] = sat;
857 reg_w(gspca_dev, 0x0051, reg51c, 2);
858 reg_w(gspca_dev, 0x0010, reg10, 2);
859 reg_w_val(gspca_dev, 0x0070, reg70);
860}
861
862static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
863{
864 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
865/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
866 __u8 reg51c[2];
867
868 regE5acx[2] = val;
869 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
870 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
871 reg51c[0] = 0x77;
872 reg51c[1] = sat;
873 reg_w(gspca_dev, 0x0051, reg51c, 2);
874 reg_w(gspca_dev, 0x0010, reg10, 2);
875 reg_w_val(gspca_dev, 0x0070, reg70);
876}
877
878static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
879{
880 struct gspca_dev *gspca_dev =
881 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
882 struct sd *sd = (struct sd *)gspca_dev;
883
884 gspca_dev->usb_err = 0;
885
886 if (!gspca_dev->streaming)
887 return 0;
888
889 switch (ctrl->id) {
890 case V4L2_CID_BRIGHTNESS:
891 setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
892 break;
893 case V4L2_CID_CONTRAST:
894 setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
895 break;
896 case V4L2_CID_SATURATION:
897 setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
898 setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
899 break;
900 }
901 return gspca_dev->usb_err;
902}
903
904static const struct v4l2_ctrl_ops sd_ctrl_ops = {
905 .s_ctrl = sd_s_ctrl,
906};
907
908static int sd_init_controls(struct gspca_dev *gspca_dev)
909{
910 struct sd *sd = (struct sd *)gspca_dev;
911 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
912
913 gspca_dev->vdev.ctrl_handler = hdl;
914 v4l2_ctrl_handler_init(hdl, 3);
915 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
916 V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
917 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
918 V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
919 sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
920 V4L2_CID_SATURATION, 0, 7, 1, 3);
921 if (hdl->error) {
922 pr_err("Could not initialize controls\n");
923 return hdl->error;
924 }
925 return 0;
926}
927
928/* sub-driver description */
929static const struct sd_desc sd_desc = {
930 .name = MODULE_NAME,
931 .config = sd_config,
932 .init = sd_init,
933 .init_controls = sd_init_controls,
934 .start = sd_start,
935 .stop0 = sd_stop0,
936 .pkt_scan = sd_pkt_scan,
937};
938
939/* -- module initialisation -- */
940static const struct usb_device_id device_table[] = {
941 {USB_DEVICE(0x0572, 0x0041)},
942 {}
943};
944MODULE_DEVICE_TABLE(usb, device_table);
945
946/* -- device connect -- */
947static int sd_probe(struct usb_interface *intf,
948 const struct usb_device_id *id)
949{
950 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
951 THIS_MODULE);
952}
953
954static struct usb_driver sd_driver = {
955 .name = MODULE_NAME,
956 .id_table = device_table,
957 .probe = sd_probe,
958 .disconnect = gspca_disconnect,
959#ifdef CONFIG_PM
960 .suspend = gspca_suspend,
961 .resume = gspca_resume,
962 .reset_resume = gspca_resume,
963#endif
964};
965
966module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
new file mode 100644
index 00000000000..2499a881d9a
--- /dev/null
+++ b/drivers/media/usb/gspca/cpia1.c
@@ -0,0 +1,1905 @@
1/*
2 * cpia CPiA (1) gspca driver
3 *
4 * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>
5 *
6 * This module is adapted from the in kernel v4l1 cpia driver which is :
7 *
8 * (C) Copyright 1999-2000 Peter Pregler
9 * (C) Copyright 1999-2000 Scott J. Bertin
10 * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
11 * (C) Copyright 2000 STMicroelectronics
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#define MODULE_NAME "cpia1"
32
33#include <linux/input.h>
34#include "gspca.h"
35
36MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
37MODULE_DESCRIPTION("Vision CPiA");
38MODULE_LICENSE("GPL");
39
40/* constant value's */
41#define MAGIC_0 0x19
42#define MAGIC_1 0x68
43#define DATA_IN 0xc0
44#define DATA_OUT 0x40
45#define VIDEOSIZE_QCIF 0 /* 176x144 */
46#define VIDEOSIZE_CIF 1 /* 352x288 */
47#define SUBSAMPLE_420 0
48#define SUBSAMPLE_422 1
49#define YUVORDER_YUYV 0
50#define YUVORDER_UYVY 1
51#define NOT_COMPRESSED 0
52#define COMPRESSED 1
53#define NO_DECIMATION 0
54#define DECIMATION_ENAB 1
55#define EOI 0xff /* End Of Image */
56#define EOL 0xfd /* End Of Line */
57#define FRAME_HEADER_SIZE 64
58
59/* Image grab modes */
60#define CPIA_GRAB_SINGLE 0
61#define CPIA_GRAB_CONTINEOUS 1
62
63/* Compression parameters */
64#define CPIA_COMPRESSION_NONE 0
65#define CPIA_COMPRESSION_AUTO 1
66#define CPIA_COMPRESSION_MANUAL 2
67#define CPIA_COMPRESSION_TARGET_QUALITY 0
68#define CPIA_COMPRESSION_TARGET_FRAMERATE 1
69
70/* Return offsets for GetCameraState */
71#define SYSTEMSTATE 0
72#define GRABSTATE 1
73#define STREAMSTATE 2
74#define FATALERROR 3
75#define CMDERROR 4
76#define DEBUGFLAGS 5
77#define VPSTATUS 6
78#define ERRORCODE 7
79
80/* SystemState */
81#define UNINITIALISED_STATE 0
82#define PASS_THROUGH_STATE 1
83#define LO_POWER_STATE 2
84#define HI_POWER_STATE 3
85#define WARM_BOOT_STATE 4
86
87/* GrabState */
88#define GRAB_IDLE 0
89#define GRAB_ACTIVE 1
90#define GRAB_DONE 2
91
92/* StreamState */
93#define STREAM_NOT_READY 0
94#define STREAM_READY 1
95#define STREAM_OPEN 2
96#define STREAM_PAUSED 3
97#define STREAM_FINISHED 4
98
99/* Fatal Error, CmdError, and DebugFlags */
100#define CPIA_FLAG 1
101#define SYSTEM_FLAG 2
102#define INT_CTRL_FLAG 4
103#define PROCESS_FLAG 8
104#define COM_FLAG 16
105#define VP_CTRL_FLAG 32
106#define CAPTURE_FLAG 64
107#define DEBUG_FLAG 128
108
109/* VPStatus */
110#define VP_STATE_OK 0x00
111
112#define VP_STATE_FAILED_VIDEOINIT 0x01
113#define VP_STATE_FAILED_AECACBINIT 0x02
114#define VP_STATE_AEC_MAX 0x04
115#define VP_STATE_ACB_BMAX 0x08
116
117#define VP_STATE_ACB_RMIN 0x10
118#define VP_STATE_ACB_GMIN 0x20
119#define VP_STATE_ACB_RMAX 0x40
120#define VP_STATE_ACB_GMAX 0x80
121
122/* default (minimum) compensation values */
123#define COMP_RED 220
124#define COMP_GREEN1 214
125#define COMP_GREEN2 COMP_GREEN1
126#define COMP_BLUE 230
127
128/* exposure status */
129#define EXPOSURE_VERY_LIGHT 0
130#define EXPOSURE_LIGHT 1
131#define EXPOSURE_NORMAL 2
132#define EXPOSURE_DARK 3
133#define EXPOSURE_VERY_DARK 4
134
135#define CPIA_MODULE_CPIA (0 << 5)
136#define CPIA_MODULE_SYSTEM (1 << 5)
137#define CPIA_MODULE_VP_CTRL (5 << 5)
138#define CPIA_MODULE_CAPTURE (6 << 5)
139#define CPIA_MODULE_DEBUG (7 << 5)
140
141#define INPUT (DATA_IN << 8)
142#define OUTPUT (DATA_OUT << 8)
143
144#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
145#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
146#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
147#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
148#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
149#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
150#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
151#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
152
153#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
154#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
155#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
156#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
157#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
158#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
159#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
160#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
161#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
162#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
163#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
164#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
165#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
166
167#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
168#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
169#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
170#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
171#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
172#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
173#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
174#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
175#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
176#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
177#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
178#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
179#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
180#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
181#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
182#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
183#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
184
185#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
186#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
187#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
188#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
189#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
190#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
191#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
192#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
193#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
194#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
195#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
196#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
197#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
198#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
199#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)
200
201#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
202#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
203#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
204#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
205#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
206#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
207#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
208#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)
209
210#define ROUND_UP_EXP_FOR_FLICKER 15
211
212/* Constants for automatic frame rate adjustment */
213#define MAX_EXP 302
214#define MAX_EXP_102 255
215#define LOW_EXP 140
216#define VERY_LOW_EXP 70
217#define TC 94
218#define EXP_ACC_DARK 50
219#define EXP_ACC_LIGHT 90
220#define HIGH_COMP_102 160
221#define MAX_COMP 239
222#define DARK_TIME 3
223#define LIGHT_TIME 3
224
225#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
226 sd->params.version.firmwareRevision == (y))
227
228#define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000)
229#define BRIGHTNESS_DEF 50
230#define CONTRAST_DEF 48
231#define SATURATION_DEF 50
232#define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ
233#define ILLUMINATORS_1_DEF 0
234#define ILLUMINATORS_2_DEF 0
235#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
236
237/* Developer's Guide Table 5 p 3-34
238 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
239static u8 flicker_jumps[2][2][4] =
240{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
241 { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
242};
243
244struct cam_params {
245 struct {
246 u8 firmwareVersion;
247 u8 firmwareRevision;
248 u8 vcVersion;
249 u8 vcRevision;
250 } version;
251 struct {
252 u16 vendor;
253 u16 product;
254 u16 deviceRevision;
255 } pnpID;
256 struct {
257 u8 vpVersion;
258 u8 vpRevision;
259 u16 cameraHeadID;
260 } vpVersion;
261 struct {
262 u8 systemState;
263 u8 grabState;
264 u8 streamState;
265 u8 fatalError;
266 u8 cmdError;
267 u8 debugFlags;
268 u8 vpStatus;
269 u8 errorCode;
270 } status;
271 struct {
272 u8 brightness;
273 u8 contrast;
274 u8 saturation;
275 } colourParams;
276 struct {
277 u8 gainMode;
278 u8 expMode;
279 u8 compMode;
280 u8 centreWeight;
281 u8 gain;
282 u8 fineExp;
283 u8 coarseExpLo;
284 u8 coarseExpHi;
285 u8 redComp;
286 u8 green1Comp;
287 u8 green2Comp;
288 u8 blueComp;
289 } exposure;
290 struct {
291 u8 balanceMode;
292 u8 redGain;
293 u8 greenGain;
294 u8 blueGain;
295 } colourBalance;
296 struct {
297 u8 divisor;
298 u8 baserate;
299 } sensorFps;
300 struct {
301 u8 gain1;
302 u8 gain2;
303 u8 gain4;
304 u8 gain8;
305 } apcor;
306 struct {
307 u8 disabled;
308 u8 flickerMode;
309 u8 coarseJump;
310 u8 allowableOverExposure;
311 } flickerControl;
312 struct {
313 u8 gain1;
314 u8 gain2;
315 u8 gain4;
316 u8 gain8;
317 } vlOffset;
318 struct {
319 u8 mode;
320 u8 decimation;
321 } compression;
322 struct {
323 u8 frTargeting;
324 u8 targetFR;
325 u8 targetQ;
326 } compressionTarget;
327 struct {
328 u8 yThreshold;
329 u8 uvThreshold;
330 } yuvThreshold;
331 struct {
332 u8 hysteresis;
333 u8 threshMax;
334 u8 smallStep;
335 u8 largeStep;
336 u8 decimationHysteresis;
337 u8 frDiffStepThresh;
338 u8 qDiffStepThresh;
339 u8 decimationThreshMod;
340 } compressionParams;
341 struct {
342 u8 videoSize; /* CIF/QCIF */
343 u8 subSample;
344 u8 yuvOrder;
345 } format;
346 struct { /* Intel QX3 specific data */
347 u8 qx3_detected; /* a QX3 is present */
348 u8 toplight; /* top light lit , R/W */
349 u8 bottomlight; /* bottom light lit, R/W */
350 u8 button; /* snapshot button pressed (R/O) */
351 u8 cradled; /* microscope is in cradle (R/O) */
352 } qx3;
353 struct {
354 u8 colStart; /* skip first 8*colStart pixels */
355 u8 colEnd; /* finish at 8*colEnd pixels */
356 u8 rowStart; /* skip first 4*rowStart lines */
357 u8 rowEnd; /* finish at 4*rowEnd lines */
358 } roi;
359 u8 ecpTiming;
360 u8 streamStartLine;
361};
362
363/* specific webcam descriptor */
364struct sd {
365 struct gspca_dev gspca_dev; /* !! must be the first item */
366 struct cam_params params; /* camera settings */
367
368 atomic_t cam_exposure;
369 atomic_t fps;
370 int exposure_count;
371 u8 exposure_status;
372 struct v4l2_ctrl *freq;
373 u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */
374 u8 first_frame;
375};
376
377static const struct v4l2_pix_format mode[] = {
378 {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
379 /* The sizeimage is trial and error, as with low framerates
380 the camera will pad out usb frames, making the image
381 data larger then strictly necessary */
382 .bytesperline = 160,
383 .sizeimage = 65536,
384 .colorspace = V4L2_COLORSPACE_SRGB,
385 .priv = 3},
386 {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
387 .bytesperline = 172,
388 .sizeimage = 65536,
389 .colorspace = V4L2_COLORSPACE_SRGB,
390 .priv = 2},
391 {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
392 .bytesperline = 320,
393 .sizeimage = 262144,
394 .colorspace = V4L2_COLORSPACE_SRGB,
395 .priv = 1},
396 {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
397 .bytesperline = 352,
398 .sizeimage = 262144,
399 .colorspace = V4L2_COLORSPACE_SRGB,
400 .priv = 0},
401};
402
403/**********************************************************************
404 *
405 * General functions
406 *
407 **********************************************************************/
408
409static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
410{
411 u8 requesttype;
412 unsigned int pipe;
413 int ret, databytes = command[6] | (command[7] << 8);
414 /* Sometimes we see spurious EPIPE errors */
415 int retries = 3;
416
417 if (command[0] == DATA_IN) {
418 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
419 requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
420 } else if (command[0] == DATA_OUT) {
421 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
422 requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
423 } else {
424 PDEBUG(D_ERR, "Unexpected first byte of command: %x",
425 command[0]);
426 return -EINVAL;
427 }
428
429retry:
430 ret = usb_control_msg(gspca_dev->dev, pipe,
431 command[1],
432 requesttype,
433 command[2] | (command[3] << 8),
434 command[4] | (command[5] << 8),
435 gspca_dev->usb_buf, databytes, 1000);
436
437 if (ret < 0)
438 pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
439
440 if (ret == -EPIPE && retries > 0) {
441 retries--;
442 goto retry;
443 }
444
445 return (ret < 0) ? ret : 0;
446}
447
448/* send an arbitrary command to the camera */
449static int do_command(struct gspca_dev *gspca_dev, u16 command,
450 u8 a, u8 b, u8 c, u8 d)
451{
452 struct sd *sd = (struct sd *) gspca_dev;
453 int ret, datasize;
454 u8 cmd[8];
455
456 switch (command) {
457 case CPIA_COMMAND_GetCPIAVersion:
458 case CPIA_COMMAND_GetPnPID:
459 case CPIA_COMMAND_GetCameraStatus:
460 case CPIA_COMMAND_GetVPVersion:
461 case CPIA_COMMAND_GetColourParams:
462 case CPIA_COMMAND_GetColourBalance:
463 case CPIA_COMMAND_GetExposure:
464 datasize = 8;
465 break;
466 case CPIA_COMMAND_ReadMCPorts:
467 case CPIA_COMMAND_ReadVCRegs:
468 datasize = 4;
469 break;
470 default:
471 datasize = 0;
472 break;
473 }
474
475 cmd[0] = command >> 8;
476 cmd[1] = command & 0xff;
477 cmd[2] = a;
478 cmd[3] = b;
479 cmd[4] = c;
480 cmd[5] = d;
481 cmd[6] = datasize;
482 cmd[7] = 0;
483
484 ret = cpia_usb_transferCmd(gspca_dev, cmd);
485 if (ret)
486 return ret;
487
488 switch (command) {
489 case CPIA_COMMAND_GetCPIAVersion:
490 sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
491 sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
492 sd->params.version.vcVersion = gspca_dev->usb_buf[2];
493 sd->params.version.vcRevision = gspca_dev->usb_buf[3];
494 break;
495 case CPIA_COMMAND_GetPnPID:
496 sd->params.pnpID.vendor =
497 gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
498 sd->params.pnpID.product =
499 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
500 sd->params.pnpID.deviceRevision =
501 gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
502 break;
503 case CPIA_COMMAND_GetCameraStatus:
504 sd->params.status.systemState = gspca_dev->usb_buf[0];
505 sd->params.status.grabState = gspca_dev->usb_buf[1];
506 sd->params.status.streamState = gspca_dev->usb_buf[2];
507 sd->params.status.fatalError = gspca_dev->usb_buf[3];
508 sd->params.status.cmdError = gspca_dev->usb_buf[4];
509 sd->params.status.debugFlags = gspca_dev->usb_buf[5];
510 sd->params.status.vpStatus = gspca_dev->usb_buf[6];
511 sd->params.status.errorCode = gspca_dev->usb_buf[7];
512 break;
513 case CPIA_COMMAND_GetVPVersion:
514 sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
515 sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
516 sd->params.vpVersion.cameraHeadID =
517 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
518 break;
519 case CPIA_COMMAND_GetColourParams:
520 sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
521 sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
522 sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
523 break;
524 case CPIA_COMMAND_GetColourBalance:
525 sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
526 sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
527 sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
528 break;
529 case CPIA_COMMAND_GetExposure:
530 sd->params.exposure.gain = gspca_dev->usb_buf[0];
531 sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
532 sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
533 sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
534 sd->params.exposure.redComp = gspca_dev->usb_buf[4];
535 sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
536 sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
537 sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
538 break;
539
540 case CPIA_COMMAND_ReadMCPorts:
541 /* test button press */
542 a = ((gspca_dev->usb_buf[1] & 0x02) == 0);
543 if (a != sd->params.qx3.button) {
544#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
545 input_report_key(gspca_dev->input_dev, KEY_CAMERA, a);
546 input_sync(gspca_dev->input_dev);
547#endif
548 sd->params.qx3.button = a;
549 }
550 if (sd->params.qx3.button) {
551 /* button pressed - unlock the latch */
552 do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
553 3, 0xdf, 0xdf, 0);
554 do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
555 3, 0xff, 0xff, 0);
556 }
557
558 /* test whether microscope is cradled */
559 sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
560 break;
561 }
562
563 return 0;
564}
565
566/* send a command to the camera with an additional data transaction */
567static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
568 u8 a, u8 b, u8 c, u8 d,
569 u8 e, u8 f, u8 g, u8 h,
570 u8 i, u8 j, u8 k, u8 l)
571{
572 u8 cmd[8];
573
574 cmd[0] = command >> 8;
575 cmd[1] = command & 0xff;
576 cmd[2] = a;
577 cmd[3] = b;
578 cmd[4] = c;
579 cmd[5] = d;
580 cmd[6] = 8;
581 cmd[7] = 0;
582 gspca_dev->usb_buf[0] = e;
583 gspca_dev->usb_buf[1] = f;
584 gspca_dev->usb_buf[2] = g;
585 gspca_dev->usb_buf[3] = h;
586 gspca_dev->usb_buf[4] = i;
587 gspca_dev->usb_buf[5] = j;
588 gspca_dev->usb_buf[6] = k;
589 gspca_dev->usb_buf[7] = l;
590
591 return cpia_usb_transferCmd(gspca_dev, cmd);
592}
593
594/* find_over_exposure
595 * Finds a suitable value of OverExposure for use with SetFlickerCtrl
596 * Some calculation is required because this value changes with the brightness
597 * set with SetColourParameters
598 *
599 * Parameters: Brightness - last brightness value set with SetColourParameters
600 *
601 * Returns: OverExposure value to use with SetFlickerCtrl
602 */
603#define FLICKER_MAX_EXPOSURE 250
604#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146
605#define FLICKER_BRIGHTNESS_CONSTANT 59
606static int find_over_exposure(int brightness)
607{
608 int MaxAllowableOverExposure, OverExposure;
609
610 MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
611 FLICKER_BRIGHTNESS_CONSTANT;
612
613 if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
614 OverExposure = MaxAllowableOverExposure;
615 else
616 OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
617
618 return OverExposure;
619}
620#undef FLICKER_MAX_EXPOSURE
621#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
622#undef FLICKER_BRIGHTNESS_CONSTANT
623
624/* initialise cam_data structure */
625static void reset_camera_params(struct gspca_dev *gspca_dev)
626{
627 struct sd *sd = (struct sd *) gspca_dev;
628 struct cam_params *params = &sd->params;
629
630 /* The following parameter values are the defaults from
631 * "Software Developer's Guide for CPiA Cameras". Any changes
632 * to the defaults are noted in comments. */
633 params->colourParams.brightness = BRIGHTNESS_DEF;
634 params->colourParams.contrast = CONTRAST_DEF;
635 params->colourParams.saturation = SATURATION_DEF;
636 params->exposure.gainMode = 4;
637 params->exposure.expMode = 2; /* AEC */
638 params->exposure.compMode = 1;
639 params->exposure.centreWeight = 1;
640 params->exposure.gain = 0;
641 params->exposure.fineExp = 0;
642 params->exposure.coarseExpLo = 185;
643 params->exposure.coarseExpHi = 0;
644 params->exposure.redComp = COMP_RED;
645 params->exposure.green1Comp = COMP_GREEN1;
646 params->exposure.green2Comp = COMP_GREEN2;
647 params->exposure.blueComp = COMP_BLUE;
648 params->colourBalance.balanceMode = 2; /* ACB */
649 params->colourBalance.redGain = 32;
650 params->colourBalance.greenGain = 6;
651 params->colourBalance.blueGain = 92;
652 params->apcor.gain1 = 0x18;
653 params->apcor.gain2 = 0x16;
654 params->apcor.gain4 = 0x24;
655 params->apcor.gain8 = 0x34;
656 params->vlOffset.gain1 = 20;
657 params->vlOffset.gain2 = 24;
658 params->vlOffset.gain4 = 26;
659 params->vlOffset.gain8 = 26;
660 params->compressionParams.hysteresis = 3;
661 params->compressionParams.threshMax = 11;
662 params->compressionParams.smallStep = 1;
663 params->compressionParams.largeStep = 3;
664 params->compressionParams.decimationHysteresis = 2;
665 params->compressionParams.frDiffStepThresh = 5;
666 params->compressionParams.qDiffStepThresh = 3;
667 params->compressionParams.decimationThreshMod = 2;
668 /* End of default values from Software Developer's Guide */
669
670 /* Set Sensor FPS to 15fps. This seems better than 30fps
671 * for indoor lighting. */
672 params->sensorFps.divisor = 1;
673 params->sensorFps.baserate = 1;
674
675 params->flickerControl.flickerMode = 0;
676 params->flickerControl.disabled = 1;
677 params->flickerControl.coarseJump =
678 flicker_jumps[sd->mainsFreq]
679 [params->sensorFps.baserate]
680 [params->sensorFps.divisor];
681 params->flickerControl.allowableOverExposure =
682 find_over_exposure(params->colourParams.brightness);
683
684 params->yuvThreshold.yThreshold = 6; /* From windows driver */
685 params->yuvThreshold.uvThreshold = 6; /* From windows driver */
686
687 params->format.subSample = SUBSAMPLE_420;
688 params->format.yuvOrder = YUVORDER_YUYV;
689
690 params->compression.mode = CPIA_COMPRESSION_AUTO;
691 params->compression.decimation = NO_DECIMATION;
692
693 params->compressionTarget.frTargeting = COMP_TARGET_DEF;
694 params->compressionTarget.targetFR = 15; /* From windows driver */
695 params->compressionTarget.targetQ = 5; /* From windows driver */
696
697 params->qx3.qx3_detected = 0;
698 params->qx3.toplight = 0;
699 params->qx3.bottomlight = 0;
700 params->qx3.button = 0;
701 params->qx3.cradled = 0;
702}
703
704static void printstatus(struct cam_params *params)
705{
706 PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
707 params->status.systemState, params->status.grabState,
708 params->status.streamState, params->status.fatalError,
709 params->status.cmdError, params->status.debugFlags,
710 params->status.vpStatus, params->status.errorCode);
711}
712
713static int goto_low_power(struct gspca_dev *gspca_dev)
714{
715 struct sd *sd = (struct sd *) gspca_dev;
716 int ret;
717
718 ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
719 if (ret)
720 return ret;
721
722 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
723 if (ret)
724 return ret;
725
726 if (sd->params.status.systemState != LO_POWER_STATE) {
727 if (sd->params.status.systemState != WARM_BOOT_STATE) {
728 PDEBUG(D_ERR,
729 "unexpected state after lo power cmd: %02x",
730 sd->params.status.systemState);
731 printstatus(&sd->params);
732 }
733 return -EIO;
734 }
735
736 PDEBUG(D_CONF, "camera now in LOW power state");
737 return 0;
738}
739
740static int goto_high_power(struct gspca_dev *gspca_dev)
741{
742 struct sd *sd = (struct sd *) gspca_dev;
743 int ret;
744
745 ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
746 if (ret)
747 return ret;
748
749 msleep_interruptible(40); /* windows driver does it too */
750
751 if (signal_pending(current))
752 return -EINTR;
753
754 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
755 if (ret)
756 return ret;
757
758 if (sd->params.status.systemState != HI_POWER_STATE) {
759 PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
760 sd->params.status.systemState);
761 printstatus(&sd->params);
762 return -EIO;
763 }
764
765 PDEBUG(D_CONF, "camera now in HIGH power state");
766 return 0;
767}
768
769static int get_version_information(struct gspca_dev *gspca_dev)
770{
771 int ret;
772
773 /* GetCPIAVersion */
774 ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
775 if (ret)
776 return ret;
777
778 /* GetPnPID */
779 return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
780}
781
782static int save_camera_state(struct gspca_dev *gspca_dev)
783{
784 int ret;
785
786 ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
787 if (ret)
788 return ret;
789
790 return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
791}
792
793static int command_setformat(struct gspca_dev *gspca_dev)
794{
795 struct sd *sd = (struct sd *) gspca_dev;
796 int ret;
797
798 ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
799 sd->params.format.videoSize,
800 sd->params.format.subSample,
801 sd->params.format.yuvOrder, 0);
802 if (ret)
803 return ret;
804
805 return do_command(gspca_dev, CPIA_COMMAND_SetROI,
806 sd->params.roi.colStart, sd->params.roi.colEnd,
807 sd->params.roi.rowStart, sd->params.roi.rowEnd);
808}
809
810static int command_setcolourparams(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813 return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
814 sd->params.colourParams.brightness,
815 sd->params.colourParams.contrast,
816 sd->params.colourParams.saturation, 0);
817}
818
819static int command_setapcor(struct gspca_dev *gspca_dev)
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822 return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
823 sd->params.apcor.gain1,
824 sd->params.apcor.gain2,
825 sd->params.apcor.gain4,
826 sd->params.apcor.gain8);
827}
828
829static int command_setvloffset(struct gspca_dev *gspca_dev)
830{
831 struct sd *sd = (struct sd *) gspca_dev;
832 return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
833 sd->params.vlOffset.gain1,
834 sd->params.vlOffset.gain2,
835 sd->params.vlOffset.gain4,
836 sd->params.vlOffset.gain8);
837}
838
839static int command_setexposure(struct gspca_dev *gspca_dev)
840{
841 struct sd *sd = (struct sd *) gspca_dev;
842 int ret;
843
844 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
845 sd->params.exposure.gainMode,
846 1,
847 sd->params.exposure.compMode,
848 sd->params.exposure.centreWeight,
849 sd->params.exposure.gain,
850 sd->params.exposure.fineExp,
851 sd->params.exposure.coarseExpLo,
852 sd->params.exposure.coarseExpHi,
853 sd->params.exposure.redComp,
854 sd->params.exposure.green1Comp,
855 sd->params.exposure.green2Comp,
856 sd->params.exposure.blueComp);
857 if (ret)
858 return ret;
859
860 if (sd->params.exposure.expMode != 1) {
861 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
862 0,
863 sd->params.exposure.expMode,
864 0, 0,
865 sd->params.exposure.gain,
866 sd->params.exposure.fineExp,
867 sd->params.exposure.coarseExpLo,
868 sd->params.exposure.coarseExpHi,
869 0, 0, 0, 0);
870 }
871
872 return ret;
873}
874
875static int command_setcolourbalance(struct gspca_dev *gspca_dev)
876{
877 struct sd *sd = (struct sd *) gspca_dev;
878
879 if (sd->params.colourBalance.balanceMode == 1) {
880 int ret;
881
882 ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
883 1,
884 sd->params.colourBalance.redGain,
885 sd->params.colourBalance.greenGain,
886 sd->params.colourBalance.blueGain);
887 if (ret)
888 return ret;
889
890 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
891 3, 0, 0, 0);
892 }
893 if (sd->params.colourBalance.balanceMode == 2) {
894 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
895 2, 0, 0, 0);
896 }
897 if (sd->params.colourBalance.balanceMode == 3) {
898 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
899 3, 0, 0, 0);
900 }
901
902 return -EINVAL;
903}
904
905static int command_setcompressiontarget(struct gspca_dev *gspca_dev)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
910 sd->params.compressionTarget.frTargeting,
911 sd->params.compressionTarget.targetFR,
912 sd->params.compressionTarget.targetQ, 0);
913}
914
915static int command_setyuvtresh(struct gspca_dev *gspca_dev)
916{
917 struct sd *sd = (struct sd *) gspca_dev;
918
919 return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
920 sd->params.yuvThreshold.yThreshold,
921 sd->params.yuvThreshold.uvThreshold, 0, 0);
922}
923
924static int command_setcompressionparams(struct gspca_dev *gspca_dev)
925{
926 struct sd *sd = (struct sd *) gspca_dev;
927
928 return do_command_extended(gspca_dev,
929 CPIA_COMMAND_SetCompressionParams,
930 0, 0, 0, 0,
931 sd->params.compressionParams.hysteresis,
932 sd->params.compressionParams.threshMax,
933 sd->params.compressionParams.smallStep,
934 sd->params.compressionParams.largeStep,
935 sd->params.compressionParams.decimationHysteresis,
936 sd->params.compressionParams.frDiffStepThresh,
937 sd->params.compressionParams.qDiffStepThresh,
938 sd->params.compressionParams.decimationThreshMod);
939}
940
941static int command_setcompression(struct gspca_dev *gspca_dev)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
944
945 return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
946 sd->params.compression.mode,
947 sd->params.compression.decimation, 0, 0);
948}
949
950static int command_setsensorfps(struct gspca_dev *gspca_dev)
951{
952 struct sd *sd = (struct sd *) gspca_dev;
953
954 return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
955 sd->params.sensorFps.divisor,
956 sd->params.sensorFps.baserate, 0, 0);
957}
958
959static int command_setflickerctrl(struct gspca_dev *gspca_dev)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
964 sd->params.flickerControl.flickerMode,
965 sd->params.flickerControl.coarseJump,
966 sd->params.flickerControl.allowableOverExposure,
967 0);
968}
969
970static int command_setecptiming(struct gspca_dev *gspca_dev)
971{
972 struct sd *sd = (struct sd *) gspca_dev;
973
974 return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
975 sd->params.ecpTiming, 0, 0, 0);
976}
977
978static int command_pause(struct gspca_dev *gspca_dev)
979{
980 return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
981}
982
983static int command_resume(struct gspca_dev *gspca_dev)
984{
985 struct sd *sd = (struct sd *) gspca_dev;
986
987 return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
988 0, sd->params.streamStartLine, 0, 0);
989}
990
991static int command_setlights(struct gspca_dev *gspca_dev)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994 int ret, p1, p2;
995
996 p1 = (sd->params.qx3.bottomlight == 0) << 1;
997 p2 = (sd->params.qx3.toplight == 0) << 3;
998
999 ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
1000 0x90, 0x8f, 0x50, 0);
1001 if (ret)
1002 return ret;
1003
1004 return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
1005 p1 | p2 | 0xe0, 0);
1006}
1007
1008static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
1009{
1010 /* Everything in here is from the Windows driver */
1011/* define for compgain calculation */
1012#if 0
1013#define COMPGAIN(base, curexp, newexp) \
1014 (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
1015#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
1016 (u16)((float)curexp * (float)(u8)(curcomp + 128) / \
1017 (float)(u8)(basecomp - 128))
1018#else
1019 /* equivalent functions without floating point math */
1020#define COMPGAIN(base, curexp, newexp) \
1021 (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
1022#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
1023 (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
1024#endif
1025
1026 struct sd *sd = (struct sd *) gspca_dev;
1027 int currentexp = sd->params.exposure.coarseExpLo +
1028 sd->params.exposure.coarseExpHi * 256;
1029 int ret, startexp;
1030
1031 if (on) {
1032 int cj = sd->params.flickerControl.coarseJump;
1033 sd->params.flickerControl.flickerMode = 1;
1034 sd->params.flickerControl.disabled = 0;
1035 if (sd->params.exposure.expMode != 2) {
1036 sd->params.exposure.expMode = 2;
1037 sd->exposure_status = EXPOSURE_NORMAL;
1038 }
1039 currentexp = currentexp << sd->params.exposure.gain;
1040 sd->params.exposure.gain = 0;
1041 /* round down current exposure to nearest value */
1042 startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
1043 if (startexp < 1)
1044 startexp = 1;
1045 startexp = (startexp * cj) - 1;
1046 if (FIRMWARE_VERSION(1, 2))
1047 while (startexp > MAX_EXP_102)
1048 startexp -= cj;
1049 else
1050 while (startexp > MAX_EXP)
1051 startexp -= cj;
1052 sd->params.exposure.coarseExpLo = startexp & 0xff;
1053 sd->params.exposure.coarseExpHi = startexp >> 8;
1054 if (currentexp > startexp) {
1055 if (currentexp > (2 * startexp))
1056 currentexp = 2 * startexp;
1057 sd->params.exposure.redComp =
1058 COMPGAIN(COMP_RED, currentexp, startexp);
1059 sd->params.exposure.green1Comp =
1060 COMPGAIN(COMP_GREEN1, currentexp, startexp);
1061 sd->params.exposure.green2Comp =
1062 COMPGAIN(COMP_GREEN2, currentexp, startexp);
1063 sd->params.exposure.blueComp =
1064 COMPGAIN(COMP_BLUE, currentexp, startexp);
1065 } else {
1066 sd->params.exposure.redComp = COMP_RED;
1067 sd->params.exposure.green1Comp = COMP_GREEN1;
1068 sd->params.exposure.green2Comp = COMP_GREEN2;
1069 sd->params.exposure.blueComp = COMP_BLUE;
1070 }
1071 if (FIRMWARE_VERSION(1, 2))
1072 sd->params.exposure.compMode = 0;
1073 else
1074 sd->params.exposure.compMode = 1;
1075
1076 sd->params.apcor.gain1 = 0x18;
1077 sd->params.apcor.gain2 = 0x18;
1078 sd->params.apcor.gain4 = 0x16;
1079 sd->params.apcor.gain8 = 0x14;
1080 } else {
1081 sd->params.flickerControl.flickerMode = 0;
1082 sd->params.flickerControl.disabled = 1;
1083 /* Average equivalent coarse for each comp channel */
1084 startexp = EXP_FROM_COMP(COMP_RED,
1085 sd->params.exposure.redComp, currentexp);
1086 startexp += EXP_FROM_COMP(COMP_GREEN1,
1087 sd->params.exposure.green1Comp, currentexp);
1088 startexp += EXP_FROM_COMP(COMP_GREEN2,
1089 sd->params.exposure.green2Comp, currentexp);
1090 startexp += EXP_FROM_COMP(COMP_BLUE,
1091 sd->params.exposure.blueComp, currentexp);
1092 startexp = startexp >> 2;
1093 while (startexp > MAX_EXP && sd->params.exposure.gain <
1094 sd->params.exposure.gainMode - 1) {
1095 startexp = startexp >> 1;
1096 ++sd->params.exposure.gain;
1097 }
1098 if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
1099 startexp = MAX_EXP_102;
1100 if (startexp > MAX_EXP)
1101 startexp = MAX_EXP;
1102 sd->params.exposure.coarseExpLo = startexp & 0xff;
1103 sd->params.exposure.coarseExpHi = startexp >> 8;
1104 sd->params.exposure.redComp = COMP_RED;
1105 sd->params.exposure.green1Comp = COMP_GREEN1;
1106 sd->params.exposure.green2Comp = COMP_GREEN2;
1107 sd->params.exposure.blueComp = COMP_BLUE;
1108 sd->params.exposure.compMode = 1;
1109 sd->params.apcor.gain1 = 0x18;
1110 sd->params.apcor.gain2 = 0x16;
1111 sd->params.apcor.gain4 = 0x24;
1112 sd->params.apcor.gain8 = 0x34;
1113 }
1114 sd->params.vlOffset.gain1 = 20;
1115 sd->params.vlOffset.gain2 = 24;
1116 sd->params.vlOffset.gain4 = 26;
1117 sd->params.vlOffset.gain8 = 26;
1118
1119 if (apply) {
1120 ret = command_setexposure(gspca_dev);
1121 if (ret)
1122 return ret;
1123
1124 ret = command_setapcor(gspca_dev);
1125 if (ret)
1126 return ret;
1127
1128 ret = command_setvloffset(gspca_dev);
1129 if (ret)
1130 return ret;
1131
1132 ret = command_setflickerctrl(gspca_dev);
1133 if (ret)
1134 return ret;
1135 }
1136
1137 return 0;
1138#undef EXP_FROM_COMP
1139#undef COMPGAIN
1140}
1141
1142/* monitor the exposure and adjust the sensor frame rate if needed */
1143static void monitor_exposure(struct gspca_dev *gspca_dev)
1144{
1145 struct sd *sd = (struct sd *) gspca_dev;
1146 u8 exp_acc, bcomp, cmd[8];
1147 int ret, light_exp, dark_exp, very_dark_exp;
1148 int old_exposure, new_exposure, framerate;
1149 int setfps = 0, setexp = 0, setflicker = 0;
1150
1151 /* get necessary stats and register settings from camera */
1152 /* do_command can't handle this, so do it ourselves */
1153 cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
1154 cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
1155 cmd[2] = 30;
1156 cmd[3] = 4;
1157 cmd[4] = 9;
1158 cmd[5] = 8;
1159 cmd[6] = 8;
1160 cmd[7] = 0;
1161 ret = cpia_usb_transferCmd(gspca_dev, cmd);
1162 if (ret) {
1163 pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
1164 return;
1165 }
1166 exp_acc = gspca_dev->usb_buf[0];
1167 bcomp = gspca_dev->usb_buf[1];
1168
1169 light_exp = sd->params.colourParams.brightness +
1170 TC - 50 + EXP_ACC_LIGHT;
1171 if (light_exp > 255)
1172 light_exp = 255;
1173 dark_exp = sd->params.colourParams.brightness +
1174 TC - 50 - EXP_ACC_DARK;
1175 if (dark_exp < 0)
1176 dark_exp = 0;
1177 very_dark_exp = dark_exp / 2;
1178
1179 old_exposure = sd->params.exposure.coarseExpHi * 256 +
1180 sd->params.exposure.coarseExpLo;
1181
1182 if (!sd->params.flickerControl.disabled) {
1183 /* Flicker control on */
1184 int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
1185 HIGH_COMP_102;
1186 bcomp += 128; /* decode */
1187 if (bcomp >= max_comp && exp_acc < dark_exp) {
1188 /* dark */
1189 if (exp_acc < very_dark_exp) {
1190 /* very dark */
1191 if (sd->exposure_status == EXPOSURE_VERY_DARK)
1192 ++sd->exposure_count;
1193 else {
1194 sd->exposure_status =
1195 EXPOSURE_VERY_DARK;
1196 sd->exposure_count = 1;
1197 }
1198 } else {
1199 /* just dark */
1200 if (sd->exposure_status == EXPOSURE_DARK)
1201 ++sd->exposure_count;
1202 else {
1203 sd->exposure_status = EXPOSURE_DARK;
1204 sd->exposure_count = 1;
1205 }
1206 }
1207 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
1208 /* light */
1209 if (old_exposure <= VERY_LOW_EXP) {
1210 /* very light */
1211 if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
1212 ++sd->exposure_count;
1213 else {
1214 sd->exposure_status =
1215 EXPOSURE_VERY_LIGHT;
1216 sd->exposure_count = 1;
1217 }
1218 } else {
1219 /* just light */
1220 if (sd->exposure_status == EXPOSURE_LIGHT)
1221 ++sd->exposure_count;
1222 else {
1223 sd->exposure_status = EXPOSURE_LIGHT;
1224 sd->exposure_count = 1;
1225 }
1226 }
1227 } else {
1228 /* not dark or light */
1229 sd->exposure_status = EXPOSURE_NORMAL;
1230 }
1231 } else {
1232 /* Flicker control off */
1233 if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
1234 /* dark */
1235 if (exp_acc < very_dark_exp) {
1236 /* very dark */
1237 if (sd->exposure_status == EXPOSURE_VERY_DARK)
1238 ++sd->exposure_count;
1239 else {
1240 sd->exposure_status =
1241 EXPOSURE_VERY_DARK;
1242 sd->exposure_count = 1;
1243 }
1244 } else {
1245 /* just dark */
1246 if (sd->exposure_status == EXPOSURE_DARK)
1247 ++sd->exposure_count;
1248 else {
1249 sd->exposure_status = EXPOSURE_DARK;
1250 sd->exposure_count = 1;
1251 }
1252 }
1253 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
1254 /* light */
1255 if (old_exposure <= VERY_LOW_EXP) {
1256 /* very light */
1257 if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
1258 ++sd->exposure_count;
1259 else {
1260 sd->exposure_status =
1261 EXPOSURE_VERY_LIGHT;
1262 sd->exposure_count = 1;
1263 }
1264 } else {
1265 /* just light */
1266 if (sd->exposure_status == EXPOSURE_LIGHT)
1267 ++sd->exposure_count;
1268 else {
1269 sd->exposure_status = EXPOSURE_LIGHT;
1270 sd->exposure_count = 1;
1271 }
1272 }
1273 } else {
1274 /* not dark or light */
1275 sd->exposure_status = EXPOSURE_NORMAL;
1276 }
1277 }
1278
1279 framerate = atomic_read(&sd->fps);
1280 if (framerate > 30 || framerate < 1)
1281 framerate = 1;
1282
1283 if (!sd->params.flickerControl.disabled) {
1284 /* Flicker control on */
1285 if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
1286 sd->exposure_status == EXPOSURE_DARK) &&
1287 sd->exposure_count >= DARK_TIME * framerate &&
1288 sd->params.sensorFps.divisor < 2) {
1289
1290 /* dark for too long */
1291 ++sd->params.sensorFps.divisor;
1292 setfps = 1;
1293
1294 sd->params.flickerControl.coarseJump =
1295 flicker_jumps[sd->mainsFreq]
1296 [sd->params.sensorFps.baserate]
1297 [sd->params.sensorFps.divisor];
1298 setflicker = 1;
1299
1300 new_exposure = sd->params.flickerControl.coarseJump-1;
1301 while (new_exposure < old_exposure / 2)
1302 new_exposure +=
1303 sd->params.flickerControl.coarseJump;
1304 sd->params.exposure.coarseExpLo = new_exposure & 0xff;
1305 sd->params.exposure.coarseExpHi = new_exposure >> 8;
1306 setexp = 1;
1307 sd->exposure_status = EXPOSURE_NORMAL;
1308 PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
1309
1310 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
1311 sd->exposure_status == EXPOSURE_LIGHT) &&
1312 sd->exposure_count >= LIGHT_TIME * framerate &&
1313 sd->params.sensorFps.divisor > 0) {
1314
1315 /* light for too long */
1316 int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
1317 MAX_EXP;
1318 --sd->params.sensorFps.divisor;
1319 setfps = 1;
1320
1321 sd->params.flickerControl.coarseJump =
1322 flicker_jumps[sd->mainsFreq]
1323 [sd->params.sensorFps.baserate]
1324 [sd->params.sensorFps.divisor];
1325 setflicker = 1;
1326
1327 new_exposure = sd->params.flickerControl.coarseJump-1;
1328 while (new_exposure < 2 * old_exposure &&
1329 new_exposure +
1330 sd->params.flickerControl.coarseJump < max_exp)
1331 new_exposure +=
1332 sd->params.flickerControl.coarseJump;
1333 sd->params.exposure.coarseExpLo = new_exposure & 0xff;
1334 sd->params.exposure.coarseExpHi = new_exposure >> 8;
1335 setexp = 1;
1336 sd->exposure_status = EXPOSURE_NORMAL;
1337 PDEBUG(D_CONF, "Automatically increasing sensor_fps");
1338 }
1339 } else {
1340 /* Flicker control off */
1341 if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
1342 sd->exposure_status == EXPOSURE_DARK) &&
1343 sd->exposure_count >= DARK_TIME * framerate &&
1344 sd->params.sensorFps.divisor < 2) {
1345
1346 /* dark for too long */
1347 ++sd->params.sensorFps.divisor;
1348 setfps = 1;
1349
1350 if (sd->params.exposure.gain > 0) {
1351 --sd->params.exposure.gain;
1352 setexp = 1;
1353 }
1354 sd->exposure_status = EXPOSURE_NORMAL;
1355 PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
1356
1357 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
1358 sd->exposure_status == EXPOSURE_LIGHT) &&
1359 sd->exposure_count >= LIGHT_TIME * framerate &&
1360 sd->params.sensorFps.divisor > 0) {
1361
1362 /* light for too long */
1363 --sd->params.sensorFps.divisor;
1364 setfps = 1;
1365
1366 if (sd->params.exposure.gain <
1367 sd->params.exposure.gainMode - 1) {
1368 ++sd->params.exposure.gain;
1369 setexp = 1;
1370 }
1371 sd->exposure_status = EXPOSURE_NORMAL;
1372 PDEBUG(D_CONF, "Automatically increasing sensor_fps");
1373 }
1374 }
1375
1376 if (setexp)
1377 command_setexposure(gspca_dev);
1378
1379 if (setfps)
1380 command_setsensorfps(gspca_dev);
1381
1382 if (setflicker)
1383 command_setflickerctrl(gspca_dev);
1384}
1385
1386/*-----------------------------------------------------------------*/
1387/* if flicker is switched off, this function switches it back on.It checks,
1388 however, that conditions are suitable before restarting it.
1389 This should only be called for firmware version 1.2.
1390
1391 It also adjust the colour balance when an exposure step is detected - as
1392 long as flicker is running
1393*/
1394static void restart_flicker(struct gspca_dev *gspca_dev)
1395{
1396 struct sd *sd = (struct sd *) gspca_dev;
1397 int cam_exposure, old_exp;
1398
1399 if (!FIRMWARE_VERSION(1, 2))
1400 return;
1401
1402 cam_exposure = atomic_read(&sd->cam_exposure);
1403
1404 if (sd->params.flickerControl.flickerMode == 0 ||
1405 cam_exposure == 0)
1406 return;
1407
1408 old_exp = sd->params.exposure.coarseExpLo +
1409 sd->params.exposure.coarseExpHi*256;
1410 /*
1411 see how far away camera exposure is from a valid
1412 flicker exposure value
1413 */
1414 cam_exposure %= sd->params.flickerControl.coarseJump;
1415 if (!sd->params.flickerControl.disabled &&
1416 cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
1417 /* Flicker control auto-disabled */
1418 sd->params.flickerControl.disabled = 1;
1419 }
1420
1421 if (sd->params.flickerControl.disabled &&
1422 old_exp > sd->params.flickerControl.coarseJump +
1423 ROUND_UP_EXP_FOR_FLICKER) {
1424 /* exposure is now high enough to switch
1425 flicker control back on */
1426 set_flicker(gspca_dev, 1, 1);
1427 }
1428}
1429
1430/* this function is called at probe time */
1431static int sd_config(struct gspca_dev *gspca_dev,
1432 const struct usb_device_id *id)
1433{
1434 struct sd *sd = (struct sd *) gspca_dev;
1435 struct cam *cam;
1436
1437 sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
1438 reset_camera_params(gspca_dev);
1439
1440 PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)",
1441 id->idVendor, id->idProduct);
1442
1443 cam = &gspca_dev->cam;
1444 cam->cam_mode = mode;
1445 cam->nmodes = ARRAY_SIZE(mode);
1446
1447 goto_low_power(gspca_dev);
1448 /* Check the firmware version. */
1449 sd->params.version.firmwareVersion = 0;
1450 get_version_information(gspca_dev);
1451 if (sd->params.version.firmwareVersion != 1) {
1452 PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
1453 sd->params.version.firmwareVersion);
1454 return -ENODEV;
1455 }
1456
1457 /* A bug in firmware 1-02 limits gainMode to 2 */
1458 if (sd->params.version.firmwareRevision <= 2 &&
1459 sd->params.exposure.gainMode > 2) {
1460 sd->params.exposure.gainMode = 2;
1461 }
1462
1463 /* set QX3 detected flag */
1464 sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
1465 sd->params.pnpID.product == 0x0001);
1466 return 0;
1467}
1468
1469/* -- start the camera -- */
1470static int sd_start(struct gspca_dev *gspca_dev)
1471{
1472 struct sd *sd = (struct sd *) gspca_dev;
1473 int priv, ret;
1474
1475 /* Start the camera in low power mode */
1476 if (goto_low_power(gspca_dev)) {
1477 if (sd->params.status.systemState != WARM_BOOT_STATE) {
1478 PDEBUG(D_ERR, "unexpected systemstate: %02x",
1479 sd->params.status.systemState);
1480 printstatus(&sd->params);
1481 return -ENODEV;
1482 }
1483
1484 /* FIXME: this is just dirty trial and error */
1485 ret = goto_high_power(gspca_dev);
1486 if (ret)
1487 return ret;
1488
1489 ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
1490 0, 0, 0, 0);
1491 if (ret)
1492 return ret;
1493
1494 ret = goto_low_power(gspca_dev);
1495 if (ret)
1496 return ret;
1497 }
1498
1499 /* procedure described in developer's guide p3-28 */
1500
1501 /* Check the firmware version. */
1502 sd->params.version.firmwareVersion = 0;
1503 get_version_information(gspca_dev);
1504
1505 /* The fatal error checking should be done after
1506 * the camera powers up (developer's guide p 3-38) */
1507
1508 /* Set streamState before transition to high power to avoid bug
1509 * in firmware 1-02 */
1510 ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
1511 STREAMSTATE, 0, STREAM_NOT_READY, 0);
1512 if (ret)
1513 return ret;
1514
1515 /* GotoHiPower */
1516 ret = goto_high_power(gspca_dev);
1517 if (ret)
1518 return ret;
1519
1520 /* Check the camera status */
1521 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
1522 if (ret)
1523 return ret;
1524
1525 if (sd->params.status.fatalError) {
1526 PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
1527 sd->params.status.fatalError,
1528 sd->params.status.vpStatus);
1529 return -EIO;
1530 }
1531
1532 /* VPVersion can't be retrieved before the camera is in HiPower,
1533 * so get it here instead of in get_version_information. */
1534 ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
1535 if (ret)
1536 return ret;
1537
1538 /* Determine video mode settings */
1539 sd->params.streamStartLine = 120;
1540
1541 priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1542 if (priv & 0x01) { /* crop */
1543 sd->params.roi.colStart = 2;
1544 sd->params.roi.rowStart = 6;
1545 } else {
1546 sd->params.roi.colStart = 0;
1547 sd->params.roi.rowStart = 0;
1548 }
1549
1550 if (priv & 0x02) { /* quarter */
1551 sd->params.format.videoSize = VIDEOSIZE_QCIF;
1552 sd->params.roi.colStart /= 2;
1553 sd->params.roi.rowStart /= 2;
1554 sd->params.streamStartLine /= 2;
1555 } else
1556 sd->params.format.videoSize = VIDEOSIZE_CIF;
1557
1558 sd->params.roi.colEnd = sd->params.roi.colStart +
1559 (gspca_dev->width >> 3);
1560 sd->params.roi.rowEnd = sd->params.roi.rowStart +
1561 (gspca_dev->height >> 2);
1562
1563 /* And now set the camera to a known state */
1564 ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
1565 CPIA_GRAB_CONTINEOUS, 0, 0, 0);
1566 if (ret)
1567 return ret;
1568 /* We start with compression disabled, as we need one uncompressed
1569 frame to handle later compressed frames */
1570 ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
1571 CPIA_COMPRESSION_NONE,
1572 NO_DECIMATION, 0, 0);
1573 if (ret)
1574 return ret;
1575 ret = command_setcompressiontarget(gspca_dev);
1576 if (ret)
1577 return ret;
1578 ret = command_setcolourparams(gspca_dev);
1579 if (ret)
1580 return ret;
1581 ret = command_setformat(gspca_dev);
1582 if (ret)
1583 return ret;
1584 ret = command_setyuvtresh(gspca_dev);
1585 if (ret)
1586 return ret;
1587 ret = command_setecptiming(gspca_dev);
1588 if (ret)
1589 return ret;
1590 ret = command_setcompressionparams(gspca_dev);
1591 if (ret)
1592 return ret;
1593 ret = command_setexposure(gspca_dev);
1594 if (ret)
1595 return ret;
1596 ret = command_setcolourbalance(gspca_dev);
1597 if (ret)
1598 return ret;
1599 ret = command_setsensorfps(gspca_dev);
1600 if (ret)
1601 return ret;
1602 ret = command_setapcor(gspca_dev);
1603 if (ret)
1604 return ret;
1605 ret = command_setflickerctrl(gspca_dev);
1606 if (ret)
1607 return ret;
1608 ret = command_setvloffset(gspca_dev);
1609 if (ret)
1610 return ret;
1611
1612 /* Start stream */
1613 ret = command_resume(gspca_dev);
1614 if (ret)
1615 return ret;
1616
1617 /* Wait 6 frames before turning compression on for the sensor to get
1618 all settings and AEC/ACB to settle */
1619 sd->first_frame = 6;
1620 sd->exposure_status = EXPOSURE_NORMAL;
1621 sd->exposure_count = 0;
1622 atomic_set(&sd->cam_exposure, 0);
1623 atomic_set(&sd->fps, 0);
1624
1625 return 0;
1626}
1627
1628static void sd_stopN(struct gspca_dev *gspca_dev)
1629{
1630 struct sd *sd = (struct sd *) gspca_dev;
1631
1632 command_pause(gspca_dev);
1633
1634 /* save camera state for later open (developers guide ch 3.5.3) */
1635 save_camera_state(gspca_dev);
1636
1637 /* GotoLoPower */
1638 goto_low_power(gspca_dev);
1639
1640 /* Update the camera status */
1641 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
1642
1643#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1644 /* If the last button state is pressed, release it now! */
1645 if (sd->params.qx3.button) {
1646 /* The camera latch will hold the pressed state until we reset
1647 the latch, so we do not reset sd->params.qx3.button now, to
1648 avoid a false keypress being reported the next sd_start */
1649 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1650 input_sync(gspca_dev->input_dev);
1651 }
1652#endif
1653}
1654
1655/* this function is called at probe and resume time */
1656static int sd_init(struct gspca_dev *gspca_dev)
1657{
1658 struct sd *sd = (struct sd *) gspca_dev;
1659 int ret;
1660
1661 /* Start / Stop the camera to make sure we are talking to
1662 a supported camera, and to get some information from it
1663 to print. */
1664 ret = sd_start(gspca_dev);
1665 if (ret)
1666 return ret;
1667
1668 /* Ensure the QX3 illuminators' states are restored upon resume,
1669 or disable the illuminator controls, if this isn't a QX3 */
1670 if (sd->params.qx3.qx3_detected)
1671 command_setlights(gspca_dev);
1672
1673 sd_stopN(gspca_dev);
1674
1675 PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)",
1676 sd->params.version.firmwareVersion,
1677 sd->params.version.firmwareRevision,
1678 sd->params.version.vcVersion,
1679 sd->params.version.vcRevision);
1680 PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x",
1681 sd->params.pnpID.vendor, sd->params.pnpID.product,
1682 sd->params.pnpID.deviceRevision);
1683 PDEBUG(D_PROBE, "VP-Version: %d.%d %04x",
1684 sd->params.vpVersion.vpVersion,
1685 sd->params.vpVersion.vpRevision,
1686 sd->params.vpVersion.cameraHeadID);
1687
1688 return 0;
1689}
1690
1691static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1692 u8 *data,
1693 int len)
1694{
1695 struct sd *sd = (struct sd *) gspca_dev;
1696
1697 /* Check for SOF */
1698 if (len >= 64 &&
1699 data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
1700 data[16] == sd->params.format.videoSize &&
1701 data[17] == sd->params.format.subSample &&
1702 data[18] == sd->params.format.yuvOrder &&
1703 data[24] == sd->params.roi.colStart &&
1704 data[25] == sd->params.roi.colEnd &&
1705 data[26] == sd->params.roi.rowStart &&
1706 data[27] == sd->params.roi.rowEnd) {
1707 u8 *image;
1708
1709 atomic_set(&sd->cam_exposure, data[39] * 2);
1710 atomic_set(&sd->fps, data[41]);
1711
1712 /* Check for proper EOF for last frame */
1713 image = gspca_dev->image;
1714 if (image != NULL &&
1715 gspca_dev->image_len > 4 &&
1716 image[gspca_dev->image_len - 4] == 0xff &&
1717 image[gspca_dev->image_len - 3] == 0xff &&
1718 image[gspca_dev->image_len - 2] == 0xff &&
1719 image[gspca_dev->image_len - 1] == 0xff)
1720 gspca_frame_add(gspca_dev, LAST_PACKET,
1721 NULL, 0);
1722
1723 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1724 return;
1725 }
1726
1727 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1728}
1729
1730static void sd_dq_callback(struct gspca_dev *gspca_dev)
1731{
1732 struct sd *sd = (struct sd *) gspca_dev;
1733
1734 /* Set the normal compression settings once we have captured a
1735 few uncompressed frames (and AEC has hopefully settled) */
1736 if (sd->first_frame) {
1737 sd->first_frame--;
1738 if (sd->first_frame == 0)
1739 command_setcompression(gspca_dev);
1740 }
1741
1742 /* Switch flicker control back on if it got turned off */
1743 restart_flicker(gspca_dev);
1744
1745 /* If AEC is enabled, monitor the exposure and
1746 adjust the sensor frame rate if needed */
1747 if (sd->params.exposure.expMode == 2)
1748 monitor_exposure(gspca_dev);
1749
1750 /* Update our knowledge of the camera state */
1751 do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
1752 do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
1753}
1754
1755static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1756{
1757 struct gspca_dev *gspca_dev =
1758 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1759 struct sd *sd = (struct sd *)gspca_dev;
1760
1761 gspca_dev->usb_err = 0;
1762
1763 if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
1764 return 0;
1765
1766 switch (ctrl->id) {
1767 case V4L2_CID_BRIGHTNESS:
1768 sd->params.colourParams.brightness = ctrl->val;
1769 sd->params.flickerControl.allowableOverExposure =
1770 find_over_exposure(sd->params.colourParams.brightness);
1771 gspca_dev->usb_err = command_setcolourparams(gspca_dev);
1772 if (!gspca_dev->usb_err)
1773 gspca_dev->usb_err = command_setflickerctrl(gspca_dev);
1774 break;
1775 case V4L2_CID_CONTRAST:
1776 sd->params.colourParams.contrast = ctrl->val;
1777 gspca_dev->usb_err = command_setcolourparams(gspca_dev);
1778 break;
1779 case V4L2_CID_SATURATION:
1780 sd->params.colourParams.saturation = ctrl->val;
1781 gspca_dev->usb_err = command_setcolourparams(gspca_dev);
1782 break;
1783 case V4L2_CID_POWER_LINE_FREQUENCY:
1784 sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
1785 sd->params.flickerControl.coarseJump =
1786 flicker_jumps[sd->mainsFreq]
1787 [sd->params.sensorFps.baserate]
1788 [sd->params.sensorFps.divisor];
1789
1790 gspca_dev->usb_err = set_flicker(gspca_dev,
1791 ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
1792 gspca_dev->streaming);
1793 break;
1794 case V4L2_CID_ILLUMINATORS_1:
1795 sd->params.qx3.bottomlight = ctrl->val;
1796 gspca_dev->usb_err = command_setlights(gspca_dev);
1797 break;
1798 case V4L2_CID_ILLUMINATORS_2:
1799 sd->params.qx3.toplight = ctrl->val;
1800 gspca_dev->usb_err = command_setlights(gspca_dev);
1801 break;
1802 case CPIA1_CID_COMP_TARGET:
1803 sd->params.compressionTarget.frTargeting = ctrl->val;
1804 gspca_dev->usb_err = command_setcompressiontarget(gspca_dev);
1805 break;
1806 }
1807 return gspca_dev->usb_err;
1808}
1809
1810static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1811 .s_ctrl = sd_s_ctrl,
1812};
1813
1814static int sd_init_controls(struct gspca_dev *gspca_dev)
1815{
1816 struct sd *sd = (struct sd *)gspca_dev;
1817 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1818 static const char * const comp_target_menu[] = {
1819 "Quality",
1820 "Framerate",
1821 NULL
1822 };
1823 static const struct v4l2_ctrl_config comp_target = {
1824 .ops = &sd_ctrl_ops,
1825 .id = CPIA1_CID_COMP_TARGET,
1826 .type = V4L2_CTRL_TYPE_MENU,
1827 .name = "Compression Target",
1828 .qmenu = comp_target_menu,
1829 .max = 1,
1830 .def = COMP_TARGET_DEF,
1831 };
1832
1833 gspca_dev->vdev.ctrl_handler = hdl;
1834 v4l2_ctrl_handler_init(hdl, 7);
1835 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1836 V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF);
1837 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1838 V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF);
1839 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1840 V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF);
1841 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
1842 V4L2_CID_POWER_LINE_FREQUENCY,
1843 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
1844 FREQ_DEF);
1845 if (sd->params.qx3.qx3_detected) {
1846 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1847 V4L2_CID_ILLUMINATORS_1, 0, 1, 1,
1848 ILLUMINATORS_1_DEF);
1849 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1850 V4L2_CID_ILLUMINATORS_2, 0, 1, 1,
1851 ILLUMINATORS_2_DEF);
1852 }
1853 v4l2_ctrl_new_custom(hdl, &comp_target, NULL);
1854
1855 if (hdl->error) {
1856 pr_err("Could not initialize controls\n");
1857 return hdl->error;
1858 }
1859 return 0;
1860}
1861
1862/* sub-driver description */
1863static const struct sd_desc sd_desc = {
1864 .name = MODULE_NAME,
1865 .config = sd_config,
1866 .init = sd_init,
1867 .init_controls = sd_init_controls,
1868 .start = sd_start,
1869 .stopN = sd_stopN,
1870 .dq_callback = sd_dq_callback,
1871 .pkt_scan = sd_pkt_scan,
1872#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1873 .other_input = 1,
1874#endif
1875};
1876
1877/* -- module initialisation -- */
1878static const struct usb_device_id device_table[] = {
1879 {USB_DEVICE(0x0553, 0x0002)},
1880 {USB_DEVICE(0x0813, 0x0001)},
1881 {}
1882};
1883MODULE_DEVICE_TABLE(usb, device_table);
1884
1885/* -- device connect -- */
1886static int sd_probe(struct usb_interface *intf,
1887 const struct usb_device_id *id)
1888{
1889 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1890 THIS_MODULE);
1891}
1892
1893static struct usb_driver sd_driver = {
1894 .name = MODULE_NAME,
1895 .id_table = device_table,
1896 .probe = sd_probe,
1897 .disconnect = gspca_disconnect,
1898#ifdef CONFIG_PM
1899 .suspend = gspca_suspend,
1900 .resume = gspca_resume,
1901 .reset_resume = gspca_resume,
1902#endif
1903};
1904
1905module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/etoms.c b/drivers/media/usb/gspca/etoms.c
new file mode 100644
index 00000000000..38f68e11c3a
--- /dev/null
+++ b/drivers/media/usb/gspca/etoms.c
@@ -0,0 +1,799 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "etoms"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("Etoms USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
35 unsigned char autogain;
36
37 char sensor;
38#define SENSOR_PAS106 0
39#define SENSOR_TAS5130CXX 1
40 signed char ag_cnt;
41#define AG_CNT_START 13
42};
43
44static const struct v4l2_pix_format vga_mode[] = {
45 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
46 .bytesperline = 320,
47 .sizeimage = 320 * 240,
48 .colorspace = V4L2_COLORSPACE_SRGB,
49 .priv = 1},
50/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
51 .bytesperline = 640,
52 .sizeimage = 640 * 480,
53 .colorspace = V4L2_COLORSPACE_SRGB,
54 .priv = 0}, */
55};
56
57static const struct v4l2_pix_format sif_mode[] = {
58 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
59 .bytesperline = 176,
60 .sizeimage = 176 * 144,
61 .colorspace = V4L2_COLORSPACE_SRGB,
62 .priv = 1},
63 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
64 .bytesperline = 352,
65 .sizeimage = 352 * 288,
66 .colorspace = V4L2_COLORSPACE_SRGB,
67 .priv = 0},
68};
69
70#define ETOMS_ALT_SIZE_1000 12
71
72#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */
73#define ET_GPIO_OUT 0x05 /* Only IO data */
74#define ET_GPIO_IN 0x06 /* Read Only IO data */
75#define ET_RESET_ALL 0x03
76#define ET_ClCK 0x01
77#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */
78
79#define ET_COMP 0x12 /* Compression register */
80#define ET_MAXQt 0x13
81#define ET_MINQt 0x14
82#define ET_COMP_VAL0 0x02
83#define ET_COMP_VAL1 0x03
84
85#define ET_REG1d 0x1d
86#define ET_REG1e 0x1e
87#define ET_REG1f 0x1f
88#define ET_REG20 0x20
89#define ET_REG21 0x21
90#define ET_REG22 0x22
91#define ET_REG23 0x23
92#define ET_REG24 0x24
93#define ET_REG25 0x25
94/* base registers for luma calculation */
95#define ET_LUMA_CENTER 0x39
96
97#define ET_G_RED 0x4d
98#define ET_G_GREEN1 0x4e
99#define ET_G_BLUE 0x4f
100#define ET_G_GREEN2 0x50
101#define ET_G_GR_H 0x51
102#define ET_G_GB_H 0x52
103
104#define ET_O_RED 0x34
105#define ET_O_GREEN1 0x35
106#define ET_O_BLUE 0x36
107#define ET_O_GREEN2 0x37
108
109#define ET_SYNCHRO 0x68
110#define ET_STARTX 0x69
111#define ET_STARTY 0x6a
112#define ET_WIDTH_LOW 0x6b
113#define ET_HEIGTH_LOW 0x6c
114#define ET_W_H_HEIGTH 0x6d
115
116#define ET_REG6e 0x6e /* OBW */
117#define ET_REG6f 0x6f /* OBW */
118#define ET_REG70 0x70 /* OBW_AWB */
119#define ET_REG71 0x71 /* OBW_AWB */
120#define ET_REG72 0x72 /* OBW_AWB */
121#define ET_REG73 0x73 /* Clkdelay ns */
122#define ET_REG74 0x74 /* test pattern */
123#define ET_REG75 0x75 /* test pattern */
124
125#define ET_I2C_CLK 0x8c
126#define ET_PXL_CLK 0x60
127
128#define ET_I2C_BASE 0x89
129#define ET_I2C_COUNT 0x8a
130#define ET_I2C_PREFETCH 0x8b
131#define ET_I2C_REG 0x88
132#define ET_I2C_DATA7 0x87
133#define ET_I2C_DATA6 0x86
134#define ET_I2C_DATA5 0x85
135#define ET_I2C_DATA4 0x84
136#define ET_I2C_DATA3 0x83
137#define ET_I2C_DATA2 0x82
138#define ET_I2C_DATA1 0x81
139#define ET_I2C_DATA0 0x80
140
141#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */
142#define PAS106_REG3 0x03 /* line/frame H [11..4] */
143#define PAS106_REG4 0x04 /* line/frame L [3..0] */
144#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */
145#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */
146#define PAS106_REG7 0x07 /* signbit Dac (default 0) */
147#define PAS106_REG9 0x09
148#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */
149#define PAS106_REG13 0x13 /* end i2c write */
150
151static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
152
153static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };
154
155static const __u8 I2c3[] = { 0x12, 0x05 };
156
157static const __u8 I2c4[] = { 0x41, 0x08 };
158
159/* read 'len' bytes to gspca_dev->usb_buf */
160static void reg_r(struct gspca_dev *gspca_dev,
161 __u16 index,
162 __u16 len)
163{
164 struct usb_device *dev = gspca_dev->dev;
165
166#ifdef GSPCA_DEBUG
167 if (len > USB_BUF_SZ) {
168 pr_err("reg_r: buffer overflow\n");
169 return;
170 }
171#endif
172 usb_control_msg(dev,
173 usb_rcvctrlpipe(dev, 0),
174 0,
175 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
176 0,
177 index, gspca_dev->usb_buf, len, 500);
178 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
179 index, gspca_dev->usb_buf[0]);
180}
181
182static void reg_w_val(struct gspca_dev *gspca_dev,
183 __u16 index,
184 __u8 val)
185{
186 struct usb_device *dev = gspca_dev->dev;
187
188 gspca_dev->usb_buf[0] = val;
189 usb_control_msg(dev,
190 usb_sndctrlpipe(dev, 0),
191 0,
192 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
193 0,
194 index, gspca_dev->usb_buf, 1, 500);
195}
196
197static void reg_w(struct gspca_dev *gspca_dev,
198 __u16 index,
199 const __u8 *buffer,
200 __u16 len)
201{
202 struct usb_device *dev = gspca_dev->dev;
203
204#ifdef GSPCA_DEBUG
205 if (len > USB_BUF_SZ) {
206 pr_err("reg_w: buffer overflow\n");
207 return;
208 }
209 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
210#endif
211 memcpy(gspca_dev->usb_buf, buffer, len);
212 usb_control_msg(dev,
213 usb_sndctrlpipe(dev, 0),
214 0,
215 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
216 0, index, gspca_dev->usb_buf, len, 500);
217}
218
219static int i2c_w(struct gspca_dev *gspca_dev,
220 __u8 reg,
221 const __u8 *buffer,
222 int len, __u8 mode)
223{
224 /* buffer should be [D0..D7] */
225 __u8 ptchcount;
226
227 /* set the base address */
228 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
229 /* sensor base for the pas106 */
230 /* set count and prefetch */
231 ptchcount = ((len & 0x07) << 4) | (mode & 0x03);
232 reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount);
233 /* set the register base */
234 reg_w_val(gspca_dev, ET_I2C_REG, reg);
235 while (--len >= 0)
236 reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]);
237 return 0;
238}
239
240static int i2c_r(struct gspca_dev *gspca_dev,
241 __u8 reg)
242{
243 /* set the base address */
244 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
245 /* sensor base for the pas106 */
246 /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */
247 reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11);
248 reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */
249 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */
250 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00);
251 reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */
252 return 0;
253}
254
255static int Et_WaitStatus(struct gspca_dev *gspca_dev)
256{
257 int retry = 10;
258
259 while (retry--) {
260 reg_r(gspca_dev, ET_ClCK, 1);
261 if (gspca_dev->usb_buf[0] != 0)
262 return 1;
263 }
264 return 0;
265}
266
267static int et_video(struct gspca_dev *gspca_dev,
268 int on)
269{
270 int ret;
271
272 reg_w_val(gspca_dev, ET_GPIO_OUT,
273 on ? 0x10 /* startvideo - set Bit5 */
274 : 0); /* stopvideo */
275 ret = Et_WaitStatus(gspca_dev);
276 if (ret != 0)
277 PDEBUG(D_ERR, "timeout video on/off");
278 return ret;
279}
280
281static void Et_init2(struct gspca_dev *gspca_dev)
282{
283 __u8 value;
284 static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 };
285
286 PDEBUG(D_STREAM, "Open Init2 ET");
287 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f);
288 reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10);
289 reg_r(gspca_dev, ET_GPIO_IN, 1);
290 reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */
291 reg_w_val(gspca_dev, ET_CTRL, 0x1b);
292
293 /* compression et subsampling */
294 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
295 value = ET_COMP_VAL1; /* 320 */
296 else
297 value = ET_COMP_VAL0; /* 640 */
298 reg_w_val(gspca_dev, ET_COMP, value);
299 reg_w_val(gspca_dev, ET_MAXQt, 0x1f);
300 reg_w_val(gspca_dev, ET_MINQt, 0x04);
301 /* undocumented registers */
302 reg_w_val(gspca_dev, ET_REG1d, 0xff);
303 reg_w_val(gspca_dev, ET_REG1e, 0xff);
304 reg_w_val(gspca_dev, ET_REG1f, 0xff);
305 reg_w_val(gspca_dev, ET_REG20, 0x35);
306 reg_w_val(gspca_dev, ET_REG21, 0x01);
307 reg_w_val(gspca_dev, ET_REG22, 0x00);
308 reg_w_val(gspca_dev, ET_REG23, 0xff);
309 reg_w_val(gspca_dev, ET_REG24, 0xff);
310 reg_w_val(gspca_dev, ET_REG25, 0x0f);
311 /* colors setting */
312 reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */
313 reg_w_val(gspca_dev, 0x31, 0x40);
314 reg_w_val(gspca_dev, 0x32, 0x00);
315 reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */
316 reg_w_val(gspca_dev, ET_O_GREEN1, 0x00);
317 reg_w_val(gspca_dev, ET_O_BLUE, 0x00);
318 reg_w_val(gspca_dev, ET_O_GREEN2, 0x00);
319 /*************/
320 reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */
321 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
322 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
323 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
324 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
325 reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */
326 /* Window control registers */
327 reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */
328 reg_w_val(gspca_dev, 0x62, 0x02);
329 reg_w_val(gspca_dev, 0x63, 0x03);
330 reg_w_val(gspca_dev, 0x64, 0x14);
331 reg_w_val(gspca_dev, 0x65, 0x0e);
332 reg_w_val(gspca_dev, 0x66, 0x02);
333 reg_w_val(gspca_dev, 0x67, 0x02);
334
335 /**************************************/
336 reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */
337 reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */
338 reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */
339 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80);
340 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0);
341 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */
342 reg_w_val(gspca_dev, ET_REG6e, 0x86);
343 reg_w_val(gspca_dev, ET_REG6f, 0x01);
344 reg_w_val(gspca_dev, ET_REG70, 0x26);
345 reg_w_val(gspca_dev, ET_REG71, 0x7a);
346 reg_w_val(gspca_dev, ET_REG72, 0x01);
347 /* Clock Pattern registers ***************** */
348 reg_w_val(gspca_dev, ET_REG73, 0x00);
349 reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */
350 reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */
351 /**********************************************/
352 reg_w_val(gspca_dev, 0x8a, 0x20);
353 reg_w_val(gspca_dev, 0x8d, 0x0f);
354 reg_w_val(gspca_dev, 0x8e, 0x08);
355 /**************************************/
356 reg_w_val(gspca_dev, 0x03, 0x08);
357 reg_w_val(gspca_dev, ET_PXL_CLK, 0x03);
358 reg_w_val(gspca_dev, 0x81, 0xff);
359 reg_w_val(gspca_dev, 0x80, 0x00);
360 reg_w_val(gspca_dev, 0x81, 0xff);
361 reg_w_val(gspca_dev, 0x80, 0x20);
362 reg_w_val(gspca_dev, 0x03, 0x01);
363 reg_w_val(gspca_dev, 0x03, 0x00);
364 reg_w_val(gspca_dev, 0x03, 0x08);
365 /********************************************/
366
367/* reg_r(gspca_dev, ET_I2C_BASE, 1);
368 always 0x40 as the pas106 ??? */
369 /* set the sensor */
370 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
371 value = 0x04; /* 320 */
372 else /* 640 */
373 value = 0x1e; /* 0x17 * setting PixelClock
374 * 0x03 mean 24/(3+1) = 6 Mhz
375 * 0x05 -> 24/(5+1) = 4 Mhz
376 * 0x0b -> 24/(11+1) = 2 Mhz
377 * 0x17 -> 24/(23+1) = 1 Mhz
378 */
379 reg_w_val(gspca_dev, ET_PXL_CLK, value);
380 /* now set by fifo the FormatLine setting */
381 reg_w(gspca_dev, 0x62, FormLine, 6);
382
383 /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */
384 reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */
385 reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */
386 /* Pedro change */
387 /* Brightness change Brith+ decrease value */
388 /* Brigth- increase value */
389 /* original value = 0x70; */
390 reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */
391 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */
392}
393
394static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
395{
396 int i;
397
398 for (i = 0; i < 4; i++)
399 reg_w_val(gspca_dev, ET_O_RED + i, val);
400}
401
402static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
403{
404 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
405
406 memset(RGBG, val, sizeof(RGBG) - 2);
407 reg_w(gspca_dev, ET_G_RED, RGBG, 6);
408}
409
410static void setcolors(struct gspca_dev *gspca_dev, s32 val)
411{
412 struct sd *sd = (struct sd *) gspca_dev;
413 __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d };
414 __u8 i2cflags = 0x01;
415 /* __u8 green = 0; */
416
417 I2cc[3] = val; /* red */
418 I2cc[0] = 15 - val; /* blue */
419 /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */
420 /* I2cc[1] = I2cc[2] = green; */
421 if (sd->sensor == SENSOR_PAS106) {
422 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
423 i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1);
424 }
425/* PDEBUG(D_CONF , "Etoms red %d blue %d green %d",
426 I2cc[3], I2cc[0], green); */
427}
428
429static s32 getcolors(struct gspca_dev *gspca_dev)
430{
431 struct sd *sd = (struct sd *) gspca_dev;
432
433 if (sd->sensor == SENSOR_PAS106) {
434/* i2c_r(gspca_dev, PAS106_REG9); * blue */
435 i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */
436 return gspca_dev->usb_buf[0] & 0x0f;
437 }
438 return 0;
439}
440
441static void setautogain(struct gspca_dev *gspca_dev)
442{
443 struct sd *sd = (struct sd *) gspca_dev;
444
445 if (sd->autogain)
446 sd->ag_cnt = AG_CNT_START;
447 else
448 sd->ag_cnt = -1;
449}
450
451static void Et_init1(struct gspca_dev *gspca_dev)
452{
453 __u8 value;
454/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */
455 __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 };
456 /* try 1/120 0x6d 0xcd 0x40 */
457/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00};
458 * 1/60000 hmm ?? */
459
460 PDEBUG(D_STREAM, "Open Init1 ET");
461 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7);
462 reg_r(gspca_dev, ET_GPIO_IN, 1);
463 reg_w_val(gspca_dev, ET_RESET_ALL, 1);
464 reg_w_val(gspca_dev, ET_RESET_ALL, 0);
465 reg_w_val(gspca_dev, ET_ClCK, 0x10);
466 reg_w_val(gspca_dev, ET_CTRL, 0x19);
467 /* compression et subsampling */
468 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
469 value = ET_COMP_VAL1;
470 else
471 value = ET_COMP_VAL0;
472 PDEBUG(D_STREAM, "Open mode %d Compression %d",
473 gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv,
474 value);
475 reg_w_val(gspca_dev, ET_COMP, value);
476 reg_w_val(gspca_dev, ET_MAXQt, 0x1d);
477 reg_w_val(gspca_dev, ET_MINQt, 0x02);
478 /* undocumented registers */
479 reg_w_val(gspca_dev, ET_REG1d, 0xff);
480 reg_w_val(gspca_dev, ET_REG1e, 0xff);
481 reg_w_val(gspca_dev, ET_REG1f, 0xff);
482 reg_w_val(gspca_dev, ET_REG20, 0x35);
483 reg_w_val(gspca_dev, ET_REG21, 0x01);
484 reg_w_val(gspca_dev, ET_REG22, 0x00);
485 reg_w_val(gspca_dev, ET_REG23, 0xf7);
486 reg_w_val(gspca_dev, ET_REG24, 0xff);
487 reg_w_val(gspca_dev, ET_REG25, 0x07);
488 /* colors setting */
489 reg_w_val(gspca_dev, ET_G_RED, 0x80);
490 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
491 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
492 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
493 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
494 reg_w_val(gspca_dev, ET_G_GB_H, 0x00);
495 /* Window control registers */
496 reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0);
497 reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */
498 reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */
499 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60);
500 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20);
501 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50);
502 reg_w_val(gspca_dev, ET_REG6e, 0x86);
503 reg_w_val(gspca_dev, ET_REG6f, 0x01);
504 reg_w_val(gspca_dev, ET_REG70, 0x86);
505 reg_w_val(gspca_dev, ET_REG71, 0x14);
506 reg_w_val(gspca_dev, ET_REG72, 0x00);
507 /* Clock Pattern registers */
508 reg_w_val(gspca_dev, ET_REG73, 0x00);
509 reg_w_val(gspca_dev, ET_REG74, 0x00);
510 reg_w_val(gspca_dev, ET_REG75, 0x0a);
511 reg_w_val(gspca_dev, ET_I2C_CLK, 0x04);
512 reg_w_val(gspca_dev, ET_PXL_CLK, 0x01);
513 /* set the sensor */
514 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
515 I2c0[0] = 0x06;
516 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
517 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
518 value = 0x06;
519 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
520 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
521 /* value = 0x1f; */
522 value = 0x04;
523 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
524 } else {
525 I2c0[0] = 0x0a;
526
527 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
528 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
529 value = 0x0a;
530 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
531 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
532 value = 0x04;
533 /* value = 0x10; */
534 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
535 /* bit 2 enable bit 1:2 select 0 1 2 3
536 value = 0x07; * curve 0 *
537 i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1);
538 */
539 }
540
541/* value = 0x01; */
542/* value = 0x22; */
543/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */
544 /* magnetude and sign bit for DAC */
545 i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1);
546 /* now set by fifo the whole colors setting */
547 reg_w(gspca_dev, ET_G_RED, GainRGBG, 6);
548 setcolors(gspca_dev, getcolors(gspca_dev));
549}
550
551/* this function is called at probe time */
552static int sd_config(struct gspca_dev *gspca_dev,
553 const struct usb_device_id *id)
554{
555 struct sd *sd = (struct sd *) gspca_dev;
556 struct cam *cam;
557
558 cam = &gspca_dev->cam;
559 sd->sensor = id->driver_info;
560 if (sd->sensor == SENSOR_PAS106) {
561 cam->cam_mode = sif_mode;
562 cam->nmodes = ARRAY_SIZE(sif_mode);
563 } else {
564 cam->cam_mode = vga_mode;
565 cam->nmodes = ARRAY_SIZE(vga_mode);
566 }
567 sd->ag_cnt = -1;
568 return 0;
569}
570
571/* this function is called at probe and resume time */
572static int sd_init(struct gspca_dev *gspca_dev)
573{
574 struct sd *sd = (struct sd *) gspca_dev;
575
576 if (sd->sensor == SENSOR_PAS106)
577 Et_init1(gspca_dev);
578 else
579 Et_init2(gspca_dev);
580 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
581 et_video(gspca_dev, 0); /* video off */
582 return 0;
583}
584
585/* -- start the camera -- */
586static int sd_start(struct gspca_dev *gspca_dev)
587{
588 struct sd *sd = (struct sd *) gspca_dev;
589
590 if (sd->sensor == SENSOR_PAS106)
591 Et_init1(gspca_dev);
592 else
593 Et_init2(gspca_dev);
594
595 setautogain(gspca_dev);
596
597 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
598 et_video(gspca_dev, 1); /* video on */
599 return 0;
600}
601
602static void sd_stopN(struct gspca_dev *gspca_dev)
603{
604 et_video(gspca_dev, 0); /* video off */
605}
606
607static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
608{
609 struct sd *sd = (struct sd *) gspca_dev;
610
611 if (sd->sensor == SENSOR_PAS106) {
612 i2c_r(gspca_dev, PAS106_REG0e);
613 PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]);
614 return gspca_dev->usb_buf[0];
615 }
616 return 0x1f;
617}
618
619static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
620{
621 struct sd *sd = (struct sd *) gspca_dev;
622
623 if (sd->sensor == SENSOR_PAS106) {
624 __u8 i2cflags = 0x01;
625
626 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
627 i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
628 }
629}
630
631#define BLIMIT(bright) \
632 (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright))
633#define LIMIT(color) \
634 (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color))
635
636static void do_autogain(struct gspca_dev *gspca_dev)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639 __u8 luma;
640 __u8 luma_mean = 128;
641 __u8 luma_delta = 20;
642 __u8 spring = 4;
643 int Gbright;
644 __u8 r, g, b;
645
646 if (sd->ag_cnt < 0)
647 return;
648 if (--sd->ag_cnt >= 0)
649 return;
650 sd->ag_cnt = AG_CNT_START;
651
652 Gbright = Et_getgainG(gspca_dev);
653 reg_r(gspca_dev, ET_LUMA_CENTER, 4);
654 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
655 r = gspca_dev->usb_buf[1];
656 b = gspca_dev->usb_buf[2];
657 r = ((r << 8) - (r << 4) - (r << 3)) >> 10;
658 b = ((b << 7) >> 10);
659 g = ((g << 9) + (g << 7) + (g << 5)) >> 10;
660 luma = LIMIT(r + g + b);
661 PDEBUG(D_FRAM, "Etoms luma G %d", luma);
662 if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) {
663 Gbright += (luma_mean - luma) >> spring;
664 Gbright = BLIMIT(Gbright);
665 PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright);
666 Et_setgainG(gspca_dev, (__u8) Gbright);
667 }
668}
669
670#undef BLIMIT
671#undef LIMIT
672
673static void sd_pkt_scan(struct gspca_dev *gspca_dev,
674 u8 *data, /* isoc packet */
675 int len) /* iso packet length */
676{
677 int seqframe;
678
679 seqframe = data[0] & 0x3f;
680 len = (int) (((data[0] & 0xc0) << 2) | data[1]);
681 if (seqframe == 0x3f) {
682 PDEBUG(D_FRAM,
683 "header packet found datalength %d !!", len);
684 PDEBUG(D_FRAM, "G %d R %d G %d B %d",
685 data[2], data[3], data[4], data[5]);
686 data += 30;
687 /* don't change datalength as the chips provided it */
688 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
689 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
690 return;
691 }
692 if (len) {
693 data += 8;
694 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
695 } else { /* Drop Packet */
696 gspca_dev->last_packet_type = DISCARD_PACKET;
697 }
698}
699
700static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
701{
702 struct gspca_dev *gspca_dev =
703 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
704 struct sd *sd = (struct sd *)gspca_dev;
705
706 gspca_dev->usb_err = 0;
707
708 if (!gspca_dev->streaming)
709 return 0;
710
711 switch (ctrl->id) {
712 case V4L2_CID_BRIGHTNESS:
713 setbrightness(gspca_dev, ctrl->val);
714 break;
715 case V4L2_CID_CONTRAST:
716 setcontrast(gspca_dev, ctrl->val);
717 break;
718 case V4L2_CID_SATURATION:
719 setcolors(gspca_dev, ctrl->val);
720 break;
721 case V4L2_CID_AUTOGAIN:
722 sd->autogain = ctrl->val;
723 setautogain(gspca_dev);
724 break;
725 }
726 return gspca_dev->usb_err;
727}
728
729static const struct v4l2_ctrl_ops sd_ctrl_ops = {
730 .s_ctrl = sd_s_ctrl,
731};
732
733static int sd_init_controls(struct gspca_dev *gspca_dev)
734{
735 struct sd *sd = (struct sd *)gspca_dev;
736 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
737
738 gspca_dev->vdev.ctrl_handler = hdl;
739 v4l2_ctrl_handler_init(hdl, 4);
740 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
741 V4L2_CID_BRIGHTNESS, 1, 127, 1, 63);
742 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
743 V4L2_CID_CONTRAST, 0, 255, 1, 127);
744 if (sd->sensor == SENSOR_PAS106)
745 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
746 V4L2_CID_SATURATION, 0, 15, 1, 7);
747 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
748 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
749 if (hdl->error) {
750 pr_err("Could not initialize controls\n");
751 return hdl->error;
752 }
753 return 0;
754}
755
756/* sub-driver description */
757static const struct sd_desc sd_desc = {
758 .name = MODULE_NAME,
759 .config = sd_config,
760 .init = sd_init,
761 .init_controls = sd_init_controls,
762 .start = sd_start,
763 .stopN = sd_stopN,
764 .pkt_scan = sd_pkt_scan,
765 .dq_callback = do_autogain,
766};
767
768/* -- module initialisation -- */
769static const struct usb_device_id device_table[] = {
770 {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
771#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
772 {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
773#endif
774 {}
775};
776
777MODULE_DEVICE_TABLE(usb, device_table);
778
779/* -- device connect -- */
780static int sd_probe(struct usb_interface *intf,
781 const struct usb_device_id *id)
782{
783 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
784 THIS_MODULE);
785}
786
787static struct usb_driver sd_driver = {
788 .name = MODULE_NAME,
789 .id_table = device_table,
790 .probe = sd_probe,
791 .disconnect = gspca_disconnect,
792#ifdef CONFIG_PM
793 .suspend = gspca_suspend,
794 .resume = gspca_resume,
795 .reset_resume = gspca_resume,
796#endif
797};
798
799module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/finepix.c b/drivers/media/usb/gspca/finepix.c
new file mode 100644
index 00000000000..c8f2201cc35
--- /dev/null
+++ b/drivers/media/usb/gspca/finepix.c
@@ -0,0 +1,306 @@
1/*
2 * Fujifilm Finepix subdriver
3 *
4 * Copyright (C) 2008 Frank Zago
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "finepix"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Frank Zago <frank@zago.net>");
28MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
29MODULE_LICENSE("GPL");
30
31/* Default timeout, in ms */
32#define FPIX_TIMEOUT 250
33
34/* Maximum transfer size to use. The windows driver reads by chunks of
35 * 0x2000 bytes, so do the same. Note: reading more seems to work
36 * too. */
37#define FPIX_MAX_TRANSFER 0x2000
38
39/* Structure to hold all of our device specific stuff */
40struct usb_fpix {
41 struct gspca_dev gspca_dev; /* !! must be the first item */
42
43 struct work_struct work_struct;
44 struct workqueue_struct *work_thread;
45};
46
47/* Delay after which claim the next frame. If the delay is too small,
48 * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
49 * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
50 * 30ms is bad while 35ms is perfect. */
51#define NEXT_FRAME_DELAY 35
52
53/* These cameras only support 320x200. */
54static const struct v4l2_pix_format fpix_mode[1] = {
55 { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
56 .bytesperline = 320,
57 .sizeimage = 320 * 240 * 3 / 8 + 590,
58 .colorspace = V4L2_COLORSPACE_SRGB,
59 .priv = 0}
60};
61
62/* send a command to the webcam */
63static int command(struct gspca_dev *gspca_dev,
64 int order) /* 0: reset, 1: frame request */
65{
66 static u8 order_values[2][12] = {
67 {0xc6, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0}, /* reset */
68 {0xd3, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0}, /* fr req */
69 };
70
71 memcpy(gspca_dev->usb_buf, order_values[order], 12);
72 return usb_control_msg(gspca_dev->dev,
73 usb_sndctrlpipe(gspca_dev->dev, 0),
74 USB_REQ_GET_STATUS,
75 USB_DIR_OUT | USB_TYPE_CLASS |
76 USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
77 12, FPIX_TIMEOUT);
78}
79
80/* workqueue */
81static void dostream(struct work_struct *work)
82{
83 struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
84 struct gspca_dev *gspca_dev = &dev->gspca_dev;
85 struct urb *urb = gspca_dev->urb[0];
86 u8 *data = urb->transfer_buffer;
87 int ret = 0;
88 int len;
89
90 /* synchronize with the main driver */
91 mutex_lock(&gspca_dev->usb_lock);
92 mutex_unlock(&gspca_dev->usb_lock);
93 PDEBUG(D_STREAM, "dostream started");
94
95 /* loop reading a frame */
96again:
97 while (gspca_dev->dev && gspca_dev->streaming) {
98#ifdef CONFIG_PM
99 if (gspca_dev->frozen)
100 break;
101#endif
102
103 /* request a frame */
104 mutex_lock(&gspca_dev->usb_lock);
105 ret = command(gspca_dev, 1);
106 mutex_unlock(&gspca_dev->usb_lock);
107 if (ret < 0)
108 break;
109#ifdef CONFIG_PM
110 if (gspca_dev->frozen)
111 break;
112#endif
113 if (!gspca_dev->dev || !gspca_dev->streaming)
114 break;
115
116 /* the frame comes in parts */
117 for (;;) {
118 ret = usb_bulk_msg(gspca_dev->dev,
119 urb->pipe,
120 data,
121 FPIX_MAX_TRANSFER,
122 &len, FPIX_TIMEOUT);
123 if (ret < 0) {
124 /* Most of the time we get a timeout
125 * error. Just restart. */
126 goto again;
127 }
128#ifdef CONFIG_PM
129 if (gspca_dev->frozen)
130 goto out;
131#endif
132 if (!gspca_dev->dev || !gspca_dev->streaming)
133 goto out;
134 if (len < FPIX_MAX_TRANSFER ||
135 (data[len - 2] == 0xff &&
136 data[len - 1] == 0xd9)) {
137
138 /* If the result is less than what was asked
139 * for, then it's the end of the
140 * frame. Sometimes the jpeg is not complete,
141 * but there's nothing we can do. We also end
142 * here if the the jpeg ends right at the end
143 * of the frame. */
144 gspca_frame_add(gspca_dev, LAST_PACKET,
145 data, len);
146 break;
147 }
148
149 /* got a partial image */
150 gspca_frame_add(gspca_dev,
151 gspca_dev->last_packet_type
152 == LAST_PACKET
153 ? FIRST_PACKET : INTER_PACKET,
154 data, len);
155 }
156
157 /* We must wait before trying reading the next
158 * frame. If we don't, or if the delay is too short,
159 * the camera will disconnect. */
160 msleep(NEXT_FRAME_DELAY);
161 }
162
163out:
164 PDEBUG(D_STREAM, "dostream stopped");
165}
166
167/* this function is called at probe time */
168static int sd_config(struct gspca_dev *gspca_dev,
169 const struct usb_device_id *id)
170{
171 struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
172 struct cam *cam = &gspca_dev->cam;
173
174 cam->cam_mode = fpix_mode;
175 cam->nmodes = 1;
176 cam->bulk = 1;
177 cam->bulk_size = FPIX_MAX_TRANSFER;
178
179 INIT_WORK(&dev->work_struct, dostream);
180
181 return 0;
182}
183
184/* this function is called at probe and resume time */
185static int sd_init(struct gspca_dev *gspca_dev)
186{
187 return 0;
188}
189
190/* start the camera */
191static int sd_start(struct gspca_dev *gspca_dev)
192{
193 struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
194 int ret, len;
195
196 /* Init the device */
197 ret = command(gspca_dev, 0);
198 if (ret < 0) {
199 pr_err("init failed %d\n", ret);
200 return ret;
201 }
202
203 /* Read the result of the command. Ignore the result, for it
204 * varies with the device. */
205 ret = usb_bulk_msg(gspca_dev->dev,
206 gspca_dev->urb[0]->pipe,
207 gspca_dev->urb[0]->transfer_buffer,
208 FPIX_MAX_TRANSFER, &len,
209 FPIX_TIMEOUT);
210 if (ret < 0) {
211 pr_err("usb_bulk_msg failed %d\n", ret);
212 return ret;
213 }
214
215 /* Request a frame, but don't read it */
216 ret = command(gspca_dev, 1);
217 if (ret < 0) {
218 pr_err("frame request failed %d\n", ret);
219 return ret;
220 }
221
222 /* Again, reset bulk in endpoint */
223 usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
224
225 /* Start the workqueue function to do the streaming */
226 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
227 queue_work(dev->work_thread, &dev->work_struct);
228
229 return 0;
230}
231
232/* called on streamoff with alt==0 and on disconnect */
233/* the usb_lock is held at entry - restore on exit */
234static void sd_stop0(struct gspca_dev *gspca_dev)
235{
236 struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
237
238 /* wait for the work queue to terminate */
239 mutex_unlock(&gspca_dev->usb_lock);
240 destroy_workqueue(dev->work_thread);
241 mutex_lock(&gspca_dev->usb_lock);
242 dev->work_thread = NULL;
243}
244
245/* Table of supported USB devices */
246static const struct usb_device_id device_table[] = {
247 {USB_DEVICE(0x04cb, 0x0104)},
248 {USB_DEVICE(0x04cb, 0x0109)},
249 {USB_DEVICE(0x04cb, 0x010b)},
250 {USB_DEVICE(0x04cb, 0x010f)},
251 {USB_DEVICE(0x04cb, 0x0111)},
252 {USB_DEVICE(0x04cb, 0x0113)},
253 {USB_DEVICE(0x04cb, 0x0115)},
254 {USB_DEVICE(0x04cb, 0x0117)},
255 {USB_DEVICE(0x04cb, 0x0119)},
256 {USB_DEVICE(0x04cb, 0x011b)},
257 {USB_DEVICE(0x04cb, 0x011d)},
258 {USB_DEVICE(0x04cb, 0x0121)},
259 {USB_DEVICE(0x04cb, 0x0123)},
260 {USB_DEVICE(0x04cb, 0x0125)},
261 {USB_DEVICE(0x04cb, 0x0127)},
262 {USB_DEVICE(0x04cb, 0x0129)},
263 {USB_DEVICE(0x04cb, 0x012b)},
264 {USB_DEVICE(0x04cb, 0x012d)},
265 {USB_DEVICE(0x04cb, 0x012f)},
266 {USB_DEVICE(0x04cb, 0x0131)},
267 {USB_DEVICE(0x04cb, 0x013b)},
268 {USB_DEVICE(0x04cb, 0x013d)},
269 {USB_DEVICE(0x04cb, 0x013f)},
270 {}
271};
272
273MODULE_DEVICE_TABLE(usb, device_table);
274
275/* sub-driver description */
276static const struct sd_desc sd_desc = {
277 .name = MODULE_NAME,
278 .config = sd_config,
279 .init = sd_init,
280 .start = sd_start,
281 .stop0 = sd_stop0,
282};
283
284/* -- device connect -- */
285static int sd_probe(struct usb_interface *intf,
286 const struct usb_device_id *id)
287{
288 return gspca_dev_probe(intf, id,
289 &sd_desc,
290 sizeof(struct usb_fpix),
291 THIS_MODULE);
292}
293
294static struct usb_driver sd_driver = {
295 .name = MODULE_NAME,
296 .id_table = device_table,
297 .probe = sd_probe,
298 .disconnect = gspca_disconnect,
299#ifdef CONFIG_PM
300 .suspend = gspca_suspend,
301 .resume = gspca_resume,
302 .reset_resume = gspca_resume,
303#endif
304};
305
306module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/gl860/Kconfig b/drivers/media/usb/gspca/gl860/Kconfig
new file mode 100644
index 00000000000..22772f53ec7
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/Kconfig
@@ -0,0 +1,8 @@
1config USB_GL860
2 tristate "GL860 USB Camera Driver"
3 depends on VIDEO_V4L2 && USB_GSPCA
4 help
5 Say Y here if you want support for cameras based on the GL860 chip.
6
7 To compile this driver as a module, choose M here: the
8 module will be called gspca_gl860.
diff --git a/drivers/media/usb/gspca/gl860/Makefile b/drivers/media/usb/gspca/gl860/Makefile
new file mode 100644
index 00000000000..cf6397415aa
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/Makefile
@@ -0,0 +1,10 @@
1obj-$(CONFIG_USB_GL860) += gspca_gl860.o
2
3gspca_gl860-objs := gl860.o \
4 gl860-mi1320.o \
5 gl860-ov2640.o \
6 gl860-ov9655.o \
7 gl860-mi2020.o
8
9ccflags-y += -I$(srctree)/drivers/media/usb/gspca
10
diff --git a/drivers/media/usb/gspca/gl860/gl860-mi1320.c b/drivers/media/usb/gspca/gl860/gl860-mi1320.c
new file mode 100644
index 00000000000..b57160e0486
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/gl860-mi1320.c
@@ -0,0 +1,536 @@
1/* Subdriver for the GL860 chip with the MI1320 sensor
2 * Author Olivier LORIN from own logs
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* Sensor : MI1320 */
19
20#include "gl860.h"
21
22static struct validx tbl_common[] = {
23 {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1},
24 {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
25 {0xffff, 0xffff},
26 {0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1},
27 {0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1},
28 {0xba70, 0x0006}, {0xba0e, 0x00f1},
29 {0xffff, 0xffff},
30 {0xba74, 0x0006}, {0xba0e, 0x00f1},
31 {0xffff, 0xffff},
32 {0x0061, 0x0000}, {0x0068, 0x000d},
33};
34
35static struct validx tbl_init_at_startup[] = {
36 {0x0000, 0x0000}, {0x0010, 0x0010},
37 {35, 0xffff},
38 {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006},
39 {0x006a, 0x000d},
40};
41
42static struct validx tbl_sensor_settings_common[] = {
43 {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
44 {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
45};
46static struct validx tbl_sensor_settings_1280[] = {
47 {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
48 {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
49};
50static struct validx tbl_sensor_settings_800[] = {
51 {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
52 {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
53};
54static struct validx tbl_sensor_settings_640[] = {
55 {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
56 {0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1},
57 {0xba20, 0x0065}, {0xba00, 0x00f1},
58};
59static struct validx tbl_post_unset_alt[] = {
60 {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
61 {0x0061, 0x0000}, {0x0068, 0x000d},
62};
63
64static u8 *tbl_1280[] = {
65 "\x0d\x80\xf1\x08\x03\x04\xf1\x00" "\x04\x05\xf1\x02\x05\x00\xf1\xf1"
66 "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08"
67 "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00"
68 "\xa9\x04\xf1\x00\xa1\x05\xf1\x00" "\xa4\x04\xf1\x00\xae\x0a\xf1\x08"
69 ,
70 "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47"
71 "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c"
72 "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01"
73 ,
74 "\xd3\x02\xd4\x28\xd5\x01\xd0\x02" "\xd1\x18\xd2\xc1"
75};
76
77static u8 *tbl_800[] = {
78 "\x0d\x80\xf1\x08\x03\x03\xf1\xc0" "\x04\x05\xf1\x02\x05\x00\xf1\xf1"
79 "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08"
80 "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00"
81 "\xa9\x03\xf1\xc0\xa1\x03\xf1\x20" "\xa4\x02\xf1\x5a\xae\x0a\xf1\x08"
82 ,
83 "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47"
84 "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c"
85 "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01"
86 ,
87 "\xd3\x02\xd4\x18\xd5\x21\xd0\x02" "\xd1\x10\xd2\x59"
88};
89
90static u8 *tbl_640[] = {
91 "\x0d\x80\xf1\x08\x03\x04\xf1\x04" "\x04\x05\xf1\x02\x07\x01\xf1\x7c"
92 "\x08\x00\xf1\x0e\x21\x80\xf1\x00" "\x0d\x00\xf1\x08\xf0\x00\xf1\x01"
93 "\x34\x10\xf1\x10\x3a\x43\xf1\x00" "\xa6\x05\xf1\x02\xa9\x04\xf1\x04"
94 "\xa7\x02\xf1\x81\xaa\x01\xf1\xe2" "\xae\x0c\xf1\x09"
95 ,
96 "\xf0\x00\xf1\x02\x39\x03\xf1\xfc" "\x3b\x04\xf1\x04\x57\x01\xf1\xb6"
97 "\x58\x02\xf1\x0d\x5c\x1f\xf1\x19" "\x5d\x24\xf1\x1e\x64\x5e\xf1\x1c"
98 "\xd2\x00\xf1\x00\xcb\x00\xf1\x01"
99 ,
100 "\xd3\x02\xd4\x10\xd5\x81\xd0\x02" "\xd1\x08\xd2\xe1"
101};
102
103static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
104static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
105static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
106
107static s32 tbl_cntr1[] = {
108 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
109static s32 tbl_cntr2[] = {
110 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
111
112static u8 dat_wbalNL[] =
113 "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10"
114 "\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20"
115 "\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00";
116
117static u8 dat_wbalLL[] =
118 "\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40"
119 "\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00"
120 "\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00";
121
122static u8 dat_wbalBL[] =
123 "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae"
124 "\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20"
125 "\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00";
126
127static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
128
129static u8 dat_common00[] =
130 "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42"
131 "\xd8\x04\x58\x00\x04\x02";
132static u8 dat_common01[] =
133 "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d"
134 "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0";
135static u8 dat_common02[] =
136 "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e"
137 "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00"
138 "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff";
139static u8 dat_common03[] =
140 "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda"
141 "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c"
142 "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c";
143static u8 dat_common04[] =
144 "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
145static u8 dat_common05[] =
146 "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68"
147 "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82"
148 "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b";
149static u8 dat_common06[] =
150 "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06"
151 "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4"
152 "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f";
153static u8 dat_common07[] =
154 "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72"
155 "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03"
156 "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea"
157 "\xe1\xff\xf1\x00";
158static u8 dat_common08[] =
159 "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7"
160 "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06"
161 "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a";
162static u8 dat_common09[] =
163 "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03"
164 "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa"
165 "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14";
166static u8 dat_common10[] =
167 "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00"
168 "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f"
169 "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01"
170 "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10";
171static u8 dat_common11[] =
172 "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10"
173 "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00"
174 "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81";
175
176static int mi1320_init_at_startup(struct gspca_dev *gspca_dev);
177static int mi1320_configure_alt(struct gspca_dev *gspca_dev);
178static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
179static int mi1320_init_post_alt(struct gspca_dev *gspca_dev);
180static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
181static int mi1320_sensor_settings(struct gspca_dev *gspca_dev);
182static int mi1320_camera_settings(struct gspca_dev *gspca_dev);
183/*==========================================================================*/
184
185void mi1320_init_settings(struct gspca_dev *gspca_dev)
186{
187 struct sd *sd = (struct sd *) gspca_dev;
188
189 sd->vcur.backlight = 0;
190 sd->vcur.brightness = 0;
191 sd->vcur.sharpness = 6;
192 sd->vcur.contrast = 10;
193 sd->vcur.gamma = 20;
194 sd->vcur.hue = 0;
195 sd->vcur.saturation = 6;
196 sd->vcur.whitebal = 0;
197 sd->vcur.mirror = 0;
198 sd->vcur.flip = 0;
199 sd->vcur.AC50Hz = 1;
200
201 sd->vmax.backlight = 2;
202 sd->vmax.brightness = 8;
203 sd->vmax.sharpness = 7;
204 sd->vmax.contrast = 0; /* 10 but not working with this driver */
205 sd->vmax.gamma = 40;
206 sd->vmax.hue = 5 + 1;
207 sd->vmax.saturation = 8;
208 sd->vmax.whitebal = 2;
209 sd->vmax.mirror = 1;
210 sd->vmax.flip = 1;
211 sd->vmax.AC50Hz = 1;
212
213 sd->dev_camera_settings = mi1320_camera_settings;
214 sd->dev_init_at_startup = mi1320_init_at_startup;
215 sd->dev_configure_alt = mi1320_configure_alt;
216 sd->dev_init_pre_alt = mi1320_init_pre_alt;
217 sd->dev_post_unset_alt = mi1320_post_unset_alt;
218}
219
220/*==========================================================================*/
221
222static void common(struct gspca_dev *gspca_dev)
223{
224 s32 n; /* reserved for FETCH functions */
225
226 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00);
227 ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
228 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01);
229 n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
230 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02);
231 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03);
232 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04);
233 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05);
234 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06);
235 keep_on_fetching_validx(gspca_dev, tbl_common,
236 ARRAY_SIZE(tbl_common), n);
237 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07);
238 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08);
239 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09);
240 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10);
241 keep_on_fetching_validx(gspca_dev, tbl_common,
242 ARRAY_SIZE(tbl_common), n);
243 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11);
244 keep_on_fetching_validx(gspca_dev, tbl_common,
245 ARRAY_SIZE(tbl_common), n);
246}
247
248static int mi1320_init_at_startup(struct gspca_dev *gspca_dev)
249{
250 fetch_validx(gspca_dev, tbl_init_at_startup,
251 ARRAY_SIZE(tbl_init_at_startup));
252
253 common(gspca_dev);
254
255/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
256
257 return 0;
258}
259
260static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev)
261{
262 struct sd *sd = (struct sd *) gspca_dev;
263
264 sd->mirrorMask = 0;
265
266 sd->vold.backlight = -1;
267 sd->vold.brightness = -1;
268 sd->vold.sharpness = -1;
269 sd->vold.contrast = -1;
270 sd->vold.saturation = -1;
271 sd->vold.gamma = -1;
272 sd->vold.hue = -1;
273 sd->vold.whitebal = -1;
274 sd->vold.mirror = -1;
275 sd->vold.flip = -1;
276 sd->vold.AC50Hz = -1;
277
278 common(gspca_dev);
279
280 mi1320_sensor_settings(gspca_dev);
281
282 mi1320_init_post_alt(gspca_dev);
283
284 return 0;
285}
286
287static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
288{
289 mi1320_camera_settings(gspca_dev);
290
291 return 0;
292}
293
294static int mi1320_sensor_settings(struct gspca_dev *gspca_dev)
295{
296 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
297
298 ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
299
300 fetch_validx(gspca_dev, tbl_sensor_settings_common,
301 ARRAY_SIZE(tbl_sensor_settings_common));
302
303 switch (reso) {
304 case IMAGE_1280:
305 fetch_validx(gspca_dev, tbl_sensor_settings_1280,
306 ARRAY_SIZE(tbl_sensor_settings_1280));
307 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]);
308 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]);
309 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]);
310 break;
311
312 case IMAGE_800:
313 fetch_validx(gspca_dev, tbl_sensor_settings_800,
314 ARRAY_SIZE(tbl_sensor_settings_800));
315 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]);
316 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]);
317 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]);
318 break;
319
320 default:
321 fetch_validx(gspca_dev, tbl_sensor_settings_640,
322 ARRAY_SIZE(tbl_sensor_settings_640));
323 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]);
324 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]);
325 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]);
326 break;
327 }
328 return 0;
329}
330
331static int mi1320_configure_alt(struct gspca_dev *gspca_dev)
332{
333 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
334
335 switch (reso) {
336 case IMAGE_640:
337 gspca_dev->alt = 3 + 1;
338 break;
339
340 case IMAGE_800:
341 case IMAGE_1280:
342 gspca_dev->alt = 1 + 1;
343 break;
344 }
345 return 0;
346}
347
348static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
349{
350 struct sd *sd = (struct sd *) gspca_dev;
351
352 s32 backlight = sd->vcur.backlight;
353 s32 bright = sd->vcur.brightness;
354 s32 sharp = sd->vcur.sharpness;
355 s32 cntr = sd->vcur.contrast;
356 s32 gam = sd->vcur.gamma;
357 s32 hue = sd->vcur.hue;
358 s32 sat = sd->vcur.saturation;
359 s32 wbal = sd->vcur.whitebal;
360 s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
361 s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0);
362 s32 freq = (sd->vcur.AC50Hz > 0);
363 s32 i;
364
365 if (freq != sd->vold.AC50Hz) {
366 sd->vold.AC50Hz = freq;
367
368 freq = 2 * (freq == 0);
369 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
370 ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL);
371 ctrl_out(gspca_dev, 0x40, 1, 0xba00 , 0x005b, 0, NULL);
372 ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL);
373 }
374
375 if (wbal != sd->vold.whitebal) {
376 sd->vold.whitebal = wbal;
377 if (wbal < 0 || wbal > sd->vmax.whitebal)
378 wbal = 0;
379
380 for (i = 0; i < 2; i++) {
381 if (wbal == 0) { /* Normal light */
382 ctrl_out(gspca_dev, 0x40, 1,
383 0x0010, 0x0010, 0, NULL);
384 ctrl_out(gspca_dev, 0x40, 1,
385 0x0003, 0x00c1, 0, NULL);
386 ctrl_out(gspca_dev, 0x40, 1,
387 0x0042, 0x00c2, 0, NULL);
388 ctrl_out(gspca_dev, 0x40, 3,
389 0xba00, 0x0200, 48, dat_wbalNL);
390 }
391
392 if (wbal == 1) { /* Low light */
393 ctrl_out(gspca_dev, 0x40, 1,
394 0x0010, 0x0010, 0, NULL);
395 ctrl_out(gspca_dev, 0x40, 1,
396 0x0004, 0x00c1, 0, NULL);
397 ctrl_out(gspca_dev, 0x40, 1,
398 0x0043, 0x00c2, 0, NULL);
399 ctrl_out(gspca_dev, 0x40, 3,
400 0xba00, 0x0200, 48, dat_wbalLL);
401 }
402
403 if (wbal == 2) { /* Back light */
404 ctrl_out(gspca_dev, 0x40, 1,
405 0x0010, 0x0010, 0, NULL);
406 ctrl_out(gspca_dev, 0x40, 1,
407 0x0003, 0x00c1, 0, NULL);
408 ctrl_out(gspca_dev, 0x40, 1,
409 0x0042, 0x00c2, 0, NULL);
410 ctrl_out(gspca_dev, 0x40, 3,
411 0xba00, 0x0200, 44, dat_wbalBL);
412 }
413 }
414 }
415
416 if (bright != sd->vold.brightness) {
417 sd->vold.brightness = bright;
418 if (bright < 0 || bright > sd->vmax.brightness)
419 bright = 0;
420
421 bright = tbl_bright[bright];
422 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
423 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
424 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL);
425 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL);
426 }
427
428 if (sat != sd->vold.saturation) {
429 sd->vold.saturation = sat;
430 if (sat < 0 || sat > sd->vmax.saturation)
431 sat = 0;
432
433 sat = tbl_sat[sat];
434 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
435 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
436 ctrl_out(gspca_dev, 0x40, 1, 0xba00 , 0x0025, 0, NULL);
437 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL);
438 }
439
440 if (sharp != sd->vold.sharpness) {
441 sd->vold.sharpness = sharp;
442 if (sharp < 0 || sharp > sd->vmax.sharpness)
443 sharp = 0;
444
445 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
446 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
447 ctrl_out(gspca_dev, 0x40, 1, 0xba00 , 0x0005, 0, NULL);
448 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL);
449 }
450
451 if (hue != sd->vold.hue) {
452 /* 0=normal 1=NB 2="sepia" 3=negative 4=other 5=other2 */
453 if (hue < 0 || hue > sd->vmax.hue)
454 hue = 0;
455 if (hue == sd->vmax.hue)
456 sd->swapRB = 1;
457 else
458 sd->swapRB = 0;
459
460 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
461 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
462 ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
463 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
464 0, NULL);
465 }
466
467 if (backlight != sd->vold.backlight) {
468 sd->vold.backlight = backlight;
469 if (backlight < 0 || backlight > sd->vmax.backlight)
470 backlight = 0;
471
472 backlight = tbl_backlight[backlight];
473 for (i = 0; i < 2; i++) {
474 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
475 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
476 ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL);
477 ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1,
478 0, NULL);
479 }
480 }
481
482 if (hue != sd->vold.hue) {
483 sd->vold.hue = hue;
484
485 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
486 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
487 ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
488 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
489 0, NULL);
490 }
491
492 if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
493 u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00};
494 sd->vold.mirror = mirror;
495 sd->vold.flip = flip;
496
497 dat_hvflip2[3] = flip + 2 * mirror;
498 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1);
499 ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2);
500 }
501
502 if (gam != sd->vold.gamma) {
503 sd->vold.gamma = gam;
504 if (gam < 0 || gam > sd->vmax.gamma)
505 gam = 0;
506
507 gam = 2 * gam;
508 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
509 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
510 ctrl_out(gspca_dev, 0x40, 1, 0xba04 , 0x003b, 0, NULL);
511 ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL);
512 }
513
514 if (cntr != sd->vold.contrast) {
515 sd->vold.contrast = cntr;
516 if (cntr < 0 || cntr > sd->vmax.contrast)
517 cntr = 0;
518
519 ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
520 ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
521 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035,
522 0, NULL);
523 ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1,
524 0, NULL);
525 }
526
527 return 0;
528}
529
530static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev)
531{
532 ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
533
534 fetch_validx(gspca_dev, tbl_post_unset_alt,
535 ARRAY_SIZE(tbl_post_unset_alt));
536}
diff --git a/drivers/media/usb/gspca/gl860/gl860-mi2020.c b/drivers/media/usb/gspca/gl860/gl860-mi2020.c
new file mode 100644
index 00000000000..2edda6b7d65
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/gl860-mi2020.c
@@ -0,0 +1,733 @@
1/* Subdriver for the GL860 chip with the MI2020 sensor
2 * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid
3 * with the help of Kytrix/BUGabundo/Blazercist.
4 * Driver achieved thanks to a webcam gift by Kytrix.
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, see <http://www.gnu.org/licenses/>.
18 */
19
20/* Sensor : MI2020 */
21
22#include "gl860.h"
23
24static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c};
25
26static u8 dat_bright1[] = {0x8c, 0xa2, 0x06};
27static u8 dat_bright3[] = {0x8c, 0xa1, 0x02};
28static u8 dat_bright4[] = {0x90, 0x00, 0x0f};
29static u8 dat_bright5[] = {0x8c, 0xa1, 0x03};
30static u8 dat_bright6[] = {0x90, 0x00, 0x05};
31
32static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19};
33static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b};
34static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03};
35static u8 dat_hvflip6[] = {0x90, 0x00, 0x06};
36
37static struct idxdata tbl_middle_hvflip_low[] = {
38 {0x33, "\x90\x00\x06"},
39 {6, "\xff\xff\xff"},
40 {0x33, "\x90\x00\x06"},
41 {6, "\xff\xff\xff"},
42 {0x33, "\x90\x00\x06"},
43 {6, "\xff\xff\xff"},
44 {0x33, "\x90\x00\x06"},
45 {6, "\xff\xff\xff"},
46};
47
48static struct idxdata tbl_middle_hvflip_big[] = {
49 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa1\x20"},
50 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
51 {102, "\xff\xff\xff"},
52 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x20"},
53 {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
54};
55
56static struct idxdata tbl_end_hvflip[] = {
57 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
58 {6, "\xff\xff\xff"},
59 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
60 {6, "\xff\xff\xff"},
61 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
62 {6, "\xff\xff\xff"},
63 {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
64};
65
66static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 };
67
68static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 };
69static u8 dat_multi6[] = { 0x90, 0x00, 0x05 };
70
71static struct validx tbl_init_at_startup[] = {
72 {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
73 {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
74 {53, 0xffff},
75 {0x0040, 0x0000}, {0x0063, 0x0006},
76};
77
78static struct validx tbl_common_0B[] = {
79 {0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
80 {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2},
81 {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000},
82};
83
84static struct idxdata tbl_common_3B[] = {
85 {0x33, "\x86\x25\x01"}, {0x33, "\x86\x25\x00"},
86 {2, "\xff\xff\xff"},
87 {0x30, "\x1a\x0a\xcc"}, {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"},
88 {6, "\xff\xff\xff"}, /* 12 */
89 {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
90 {2, "\xff\xff\xff"}, /* - */
91 {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\x22\x23"},
92 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0f"}, {0x33, "\x90\x00\x0d"},
93 {0x33, "\x8c\xa2\x10"}, {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x11"},
94 {0x33, "\x90\x00\x07"}, {0x33, "\xf4\x03\x1d"}, {0x35, "\xa2\x00\xe2"},
95 {0x33, "\x8c\xab\x05"}, {0x33, "\x90\x00\x01"}, {0x32, "\x6e\x00\x86"},
96 {0x32, "\x70\x0f\xaa"}, {0x32, "\x72\x0f\xe4"}, {0x33, "\x8c\xa3\x4a"},
97 {0x33, "\x90\x00\x5a"}, {0x33, "\x8c\xa3\x4b"}, {0x33, "\x90\x00\xa6"},
98 {0x33, "\x8c\xa3\x61"}, {0x33, "\x90\x00\xc8"}, {0x33, "\x8c\xa3\x62"},
99 {0x33, "\x90\x00\xe1"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
100 {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
101 {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
102 {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
103 {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
104 {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
105 {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
106 {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
107 {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
108 {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
109 {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
110 {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
111 {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
112 {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
113 {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
114 {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
115 {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
116 {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
117 {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
118 {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
119 {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
120 {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
121 {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
122 {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
123 {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
124 {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
125 {0x33, "\x78\x00\x00"},
126 {2, "\xff\xff\xff"},
127 {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"},
128 {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"},
129 {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"},
130 {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"},
131 {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, {0x33, "\x8c\xa4\x04"},
132 {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"},
133 {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"},
134 {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, {0x33, "\x90\x00\x04"},
135 {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, {0x33, "\x8c\xa1\x03"},
136 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
137 {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x25"},
138 {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"},
139 {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x47"},
140 {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x02\x84"},
141 {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, {0x33, "\x8c\x27\x07"},
142 {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, {0x33, "\x90\x04\xb0"},
143 {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x0f"},
144 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, {0x33, "\x90\x04\xbd"},
145 {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, {0x33, "\x8c\x27\x15"},
146 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
147 {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, {0x33, "\x8c\x27\x1b"},
148 {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, {0x33, "\x90\x01\x02"},
149 {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, {0x33, "\x8c\x27\x21"},
150 {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, {0x33, "\x90\x02\x85"},
151 {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x27"},
152 {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, {0x33, "\x90\x20\x20"},
153 {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, {0x33, "\x8c\x27\x2d"},
154 {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, {0x33, "\x90\x00\x04"},
155 {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x33"},
156 {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, {0x33, "\x90\x06\x4b"},
157 {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x39"},
158 {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"},
159 {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x41"},
160 {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, {0x33, "\x90\x04\xed"},
161 {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x51"},
162 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, {0x33, "\x90\x03\x20"},
163 {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x57"},
164 {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, {0x33, "\x90\x00\x00"},
165 {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x63"},
166 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, {0x33, "\x90\x04\xb0"},
167 {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\xa4\x08"},
168 {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"},
169 {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"},
170 {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa1"},
171 {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, {0x33, "\x8c\x24\x15"},
172 {0x33, "\x90\x00\x6a"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\x80"},
173 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
174 {2, "\xff\xff\xff"},
175 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
176 {3, "\xff\xff\xff"},
177};
178
179static struct idxdata tbl_init_post_alt_low1[] = {
180 {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"},
181 {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"},
182 {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"},
183 {0x33, "\x90\x00\x1d"}, {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x20"},
184 {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\x24\x13"},
185 {0x33, "\x90\x00\x9b"},
186};
187
188static struct idxdata tbl_init_post_alt_low2[] = {
189 {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"},
190 {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
191 {2, "\xff\xff\xff"},
192 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
193 {2, "\xff\xff\xff"},
194};
195
196static struct idxdata tbl_init_post_alt_low3[] = {
197 {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
198 {2, "\xff\xff\xff"},
199 {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"},
200 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"},
201 {0x33, "\x2e\x01\x00"}, {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"},
202 {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x95"}, {0x33, "\x90\x01\x00"},
203 {2, "\xff\xff\xff"},
204 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
205 {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
206 {2, "\xff\xff\xff"},
207 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
208 {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
209 {2, "\xff\xff\xff"},
210 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
211 {2, "\xff\xff\xff"},
212 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
213 {2, "\xff\xff\xff"},
214 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
215 {2, "\xff\xff\xff"},
216 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
217};
218
219static struct idxdata tbl_init_post_alt_big[] = {
220 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
221 {2, "\xff\xff\xff"},
222 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
223 {2, "\xff\xff\xff"},
224 {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
225 {2, "\xff\xff\xff"},
226 {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"},
227 {0x33, "\x90\x00\x05"},
228 {2, "\xff\xff\xff"},
229 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
230 {2, "\xff\xff\xff"},
231 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
232 {2, "\xff\xff\xff"},
233 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, {0x33, "\x8c\xa1\x20"},
234 {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x30"}, {0x33, "\x90\x00\x03"},
235 {0x33, "\x8c\xa1\x31"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x32"},
236 {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"},
237 {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"},
238 {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
239 {0x33, "\x8c\x27\x97"}, {0x33, "\x90\x01\x00"},
240 {51, "\xff\xff\xff"},
241 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
242 {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
243 {51, "\xff\xff\xff"},
244 {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
245 {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
246 {51, "\xff\xff\xff"},
247};
248
249static struct idxdata tbl_init_post_alt_3B[] = {
250 {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
251 {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
252 {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
253 {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
254 {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
255 {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
256 {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
257 {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
258 {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
259 {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
260 {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
261 {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
262 {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
263 {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
264 {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
265 {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
266 {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
267 {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
268 {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
269 {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
270 {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
271 {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
272 {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
273 {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
274 {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
275 {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
276};
277
278static u8 *dat_640 = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81";
279static u8 *dat_800 = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21";
280static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01";
281static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41";
282
283static int mi2020_init_at_startup(struct gspca_dev *gspca_dev);
284static int mi2020_configure_alt(struct gspca_dev *gspca_dev);
285static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev);
286static int mi2020_init_post_alt(struct gspca_dev *gspca_dev);
287static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev);
288static int mi2020_camera_settings(struct gspca_dev *gspca_dev);
289/*==========================================================================*/
290
291void mi2020_init_settings(struct gspca_dev *gspca_dev)
292{
293 struct sd *sd = (struct sd *) gspca_dev;
294
295 sd->vcur.backlight = 0;
296 sd->vcur.brightness = 70;
297 sd->vcur.sharpness = 20;
298 sd->vcur.contrast = 0;
299 sd->vcur.gamma = 0;
300 sd->vcur.hue = 0;
301 sd->vcur.saturation = 60;
302 sd->vcur.whitebal = 0; /* 50, not done by hardware */
303 sd->vcur.mirror = 0;
304 sd->vcur.flip = 0;
305 sd->vcur.AC50Hz = 1;
306
307 sd->vmax.backlight = 64;
308 sd->vmax.brightness = 128;
309 sd->vmax.sharpness = 40;
310 sd->vmax.contrast = 3;
311 sd->vmax.gamma = 2;
312 sd->vmax.hue = 0 + 1; /* 200, not done by hardware */
313 sd->vmax.saturation = 0; /* 100, not done by hardware */
314 sd->vmax.whitebal = 2; /* 100, not done by hardware */
315 sd->vmax.mirror = 1;
316 sd->vmax.flip = 1;
317 sd->vmax.AC50Hz = 1;
318
319 sd->dev_camera_settings = mi2020_camera_settings;
320 sd->dev_init_at_startup = mi2020_init_at_startup;
321 sd->dev_configure_alt = mi2020_configure_alt;
322 sd->dev_init_pre_alt = mi2020_init_pre_alt;
323 sd->dev_post_unset_alt = mi2020_post_unset_alt;
324}
325
326/*==========================================================================*/
327
328static void common(struct gspca_dev *gspca_dev)
329{
330 fetch_validx(gspca_dev, tbl_common_0B, ARRAY_SIZE(tbl_common_0B));
331 fetch_idxdata(gspca_dev, tbl_common_3B, ARRAY_SIZE(tbl_common_3B));
332 ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
333}
334
335static int mi2020_init_at_startup(struct gspca_dev *gspca_dev)
336{
337 u8 c;
338
339 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
340 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
341
342 fetch_validx(gspca_dev, tbl_init_at_startup,
343 ARRAY_SIZE(tbl_init_at_startup));
344
345 ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
346 ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &c);
347
348 common(gspca_dev);
349
350 msleep(61);
351/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
352/* msleep(36); */
353 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL);
354
355 return 0;
356}
357
358static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev)
359{
360 struct sd *sd = (struct sd *) gspca_dev;
361
362 sd->mirrorMask = 0;
363 sd->vold.hue = -1;
364
365 /* These controls need to be reset */
366 sd->vold.brightness = -1;
367 sd->vold.sharpness = -1;
368
369 /* If not different from default, they do not need to be set */
370 sd->vold.contrast = 0;
371 sd->vold.gamma = 0;
372 sd->vold.backlight = 0;
373
374 mi2020_init_post_alt(gspca_dev);
375
376 return 0;
377}
378
379static int mi2020_init_post_alt(struct gspca_dev *gspca_dev)
380{
381 struct sd *sd = (struct sd *) gspca_dev;
382 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
383
384 s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
385 s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0);
386 s32 freq = (sd->vcur.AC50Hz > 0);
387 s32 wbal = sd->vcur.whitebal;
388
389 u8 dat_freq2[] = {0x90, 0x00, 0x80};
390 u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
391 u8 dat_multi2[] = {0x90, 0x00, 0x00};
392 u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
393 u8 dat_multi4[] = {0x90, 0x00, 0x00};
394 u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
395 u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
396 u8 dat_wbal2[] = {0x90, 0x00, 0x00};
397 u8 c;
398
399 sd->nbIm = -1;
400
401 dat_freq2[2] = freq ? 0xc0 : 0x80;
402 dat_multi1[2] = 0x9d;
403 dat_multi3[2] = dat_multi1[2] + 1;
404 if (wbal == 0) {
405 dat_multi4[2] = dat_multi2[2] = 0;
406 dat_wbal2[2] = 0x17;
407 } else if (wbal == 1) {
408 dat_multi4[2] = dat_multi2[2] = 0;
409 dat_wbal2[2] = 0x35;
410 } else if (wbal == 2) {
411 dat_multi4[2] = dat_multi2[2] = 0x20;
412 dat_wbal2[2] = 0x17;
413 }
414 dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
415 dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
416
417 msleep(200);
418 ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
419 msleep(2);
420
421 common(gspca_dev);
422
423 msleep(142);
424 ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
425 ctrl_out(gspca_dev, 0x40, 1, 0x0003, 0x00c1, 0, NULL);
426 ctrl_out(gspca_dev, 0x40, 1, 0x0042, 0x00c2, 0, NULL);
427 ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
428
429 switch (reso) {
430 case IMAGE_640:
431 case IMAGE_800:
432 if (reso != IMAGE_800)
433 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
434 12, dat_640);
435 else
436 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
437 12, dat_800);
438
439 fetch_idxdata(gspca_dev, tbl_init_post_alt_low1,
440 ARRAY_SIZE(tbl_init_post_alt_low1));
441
442 if (reso == IMAGE_800)
443 fetch_idxdata(gspca_dev, tbl_init_post_alt_low2,
444 ARRAY_SIZE(tbl_init_post_alt_low2));
445
446 fetch_idxdata(gspca_dev, tbl_init_post_alt_low3,
447 ARRAY_SIZE(tbl_init_post_alt_low3));
448
449 ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
450 ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
451 ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
452 msleep(120);
453 break;
454
455 case IMAGE_1280:
456 case IMAGE_1600:
457 if (reso == IMAGE_1280) {
458 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
459 12, dat_1280);
460 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
461 3, "\x8c\x27\x07");
462 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
463 3, "\x90\x05\x04");
464 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
465 3, "\x8c\x27\x09");
466 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
467 3, "\x90\x04\x02");
468 } else {
469 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
470 12, dat_1600);
471 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
472 3, "\x8c\x27\x07");
473 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
474 3, "\x90\x06\x40");
475 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
476 3, "\x8c\x27\x09");
477 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
478 3, "\x90\x04\xb0");
479 }
480
481 fetch_idxdata(gspca_dev, tbl_init_post_alt_big,
482 ARRAY_SIZE(tbl_init_post_alt_big));
483
484 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
485 ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
486 ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
487 msleep(1850);
488 }
489
490 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
491 msleep(40);
492
493 /* AC power frequency */
494 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
495 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
496 msleep(33);
497 /* light source */
498 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
499 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
500 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
501 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
502 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
503 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
504 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
505 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
506 msleep(7);
507 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
508
509 fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
510 ARRAY_SIZE(tbl_init_post_alt_3B));
511
512 /* hvflip */
513 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
514 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
515 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
516 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
517 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
518 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
519 msleep(250);
520
521 if (reso == IMAGE_640 || reso == IMAGE_800)
522 fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
523 ARRAY_SIZE(tbl_middle_hvflip_low));
524 else
525 fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
526 ARRAY_SIZE(tbl_middle_hvflip_big));
527
528 fetch_idxdata(gspca_dev, tbl_end_hvflip,
529 ARRAY_SIZE(tbl_end_hvflip));
530
531 sd->nbIm = 0;
532
533 sd->vold.mirror = mirror;
534 sd->vold.flip = flip;
535 sd->vold.AC50Hz = freq;
536 sd->vold.whitebal = wbal;
537
538 mi2020_camera_settings(gspca_dev);
539
540 return 0;
541}
542
543static int mi2020_configure_alt(struct gspca_dev *gspca_dev)
544{
545 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
546
547 switch (reso) {
548 case IMAGE_640:
549 gspca_dev->alt = 3 + 1;
550 break;
551
552 case IMAGE_800:
553 case IMAGE_1280:
554 case IMAGE_1600:
555 gspca_dev->alt = 1 + 1;
556 break;
557 }
558 return 0;
559}
560
561static int mi2020_camera_settings(struct gspca_dev *gspca_dev)
562{
563 struct sd *sd = (struct sd *) gspca_dev;
564 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
565
566 s32 backlight = sd->vcur.backlight;
567 s32 bright = sd->vcur.brightness;
568 s32 sharp = sd->vcur.sharpness;
569 s32 cntr = sd->vcur.contrast;
570 s32 gam = sd->vcur.gamma;
571 s32 hue = (sd->vcur.hue > 0);
572 s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
573 s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0);
574 s32 freq = (sd->vcur.AC50Hz > 0);
575 s32 wbal = sd->vcur.whitebal;
576
577 u8 dat_sharp[] = {0x6c, 0x00, 0x08};
578 u8 dat_bright2[] = {0x90, 0x00, 0x00};
579 u8 dat_freq2[] = {0x90, 0x00, 0x80};
580 u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
581 u8 dat_multi2[] = {0x90, 0x00, 0x00};
582 u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
583 u8 dat_multi4[] = {0x90, 0x00, 0x00};
584 u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
585 u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
586 u8 dat_wbal2[] = {0x90, 0x00, 0x00};
587
588 /* Less than 4 images received -> too early to set the settings */
589 if (sd->nbIm < 4) {
590 sd->waitSet = 1;
591 return 0;
592 }
593 sd->waitSet = 0;
594
595 if (freq != sd->vold.AC50Hz) {
596 sd->vold.AC50Hz = freq;
597
598 dat_freq2[2] = freq ? 0xc0 : 0x80;
599 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
600 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
601 msleep(20);
602 }
603
604 if (wbal != sd->vold.whitebal) {
605 sd->vold.whitebal = wbal;
606 if (wbal < 0 || wbal > sd->vmax.whitebal)
607 wbal = 0;
608
609 dat_multi1[2] = 0x9d;
610 dat_multi3[2] = dat_multi1[2] + 1;
611 if (wbal == 0) {
612 dat_multi4[2] = dat_multi2[2] = 0;
613 dat_wbal2[2] = 0x17;
614 } else if (wbal == 1) {
615 dat_multi4[2] = dat_multi2[2] = 0;
616 dat_wbal2[2] = 0x35;
617 } else if (wbal == 2) {
618 dat_multi4[2] = dat_multi2[2] = 0x20;
619 dat_wbal2[2] = 0x17;
620 }
621 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
622 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
623 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
624 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
625 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
626 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
627 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
628 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
629 }
630
631 if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
632 sd->vold.mirror = mirror;
633 sd->vold.flip = flip;
634
635 dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
636 dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
637
638 fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
639 ARRAY_SIZE(tbl_init_post_alt_3B));
640
641 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
642 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
643 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
644 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
645 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
646 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
647 msleep(40);
648
649 if (reso == IMAGE_640 || reso == IMAGE_800)
650 fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
651 ARRAY_SIZE(tbl_middle_hvflip_low));
652 else
653 fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
654 ARRAY_SIZE(tbl_middle_hvflip_big));
655
656 fetch_idxdata(gspca_dev, tbl_end_hvflip,
657 ARRAY_SIZE(tbl_end_hvflip));
658 }
659
660 if (bright != sd->vold.brightness) {
661 sd->vold.brightness = bright;
662 if (bright < 0 || bright > sd->vmax.brightness)
663 bright = 0;
664
665 dat_bright2[2] = bright;
666 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1);
667 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2);
668 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3);
669 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4);
670 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5);
671 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6);
672 }
673
674 if (cntr != sd->vold.contrast || gam != sd->vold.gamma) {
675 sd->vold.contrast = cntr;
676 if (cntr < 0 || cntr > sd->vmax.contrast)
677 cntr = 0;
678 sd->vold.gamma = gam;
679 if (gam < 0 || gam > sd->vmax.gamma)
680 gam = 0;
681
682 dat_multi1[2] = 0x6d;
683 dat_multi3[2] = dat_multi1[2] + 1;
684 if (cntr == 0)
685 cntr = 4;
686 dat_multi4[2] = dat_multi2[2] = cntr * 0x10 + 2 - gam;
687 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
688 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
689 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
690 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
691 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
692 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
693 }
694
695 if (backlight != sd->vold.backlight) {
696 sd->vold.backlight = backlight;
697 if (backlight < 0 || backlight > sd->vmax.backlight)
698 backlight = 0;
699
700 dat_multi1[2] = 0x9d;
701 dat_multi3[2] = dat_multi1[2] + 1;
702 dat_multi4[2] = dat_multi2[2] = backlight;
703 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
704 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
705 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
706 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
707 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
708 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
709 }
710
711 if (sharp != sd->vold.sharpness) {
712 sd->vold.sharpness = sharp;
713 if (sharp < 0 || sharp > sd->vmax.sharpness)
714 sharp = 0;
715
716 dat_sharp[1] = sharp;
717 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp);
718 }
719
720 if (hue != sd->vold.hue) {
721 sd->swapRB = hue;
722 sd->vold.hue = hue;
723 }
724
725 return 0;
726}
727
728static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev)
729{
730 ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
731 msleep(40);
732 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL);
733}
diff --git a/drivers/media/usb/gspca/gl860/gl860-ov2640.c b/drivers/media/usb/gspca/gl860/gl860-ov2640.c
new file mode 100644
index 00000000000..768cac5cd72
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/gl860-ov2640.c
@@ -0,0 +1,489 @@
1/* Subdriver for the GL860 chip with the OV2640 sensor
2 * Author Olivier LORIN, from Malmostoso's logs
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* Sensor : OV2640 */
19
20#include "gl860.h"
21
22static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01";
23
24static u8 c61[] = {0x61}; /* expected */
25static u8 c51[] = {0x51}; /* expected */
26static u8 c50[] = {0x50}; /* expected */
27static u8 c28[] = {0x28}; /* expected */
28static u8 ca8[] = {0xa8}; /* expected */
29
30static u8 dat_post[] =
31 "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01";
32
33static u8 dat_640[] = "\xd0\x01\xd1\x08\xd2\xe0\xd3\x02\xd4\x10\xd5\x81";
34static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21";
35static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01";
36static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41";
37
38static struct validx tbl_init_at_startup[] = {
39 {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
40 {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
41 {0x0050, 0x0000}, {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0061, 0x0006},
42 {0x006a, 0x000d}, {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1},
43 {0x0041, 0x00c2}, {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058},
44 {0x0041, 0x0000}, {0x0061, 0x0000},
45};
46
47static struct validx tbl_common[] = {
48 {0x6000, 0x00ff}, {0x60ff, 0x002c}, {0x60df, 0x002e}, {0x6001, 0x00ff},
49 {0x6080, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010},
50 {0x6035, 0x003c}, {0x6000, 0x0011}, {0x6028, 0x0004}, {0x60e5, 0x0013},
51 {0x6088, 0x0014}, {0x600c, 0x002c}, {0x6078, 0x0033}, {0x60f7, 0x003b},
52 {0x6000, 0x003e}, {0x6011, 0x0043}, {0x6010, 0x0016}, {0x6082, 0x0039},
53 {0x6088, 0x0035}, {0x600a, 0x0022}, {0x6040, 0x0037}, {0x6000, 0x0023},
54 {0x60a0, 0x0034}, {0x601a, 0x0036}, {0x6002, 0x0006}, {0x60c0, 0x0007},
55 {0x60b7, 0x000d}, {0x6001, 0x000e}, {0x6000, 0x004c}, {0x6081, 0x004a},
56 {0x6099, 0x0021}, {0x6002, 0x0009}, {0x603e, 0x0024}, {0x6034, 0x0025},
57 {0x6081, 0x0026}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010},
58 {0x6000, 0x005c}, {0x6000, 0x0063}, {0x6000, 0x007c}, {0x6070, 0x0061},
59 {0x6080, 0x0062}, {0x6080, 0x0020}, {0x6030, 0x0028}, {0x6000, 0x006c},
60 {0x6000, 0x006e}, {0x6002, 0x0070}, {0x6094, 0x0071}, {0x60c1, 0x0073},
61 {0x6034, 0x003d}, {0x6057, 0x005a}, {0x60bb, 0x004f}, {0x609c, 0x0050},
62 {0x6080, 0x006d}, {0x6002, 0x0039}, {0x6033, 0x003a}, {0x60f1, 0x003b},
63 {0x6031, 0x003c}, {0x6000, 0x00ff}, {0x6014, 0x00e0}, {0x60ff, 0x0076},
64 {0x60a0, 0x0033}, {0x6020, 0x0042}, {0x6018, 0x0043}, {0x6000, 0x004c},
65 {0x60d0, 0x0087}, {0x600f, 0x0088}, {0x6003, 0x00d7}, {0x6010, 0x00d9},
66 {0x6005, 0x00da}, {0x6082, 0x00d3}, {0x60c0, 0x00f9}, {0x6006, 0x0044},
67 {0x6007, 0x00d1}, {0x6002, 0x00d2}, {0x6000, 0x00d2}, {0x6011, 0x00d8},
68 {0x6008, 0x00c8}, {0x6080, 0x00c9}, {0x6008, 0x007c}, {0x6020, 0x007d},
69 {0x6020, 0x007d}, {0x6000, 0x0090}, {0x600e, 0x0091}, {0x601a, 0x0091},
70 {0x6031, 0x0091}, {0x605a, 0x0091}, {0x6069, 0x0091}, {0x6075, 0x0091},
71 {0x607e, 0x0091}, {0x6088, 0x0091}, {0x608f, 0x0091}, {0x6096, 0x0091},
72 {0x60a3, 0x0091}, {0x60af, 0x0091}, {0x60c4, 0x0091}, {0x60d7, 0x0091},
73 {0x60e8, 0x0091}, {0x6020, 0x0091}, {0x6000, 0x0092}, {0x6006, 0x0093},
74 {0x60e3, 0x0093}, {0x6005, 0x0093}, {0x6005, 0x0093}, {0x6000, 0x0093},
75 {0x6004, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093},
76 {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093},
77 {0x6000, 0x0096}, {0x6008, 0x0097}, {0x6019, 0x0097}, {0x6002, 0x0097},
78 {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, {0x6028, 0x0097},
79 {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6098, 0x0097}, {0x6080, 0x0097},
80 {0x6000, 0x0097}, {0x6000, 0x0097}, {0x60ed, 0x00c3}, {0x609a, 0x00c4},
81 {0x6000, 0x00a4}, {0x6011, 0x00c5}, {0x6051, 0x00c6}, {0x6010, 0x00c7},
82 {0x6066, 0x00b6}, {0x60a5, 0x00b8}, {0x6064, 0x00b7}, {0x607c, 0x00b9},
83 {0x60af, 0x00b3}, {0x6097, 0x00b4}, {0x60ff, 0x00b5}, {0x60c5, 0x00b0},
84 {0x6094, 0x00b1}, {0x600f, 0x00b2}, {0x605c, 0x00c4}, {0x6000, 0x00a8},
85 {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x601d, 0x0086}, {0x6000, 0x0050},
86 {0x6090, 0x0051}, {0x6018, 0x0052}, {0x6000, 0x0053}, {0x6000, 0x0054},
87 {0x6088, 0x0055}, {0x6000, 0x0057}, {0x6090, 0x005a}, {0x6018, 0x005b},
88 {0x6005, 0x005c}, {0x60ed, 0x00c3}, {0x6000, 0x007f}, {0x6005, 0x00da},
89 {0x601f, 0x00e5}, {0x6067, 0x00e1}, {0x6000, 0x00e0}, {0x60ff, 0x00dd},
90 {0x6000, 0x0005}, {0x6001, 0x00ff}, {0x6000, 0x0000}, {0x6000, 0x0045},
91 {0x6000, 0x0010},
92};
93
94static struct validx tbl_sensor_settings_common1[] = {
95 {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
96 {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
97 {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000},
98 {50, 0xffff},
99 {0x0061, 0x0000},
100 {0xffff, 0xffff},
101 {0x6000, 0x00ff}, {0x6000, 0x007c}, {0x6007, 0x007d},
102 {30, 0xffff},
103 {0x0040, 0x0000},
104};
105
106static struct validx tbl_sensor_settings_common2[] = {
107 {0x6001, 0x00ff}, {0x6038, 0x000c},
108 {10, 0xffff},
109 {0x6000, 0x0011},
110};
111
112static struct validx tbl_640[] = {
113 {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1},
114 {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
115 {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017},
116 {0x6075, 0x0018}, {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032},
117 {0x60bb, 0x004f}, {0x6057, 0x005a}, {0x609c, 0x0050}, {0x6080, 0x006d},
118 {0x6092, 0x0026}, {0x60ff, 0x0020}, {0x6000, 0x0027}, {0x6000, 0x00ff},
119 {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, {0x603d, 0x0086},
120 {0x6089, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, {0x6000, 0x0053},
121 {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, {0x60a0, 0x005a},
122 {0x6078, 0x005b}, {0x6000, 0x005c}, {0x6004, 0x00d3}, {0x6000, 0x00e0},
123 {0x60ff, 0x00dd}, {0x60a1, 0x005a},
124};
125
126static struct validx tbl_800[] = {
127 {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1},
128 {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
129 {0x6001, 0x00ff}, {0x6040, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017},
130 {0x6043, 0x0018}, {0x6000, 0x0019}, {0x604b, 0x001a}, {0x6009, 0x0032},
131 {0x60ca, 0x004f}, {0x60a8, 0x0050}, {0x6000, 0x006d}, {0x6038, 0x003d},
132 {0x60c8, 0x0035}, {0x6000, 0x0022}, {0x6092, 0x0026}, {0x60ff, 0x0020},
133 {0x6000, 0x0027}, {0x6000, 0x00ff}, {0x6064, 0x00c0}, {0x604b, 0x00c1},
134 {0x6000, 0x008c}, {0x601d, 0x0086}, {0x6082, 0x00d3}, {0x6000, 0x00e0},
135 {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018},
136};
137
138static struct validx tbl_big1[] = {
139 {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
140 {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045},
141 {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018},
142 {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, {0x60bb, 0x004f},
143 {0x609c, 0x0050}, {0x6057, 0x005a}, {0x6080, 0x006d}, {0x6043, 0x000f},
144 {0x608f, 0x0003}, {0x6005, 0x007c}, {0x6081, 0x0026}, {0x6000, 0x00ff},
145 {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c},
146};
147
148static struct validx tbl_big2[] = {
149 {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052},
150 {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057},
151 {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3},
152 {0x6000, 0x008e},
153};
154
155static struct validx tbl_big3[] = {
156 {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd},
157 {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
158 {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7},
159 {0x6000, 0x0092}, {0x6006, 0x0093}, {0x60e3, 0x0093}, {0x6005, 0x0093},
160 {0x6005, 0x0093}, {0x60ed, 0x00c3}, {0x6000, 0x00a4}, {0x60d0, 0x0087},
161 {0x6003, 0x0096}, {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097},
162 {0x6028, 0x0097}, {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6001, 0x00ff},
163 {0x6043, 0x000f}, {0x608f, 0x0003}, {0x6000, 0x002d}, {0x6000, 0x002e},
164 {0x600a, 0x0022}, {0x6002, 0x0070}, {0x6008, 0x0014}, {0x6048, 0x0014},
165 {0x6000, 0x00ff}, {0x6000, 0x00e0}, {0x60ff, 0x00dd},
166};
167
168static struct validx tbl_post_unset_alt[] = {
169 {0x006a, 0x000d}, {0x6001, 0x00ff}, {0x6081, 0x0026}, {0x6000, 0x0000},
170 {0x6000, 0x0045}, {0x6000, 0x0010}, {0x6068, 0x000d},
171 {50, 0xffff},
172 {0x0021, 0x0000},
173};
174
175static int ov2640_init_at_startup(struct gspca_dev *gspca_dev);
176static int ov2640_configure_alt(struct gspca_dev *gspca_dev);
177static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev);
178static int ov2640_init_post_alt(struct gspca_dev *gspca_dev);
179static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev);
180static int ov2640_camera_settings(struct gspca_dev *gspca_dev);
181/*==========================================================================*/
182
183void ov2640_init_settings(struct gspca_dev *gspca_dev)
184{
185 struct sd *sd = (struct sd *) gspca_dev;
186
187 sd->vcur.backlight = 32;
188 sd->vcur.brightness = 0;
189 sd->vcur.sharpness = 6;
190 sd->vcur.contrast = 0;
191 sd->vcur.gamma = 32;
192 sd->vcur.hue = 0;
193 sd->vcur.saturation = 128;
194 sd->vcur.whitebal = 64;
195 sd->vcur.mirror = 0;
196 sd->vcur.flip = 0;
197
198 sd->vmax.backlight = 64;
199 sd->vmax.brightness = 255;
200 sd->vmax.sharpness = 31;
201 sd->vmax.contrast = 255;
202 sd->vmax.gamma = 64;
203 sd->vmax.hue = 254 + 2;
204 sd->vmax.saturation = 255;
205 sd->vmax.whitebal = 128;
206 sd->vmax.mirror = 1;
207 sd->vmax.flip = 1;
208 sd->vmax.AC50Hz = 0;
209
210 sd->dev_camera_settings = ov2640_camera_settings;
211 sd->dev_init_at_startup = ov2640_init_at_startup;
212 sd->dev_configure_alt = ov2640_configure_alt;
213 sd->dev_init_pre_alt = ov2640_init_pre_alt;
214 sd->dev_post_unset_alt = ov2640_post_unset_alt;
215}
216
217/*==========================================================================*/
218
219static void common(struct gspca_dev *gspca_dev)
220{
221 fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
222}
223
224static int ov2640_init_at_startup(struct gspca_dev *gspca_dev)
225{
226 fetch_validx(gspca_dev, tbl_init_at_startup,
227 ARRAY_SIZE(tbl_init_at_startup));
228
229 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_init1);
230
231 common(gspca_dev);
232
233 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61);
234
235 ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL);
236
237 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51);
238
239 ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL);
240/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
241
242 return 0;
243}
244
245static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev)
246{
247 struct sd *sd = (struct sd *) gspca_dev;
248
249 sd->mirrorMask = 0;
250
251 sd->vold.backlight = -1;
252 sd->vold.brightness = -1;
253 sd->vold.sharpness = -1;
254 sd->vold.contrast = -1;
255 sd->vold.saturation = -1;
256 sd->vold.gamma = -1;
257 sd->vold.hue = -1;
258 sd->vold.whitebal = -1;
259 sd->vold.mirror = -1;
260 sd->vold.flip = -1;
261
262 ov2640_init_post_alt(gspca_dev);
263
264 return 0;
265}
266
267static int ov2640_init_post_alt(struct gspca_dev *gspca_dev)
268{
269 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
270 s32 n; /* reserved for FETCH functions */
271
272 ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
273
274 n = fetch_validx(gspca_dev, tbl_sensor_settings_common1,
275 ARRAY_SIZE(tbl_sensor_settings_common1));
276 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post);
277 common(gspca_dev);
278 keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1,
279 ARRAY_SIZE(tbl_sensor_settings_common1), n);
280
281 switch (reso) {
282 case IMAGE_640:
283 n = fetch_validx(gspca_dev, tbl_640, ARRAY_SIZE(tbl_640));
284 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_640);
285 break;
286
287 case IMAGE_800:
288 n = fetch_validx(gspca_dev, tbl_800, ARRAY_SIZE(tbl_800));
289 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_800);
290 break;
291
292 case IMAGE_1600:
293 case IMAGE_1280:
294 n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1));
295
296 if (reso == IMAGE_1280) {
297 n = fetch_validx(gspca_dev, tbl_big2,
298 ARRAY_SIZE(tbl_big2));
299 } else {
300 ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL);
301 ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL);
302 ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL);
303 }
304
305 n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3));
306
307 if (reso == IMAGE_1280) {
308 ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
309 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
310 12, dat_1280);
311 } else {
312 ctrl_out(gspca_dev, 0x40, 1, 0x6020, 0x008c, 0, NULL);
313 ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
314 ctrl_out(gspca_dev, 0x40, 1, 0x6076, 0x0018, 0, NULL);
315 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
316 12, dat_1600);
317 }
318 break;
319 }
320
321 n = fetch_validx(gspca_dev, tbl_sensor_settings_common2,
322 ARRAY_SIZE(tbl_sensor_settings_common2));
323
324 ov2640_camera_settings(gspca_dev);
325
326 return 0;
327}
328
329static int ov2640_configure_alt(struct gspca_dev *gspca_dev)
330{
331 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
332
333 switch (reso) {
334 case IMAGE_640:
335 gspca_dev->alt = 3 + 1;
336 break;
337
338 case IMAGE_800:
339 case IMAGE_1280:
340 case IMAGE_1600:
341 gspca_dev->alt = 1 + 1;
342 break;
343 }
344 return 0;
345}
346
347static int ov2640_camera_settings(struct gspca_dev *gspca_dev)
348{
349 struct sd *sd = (struct sd *) gspca_dev;
350
351 s32 backlight = sd->vcur.backlight;
352 s32 bright = sd->vcur.brightness;
353 s32 sharp = sd->vcur.sharpness;
354 s32 gam = sd->vcur.gamma;
355 s32 cntr = sd->vcur.contrast;
356 s32 sat = sd->vcur.saturation;
357 s32 hue = sd->vcur.hue;
358 s32 wbal = sd->vcur.whitebal;
359 s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0);
360 s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) == 0);
361
362 if (backlight != sd->vold.backlight) {
363 /* No sd->vold.backlight=backlight; (to be done again later) */
364 if (backlight < 0 || backlight > sd->vmax.backlight)
365 backlight = 0;
366
367 ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff,
368 0, NULL);
369 ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024,
370 0, NULL);
371 ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
372 0, NULL);
373 }
374
375 if (bright != sd->vold.brightness) {
376 sd->vold.brightness = bright;
377 if (bright < 0 || bright > sd->vmax.brightness)
378 bright = 0;
379
380 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
381 ctrl_out(gspca_dev, 0x40, 1, 0x6009 , 0x007c, 0, NULL);
382 ctrl_out(gspca_dev, 0x40, 1, 0x6000 + bright, 0x007d, 0, NULL);
383 }
384
385 if (wbal != sd->vold.whitebal) {
386 sd->vold.whitebal = wbal;
387 if (wbal < 0 || wbal > sd->vmax.whitebal)
388 wbal = 0;
389
390 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
391 ctrl_out(gspca_dev, 0x40, 1, 0x6003 , 0x007c, 0, NULL);
392 ctrl_out(gspca_dev, 0x40, 1, 0x6000 + wbal, 0x007d, 0, NULL);
393 }
394
395 if (cntr != sd->vold.contrast) {
396 sd->vold.contrast = cntr;
397 if (cntr < 0 || cntr > sd->vmax.contrast)
398 cntr = 0;
399
400 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
401 ctrl_out(gspca_dev, 0x40, 1, 0x6007 , 0x007c, 0, NULL);
402 ctrl_out(gspca_dev, 0x40, 1, 0x6000 + cntr, 0x007d, 0, NULL);
403 }
404
405 if (sat != sd->vold.saturation) {
406 sd->vold.saturation = sat;
407 if (sat < 0 || sat > sd->vmax.saturation)
408 sat = 0;
409
410 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
411 ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x007c, 0, NULL);
412 ctrl_out(gspca_dev, 0x40, 1, 0x6000 + sat, 0x007d, 0, NULL);
413 }
414
415 if (sharp != sd->vold.sharpness) {
416 sd->vold.sharpness = sharp;
417 if (sharp < 0 || sharp > sd->vmax.sharpness)
418 sharp = 0;
419
420 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
421 ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x0092, 0, NULL);
422 ctrl_out(gspca_dev, 0x40, 1, 0x60c0 + sharp, 0x0093, 0, NULL);
423 }
424
425 if (hue != sd->vold.hue) {
426 sd->vold.hue = hue;
427 if (hue < 0 || hue > sd->vmax.hue)
428 hue = 0;
429
430 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
431 ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL);
432 ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d,
433 0, NULL);
434 if (hue >= 255)
435 sd->swapRB = 1;
436 else
437 sd->swapRB = 0;
438 }
439
440 if (gam != sd->vold.gamma) {
441 sd->vold.gamma = gam;
442 if (gam < 0 || gam > sd->vmax.gamma)
443 gam = 0;
444
445 ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL);
446 ctrl_out(gspca_dev, 0x40, 1, 0x6008 , 0x007c, 0, NULL);
447 ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL);
448 }
449
450 if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
451 sd->vold.mirror = mirror;
452 sd->vold.flip = flip;
453
454 mirror = 0x80 * mirror;
455 ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
456 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
457 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28);
458 ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL);
459
460 flip = 0x50 * flip + mirror;
461 ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
462 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
463 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8);
464 ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL);
465
466 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50);
467 }
468
469 if (backlight != sd->vold.backlight) {
470 sd->vold.backlight = backlight;
471
472 ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff,
473 0, NULL);
474 ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024,
475 0, NULL);
476 ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
477 0, NULL);
478 }
479
480 return 0;
481}
482
483static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev)
484{
485 ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
486 msleep(20);
487 fetch_validx(gspca_dev, tbl_post_unset_alt,
488 ARRAY_SIZE(tbl_post_unset_alt));
489}
diff --git a/drivers/media/usb/gspca/gl860/gl860-ov9655.c b/drivers/media/usb/gspca/gl860/gl860-ov9655.c
new file mode 100644
index 00000000000..5ae9619d72a
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/gl860-ov9655.c
@@ -0,0 +1,336 @@
1/* Subdriver for the GL860 chip with the OV9655 sensor
2 * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt
3 * on dsd's weblog
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/* Sensor : OV9655 */
20
21#include "gl860.h"
22
23static struct validx tbl_init_at_startup[] = {
24 {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
25 {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
26
27 {0x0040, 0x0000},
28};
29
30static struct validx tbl_commmon[] = {
31 {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d},
32 {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
33 {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0040, 0x0000},
34 {0x00f3, 0x0006}, {0x0058, 0x0000}, {0x0048, 0x0000}, {0x0061, 0x0000},
35};
36
37static s32 tbl_length[] = {12, 56, 52, 54, 56, 42, 32, 12};
38
39static u8 *tbl_640[] = {
40 "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01"
41 ,
42 "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x03\x0b\x57\x0e\x61"
43 "\x0f\x42\x11\x01\x12\x60\x13\x00" "\x14\x3a\x16\x24\x17\x14\x18\x00"
44 "\x19\x01\x1a\x3d\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08"
45 "\x29\x15\x2a\x00\x2b\x00\x2c\x08"
46 ,
47 "\x32\xff\x33\x00\x34\x3d\x35\x00" "\x36\xfa\x38\x72\x39\x57\x3a\x00"
48 "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc1" "\x40\xc0\x41\x00\x42\xc0\x43\x0a"
49 "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xee\x4b\xe7\x4c\xe7"
50 "\x4d\xe7\x4e\xe7"
51 ,
52 "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85"
53 "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0"
54 "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x0a\x6b\x5a\x6c\x04"
55 "\x6d\x55\x6e\x00\x6f\x9d"
56 ,
57 "\x70\x15\x71\x78\x72\x00\x73\x00" "\x74\x3a\x75\x35\x76\x01\x77\x02"
58 "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52"
59 "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5"
60 "\x8a\x23\x8c\x8d\x90\x7c\x91\x7b"
61 ,
62 "\x9d\x02\x9e\x02\x9f\x74\xa0\x73" "\xa1\x40\xa4\x50\xa5\x68\xa6\x70"
63 "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80"
64 "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf"
65 ,
66 "\xbb\xae\xbc\x4f\xbd\x4e\xbe\x6a" "\xbf\x68\xc0\xaa\xc1\xc0\xc2\x01"
67 "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93"
68 ,
69 "\xd0\x01\xd1\x08\xd2\xe0\xd3\x01" "\xd4\x10\xd5\x80"
70};
71
72static u8 *tbl_1280[] = {
73 "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01"
74 ,
75 "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x01\x0b\x57\x0e\x61"
76 "\x0f\x42\x11\x00\x12\x00\x13\x00" "\x14\x3a\x16\x24\x17\x1b\x18\xbb"
77 "\x19\x01\x1a\x81\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08"
78 "\x29\x15\x2a\x00\x2b\x00\x2c\x08"
79 ,
80 "\x32\xa4\x33\x00\x34\x3d\x35\x00" "\x36\xf8\x38\x72\x39\x57\x3a\x00"
81 "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc2" "\x40\xc0\x41\x00\x42\xc0\x43\x0a"
82 "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xec\x4b\xe8\x4c\xe8"
83 "\x4d\xe8\x4e\xe8"
84 ,
85 "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85"
86 "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0"
87 "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x02\x6b\x5a\x6c\x04"
88 "\x6d\x55\x6e\x00\x6f\x9d"
89 ,
90 "\x70\x08\x71\x78\x72\x00\x73\x01" "\x74\x3a\x75\x35\x76\x01\x77\x02"
91 "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52"
92 "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5"
93 "\x8a\x23\x8c\x0d\x90\x90\x91\x90"
94 ,
95 "\x9d\x02\x9e\x02\x9f\x94\xa0\x94" "\xa1\x01\xa4\x50\xa5\x68\xa6\x70"
96 "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80"
97 "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf"
98 ,
99 "\xbb\xae\xbc\x38\xbd\x39\xbe\x01" "\xbf\x01\xc0\xe2\xc1\xc0\xc2\x01"
100 "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93"
101 ,
102 "\xd0\x21\xd1\x18\xd2\xe0\xd3\x01" "\xd4\x28\xd5\x00"
103};
104
105static u8 c04[] = {0x04};
106static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02";
107static u8 dat_post2[] = "\x10\x10\xc1\x02";
108static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04";
109static u8 dat_post4[] = "\x10\x02\xc1\x06";
110static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08";
111static u8 dat_post6[] = "\x10\x10\xc1\x05";
112static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08";
113static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09";
114
115static struct validx tbl_init_post_alt[] = {
116 {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff},
117 {0x6003, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6001, 0x00ff},
118 {0x6000, 0x801e},
119 {0xffff, 0xffff},
120 {0x6004, 0x001e}, {0x6000, 0x801e},
121 {0xffff, 0xffff},
122 {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
123 {0xffff, 0xffff},
124 {0x6004, 0x001e}, {0x6000, 0x801e},
125 {0xffff, 0xffff},
126 {0x6004, 0x001e}, {0x6012, 0x0003},
127 {0xffff, 0xffff},
128 {0x6000, 0x801e},
129 {0xffff, 0xffff},
130 {0x6004, 0x001e}, {0x6000, 0x801e},
131 {0xffff, 0xffff},
132 {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
133 {0xffff, 0xffff},
134 {0x6004, 0x001e}, {0x6000, 0x801e},
135 {0xffff, 0xffff},
136 {0x6004, 0x001e}, {0x6012, 0x0003},
137 {0xffff, 0xffff},
138 {0x6000, 0x801e},
139 {0xffff, 0xffff},
140 {0x6004, 0x001e}, {0x6000, 0x801e},
141 {0xffff, 0xffff},
142 {0x6004, 0x001e}, {0x6012, 0x0003},
143};
144
145static int ov9655_init_at_startup(struct gspca_dev *gspca_dev);
146static int ov9655_configure_alt(struct gspca_dev *gspca_dev);
147static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev);
148static int ov9655_init_post_alt(struct gspca_dev *gspca_dev);
149static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev);
150static int ov9655_camera_settings(struct gspca_dev *gspca_dev);
151/*==========================================================================*/
152
153void ov9655_init_settings(struct gspca_dev *gspca_dev)
154{
155 struct sd *sd = (struct sd *) gspca_dev;
156
157 sd->vcur.backlight = 0;
158 sd->vcur.brightness = 128;
159 sd->vcur.sharpness = 0;
160 sd->vcur.contrast = 0;
161 sd->vcur.gamma = 0;
162 sd->vcur.hue = 0;
163 sd->vcur.saturation = 0;
164 sd->vcur.whitebal = 0;
165
166 sd->vmax.backlight = 0;
167 sd->vmax.brightness = 255;
168 sd->vmax.sharpness = 0;
169 sd->vmax.contrast = 0;
170 sd->vmax.gamma = 0;
171 sd->vmax.hue = 0 + 1;
172 sd->vmax.saturation = 0;
173 sd->vmax.whitebal = 0;
174 sd->vmax.mirror = 0;
175 sd->vmax.flip = 0;
176 sd->vmax.AC50Hz = 0;
177
178 sd->dev_camera_settings = ov9655_camera_settings;
179 sd->dev_init_at_startup = ov9655_init_at_startup;
180 sd->dev_configure_alt = ov9655_configure_alt;
181 sd->dev_init_pre_alt = ov9655_init_pre_alt;
182 sd->dev_post_unset_alt = ov9655_post_unset_alt;
183}
184
185/*==========================================================================*/
186
187static int ov9655_init_at_startup(struct gspca_dev *gspca_dev)
188{
189 fetch_validx(gspca_dev, tbl_init_at_startup,
190 ARRAY_SIZE(tbl_init_at_startup));
191 fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
192/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL);*/
193
194 return 0;
195}
196
197static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev)
198{
199 struct sd *sd = (struct sd *) gspca_dev;
200
201 sd->vold.brightness = -1;
202 sd->vold.hue = -1;
203
204 fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
205
206 ov9655_init_post_alt(gspca_dev);
207
208 return 0;
209}
210
211static int ov9655_init_post_alt(struct gspca_dev *gspca_dev)
212{
213 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
214 s32 n; /* reserved for FETCH functions */
215 s32 i;
216 u8 **tbl;
217
218 ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
219
220 tbl = (reso == IMAGE_640) ? tbl_640 : tbl_1280;
221
222 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
223 tbl_length[0], tbl[0]);
224 for (i = 1; i < 7; i++)
225 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200,
226 tbl_length[i], tbl[i]);
227 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
228 tbl_length[7], tbl[7]);
229
230 n = fetch_validx(gspca_dev, tbl_init_post_alt,
231 ARRAY_SIZE(tbl_init_post_alt));
232
233 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
234 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
235 ARRAY_SIZE(tbl_init_post_alt), n);
236 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
237 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
238 ARRAY_SIZE(tbl_init_post_alt), n);
239 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
240 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
241 ARRAY_SIZE(tbl_init_post_alt), n);
242 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
243 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
244 ARRAY_SIZE(tbl_init_post_alt), n);
245 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
246 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
247 ARRAY_SIZE(tbl_init_post_alt), n);
248
249 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
250 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
251 ARRAY_SIZE(tbl_init_post_alt), n);
252 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
253 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
254 ARRAY_SIZE(tbl_init_post_alt), n);
255 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
256 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
257 ARRAY_SIZE(tbl_init_post_alt), n);
258 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
259 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
260 ARRAY_SIZE(tbl_init_post_alt), n);
261 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
262 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
263 ARRAY_SIZE(tbl_init_post_alt), n);
264
265 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
266 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
267 ARRAY_SIZE(tbl_init_post_alt), n);
268 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
269 keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
270 ARRAY_SIZE(tbl_init_post_alt), n);
271
272 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
273
274 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2);
275 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3);
276
277 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4);
278 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5);
279
280 ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6);
281 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7);
282
283 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8);
284
285 ov9655_camera_settings(gspca_dev);
286
287 return 0;
288}
289
290static int ov9655_configure_alt(struct gspca_dev *gspca_dev)
291{
292 s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
293
294 switch (reso) {
295 case IMAGE_640:
296 gspca_dev->alt = 1 + 1;
297 break;
298
299 default:
300 gspca_dev->alt = 1 + 1;
301 break;
302 }
303 return 0;
304}
305
306static int ov9655_camera_settings(struct gspca_dev *gspca_dev)
307{
308 struct sd *sd = (struct sd *) gspca_dev;
309
310 u8 dat_bright[] = "\x04\x00\x10\x7c\xa1\x00\x00\x70";
311
312 s32 bright = sd->vcur.brightness;
313 s32 hue = sd->vcur.hue;
314
315 if (bright != sd->vold.brightness) {
316 sd->vold.brightness = bright;
317 if (bright < 0 || bright > sd->vmax.brightness)
318 bright = 0;
319
320 dat_bright[3] = bright;
321 ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_bright);
322 }
323
324 if (hue != sd->vold.hue) {
325 sd->vold.hue = hue;
326 sd->swapRB = (hue != 0);
327 }
328
329 return 0;
330}
331
332static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev)
333{
334 ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
335 ctrl_out(gspca_dev, 0x40, 1, 0x0061, 0x0000, 0, NULL);
336}
diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c
new file mode 100644
index 00000000000..ced3b71f14e
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/gl860.c
@@ -0,0 +1,725 @@
1/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
2 * Subdriver core
3 *
4 * 2009/09/24 Olivier Lorin <o.lorin@laposte.net>
5 * GSPCA by Jean-Francois Moine <http://moinejf.free.fr>
6 * Thanks BUGabundo and Malmostoso for your amazing help!
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, see <http://www.gnu.org/licenses/>.
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include "gspca.h"
25#include "gl860.h"
26
27MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>");
28MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver");
29MODULE_LICENSE("GPL");
30
31/*======================== static function declarations ====================*/
32
33static void (*dev_init_settings)(struct gspca_dev *gspca_dev);
34
35static int sd_config(struct gspca_dev *gspca_dev,
36 const struct usb_device_id *id);
37static int sd_init(struct gspca_dev *gspca_dev);
38static int sd_isoc_init(struct gspca_dev *gspca_dev);
39static int sd_start(struct gspca_dev *gspca_dev);
40static void sd_stop0(struct gspca_dev *gspca_dev);
41static void sd_pkt_scan(struct gspca_dev *gspca_dev,
42 u8 *data, int len);
43static void sd_callback(struct gspca_dev *gspca_dev);
44
45static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
46 u16 vendor_id, u16 product_id);
47
48/*============================ driver options ==============================*/
49
50static s32 AC50Hz = 0xff;
51module_param(AC50Hz, int, 0644);
52MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)");
53
54static char sensor[7];
55module_param_string(sensor, sensor, sizeof(sensor), 0644);
56MODULE_PARM_DESC(sensor,
57 " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')");
58
59/*============================ webcam controls =============================*/
60
61/* Functions to get and set a control value */
62#define SD_SETGET(thename) \
63static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\
64{\
65 struct sd *sd = (struct sd *) gspca_dev;\
66\
67 sd->vcur.thename = val;\
68 if (gspca_dev->streaming)\
69 sd->waitSet = 1;\
70 return 0;\
71} \
72static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\
73{\
74 struct sd *sd = (struct sd *) gspca_dev;\
75\
76 *val = sd->vcur.thename;\
77 return 0;\
78}
79
80SD_SETGET(mirror)
81SD_SETGET(flip)
82SD_SETGET(AC50Hz)
83SD_SETGET(backlight)
84SD_SETGET(brightness)
85SD_SETGET(gamma)
86SD_SETGET(hue)
87SD_SETGET(saturation)
88SD_SETGET(sharpness)
89SD_SETGET(whitebal)
90SD_SETGET(contrast)
91
92#define GL860_NCTRLS 11
93
94/* control table */
95static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS];
96static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS];
97static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS];
98static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS];
99
100#define SET_MY_CTRL(theid, \
101 thetype, thelabel, thename) \
102 if (sd->vmax.thename != 0) {\
103 sd_ctrls[nCtrls].qctrl.id = theid;\
104 sd_ctrls[nCtrls].qctrl.type = thetype;\
105 strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\
106 sd_ctrls[nCtrls].qctrl.minimum = 0;\
107 sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\
108 sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\
109 sd_ctrls[nCtrls].qctrl.step = \
110 (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\
111 sd_ctrls[nCtrls].set = sd_set_##thename;\
112 sd_ctrls[nCtrls].get = sd_get_##thename;\
113 nCtrls++;\
114 }
115
116static int gl860_build_control_table(struct gspca_dev *gspca_dev)
117{
118 struct sd *sd = (struct sd *) gspca_dev;
119 struct ctrl *sd_ctrls;
120 int nCtrls = 0;
121
122 if (_MI1320_)
123 sd_ctrls = sd_ctrls_mi1320;
124 else if (_MI2020_)
125 sd_ctrls = sd_ctrls_mi2020;
126 else if (_OV2640_)
127 sd_ctrls = sd_ctrls_ov2640;
128 else if (_OV9655_)
129 sd_ctrls = sd_ctrls_ov9655;
130 else
131 return 0;
132
133 memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl));
134
135 SET_MY_CTRL(V4L2_CID_BRIGHTNESS,
136 V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness)
137 SET_MY_CTRL(V4L2_CID_SHARPNESS,
138 V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness)
139 SET_MY_CTRL(V4L2_CID_CONTRAST,
140 V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast)
141 SET_MY_CTRL(V4L2_CID_GAMMA,
142 V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma)
143 SET_MY_CTRL(V4L2_CID_HUE,
144 V4L2_CTRL_TYPE_INTEGER, "Palette", hue)
145 SET_MY_CTRL(V4L2_CID_SATURATION,
146 V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation)
147 SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE,
148 V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal)
149 SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION,
150 V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight)
151
152 SET_MY_CTRL(V4L2_CID_HFLIP,
153 V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror)
154 SET_MY_CTRL(V4L2_CID_VFLIP,
155 V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip)
156 SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY,
157 V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz)
158
159 return nCtrls;
160}
161
162/*==================== sud-driver structure initialisation =================*/
163
164static const struct sd_desc sd_desc_mi1320 = {
165 .name = MODULE_NAME,
166 .ctrls = sd_ctrls_mi1320,
167 .nctrls = GL860_NCTRLS,
168 .config = sd_config,
169 .init = sd_init,
170 .isoc_init = sd_isoc_init,
171 .start = sd_start,
172 .stop0 = sd_stop0,
173 .pkt_scan = sd_pkt_scan,
174 .dq_callback = sd_callback,
175};
176
177static const struct sd_desc sd_desc_mi2020 = {
178 .name = MODULE_NAME,
179 .ctrls = sd_ctrls_mi2020,
180 .nctrls = GL860_NCTRLS,
181 .config = sd_config,
182 .init = sd_init,
183 .isoc_init = sd_isoc_init,
184 .start = sd_start,
185 .stop0 = sd_stop0,
186 .pkt_scan = sd_pkt_scan,
187 .dq_callback = sd_callback,
188};
189
190static const struct sd_desc sd_desc_ov2640 = {
191 .name = MODULE_NAME,
192 .ctrls = sd_ctrls_ov2640,
193 .nctrls = GL860_NCTRLS,
194 .config = sd_config,
195 .init = sd_init,
196 .isoc_init = sd_isoc_init,
197 .start = sd_start,
198 .stop0 = sd_stop0,
199 .pkt_scan = sd_pkt_scan,
200 .dq_callback = sd_callback,
201};
202
203static const struct sd_desc sd_desc_ov9655 = {
204 .name = MODULE_NAME,
205 .ctrls = sd_ctrls_ov9655,
206 .nctrls = GL860_NCTRLS,
207 .config = sd_config,
208 .init = sd_init,
209 .isoc_init = sd_isoc_init,
210 .start = sd_start,
211 .stop0 = sd_stop0,
212 .pkt_scan = sd_pkt_scan,
213 .dq_callback = sd_callback,
214};
215
216/*=========================== sub-driver image sizes =======================*/
217
218static struct v4l2_pix_format mi2020_mode[] = {
219 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
220 .bytesperline = 640,
221 .sizeimage = 640 * 480,
222 .colorspace = V4L2_COLORSPACE_SRGB,
223 .priv = 0
224 },
225 { 800, 598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
226 .bytesperline = 800,
227 .sizeimage = 800 * 598,
228 .colorspace = V4L2_COLORSPACE_SRGB,
229 .priv = 1
230 },
231 {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
232 .bytesperline = 1280,
233 .sizeimage = 1280 * 1024,
234 .colorspace = V4L2_COLORSPACE_SRGB,
235 .priv = 2
236 },
237 {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
238 .bytesperline = 1600,
239 .sizeimage = 1600 * 1198,
240 .colorspace = V4L2_COLORSPACE_SRGB,
241 .priv = 3
242 },
243};
244
245static struct v4l2_pix_format ov2640_mode[] = {
246 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
247 .bytesperline = 640,
248 .sizeimage = 640 * 480,
249 .colorspace = V4L2_COLORSPACE_SRGB,
250 .priv = 0
251 },
252 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
253 .bytesperline = 800,
254 .sizeimage = 800 * 600,
255 .colorspace = V4L2_COLORSPACE_SRGB,
256 .priv = 1
257 },
258 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
259 .bytesperline = 1280,
260 .sizeimage = 1280 * 960,
261 .colorspace = V4L2_COLORSPACE_SRGB,
262 .priv = 2
263 },
264 {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
265 .bytesperline = 1600,
266 .sizeimage = 1600 * 1200,
267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 3
269 },
270};
271
272static struct v4l2_pix_format mi1320_mode[] = {
273 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
274 .bytesperline = 640,
275 .sizeimage = 640 * 480,
276 .colorspace = V4L2_COLORSPACE_SRGB,
277 .priv = 0
278 },
279 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
280 .bytesperline = 800,
281 .sizeimage = 800 * 600,
282 .colorspace = V4L2_COLORSPACE_SRGB,
283 .priv = 1
284 },
285 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
286 .bytesperline = 1280,
287 .sizeimage = 1280 * 960,
288 .colorspace = V4L2_COLORSPACE_SRGB,
289 .priv = 2
290 },
291};
292
293static struct v4l2_pix_format ov9655_mode[] = {
294 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
295 .bytesperline = 640,
296 .sizeimage = 640 * 480,
297 .colorspace = V4L2_COLORSPACE_SRGB,
298 .priv = 0
299 },
300 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
301 .bytesperline = 1280,
302 .sizeimage = 1280 * 960,
303 .colorspace = V4L2_COLORSPACE_SRGB,
304 .priv = 1
305 },
306};
307
308/*========================= sud-driver functions ===========================*/
309
310/* This function is called at probe time */
311static int sd_config(struct gspca_dev *gspca_dev,
312 const struct usb_device_id *id)
313{
314 struct sd *sd = (struct sd *) gspca_dev;
315 struct cam *cam;
316 u16 vendor_id, product_id;
317
318 /* Get USB VendorID and ProductID */
319 vendor_id = id->idVendor;
320 product_id = id->idProduct;
321
322 sd->nbRightUp = 1;
323 sd->nbIm = -1;
324
325 sd->sensor = 0xff;
326 if (strcmp(sensor, "MI1320") == 0)
327 sd->sensor = ID_MI1320;
328 else if (strcmp(sensor, "OV2640") == 0)
329 sd->sensor = ID_OV2640;
330 else if (strcmp(sensor, "OV9655") == 0)
331 sd->sensor = ID_OV9655;
332 else if (strcmp(sensor, "MI2020") == 0)
333 sd->sensor = ID_MI2020;
334
335 /* Get sensor and set the suitable init/start/../stop functions */
336 if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1)
337 return -1;
338
339 cam = &gspca_dev->cam;
340
341 switch (sd->sensor) {
342 case ID_MI1320:
343 gspca_dev->sd_desc = &sd_desc_mi1320;
344 cam->cam_mode = mi1320_mode;
345 cam->nmodes = ARRAY_SIZE(mi1320_mode);
346 dev_init_settings = mi1320_init_settings;
347 break;
348
349 case ID_MI2020:
350 gspca_dev->sd_desc = &sd_desc_mi2020;
351 cam->cam_mode = mi2020_mode;
352 cam->nmodes = ARRAY_SIZE(mi2020_mode);
353 dev_init_settings = mi2020_init_settings;
354 break;
355
356 case ID_OV2640:
357 gspca_dev->sd_desc = &sd_desc_ov2640;
358 cam->cam_mode = ov2640_mode;
359 cam->nmodes = ARRAY_SIZE(ov2640_mode);
360 dev_init_settings = ov2640_init_settings;
361 break;
362
363 case ID_OV9655:
364 gspca_dev->sd_desc = &sd_desc_ov9655;
365 cam->cam_mode = ov9655_mode;
366 cam->nmodes = ARRAY_SIZE(ov9655_mode);
367 dev_init_settings = ov9655_init_settings;
368 break;
369 }
370
371 dev_init_settings(gspca_dev);
372 if (AC50Hz != 0xff)
373 ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
374 gl860_build_control_table(gspca_dev);
375
376 return 0;
377}
378
379/* This function is called at probe time after sd_config */
380static int sd_init(struct gspca_dev *gspca_dev)
381{
382 struct sd *sd = (struct sd *) gspca_dev;
383
384 return sd->dev_init_at_startup(gspca_dev);
385}
386
387/* This function is called before to choose the alt setting */
388static int sd_isoc_init(struct gspca_dev *gspca_dev)
389{
390 struct sd *sd = (struct sd *) gspca_dev;
391
392 return sd->dev_configure_alt(gspca_dev);
393}
394
395/* This function is called to start the webcam */
396static int sd_start(struct gspca_dev *gspca_dev)
397{
398 struct sd *sd = (struct sd *) gspca_dev;
399
400 return sd->dev_init_pre_alt(gspca_dev);
401}
402
403/* This function is called to stop the webcam */
404static void sd_stop0(struct gspca_dev *gspca_dev)
405{
406 struct sd *sd = (struct sd *) gspca_dev;
407
408 if (!sd->gspca_dev.present)
409 return;
410
411 return sd->dev_post_unset_alt(gspca_dev);
412}
413
414/* This function is called when an image is being received */
415static void sd_pkt_scan(struct gspca_dev *gspca_dev,
416 u8 *data, int len)
417{
418 struct sd *sd = (struct sd *) gspca_dev;
419 static s32 nSkipped;
420
421 s32 mode = (s32) gspca_dev->curr_mode;
422 s32 nToSkip =
423 sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
424
425 /* Test only against 0202h, so endianess does not matter */
426 switch (*(s16 *) data) {
427 case 0x0202: /* End of frame, start a new one */
428 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
429 nSkipped = 0;
430 if (sd->nbIm >= 0 && sd->nbIm < 10)
431 sd->nbIm++;
432 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
433 break;
434
435 default:
436 data += 2;
437 len -= 2;
438 if (nSkipped + len <= nToSkip)
439 nSkipped += len;
440 else {
441 if (nSkipped < nToSkip && nSkipped + len > nToSkip) {
442 data += nToSkip - nSkipped;
443 len -= nToSkip - nSkipped;
444 nSkipped = nToSkip + 1;
445 }
446 gspca_frame_add(gspca_dev,
447 INTER_PACKET, data, len);
448 }
449 break;
450 }
451}
452
453/* This function is called when an image has been read */
454/* This function is used to monitor webcam orientation */
455static void sd_callback(struct gspca_dev *gspca_dev)
456{
457 struct sd *sd = (struct sd *) gspca_dev;
458
459 if (!_OV9655_) {
460 u8 state;
461 u8 upsideDown;
462
463 /* Probe sensor orientation */
464 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);
465
466 /* C8/40 means upside-down (looking backwards) */
467 /* D8/50 means right-up (looking onwards) */
468 upsideDown = (state == 0xc8 || state == 0x40);
469
470 if (upsideDown && sd->nbRightUp > -4) {
471 if (sd->nbRightUp > 0)
472 sd->nbRightUp = 0;
473 if (sd->nbRightUp == -3) {
474 sd->mirrorMask = 1;
475 sd->waitSet = 1;
476 }
477 sd->nbRightUp--;
478 }
479 if (!upsideDown && sd->nbRightUp < 4) {
480 if (sd->nbRightUp < 0)
481 sd->nbRightUp = 0;
482 if (sd->nbRightUp == 3) {
483 sd->mirrorMask = 0;
484 sd->waitSet = 1;
485 }
486 sd->nbRightUp++;
487 }
488 }
489
490 if (sd->waitSet)
491 sd->dev_camera_settings(gspca_dev);
492}
493
494/*=================== USB driver structure initialisation ==================*/
495
496static const struct usb_device_id device_table[] = {
497 {USB_DEVICE(0x05e3, 0x0503)},
498 {USB_DEVICE(0x05e3, 0xf191)},
499 {}
500};
501
502MODULE_DEVICE_TABLE(usb, device_table);
503
504static int sd_probe(struct usb_interface *intf,
505 const struct usb_device_id *id)
506{
507 return gspca_dev_probe(intf, id,
508 &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE);
509}
510
511static void sd_disconnect(struct usb_interface *intf)
512{
513 gspca_disconnect(intf);
514}
515
516static struct usb_driver sd_driver = {
517 .name = MODULE_NAME,
518 .id_table = device_table,
519 .probe = sd_probe,
520 .disconnect = sd_disconnect,
521#ifdef CONFIG_PM
522 .suspend = gspca_suspend,
523 .resume = gspca_resume,
524 .reset_resume = gspca_resume,
525#endif
526};
527
528/*====================== Init and Exit module functions ====================*/
529
530module_usb_driver(sd_driver);
531
532/*==========================================================================*/
533
534int gl860_RTx(struct gspca_dev *gspca_dev,
535 unsigned char pref, u32 req, u16 val, u16 index,
536 s32 len, void *pdata)
537{
538 struct usb_device *udev = gspca_dev->dev;
539 s32 r = 0;
540
541 if (pref == 0x40) { /* Send */
542 if (len > 0) {
543 memcpy(gspca_dev->usb_buf, pdata, len);
544 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
545 req, pref, val, index,
546 gspca_dev->usb_buf,
547 len, 400 + 200 * (len > 1));
548 } else {
549 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
550 req, pref, val, index, NULL, len, 400);
551 }
552 } else { /* Receive */
553 if (len > 0) {
554 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
555 req, pref, val, index,
556 gspca_dev->usb_buf,
557 len, 400 + 200 * (len > 1));
558 memcpy(pdata, gspca_dev->usb_buf, len);
559 } else {
560 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
561 req, pref, val, index, NULL, len, 400);
562 }
563 }
564
565 if (r < 0)
566 pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
567 r, pref, req, val, index, len);
568 else if (len > 1 && r < len)
569 PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
570
571 msleep(1);
572
573 return r;
574}
575
576int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len)
577{
578 int n;
579
580 for (n = 0; n < len; n++) {
581 if (tbl[n].idx != 0xffff)
582 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val,
583 tbl[n].idx, 0, NULL);
584 else if (tbl[n].val == 0xffff)
585 break;
586 else
587 msleep(tbl[n].val);
588 }
589 return n;
590}
591
592int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
593 int len, int n)
594{
595 while (++n < len) {
596 if (tbl[n].idx != 0xffff)
597 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx,
598 0, NULL);
599 else if (tbl[n].val == 0xffff)
600 break;
601 else
602 msleep(tbl[n].val);
603 }
604 return n;
605}
606
607void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len)
608{
609 int n;
610
611 for (n = 0; n < len; n++) {
612 if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0)
613 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx,
614 3, tbl[n].data);
615 else
616 msleep(tbl[n].idx);
617 }
618}
619
620static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
621 u16 vendor_id, u16 product_id)
622{
623 struct sd *sd = (struct sd *) gspca_dev;
624 u8 probe, nb26, nb96, nOV, ntry;
625
626 if (product_id == 0xf191)
627 sd->sensor = ID_MI1320;
628
629 if (sd->sensor == 0xff) {
630 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
631 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
632
633 ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
634 msleep(3);
635 ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
636 msleep(3);
637 ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
638 msleep(3);
639 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
640 msleep(3);
641 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
642 msleep(3);
643 ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
644 msleep(3);
645 ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
646 msleep(56);
647
648 PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX");
649 nOV = 0;
650 for (ntry = 0; ntry < 4; ntry++) {
651 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
652 msleep(3);
653 ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
654 msleep(3);
655 ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
656 msleep(10);
657 ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
658 PDEBUG(D_PROBE, "probe=0x%02x", probe);
659 if (probe == 0xff)
660 nOV++;
661 }
662
663 if (nOV) {
664 PDEBUG(D_PROBE, "0xff -> OVXXXX");
665 PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655");
666
667 nb26 = nb96 = 0;
668 for (ntry = 0; ntry < 4; ntry++) {
669 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
670 0, NULL);
671 msleep(3);
672 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
673 0, NULL);
674 msleep(10);
675
676 /* Wait for 26(OV2640) or 96(OV9655) */
677 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
678 1, &probe);
679
680 if (probe == 0x26 || probe == 0x40) {
681 PDEBUG(D_PROBE,
682 "probe=0x%02x -> OV2640",
683 probe);
684 sd->sensor = ID_OV2640;
685 nb26 += 4;
686 break;
687 }
688 if (probe == 0x96 || probe == 0x55) {
689 PDEBUG(D_PROBE,
690 "probe=0x%02x -> OV9655",
691 probe);
692 sd->sensor = ID_OV9655;
693 nb96 += 4;
694 break;
695 }
696 PDEBUG(D_PROBE, "probe=0x%02x", probe);
697 if (probe == 0x00)
698 nb26++;
699 if (probe == 0xff)
700 nb96++;
701 msleep(3);
702 }
703 if (nb26 < 4 && nb96 < 4)
704 return -1;
705 } else {
706 PDEBUG(D_PROBE, "Not any 0xff -> MI2020");
707 sd->sensor = ID_MI2020;
708 }
709 }
710
711 if (_MI1320_) {
712 PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)");
713 } else if (_MI2020_) {
714 PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)");
715 } else if (_OV9655_) {
716 PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)");
717 } else if (_OV2640_) {
718 PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)");
719 } else {
720 PDEBUG(D_PROBE, "***** Unknown sensor *****");
721 return -1;
722 }
723
724 return 0;
725}
diff --git a/drivers/media/usb/gspca/gl860/gl860.h b/drivers/media/usb/gspca/gl860/gl860.h
new file mode 100644
index 00000000000..0330a0293b9
--- /dev/null
+++ b/drivers/media/usb/gspca/gl860/gl860.h
@@ -0,0 +1,105 @@
1/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
2 * Subdriver declarations
3 *
4 * 2009/10/14 Olivier LORIN <o.lorin@laposte.net>
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, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef GL860_DEV_H
20#define GL860_DEV_H
21
22#include "gspca.h"
23
24#define MODULE_NAME "gspca_gl860"
25#define DRIVER_VERSION "0.9d10"
26
27#define ctrl_in gl860_RTx
28#define ctrl_out gl860_RTx
29
30#define ID_MI1320 1
31#define ID_OV2640 2
32#define ID_OV9655 4
33#define ID_MI2020 8
34
35#define _MI1320_ (((struct sd *) gspca_dev)->sensor == ID_MI1320)
36#define _MI2020_ (((struct sd *) gspca_dev)->sensor == ID_MI2020)
37#define _OV2640_ (((struct sd *) gspca_dev)->sensor == ID_OV2640)
38#define _OV9655_ (((struct sd *) gspca_dev)->sensor == ID_OV9655)
39
40#define IMAGE_640 0
41#define IMAGE_800 1
42#define IMAGE_1280 2
43#define IMAGE_1600 3
44
45struct sd_gl860 {
46 u16 backlight;
47 u16 brightness;
48 u16 sharpness;
49 u16 contrast;
50 u16 gamma;
51 u16 hue;
52 u16 saturation;
53 u16 whitebal;
54 u8 mirror;
55 u8 flip;
56 u8 AC50Hz;
57};
58
59/* Specific webcam descriptor */
60struct sd {
61 struct gspca_dev gspca_dev; /* !! must be the first item */
62
63 struct sd_gl860 vcur;
64 struct sd_gl860 vold;
65 struct sd_gl860 vmax;
66
67 int (*dev_configure_alt) (struct gspca_dev *);
68 int (*dev_init_at_startup)(struct gspca_dev *);
69 int (*dev_init_pre_alt) (struct gspca_dev *);
70 void (*dev_post_unset_alt) (struct gspca_dev *);
71 int (*dev_camera_settings)(struct gspca_dev *);
72
73 u8 swapRB;
74 u8 mirrorMask;
75 u8 sensor;
76 s32 nbIm;
77 s32 nbRightUp;
78 u8 waitSet;
79};
80
81struct validx {
82 u16 val;
83 u16 idx;
84};
85
86struct idxdata {
87 u8 idx;
88 u8 data[3];
89};
90
91int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len);
92int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
93 int len, int n);
94void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len);
95
96int gl860_RTx(struct gspca_dev *gspca_dev,
97 unsigned char pref, u32 req, u16 val, u16 index,
98 s32 len, void *pdata);
99
100void mi1320_init_settings(struct gspca_dev *);
101void ov2640_init_settings(struct gspca_dev *);
102void ov9655_init_settings(struct gspca_dev *);
103void mi2020_init_settings(struct gspca_dev *);
104
105#endif
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
new file mode 100644
index 00000000000..d4e8343f5b1
--- /dev/null
+++ b/drivers/media/usb/gspca/gspca.c
@@ -0,0 +1,2456 @@
1/*
2 * Main USB camera driver
3 *
4 * Copyright (C) 2008-2011 Jean-François Moine <http://moinejf.free.fr>
5 *
6 * Camera button input handling by Márton Németh
7 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * 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 Foundation,
21 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
26#define GSPCA_VERSION "2.14.0"
27
28#include <linux/init.h>
29#include <linux/fs.h>
30#include <linux/vmalloc.h>
31#include <linux/sched.h>
32#include <linux/slab.h>
33#include <linux/mm.h>
34#include <linux/string.h>
35#include <linux/pagemap.h>
36#include <linux/io.h>
37#include <asm/page.h>
38#include <linux/uaccess.h>
39#include <linux/ktime.h>
40#include <media/v4l2-ioctl.h>
41#include <media/v4l2-ctrls.h>
42#include <media/v4l2-fh.h>
43#include <media/v4l2-event.h>
44
45#include "gspca.h"
46
47#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
48#include <linux/input.h>
49#include <linux/usb/input.h>
50#endif
51
52/* global values */
53#define DEF_NURBS 3 /* default number of URBs */
54#if DEF_NURBS > MAX_NURBS
55#error "DEF_NURBS too big"
56#endif
57
58MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
59MODULE_DESCRIPTION("GSPCA USB Camera Driver");
60MODULE_LICENSE("GPL");
61MODULE_VERSION(GSPCA_VERSION);
62
63#ifdef GSPCA_DEBUG
64int gspca_debug = D_ERR | D_PROBE;
65EXPORT_SYMBOL(gspca_debug);
66
67static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
68{
69 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
70 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
71 txt,
72 pixfmt & 0xff,
73 (pixfmt >> 8) & 0xff,
74 (pixfmt >> 16) & 0xff,
75 pixfmt >> 24,
76 w, h);
77 } else {
78 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
79 txt,
80 pixfmt,
81 w, h);
82 }
83}
84#else
85#define PDEBUG_MODE(txt, pixfmt, w, h)
86#endif
87
88/* specific memory types - !! should be different from V4L2_MEMORY_xxx */
89#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
90#define GSPCA_MEMORY_READ 7
91
92#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
93
94/*
95 * VMA operations.
96 */
97static void gspca_vm_open(struct vm_area_struct *vma)
98{
99 struct gspca_frame *frame = vma->vm_private_data;
100
101 frame->vma_use_count++;
102 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
103}
104
105static void gspca_vm_close(struct vm_area_struct *vma)
106{
107 struct gspca_frame *frame = vma->vm_private_data;
108
109 if (--frame->vma_use_count <= 0)
110 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
111}
112
113static const struct vm_operations_struct gspca_vm_ops = {
114 .open = gspca_vm_open,
115 .close = gspca_vm_close,
116};
117
118/*
119 * Input and interrupt endpoint handling functions
120 */
121#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
122static void int_irq(struct urb *urb)
123{
124 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
125 int ret;
126
127 ret = urb->status;
128 switch (ret) {
129 case 0:
130 if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
131 urb->transfer_buffer, urb->actual_length) < 0) {
132 PDEBUG(D_ERR, "Unknown packet received");
133 }
134 break;
135
136 case -ENOENT:
137 case -ECONNRESET:
138 case -ENODEV:
139 case -ESHUTDOWN:
140 /* Stop is requested either by software or hardware is gone,
141 * keep the ret value non-zero and don't resubmit later.
142 */
143 break;
144
145 default:
146 PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
147 urb->status = 0;
148 ret = 0;
149 }
150
151 if (ret == 0) {
152 ret = usb_submit_urb(urb, GFP_ATOMIC);
153 if (ret < 0)
154 pr_err("Resubmit URB failed with error %i\n", ret);
155 }
156}
157
158static int gspca_input_connect(struct gspca_dev *dev)
159{
160 struct input_dev *input_dev;
161 int err = 0;
162
163 dev->input_dev = NULL;
164 if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) {
165 input_dev = input_allocate_device();
166 if (!input_dev)
167 return -ENOMEM;
168
169 usb_make_path(dev->dev, dev->phys, sizeof(dev->phys));
170 strlcat(dev->phys, "/input0", sizeof(dev->phys));
171
172 input_dev->name = dev->sd_desc->name;
173 input_dev->phys = dev->phys;
174
175 usb_to_input_id(dev->dev, &input_dev->id);
176
177 input_dev->evbit[0] = BIT_MASK(EV_KEY);
178 input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
179 input_dev->dev.parent = &dev->dev->dev;
180
181 err = input_register_device(input_dev);
182 if (err) {
183 pr_err("Input device registration failed with error %i\n",
184 err);
185 input_dev->dev.parent = NULL;
186 input_free_device(input_dev);
187 } else {
188 dev->input_dev = input_dev;
189 }
190 }
191
192 return err;
193}
194
195static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
196 struct usb_endpoint_descriptor *ep)
197{
198 unsigned int buffer_len;
199 int interval;
200 struct urb *urb;
201 struct usb_device *dev;
202 void *buffer = NULL;
203 int ret = -EINVAL;
204
205 buffer_len = le16_to_cpu(ep->wMaxPacketSize);
206 interval = ep->bInterval;
207 PDEBUG(D_CONF, "found int in endpoint: 0x%x, "
208 "buffer_len=%u, interval=%u",
209 ep->bEndpointAddress, buffer_len, interval);
210
211 dev = gspca_dev->dev;
212
213 urb = usb_alloc_urb(0, GFP_KERNEL);
214 if (!urb) {
215 ret = -ENOMEM;
216 goto error;
217 }
218
219 buffer = usb_alloc_coherent(dev, buffer_len,
220 GFP_KERNEL, &urb->transfer_dma);
221 if (!buffer) {
222 ret = -ENOMEM;
223 goto error_buffer;
224 }
225 usb_fill_int_urb(urb, dev,
226 usb_rcvintpipe(dev, ep->bEndpointAddress),
227 buffer, buffer_len,
228 int_irq, (void *)gspca_dev, interval);
229 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
230 ret = usb_submit_urb(urb, GFP_KERNEL);
231 if (ret < 0) {
232 PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
233 goto error_submit;
234 }
235 gspca_dev->int_urb = urb;
236 return ret;
237
238error_submit:
239 usb_free_coherent(dev,
240 urb->transfer_buffer_length,
241 urb->transfer_buffer,
242 urb->transfer_dma);
243error_buffer:
244 usb_free_urb(urb);
245error:
246 return ret;
247}
248
249static void gspca_input_create_urb(struct gspca_dev *gspca_dev)
250{
251 struct usb_interface *intf;
252 struct usb_host_interface *intf_desc;
253 struct usb_endpoint_descriptor *ep;
254 int i;
255
256 if (gspca_dev->sd_desc->int_pkt_scan) {
257 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
258 intf_desc = intf->cur_altsetting;
259 for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
260 ep = &intf_desc->endpoint[i].desc;
261 if (usb_endpoint_dir_in(ep) &&
262 usb_endpoint_xfer_int(ep)) {
263
264 alloc_and_submit_int_urb(gspca_dev, ep);
265 break;
266 }
267 }
268 }
269}
270
271static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
272{
273 struct urb *urb;
274
275 urb = gspca_dev->int_urb;
276 if (urb) {
277 gspca_dev->int_urb = NULL;
278 usb_kill_urb(urb);
279 usb_free_coherent(gspca_dev->dev,
280 urb->transfer_buffer_length,
281 urb->transfer_buffer,
282 urb->transfer_dma);
283 usb_free_urb(urb);
284 }
285}
286#else
287static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
288{
289}
290
291static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev)
292{
293}
294
295static inline int gspca_input_connect(struct gspca_dev *dev)
296{
297 return 0;
298}
299#endif
300
301/*
302 * fill a video frame from an URB and resubmit
303 */
304static void fill_frame(struct gspca_dev *gspca_dev,
305 struct urb *urb)
306{
307 u8 *data; /* address of data in the iso message */
308 int i, len, st;
309 cam_pkt_op pkt_scan;
310
311 if (urb->status != 0) {
312 if (urb->status == -ESHUTDOWN)
313 return; /* disconnection */
314#ifdef CONFIG_PM
315 if (gspca_dev->frozen)
316 return;
317#endif
318 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
319 urb->status = 0;
320 goto resubmit;
321 }
322 pkt_scan = gspca_dev->sd_desc->pkt_scan;
323 for (i = 0; i < urb->number_of_packets; i++) {
324 len = urb->iso_frame_desc[i].actual_length;
325
326 /* check the packet status and length */
327 st = urb->iso_frame_desc[i].status;
328 if (st) {
329 pr_err("ISOC data error: [%d] len=%d, status=%d\n",
330 i, len, st);
331 gspca_dev->last_packet_type = DISCARD_PACKET;
332 continue;
333 }
334 if (len == 0) {
335 if (gspca_dev->empty_packet == 0)
336 gspca_dev->empty_packet = 1;
337 continue;
338 }
339
340 /* let the packet be analyzed by the subdriver */
341 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
342 i, urb->iso_frame_desc[i].offset, len);
343 data = (u8 *) urb->transfer_buffer
344 + urb->iso_frame_desc[i].offset;
345 pkt_scan(gspca_dev, data, len);
346 }
347
348resubmit:
349 /* resubmit the URB */
350 st = usb_submit_urb(urb, GFP_ATOMIC);
351 if (st < 0)
352 pr_err("usb_submit_urb() ret %d\n", st);
353}
354
355/*
356 * ISOC message interrupt from the USB device
357 *
358 * Analyse each packet and call the subdriver for copy to the frame buffer.
359 */
360static void isoc_irq(struct urb *urb)
361{
362 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
363
364 PDEBUG(D_PACK, "isoc irq");
365 if (!gspca_dev->streaming)
366 return;
367 fill_frame(gspca_dev, urb);
368}
369
370/*
371 * bulk message interrupt from the USB device
372 */
373static void bulk_irq(struct urb *urb)
374{
375 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
376 int st;
377
378 PDEBUG(D_PACK, "bulk irq");
379 if (!gspca_dev->streaming)
380 return;
381 switch (urb->status) {
382 case 0:
383 break;
384 case -ESHUTDOWN:
385 return; /* disconnection */
386 default:
387#ifdef CONFIG_PM
388 if (gspca_dev->frozen)
389 return;
390#endif
391 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
392 urb->status = 0;
393 goto resubmit;
394 }
395
396 PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
397 gspca_dev->sd_desc->pkt_scan(gspca_dev,
398 urb->transfer_buffer,
399 urb->actual_length);
400
401resubmit:
402 /* resubmit the URB */
403 if (gspca_dev->cam.bulk_nurbs != 0) {
404 st = usb_submit_urb(urb, GFP_ATOMIC);
405 if (st < 0)
406 pr_err("usb_submit_urb() ret %d\n", st);
407 }
408}
409
410/*
411 * add data to the current frame
412 *
413 * This function is called by the subdrivers at interrupt level.
414 *
415 * To build a frame, these ones must add
416 * - one FIRST_PACKET
417 * - 0 or many INTER_PACKETs
418 * - one LAST_PACKET
419 * DISCARD_PACKET invalidates the whole frame.
420 */
421void gspca_frame_add(struct gspca_dev *gspca_dev,
422 enum gspca_packet_type packet_type,
423 const u8 *data,
424 int len)
425{
426 struct gspca_frame *frame;
427 int i, j;
428
429 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
430
431 if (packet_type == FIRST_PACKET) {
432 i = atomic_read(&gspca_dev->fr_i);
433
434 /* if there are no queued buffer, discard the whole frame */
435 if (i == atomic_read(&gspca_dev->fr_q)) {
436 gspca_dev->last_packet_type = DISCARD_PACKET;
437 gspca_dev->sequence++;
438 return;
439 }
440 j = gspca_dev->fr_queue[i];
441 frame = &gspca_dev->frame[j];
442 frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get());
443 frame->v4l2_buf.sequence = gspca_dev->sequence++;
444 gspca_dev->image = frame->data;
445 gspca_dev->image_len = 0;
446 } else {
447 switch (gspca_dev->last_packet_type) {
448 case DISCARD_PACKET:
449 if (packet_type == LAST_PACKET) {
450 gspca_dev->last_packet_type = packet_type;
451 gspca_dev->image = NULL;
452 gspca_dev->image_len = 0;
453 }
454 return;
455 case LAST_PACKET:
456 return;
457 }
458 }
459
460 /* append the packet to the frame buffer */
461 if (len > 0) {
462 if (gspca_dev->image_len + len > gspca_dev->frsz) {
463 PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
464 gspca_dev->image_len + len,
465 gspca_dev->frsz);
466 packet_type = DISCARD_PACKET;
467 } else {
468/* !! image is NULL only when last pkt is LAST or DISCARD
469 if (gspca_dev->image == NULL) {
470 pr_err("gspca_frame_add() image == NULL\n");
471 return;
472 }
473 */
474 memcpy(gspca_dev->image + gspca_dev->image_len,
475 data, len);
476 gspca_dev->image_len += len;
477 }
478 }
479 gspca_dev->last_packet_type = packet_type;
480
481 /* if last packet, invalidate packet concatenation until
482 * next first packet, wake up the application and advance
483 * in the queue */
484 if (packet_type == LAST_PACKET) {
485 i = atomic_read(&gspca_dev->fr_i);
486 j = gspca_dev->fr_queue[i];
487 frame = &gspca_dev->frame[j];
488 frame->v4l2_buf.bytesused = gspca_dev->image_len;
489 frame->v4l2_buf.flags = (frame->v4l2_buf.flags
490 | V4L2_BUF_FLAG_DONE)
491 & ~V4L2_BUF_FLAG_QUEUED;
492 i = (i + 1) % GSPCA_MAX_FRAMES;
493 atomic_set(&gspca_dev->fr_i, i);
494 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
495 PDEBUG(D_FRAM, "frame complete len:%d",
496 frame->v4l2_buf.bytesused);
497 gspca_dev->image = NULL;
498 gspca_dev->image_len = 0;
499 }
500}
501EXPORT_SYMBOL(gspca_frame_add);
502
503static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
504 enum v4l2_memory memory, unsigned int count)
505{
506 struct gspca_frame *frame;
507 unsigned int frsz;
508 int i;
509
510 i = gspca_dev->curr_mode;
511 frsz = gspca_dev->cam.cam_mode[i].sizeimage;
512 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
513 frsz = PAGE_ALIGN(frsz);
514 if (count >= GSPCA_MAX_FRAMES)
515 count = GSPCA_MAX_FRAMES - 1;
516 gspca_dev->frbuf = vmalloc_32(frsz * count);
517 if (!gspca_dev->frbuf) {
518 pr_err("frame alloc failed\n");
519 return -ENOMEM;
520 }
521 gspca_dev->capt_file = file;
522 gspca_dev->memory = memory;
523 gspca_dev->frsz = frsz;
524 gspca_dev->nframes = count;
525 for (i = 0; i < count; i++) {
526 frame = &gspca_dev->frame[i];
527 frame->v4l2_buf.index = i;
528 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
529 frame->v4l2_buf.flags = 0;
530 frame->v4l2_buf.field = V4L2_FIELD_NONE;
531 frame->v4l2_buf.length = frsz;
532 frame->v4l2_buf.memory = memory;
533 frame->v4l2_buf.sequence = 0;
534 frame->data = gspca_dev->frbuf + i * frsz;
535 frame->v4l2_buf.m.offset = i * frsz;
536 }
537 atomic_set(&gspca_dev->fr_q, 0);
538 atomic_set(&gspca_dev->fr_i, 0);
539 gspca_dev->fr_o = 0;
540 return 0;
541}
542
543static void frame_free(struct gspca_dev *gspca_dev)
544{
545 int i;
546
547 PDEBUG(D_STREAM, "frame free");
548 if (gspca_dev->frbuf != NULL) {
549 vfree(gspca_dev->frbuf);
550 gspca_dev->frbuf = NULL;
551 for (i = 0; i < gspca_dev->nframes; i++)
552 gspca_dev->frame[i].data = NULL;
553 }
554 gspca_dev->nframes = 0;
555 gspca_dev->frsz = 0;
556 gspca_dev->capt_file = NULL;
557 gspca_dev->memory = GSPCA_MEMORY_NO;
558}
559
560static void destroy_urbs(struct gspca_dev *gspca_dev)
561{
562 struct urb *urb;
563 unsigned int i;
564
565 PDEBUG(D_STREAM, "kill transfer");
566 for (i = 0; i < MAX_NURBS; i++) {
567 urb = gspca_dev->urb[i];
568 if (urb == NULL)
569 break;
570
571 gspca_dev->urb[i] = NULL;
572 usb_kill_urb(urb);
573 if (urb->transfer_buffer != NULL)
574 usb_free_coherent(gspca_dev->dev,
575 urb->transfer_buffer_length,
576 urb->transfer_buffer,
577 urb->transfer_dma);
578 usb_free_urb(urb);
579 }
580}
581
582static int gspca_set_alt0(struct gspca_dev *gspca_dev)
583{
584 int ret;
585
586 if (gspca_dev->alt == 0)
587 return 0;
588 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
589 if (ret < 0)
590 pr_err("set alt 0 err %d\n", ret);
591 return ret;
592}
593
594/* Note: both the queue and the usb locks should be held when calling this */
595static void gspca_stream_off(struct gspca_dev *gspca_dev)
596{
597 gspca_dev->streaming = 0;
598 gspca_dev->usb_err = 0;
599 if (gspca_dev->sd_desc->stopN)
600 gspca_dev->sd_desc->stopN(gspca_dev);
601 destroy_urbs(gspca_dev);
602 gspca_input_destroy_urb(gspca_dev);
603 gspca_set_alt0(gspca_dev);
604 gspca_input_create_urb(gspca_dev);
605 if (gspca_dev->sd_desc->stop0)
606 gspca_dev->sd_desc->stop0(gspca_dev);
607 PDEBUG(D_STREAM, "stream off OK");
608}
609
610/*
611 * look for an input transfer endpoint in an alternate setting
612 */
613static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
614 int xfer)
615{
616 struct usb_host_endpoint *ep;
617 int i, attr;
618
619 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
620 ep = &alt->endpoint[i];
621 attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
622 if (attr == xfer
623 && ep->desc.wMaxPacketSize != 0
624 && usb_endpoint_dir_in(&ep->desc))
625 return ep;
626 }
627 return NULL;
628}
629
630/* compute the minimum bandwidth for the current transfer */
631static u32 which_bandwidth(struct gspca_dev *gspca_dev)
632{
633 u32 bandwidth;
634 int i;
635
636 /* get the (max) image size */
637 i = gspca_dev->curr_mode;
638 bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
639
640 /* if the image is compressed, estimate its mean size */
641 if (!gspca_dev->cam.needs_full_bandwidth &&
642 bandwidth < gspca_dev->cam.cam_mode[i].width *
643 gspca_dev->cam.cam_mode[i].height)
644 bandwidth = bandwidth * 3 / 8; /* 0.375 */
645
646 /* estimate the frame rate */
647 if (gspca_dev->sd_desc->get_streamparm) {
648 struct v4l2_streamparm parm;
649
650 gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
651 bandwidth *= parm.parm.capture.timeperframe.denominator;
652 bandwidth /= parm.parm.capture.timeperframe.numerator;
653 } else {
654
655 /* don't hope more than 15 fps with USB 1.1 and
656 * image resolution >= 640x480 */
657 if (gspca_dev->width >= 640
658 && gspca_dev->dev->speed == USB_SPEED_FULL)
659 bandwidth *= 15; /* 15 fps */
660 else
661 bandwidth *= 30; /* 30 fps */
662 }
663
664 PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
665 return bandwidth;
666}
667
668/* endpoint table */
669#define MAX_ALT 16
670struct ep_tb_s {
671 u32 alt;
672 u32 bandwidth;
673};
674
675/*
676 * build the table of the endpoints
677 * and compute the minimum bandwidth for the image transfer
678 */
679static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
680 struct usb_interface *intf,
681 struct ep_tb_s *ep_tb)
682{
683 struct usb_host_endpoint *ep;
684 int i, j, nbalt, psize, found;
685 u32 bandwidth, last_bw;
686
687 nbalt = intf->num_altsetting;
688 if (nbalt > MAX_ALT)
689 nbalt = MAX_ALT; /* fixme: should warn */
690
691 /* build the endpoint table */
692 i = 0;
693 last_bw = 0;
694 for (;;) {
695 ep_tb->bandwidth = 2000 * 2000 * 120;
696 found = 0;
697 for (j = 0; j < nbalt; j++) {
698 ep = alt_xfer(&intf->altsetting[j],
699 USB_ENDPOINT_XFER_ISOC);
700 if (ep == NULL)
701 continue;
702 if (ep->desc.bInterval == 0) {
703 pr_err("alt %d iso endp with 0 interval\n", j);
704 continue;
705 }
706 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
707 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
708 bandwidth = psize * 1000;
709 if (gspca_dev->dev->speed == USB_SPEED_HIGH
710 || gspca_dev->dev->speed == USB_SPEED_SUPER)
711 bandwidth *= 8;
712 bandwidth /= 1 << (ep->desc.bInterval - 1);
713 if (bandwidth <= last_bw)
714 continue;
715 if (bandwidth < ep_tb->bandwidth) {
716 ep_tb->bandwidth = bandwidth;
717 ep_tb->alt = j;
718 found = 1;
719 }
720 }
721 if (!found)
722 break;
723 PDEBUG(D_STREAM, "alt %d bandwidth %d",
724 ep_tb->alt, ep_tb->bandwidth);
725 last_bw = ep_tb->bandwidth;
726 i++;
727 ep_tb++;
728 }
729
730 /*
731 * If the camera:
732 * has a usb audio class interface (a built in usb mic); and
733 * is a usb 1 full speed device; and
734 * uses the max full speed iso bandwidth; and
735 * and has more than 1 alt setting
736 * then skip the highest alt setting to spare bandwidth for the mic
737 */
738 if (gspca_dev->audio &&
739 gspca_dev->dev->speed == USB_SPEED_FULL &&
740 last_bw >= 1000000 &&
741 i > 1) {
742 PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt");
743 i--;
744 ep_tb--;
745 }
746
747 /* get the requested bandwidth and start at the highest atlsetting */
748 bandwidth = which_bandwidth(gspca_dev);
749 ep_tb--;
750 while (i > 1) {
751 ep_tb--;
752 if (ep_tb->bandwidth < bandwidth)
753 break;
754 i--;
755 }
756 return i;
757}
758
759/*
760 * create the URBs for image transfer
761 */
762static int create_urbs(struct gspca_dev *gspca_dev,
763 struct usb_host_endpoint *ep)
764{
765 struct urb *urb;
766 int n, nurbs, i, psize, npkt, bsize;
767
768 /* calculate the packet size and the number of packets */
769 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
770
771 if (!gspca_dev->cam.bulk) { /* isoc */
772
773 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
774 if (gspca_dev->pkt_size == 0)
775 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
776 else
777 psize = gspca_dev->pkt_size;
778 npkt = gspca_dev->cam.npkt;
779 if (npkt == 0)
780 npkt = 32; /* default value */
781 bsize = psize * npkt;
782 PDEBUG(D_STREAM,
783 "isoc %d pkts size %d = bsize:%d",
784 npkt, psize, bsize);
785 nurbs = DEF_NURBS;
786 } else { /* bulk */
787 npkt = 0;
788 bsize = gspca_dev->cam.bulk_size;
789 if (bsize == 0)
790 bsize = psize;
791 PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
792 if (gspca_dev->cam.bulk_nurbs != 0)
793 nurbs = gspca_dev->cam.bulk_nurbs;
794 else
795 nurbs = 1;
796 }
797
798 for (n = 0; n < nurbs; n++) {
799 urb = usb_alloc_urb(npkt, GFP_KERNEL);
800 if (!urb) {
801 pr_err("usb_alloc_urb failed\n");
802 return -ENOMEM;
803 }
804 gspca_dev->urb[n] = urb;
805 urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
806 bsize,
807 GFP_KERNEL,
808 &urb->transfer_dma);
809
810 if (urb->transfer_buffer == NULL) {
811 pr_err("usb_alloc_coherent failed\n");
812 return -ENOMEM;
813 }
814 urb->dev = gspca_dev->dev;
815 urb->context = gspca_dev;
816 urb->transfer_buffer_length = bsize;
817 if (npkt != 0) { /* ISOC */
818 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
819 ep->desc.bEndpointAddress);
820 urb->transfer_flags = URB_ISO_ASAP
821 | URB_NO_TRANSFER_DMA_MAP;
822 urb->interval = 1 << (ep->desc.bInterval - 1);
823 urb->complete = isoc_irq;
824 urb->number_of_packets = npkt;
825 for (i = 0; i < npkt; i++) {
826 urb->iso_frame_desc[i].length = psize;
827 urb->iso_frame_desc[i].offset = psize * i;
828 }
829 } else { /* bulk */
830 urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
831 ep->desc.bEndpointAddress);
832 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
833 urb->complete = bulk_irq;
834 }
835 }
836 return 0;
837}
838
839/*
840 * start the USB transfer
841 */
842static int gspca_init_transfer(struct gspca_dev *gspca_dev)
843{
844 struct usb_interface *intf;
845 struct usb_host_endpoint *ep;
846 struct urb *urb;
847 struct ep_tb_s ep_tb[MAX_ALT];
848 int n, ret, xfer, alt, alt_idx;
849
850 /* reset the streaming variables */
851 gspca_dev->image = NULL;
852 gspca_dev->image_len = 0;
853 gspca_dev->last_packet_type = DISCARD_PACKET;
854 gspca_dev->sequence = 0;
855
856 gspca_dev->usb_err = 0;
857
858 /* do the specific subdriver stuff before endpoint selection */
859 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
860 gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
861 if (gspca_dev->sd_desc->isoc_init) {
862 ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
863 if (ret < 0)
864 return ret;
865 }
866 xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
867 : USB_ENDPOINT_XFER_ISOC;
868
869 /* if bulk or the subdriver forced an altsetting, get the endpoint */
870 if (gspca_dev->alt != 0) {
871 gspca_dev->alt--; /* (previous version compatibility) */
872 ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
873 if (ep == NULL) {
874 pr_err("bad altsetting %d\n", gspca_dev->alt);
875 return -EIO;
876 }
877 ep_tb[0].alt = gspca_dev->alt;
878 alt_idx = 1;
879 } else {
880
881 /* else, compute the minimum bandwidth
882 * and build the endpoint table */
883 alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb);
884 if (alt_idx <= 0) {
885 pr_err("no transfer endpoint found\n");
886 return -EIO;
887 }
888 }
889
890 /* set the highest alternate setting and
891 * loop until urb submit succeeds */
892 gspca_input_destroy_urb(gspca_dev);
893
894 gspca_dev->alt = ep_tb[--alt_idx].alt;
895 alt = -1;
896 for (;;) {
897 if (alt != gspca_dev->alt) {
898 alt = gspca_dev->alt;
899 if (intf->num_altsetting > 1) {
900 ret = usb_set_interface(gspca_dev->dev,
901 gspca_dev->iface,
902 alt);
903 if (ret < 0) {
904 if (ret == -ENOSPC)
905 goto retry; /*fixme: ugly*/
906 pr_err("set alt %d err %d\n", alt, ret);
907 goto out;
908 }
909 }
910 }
911 if (!gspca_dev->cam.no_urb_create) {
912 PDEBUG(D_STREAM, "init transfer alt %d", alt);
913 ret = create_urbs(gspca_dev,
914 alt_xfer(&intf->altsetting[alt], xfer));
915 if (ret < 0) {
916 destroy_urbs(gspca_dev);
917 goto out;
918 }
919 }
920
921 /* clear the bulk endpoint */
922 if (gspca_dev->cam.bulk)
923 usb_clear_halt(gspca_dev->dev,
924 gspca_dev->urb[0]->pipe);
925
926 /* start the cam */
927 ret = gspca_dev->sd_desc->start(gspca_dev);
928 if (ret < 0) {
929 destroy_urbs(gspca_dev);
930 goto out;
931 }
932 gspca_dev->streaming = 1;
933 v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
934
935 /* some bulk transfers are started by the subdriver */
936 if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
937 break;
938
939 /* submit the URBs */
940 for (n = 0; n < MAX_NURBS; n++) {
941 urb = gspca_dev->urb[n];
942 if (urb == NULL)
943 break;
944 ret = usb_submit_urb(urb, GFP_KERNEL);
945 if (ret < 0)
946 break;
947 }
948 if (ret >= 0)
949 break; /* transfer is started */
950
951 /* something when wrong
952 * stop the webcam and free the transfer resources */
953 gspca_stream_off(gspca_dev);
954 if (ret != -ENOSPC) {
955 pr_err("usb_submit_urb alt %d err %d\n",
956 gspca_dev->alt, ret);
957 goto out;
958 }
959
960 /* the bandwidth is not wide enough
961 * negotiate or try a lower alternate setting */
962retry:
963 PDEBUG(D_ERR|D_STREAM,
964 "alt %d - bandwidth not wide enough - trying again",
965 alt);
966 msleep(20); /* wait for kill complete */
967 if (gspca_dev->sd_desc->isoc_nego) {
968 ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
969 if (ret < 0)
970 goto out;
971 } else {
972 if (alt_idx <= 0) {
973 pr_err("no transfer endpoint found\n");
974 ret = -EIO;
975 goto out;
976 }
977 gspca_dev->alt = ep_tb[--alt_idx].alt;
978 }
979 }
980out:
981 gspca_input_create_urb(gspca_dev);
982 return ret;
983}
984
985static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
986{
987 struct gspca_ctrl *ctrl;
988 int i;
989
990 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
991 gspca_dev->curr_mode = i;
992 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
993 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
994 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
995
996 /* set the current control values to their default values
997 * which may have changed in sd_init() */
998 /* does nothing if ctrl_handler == NULL */
999 v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
1000 ctrl = gspca_dev->cam.ctrls;
1001 if (ctrl != NULL) {
1002 for (i = 0;
1003 i < gspca_dev->sd_desc->nctrls;
1004 i++, ctrl++)
1005 ctrl->val = ctrl->def;
1006 }
1007}
1008
1009static int wxh_to_mode(struct gspca_dev *gspca_dev,
1010 int width, int height)
1011{
1012 int i;
1013
1014 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
1015 if (width >= gspca_dev->cam.cam_mode[i].width
1016 && height >= gspca_dev->cam.cam_mode[i].height)
1017 break;
1018 }
1019 return i;
1020}
1021
1022/*
1023 * search a mode with the right pixel format
1024 */
1025static int gspca_get_mode(struct gspca_dev *gspca_dev,
1026 int mode,
1027 int pixfmt)
1028{
1029 int modeU, modeD;
1030
1031 modeU = modeD = mode;
1032 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
1033 if (--modeD >= 0) {
1034 if (gspca_dev->cam.cam_mode[modeD].pixelformat
1035 == pixfmt)
1036 return modeD;
1037 }
1038 if (++modeU < gspca_dev->cam.nmodes) {
1039 if (gspca_dev->cam.cam_mode[modeU].pixelformat
1040 == pixfmt)
1041 return modeU;
1042 }
1043 }
1044 return -EINVAL;
1045}
1046
1047#ifdef CONFIG_VIDEO_ADV_DEBUG
1048static int vidioc_g_register(struct file *file, void *priv,
1049 struct v4l2_dbg_register *reg)
1050{
1051 struct gspca_dev *gspca_dev = video_drvdata(file);
1052
1053 gspca_dev->usb_err = 0;
1054 return gspca_dev->sd_desc->get_register(gspca_dev, reg);
1055}
1056
1057static int vidioc_s_register(struct file *file, void *priv,
1058 struct v4l2_dbg_register *reg)
1059{
1060 struct gspca_dev *gspca_dev = video_drvdata(file);
1061
1062 gspca_dev->usb_err = 0;
1063 return gspca_dev->sd_desc->set_register(gspca_dev, reg);
1064}
1065#endif
1066
1067static int vidioc_g_chip_ident(struct file *file, void *priv,
1068 struct v4l2_dbg_chip_ident *chip)
1069{
1070 struct gspca_dev *gspca_dev = video_drvdata(file);
1071
1072 gspca_dev->usb_err = 0;
1073 return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
1074}
1075
1076static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1077 struct v4l2_fmtdesc *fmtdesc)
1078{
1079 struct gspca_dev *gspca_dev = video_drvdata(file);
1080 int i, j, index;
1081 __u32 fmt_tb[8];
1082
1083 /* give an index to each format */
1084 index = 0;
1085 j = 0;
1086 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
1087 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
1088 j = 0;
1089 for (;;) {
1090 if (fmt_tb[j] == fmt_tb[index])
1091 break;
1092 j++;
1093 }
1094 if (j == index) {
1095 if (fmtdesc->index == index)
1096 break; /* new format */
1097 index++;
1098 if (index >= ARRAY_SIZE(fmt_tb))
1099 return -EINVAL;
1100 }
1101 }
1102 if (i < 0)
1103 return -EINVAL; /* no more format */
1104
1105 fmtdesc->pixelformat = fmt_tb[index];
1106 if (gspca_dev->cam.cam_mode[i].sizeimage <
1107 gspca_dev->cam.cam_mode[i].width *
1108 gspca_dev->cam.cam_mode[i].height)
1109 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
1110 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
1111 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
1112 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
1113 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
1114 fmtdesc->description[4] = '\0';
1115 return 0;
1116}
1117
1118static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1119 struct v4l2_format *fmt)
1120{
1121 struct gspca_dev *gspca_dev = video_drvdata(file);
1122 int mode;
1123
1124 mode = gspca_dev->curr_mode;
1125 fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
1126 /* some drivers use priv internally, zero it before giving it to
1127 userspace */
1128 fmt->fmt.pix.priv = 0;
1129 return 0;
1130}
1131
1132static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
1133 struct v4l2_format *fmt)
1134{
1135 int w, h, mode, mode2;
1136
1137 w = fmt->fmt.pix.width;
1138 h = fmt->fmt.pix.height;
1139
1140#ifdef GSPCA_DEBUG
1141 if (gspca_debug & D_CONF)
1142 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
1143#endif
1144 /* search the closest mode for width and height */
1145 mode = wxh_to_mode(gspca_dev, w, h);
1146
1147 /* OK if right palette */
1148 if (gspca_dev->cam.cam_mode[mode].pixelformat
1149 != fmt->fmt.pix.pixelformat) {
1150
1151 /* else, search the closest mode with the same pixel format */
1152 mode2 = gspca_get_mode(gspca_dev, mode,
1153 fmt->fmt.pix.pixelformat);
1154 if (mode2 >= 0)
1155 mode = mode2;
1156/* else
1157 ; * no chance, return this mode */
1158 }
1159 fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
1160 /* some drivers use priv internally, zero it before giving it to
1161 userspace */
1162 fmt->fmt.pix.priv = 0;
1163 return mode; /* used when s_fmt */
1164}
1165
1166static int vidioc_try_fmt_vid_cap(struct file *file,
1167 void *priv,
1168 struct v4l2_format *fmt)
1169{
1170 struct gspca_dev *gspca_dev = video_drvdata(file);
1171 int ret;
1172
1173 ret = try_fmt_vid_cap(gspca_dev, fmt);
1174 if (ret < 0)
1175 return ret;
1176 return 0;
1177}
1178
1179static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1180 struct v4l2_format *fmt)
1181{
1182 struct gspca_dev *gspca_dev = video_drvdata(file);
1183 int ret;
1184
1185 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1186 return -ERESTARTSYS;
1187
1188 ret = try_fmt_vid_cap(gspca_dev, fmt);
1189 if (ret < 0)
1190 goto out;
1191
1192 if (gspca_dev->nframes != 0
1193 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
1194 ret = -EINVAL;
1195 goto out;
1196 }
1197
1198 if (ret == gspca_dev->curr_mode) {
1199 ret = 0;
1200 goto out; /* same mode */
1201 }
1202
1203 if (gspca_dev->streaming) {
1204 ret = -EBUSY;
1205 goto out;
1206 }
1207 gspca_dev->width = fmt->fmt.pix.width;
1208 gspca_dev->height = fmt->fmt.pix.height;
1209 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
1210 gspca_dev->curr_mode = ret;
1211
1212 ret = 0;
1213out:
1214 mutex_unlock(&gspca_dev->queue_lock);
1215 return ret;
1216}
1217
1218static int vidioc_enum_framesizes(struct file *file, void *priv,
1219 struct v4l2_frmsizeenum *fsize)
1220{
1221 struct gspca_dev *gspca_dev = video_drvdata(file);
1222 int i;
1223 __u32 index = 0;
1224
1225 for (i = 0; i < gspca_dev->cam.nmodes; i++) {
1226 if (fsize->pixel_format !=
1227 gspca_dev->cam.cam_mode[i].pixelformat)
1228 continue;
1229
1230 if (fsize->index == index) {
1231 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1232 fsize->discrete.width =
1233 gspca_dev->cam.cam_mode[i].width;
1234 fsize->discrete.height =
1235 gspca_dev->cam.cam_mode[i].height;
1236 return 0;
1237 }
1238 index++;
1239 }
1240
1241 return -EINVAL;
1242}
1243
1244static int vidioc_enum_frameintervals(struct file *filp, void *priv,
1245 struct v4l2_frmivalenum *fival)
1246{
1247 struct gspca_dev *gspca_dev = video_drvdata(filp);
1248 int mode = wxh_to_mode(gspca_dev, fival->width, fival->height);
1249 __u32 i;
1250
1251 if (gspca_dev->cam.mode_framerates == NULL ||
1252 gspca_dev->cam.mode_framerates[mode].nrates == 0)
1253 return -EINVAL;
1254
1255 if (fival->pixel_format !=
1256 gspca_dev->cam.cam_mode[mode].pixelformat)
1257 return -EINVAL;
1258
1259 for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) {
1260 if (fival->index == i) {
1261 fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1262 fival->discrete.numerator = 1;
1263 fival->discrete.denominator =
1264 gspca_dev->cam.mode_framerates[mode].rates[i];
1265 return 0;
1266 }
1267 }
1268
1269 return -EINVAL;
1270}
1271
1272static void gspca_release(struct v4l2_device *v4l2_device)
1273{
1274 struct gspca_dev *gspca_dev =
1275 container_of(v4l2_device, struct gspca_dev, v4l2_dev);
1276
1277 v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
1278 v4l2_device_unregister(&gspca_dev->v4l2_dev);
1279 kfree(gspca_dev->usb_buf);
1280 kfree(gspca_dev);
1281}
1282
1283static int dev_open(struct file *file)
1284{
1285 struct gspca_dev *gspca_dev = video_drvdata(file);
1286
1287 PDEBUG(D_STREAM, "[%s] open", current->comm);
1288
1289 /* protect the subdriver against rmmod */
1290 if (!try_module_get(gspca_dev->module))
1291 return -ENODEV;
1292
1293#ifdef GSPCA_DEBUG
1294 /* activate the v4l2 debug */
1295 if (gspca_debug & D_V4L2)
1296 gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
1297 | V4L2_DEBUG_IOCTL_ARG;
1298 else
1299 gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
1300 | V4L2_DEBUG_IOCTL_ARG);
1301#endif
1302 return v4l2_fh_open(file);
1303}
1304
1305static int dev_close(struct file *file)
1306{
1307 struct gspca_dev *gspca_dev = video_drvdata(file);
1308
1309 PDEBUG(D_STREAM, "[%s] close", current->comm);
1310
1311 /* Needed for gspca_stream_off, always lock before queue_lock! */
1312 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1313 return -ERESTARTSYS;
1314
1315 if (mutex_lock_interruptible(&gspca_dev->queue_lock)) {
1316 mutex_unlock(&gspca_dev->usb_lock);
1317 return -ERESTARTSYS;
1318 }
1319
1320 /* if the file did the capture, free the streaming resources */
1321 if (gspca_dev->capt_file == file) {
1322 if (gspca_dev->streaming)
1323 gspca_stream_off(gspca_dev);
1324 frame_free(gspca_dev);
1325 }
1326 module_put(gspca_dev->module);
1327 mutex_unlock(&gspca_dev->queue_lock);
1328 mutex_unlock(&gspca_dev->usb_lock);
1329
1330 PDEBUG(D_STREAM, "close done");
1331
1332 return v4l2_fh_release(file);
1333}
1334
1335static int vidioc_querycap(struct file *file, void *priv,
1336 struct v4l2_capability *cap)
1337{
1338 struct gspca_dev *gspca_dev = video_drvdata(file);
1339
1340 strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
1341 sizeof cap->driver);
1342 if (gspca_dev->dev->product != NULL) {
1343 strlcpy((char *) cap->card, gspca_dev->dev->product,
1344 sizeof cap->card);
1345 } else {
1346 snprintf((char *) cap->card, sizeof cap->card,
1347 "USB Camera (%04x:%04x)",
1348 le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
1349 le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
1350 }
1351 usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
1352 sizeof(cap->bus_info));
1353 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
1354 | V4L2_CAP_STREAMING
1355 | V4L2_CAP_READWRITE;
1356 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
1357 return 0;
1358}
1359
1360static int get_ctrl(struct gspca_dev *gspca_dev,
1361 int id)
1362{
1363 const struct ctrl *ctrls;
1364 int i;
1365
1366 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1367 i < gspca_dev->sd_desc->nctrls;
1368 i++, ctrls++) {
1369 if (gspca_dev->ctrl_dis & (1 << i))
1370 continue;
1371 if (id == ctrls->qctrl.id)
1372 return i;
1373 }
1374 return -1;
1375}
1376
1377static int vidioc_queryctrl(struct file *file, void *priv,
1378 struct v4l2_queryctrl *q_ctrl)
1379{
1380 struct gspca_dev *gspca_dev = video_drvdata(file);
1381 const struct ctrl *ctrls;
1382 struct gspca_ctrl *gspca_ctrl;
1383 int i, idx;
1384 u32 id;
1385
1386 id = q_ctrl->id;
1387 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1388 id &= V4L2_CTRL_ID_MASK;
1389 id++;
1390 idx = -1;
1391 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1392 if (gspca_dev->ctrl_dis & (1 << i))
1393 continue;
1394 if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
1395 continue;
1396 if (idx >= 0
1397 && gspca_dev->sd_desc->ctrls[i].qctrl.id
1398 > gspca_dev->sd_desc->ctrls[idx].qctrl.id)
1399 continue;
1400 idx = i;
1401 }
1402 } else {
1403 idx = get_ctrl(gspca_dev, id);
1404 }
1405 if (idx < 0)
1406 return -EINVAL;
1407 ctrls = &gspca_dev->sd_desc->ctrls[idx];
1408 memcpy(q_ctrl, &ctrls->qctrl, sizeof *q_ctrl);
1409 if (gspca_dev->cam.ctrls != NULL) {
1410 gspca_ctrl = &gspca_dev->cam.ctrls[idx];
1411 q_ctrl->default_value = gspca_ctrl->def;
1412 q_ctrl->minimum = gspca_ctrl->min;
1413 q_ctrl->maximum = gspca_ctrl->max;
1414 }
1415 if (gspca_dev->ctrl_inac & (1 << idx))
1416 q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
1417 return 0;
1418}
1419
1420static int vidioc_s_ctrl(struct file *file, void *priv,
1421 struct v4l2_control *ctrl)
1422{
1423 struct gspca_dev *gspca_dev = video_drvdata(file);
1424 const struct ctrl *ctrls;
1425 struct gspca_ctrl *gspca_ctrl;
1426 int idx;
1427
1428 idx = get_ctrl(gspca_dev, ctrl->id);
1429 if (idx < 0)
1430 return -EINVAL;
1431 if (gspca_dev->ctrl_inac & (1 << idx))
1432 return -EINVAL;
1433 ctrls = &gspca_dev->sd_desc->ctrls[idx];
1434 if (gspca_dev->cam.ctrls != NULL) {
1435 gspca_ctrl = &gspca_dev->cam.ctrls[idx];
1436 if (ctrl->value < gspca_ctrl->min
1437 || ctrl->value > gspca_ctrl->max)
1438 return -ERANGE;
1439 } else {
1440 gspca_ctrl = NULL;
1441 if (ctrl->value < ctrls->qctrl.minimum
1442 || ctrl->value > ctrls->qctrl.maximum)
1443 return -ERANGE;
1444 }
1445 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
1446 gspca_dev->usb_err = 0;
1447 if (ctrls->set != NULL)
1448 return ctrls->set(gspca_dev, ctrl->value);
1449 if (gspca_ctrl != NULL) {
1450 gspca_ctrl->val = ctrl->value;
1451 if (ctrls->set_control != NULL
1452 && gspca_dev->streaming)
1453 ctrls->set_control(gspca_dev);
1454 }
1455 return gspca_dev->usb_err;
1456}
1457
1458static int vidioc_g_ctrl(struct file *file, void *priv,
1459 struct v4l2_control *ctrl)
1460{
1461 struct gspca_dev *gspca_dev = video_drvdata(file);
1462 const struct ctrl *ctrls;
1463 int idx;
1464
1465 idx = get_ctrl(gspca_dev, ctrl->id);
1466 if (idx < 0)
1467 return -EINVAL;
1468 ctrls = &gspca_dev->sd_desc->ctrls[idx];
1469
1470 gspca_dev->usb_err = 0;
1471 if (ctrls->get != NULL)
1472 return ctrls->get(gspca_dev, &ctrl->value);
1473 if (gspca_dev->cam.ctrls != NULL)
1474 ctrl->value = gspca_dev->cam.ctrls[idx].val;
1475 return 0;
1476}
1477
1478static int vidioc_querymenu(struct file *file, void *priv,
1479 struct v4l2_querymenu *qmenu)
1480{
1481 struct gspca_dev *gspca_dev = video_drvdata(file);
1482
1483 if (!gspca_dev->sd_desc->querymenu)
1484 return -ENOTTY;
1485 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
1486}
1487
1488static int vidioc_enum_input(struct file *file, void *priv,
1489 struct v4l2_input *input)
1490{
1491 struct gspca_dev *gspca_dev = video_drvdata(file);
1492
1493 if (input->index != 0)
1494 return -EINVAL;
1495 input->type = V4L2_INPUT_TYPE_CAMERA;
1496 input->status = gspca_dev->cam.input_flags;
1497 strlcpy(input->name, gspca_dev->sd_desc->name,
1498 sizeof input->name);
1499 return 0;
1500}
1501
1502static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1503{
1504 *i = 0;
1505 return 0;
1506}
1507
1508static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1509{
1510 if (i > 0)
1511 return -EINVAL;
1512 return (0);
1513}
1514
1515static int vidioc_reqbufs(struct file *file, void *priv,
1516 struct v4l2_requestbuffers *rb)
1517{
1518 struct gspca_dev *gspca_dev = video_drvdata(file);
1519 int i, ret = 0, streaming;
1520
1521 i = rb->memory; /* (avoid compilation warning) */
1522 switch (i) {
1523 case GSPCA_MEMORY_READ: /* (internal call) */
1524 case V4L2_MEMORY_MMAP:
1525 case V4L2_MEMORY_USERPTR:
1526 break;
1527 default:
1528 return -EINVAL;
1529 }
1530 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1531 return -ERESTARTSYS;
1532
1533 if (gspca_dev->memory != GSPCA_MEMORY_NO
1534 && gspca_dev->memory != GSPCA_MEMORY_READ
1535 && gspca_dev->memory != rb->memory) {
1536 ret = -EBUSY;
1537 goto out;
1538 }
1539
1540 /* only one file may do the capture */
1541 if (gspca_dev->capt_file != NULL
1542 && gspca_dev->capt_file != file) {
1543 ret = -EBUSY;
1544 goto out;
1545 }
1546
1547 /* if allocated, the buffers must not be mapped */
1548 for (i = 0; i < gspca_dev->nframes; i++) {
1549 if (gspca_dev->frame[i].vma_use_count) {
1550 ret = -EBUSY;
1551 goto out;
1552 }
1553 }
1554
1555 /* stop streaming */
1556 streaming = gspca_dev->streaming;
1557 if (streaming) {
1558 gspca_stream_off(gspca_dev);
1559
1560 /* Don't restart the stream when switching from read
1561 * to mmap mode */
1562 if (gspca_dev->memory == GSPCA_MEMORY_READ)
1563 streaming = 0;
1564 }
1565
1566 /* free the previous allocated buffers, if any */
1567 if (gspca_dev->nframes != 0)
1568 frame_free(gspca_dev);
1569 if (rb->count == 0) /* unrequest */
1570 goto out;
1571 ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
1572 if (ret == 0) {
1573 rb->count = gspca_dev->nframes;
1574 if (streaming)
1575 ret = gspca_init_transfer(gspca_dev);
1576 }
1577out:
1578 mutex_unlock(&gspca_dev->queue_lock);
1579 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1580 return ret;
1581}
1582
1583static int vidioc_querybuf(struct file *file, void *priv,
1584 struct v4l2_buffer *v4l2_buf)
1585{
1586 struct gspca_dev *gspca_dev = video_drvdata(file);
1587 struct gspca_frame *frame;
1588
1589 if (v4l2_buf->index < 0
1590 || v4l2_buf->index >= gspca_dev->nframes)
1591 return -EINVAL;
1592
1593 frame = &gspca_dev->frame[v4l2_buf->index];
1594 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1595 return 0;
1596}
1597
1598static int vidioc_streamon(struct file *file, void *priv,
1599 enum v4l2_buf_type buf_type)
1600{
1601 struct gspca_dev *gspca_dev = video_drvdata(file);
1602 int ret;
1603
1604 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1605 return -EINVAL;
1606 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1607 return -ERESTARTSYS;
1608
1609 /* check the capture file */
1610 if (gspca_dev->capt_file != file) {
1611 ret = -EBUSY;
1612 goto out;
1613 }
1614
1615 if (gspca_dev->nframes == 0
1616 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
1617 ret = -EINVAL;
1618 goto out;
1619 }
1620 if (!gspca_dev->streaming) {
1621 ret = gspca_init_transfer(gspca_dev);
1622 if (ret < 0)
1623 goto out;
1624 }
1625#ifdef GSPCA_DEBUG
1626 if (gspca_debug & D_STREAM) {
1627 PDEBUG_MODE("stream on OK",
1628 gspca_dev->pixfmt,
1629 gspca_dev->width,
1630 gspca_dev->height);
1631 }
1632#endif
1633 ret = 0;
1634out:
1635 mutex_unlock(&gspca_dev->queue_lock);
1636 return ret;
1637}
1638
1639static int vidioc_streamoff(struct file *file, void *priv,
1640 enum v4l2_buf_type buf_type)
1641{
1642 struct gspca_dev *gspca_dev = video_drvdata(file);
1643 int i, ret;
1644
1645 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1646 return -EINVAL;
1647
1648 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1649 return -ERESTARTSYS;
1650
1651 if (!gspca_dev->streaming) {
1652 ret = 0;
1653 goto out;
1654 }
1655
1656 /* check the capture file */
1657 if (gspca_dev->capt_file != file) {
1658 ret = -EBUSY;
1659 goto out;
1660 }
1661
1662 /* stop streaming */
1663 gspca_stream_off(gspca_dev);
1664 /* In case another thread is waiting in dqbuf */
1665 wake_up_interruptible(&gspca_dev->wq);
1666
1667 /* empty the transfer queues */
1668 for (i = 0; i < gspca_dev->nframes; i++)
1669 gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
1670 atomic_set(&gspca_dev->fr_q, 0);
1671 atomic_set(&gspca_dev->fr_i, 0);
1672 gspca_dev->fr_o = 0;
1673 ret = 0;
1674out:
1675 mutex_unlock(&gspca_dev->queue_lock);
1676 return ret;
1677}
1678
1679static int vidioc_g_jpegcomp(struct file *file, void *priv,
1680 struct v4l2_jpegcompression *jpegcomp)
1681{
1682 struct gspca_dev *gspca_dev = video_drvdata(file);
1683
1684 gspca_dev->usb_err = 0;
1685 return gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1686}
1687
1688static int vidioc_s_jpegcomp(struct file *file, void *priv,
1689 struct v4l2_jpegcompression *jpegcomp)
1690{
1691 struct gspca_dev *gspca_dev = video_drvdata(file);
1692
1693 gspca_dev->usb_err = 0;
1694 return gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1695}
1696
1697static int vidioc_g_parm(struct file *filp, void *priv,
1698 struct v4l2_streamparm *parm)
1699{
1700 struct gspca_dev *gspca_dev = video_drvdata(filp);
1701
1702 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1703
1704 if (gspca_dev->sd_desc->get_streamparm) {
1705 gspca_dev->usb_err = 0;
1706 gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
1707 return gspca_dev->usb_err;
1708 }
1709 return 0;
1710}
1711
1712static int vidioc_s_parm(struct file *filp, void *priv,
1713 struct v4l2_streamparm *parm)
1714{
1715 struct gspca_dev *gspca_dev = video_drvdata(filp);
1716 int n;
1717
1718 n = parm->parm.capture.readbuffers;
1719 if (n == 0 || n >= GSPCA_MAX_FRAMES)
1720 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1721 else
1722 gspca_dev->nbufread = n;
1723
1724 if (gspca_dev->sd_desc->set_streamparm) {
1725 gspca_dev->usb_err = 0;
1726 gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
1727 return gspca_dev->usb_err;
1728 }
1729
1730 return 0;
1731}
1732
1733static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1734{
1735 struct gspca_dev *gspca_dev = video_drvdata(file);
1736 struct gspca_frame *frame;
1737 struct page *page;
1738 unsigned long addr, start, size;
1739 int i, ret;
1740
1741 start = vma->vm_start;
1742 size = vma->vm_end - vma->vm_start;
1743 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1744
1745 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1746 return -ERESTARTSYS;
1747 if (gspca_dev->capt_file != file) {
1748 ret = -EINVAL;
1749 goto out;
1750 }
1751
1752 frame = NULL;
1753 for (i = 0; i < gspca_dev->nframes; ++i) {
1754 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1755 PDEBUG(D_STREAM, "mmap bad memory type");
1756 break;
1757 }
1758 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1759 == vma->vm_pgoff) {
1760 frame = &gspca_dev->frame[i];
1761 break;
1762 }
1763 }
1764 if (frame == NULL) {
1765 PDEBUG(D_STREAM, "mmap no frame buffer found");
1766 ret = -EINVAL;
1767 goto out;
1768 }
1769 if (size != frame->v4l2_buf.length) {
1770 PDEBUG(D_STREAM, "mmap bad size");
1771 ret = -EINVAL;
1772 goto out;
1773 }
1774
1775 /*
1776 * - VM_IO marks the area as being a mmaped region for I/O to a
1777 * device. It also prevents the region from being core dumped.
1778 */
1779 vma->vm_flags |= VM_IO;
1780
1781 addr = (unsigned long) frame->data;
1782 while (size > 0) {
1783 page = vmalloc_to_page((void *) addr);
1784 ret = vm_insert_page(vma, start, page);
1785 if (ret < 0)
1786 goto out;
1787 start += PAGE_SIZE;
1788 addr += PAGE_SIZE;
1789 size -= PAGE_SIZE;
1790 }
1791
1792 vma->vm_ops = &gspca_vm_ops;
1793 vma->vm_private_data = frame;
1794 gspca_vm_open(vma);
1795 ret = 0;
1796out:
1797 mutex_unlock(&gspca_dev->queue_lock);
1798 return ret;
1799}
1800
1801static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file,
1802 enum v4l2_memory memory)
1803{
1804 if (!gspca_dev->present)
1805 return -ENODEV;
1806 if (gspca_dev->capt_file != file || gspca_dev->memory != memory ||
1807 !gspca_dev->streaming)
1808 return -EINVAL;
1809
1810 /* check if a frame is ready */
1811 return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i);
1812}
1813
1814static int frame_ready(struct gspca_dev *gspca_dev, struct file *file,
1815 enum v4l2_memory memory)
1816{
1817 int ret;
1818
1819 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1820 return -ERESTARTSYS;
1821 ret = frame_ready_nolock(gspca_dev, file, memory);
1822 mutex_unlock(&gspca_dev->queue_lock);
1823 return ret;
1824}
1825
1826/*
1827 * dequeue a video buffer
1828 *
1829 * If nonblock_ing is false, block until a buffer is available.
1830 */
1831static int vidioc_dqbuf(struct file *file, void *priv,
1832 struct v4l2_buffer *v4l2_buf)
1833{
1834 struct gspca_dev *gspca_dev = video_drvdata(file);
1835 struct gspca_frame *frame;
1836 int i, j, ret;
1837
1838 PDEBUG(D_FRAM, "dqbuf");
1839
1840 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1841 return -ERESTARTSYS;
1842
1843 for (;;) {
1844 ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory);
1845 if (ret < 0)
1846 goto out;
1847 if (ret > 0)
1848 break;
1849
1850 mutex_unlock(&gspca_dev->queue_lock);
1851
1852 if (file->f_flags & O_NONBLOCK)
1853 return -EAGAIN;
1854
1855 /* wait till a frame is ready */
1856 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1857 frame_ready(gspca_dev, file, v4l2_buf->memory),
1858 msecs_to_jiffies(3000));
1859 if (ret < 0)
1860 return ret;
1861 if (ret == 0)
1862 return -EIO;
1863
1864 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1865 return -ERESTARTSYS;
1866 }
1867
1868 i = gspca_dev->fr_o;
1869 j = gspca_dev->fr_queue[i];
1870 frame = &gspca_dev->frame[j];
1871
1872 gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES;
1873
1874 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1875 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1876 PDEBUG(D_FRAM, "dqbuf %d", j);
1877 ret = 0;
1878
1879 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
1880 if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
1881 frame->data,
1882 frame->v4l2_buf.bytesused)) {
1883 PDEBUG(D_ERR|D_STREAM,
1884 "dqbuf cp to user failed");
1885 ret = -EFAULT;
1886 }
1887 }
1888out:
1889 mutex_unlock(&gspca_dev->queue_lock);
1890
1891 if (ret == 0 && gspca_dev->sd_desc->dq_callback) {
1892 mutex_lock(&gspca_dev->usb_lock);
1893 gspca_dev->usb_err = 0;
1894 if (gspca_dev->present)
1895 gspca_dev->sd_desc->dq_callback(gspca_dev);
1896 mutex_unlock(&gspca_dev->usb_lock);
1897 }
1898
1899 return ret;
1900}
1901
1902/*
1903 * queue a video buffer
1904 *
1905 * Attempting to queue a buffer that has already been
1906 * queued will return -EINVAL.
1907 */
1908static int vidioc_qbuf(struct file *file, void *priv,
1909 struct v4l2_buffer *v4l2_buf)
1910{
1911 struct gspca_dev *gspca_dev = video_drvdata(file);
1912 struct gspca_frame *frame;
1913 int i, index, ret;
1914
1915 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1916
1917 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1918 return -ERESTARTSYS;
1919
1920 index = v4l2_buf->index;
1921 if ((unsigned) index >= gspca_dev->nframes) {
1922 PDEBUG(D_FRAM,
1923 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1924 ret = -EINVAL;
1925 goto out;
1926 }
1927 if (v4l2_buf->memory != gspca_dev->memory) {
1928 PDEBUG(D_FRAM, "qbuf bad memory type");
1929 ret = -EINVAL;
1930 goto out;
1931 }
1932
1933 frame = &gspca_dev->frame[index];
1934 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1935 PDEBUG(D_FRAM, "qbuf bad state");
1936 ret = -EINVAL;
1937 goto out;
1938 }
1939
1940 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
1941
1942 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
1943 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1944 frame->v4l2_buf.length = v4l2_buf->length;
1945 }
1946
1947 /* put the buffer in the 'queued' queue */
1948 i = atomic_read(&gspca_dev->fr_q);
1949 gspca_dev->fr_queue[i] = index;
1950 atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES);
1951
1952 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1953 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1954 ret = 0;
1955out:
1956 mutex_unlock(&gspca_dev->queue_lock);
1957 return ret;
1958}
1959
1960/*
1961 * allocate the resources for read()
1962 */
1963static int read_alloc(struct gspca_dev *gspca_dev,
1964 struct file *file)
1965{
1966 struct v4l2_buffer v4l2_buf;
1967 int i, ret;
1968
1969 PDEBUG(D_STREAM, "read alloc");
1970
1971 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1972 return -ERESTARTSYS;
1973
1974 if (gspca_dev->nframes == 0) {
1975 struct v4l2_requestbuffers rb;
1976
1977 memset(&rb, 0, sizeof rb);
1978 rb.count = gspca_dev->nbufread;
1979 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1980 rb.memory = GSPCA_MEMORY_READ;
1981 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1982 if (ret != 0) {
1983 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
1984 goto out;
1985 }
1986 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1987 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1988 v4l2_buf.memory = GSPCA_MEMORY_READ;
1989 for (i = 0; i < gspca_dev->nbufread; i++) {
1990 v4l2_buf.index = i;
1991 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1992 if (ret != 0) {
1993 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1994 goto out;
1995 }
1996 }
1997 }
1998
1999 /* start streaming */
2000 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
2001 if (ret != 0)
2002 PDEBUG(D_STREAM, "read streamon err %d", ret);
2003out:
2004 mutex_unlock(&gspca_dev->usb_lock);
2005 return ret;
2006}
2007
2008static unsigned int dev_poll(struct file *file, poll_table *wait)
2009{
2010 struct gspca_dev *gspca_dev = video_drvdata(file);
2011 unsigned long req_events = poll_requested_events(wait);
2012 int ret = 0;
2013
2014 PDEBUG(D_FRAM, "poll");
2015
2016 if (req_events & POLLPRI)
2017 ret |= v4l2_ctrl_poll(file, wait);
2018
2019 if (req_events & (POLLIN | POLLRDNORM)) {
2020 /* if reqbufs is not done, the user would use read() */
2021 if (gspca_dev->memory == GSPCA_MEMORY_NO) {
2022 if (read_alloc(gspca_dev, file) != 0) {
2023 ret |= POLLERR;
2024 goto out;
2025 }
2026 }
2027
2028 poll_wait(file, &gspca_dev->wq, wait);
2029
2030 /* check if an image has been received */
2031 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) {
2032 ret |= POLLERR;
2033 goto out;
2034 }
2035 if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i))
2036 ret |= POLLIN | POLLRDNORM;
2037 mutex_unlock(&gspca_dev->queue_lock);
2038 }
2039
2040out:
2041 if (!gspca_dev->present)
2042 ret |= POLLHUP;
2043
2044 return ret;
2045}
2046
2047static ssize_t dev_read(struct file *file, char __user *data,
2048 size_t count, loff_t *ppos)
2049{
2050 struct gspca_dev *gspca_dev = video_drvdata(file);
2051 struct gspca_frame *frame;
2052 struct v4l2_buffer v4l2_buf;
2053 struct timeval timestamp;
2054 int n, ret, ret2;
2055
2056 PDEBUG(D_FRAM, "read (%zd)", count);
2057 if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */
2058 ret = read_alloc(gspca_dev, file);
2059 if (ret != 0)
2060 return ret;
2061 }
2062
2063 /* get a frame */
2064 timestamp = ktime_to_timeval(ktime_get());
2065 timestamp.tv_sec--;
2066 n = 2;
2067 for (;;) {
2068 memset(&v4l2_buf, 0, sizeof v4l2_buf);
2069 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2070 v4l2_buf.memory = GSPCA_MEMORY_READ;
2071 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
2072 if (ret != 0) {
2073 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
2074 return ret;
2075 }
2076
2077 /* if the process slept for more than 1 second,
2078 * get a newer frame */
2079 frame = &gspca_dev->frame[v4l2_buf.index];
2080 if (--n < 0)
2081 break; /* avoid infinite loop */
2082 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
2083 break;
2084 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
2085 if (ret != 0) {
2086 PDEBUG(D_STREAM, "read qbuf err %d", ret);
2087 return ret;
2088 }
2089 }
2090
2091 /* copy the frame */
2092 if (count > frame->v4l2_buf.bytesused)
2093 count = frame->v4l2_buf.bytesused;
2094 ret = copy_to_user(data, frame->data, count);
2095 if (ret != 0) {
2096 PDEBUG(D_ERR|D_STREAM,
2097 "read cp to user lack %d / %zd", ret, count);
2098 ret = -EFAULT;
2099 goto out;
2100 }
2101 ret = count;
2102out:
2103 /* in each case, requeue the buffer */
2104 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
2105 if (ret2 != 0)
2106 return ret2;
2107 return ret;
2108}
2109
2110static struct v4l2_file_operations dev_fops = {
2111 .owner = THIS_MODULE,
2112 .open = dev_open,
2113 .release = dev_close,
2114 .read = dev_read,
2115 .mmap = dev_mmap,
2116 .unlocked_ioctl = video_ioctl2,
2117 .poll = dev_poll,
2118};
2119
2120static const struct v4l2_ioctl_ops dev_ioctl_ops = {
2121 .vidioc_querycap = vidioc_querycap,
2122 .vidioc_dqbuf = vidioc_dqbuf,
2123 .vidioc_qbuf = vidioc_qbuf,
2124 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2125 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2126 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2127 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
2128 .vidioc_streamon = vidioc_streamon,
2129 .vidioc_queryctrl = vidioc_queryctrl,
2130 .vidioc_g_ctrl = vidioc_g_ctrl,
2131 .vidioc_s_ctrl = vidioc_s_ctrl,
2132 .vidioc_querymenu = vidioc_querymenu,
2133 .vidioc_enum_input = vidioc_enum_input,
2134 .vidioc_g_input = vidioc_g_input,
2135 .vidioc_s_input = vidioc_s_input,
2136 .vidioc_reqbufs = vidioc_reqbufs,
2137 .vidioc_querybuf = vidioc_querybuf,
2138 .vidioc_streamoff = vidioc_streamoff,
2139 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
2140 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
2141 .vidioc_g_parm = vidioc_g_parm,
2142 .vidioc_s_parm = vidioc_s_parm,
2143 .vidioc_enum_framesizes = vidioc_enum_framesizes,
2144 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
2145#ifdef CONFIG_VIDEO_ADV_DEBUG
2146 .vidioc_g_register = vidioc_g_register,
2147 .vidioc_s_register = vidioc_s_register,
2148#endif
2149 .vidioc_g_chip_ident = vidioc_g_chip_ident,
2150 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
2151 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
2152};
2153
2154static const struct video_device gspca_template = {
2155 .name = "gspca main driver",
2156 .fops = &dev_fops,
2157 .ioctl_ops = &dev_ioctl_ops,
2158 .release = video_device_release_empty, /* We use v4l2_dev.release */
2159};
2160
2161/* initialize the controls */
2162static void ctrls_init(struct gspca_dev *gspca_dev)
2163{
2164 struct gspca_ctrl *ctrl;
2165 int i;
2166
2167 for (i = 0, ctrl = gspca_dev->cam.ctrls;
2168 i < gspca_dev->sd_desc->nctrls;
2169 i++, ctrl++) {
2170 ctrl->def = gspca_dev->sd_desc->ctrls[i].qctrl.default_value;
2171 ctrl->val = ctrl->def;
2172 ctrl->min = gspca_dev->sd_desc->ctrls[i].qctrl.minimum;
2173 ctrl->max = gspca_dev->sd_desc->ctrls[i].qctrl.maximum;
2174 }
2175}
2176
2177/*
2178 * probe and create a new gspca device
2179 *
2180 * This function must be called by the sub-driver when it is
2181 * called for probing a new device.
2182 */
2183int gspca_dev_probe2(struct usb_interface *intf,
2184 const struct usb_device_id *id,
2185 const struct sd_desc *sd_desc,
2186 int dev_size,
2187 struct module *module)
2188{
2189 struct gspca_dev *gspca_dev;
2190 struct usb_device *dev = interface_to_usbdev(intf);
2191 int ret;
2192
2193 pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
2194 sd_desc->name, id->idVendor, id->idProduct);
2195
2196 /* create the device */
2197 if (dev_size < sizeof *gspca_dev)
2198 dev_size = sizeof *gspca_dev;
2199 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
2200 if (!gspca_dev) {
2201 pr_err("couldn't kzalloc gspca struct\n");
2202 return -ENOMEM;
2203 }
2204 gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
2205 if (!gspca_dev->usb_buf) {
2206 pr_err("out of memory\n");
2207 ret = -ENOMEM;
2208 goto out;
2209 }
2210 gspca_dev->dev = dev;
2211 gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
2212
2213 /* check if any audio device */
2214 if (dev->actconfig->desc.bNumInterfaces != 1) {
2215 int i;
2216 struct usb_interface *intf2;
2217
2218 for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
2219 intf2 = dev->actconfig->interface[i];
2220 if (intf2 != NULL
2221 && intf2->altsetting != NULL
2222 && intf2->altsetting->desc.bInterfaceClass ==
2223 USB_CLASS_AUDIO) {
2224 gspca_dev->audio = 1;
2225 break;
2226 }
2227 }
2228 }
2229
2230 gspca_dev->v4l2_dev.release = gspca_release;
2231 ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev);
2232 if (ret)
2233 goto out;
2234 gspca_dev->sd_desc = sd_desc;
2235 gspca_dev->nbufread = 2;
2236 gspca_dev->empty_packet = -1; /* don't check the empty packets */
2237 gspca_dev->vdev = gspca_template;
2238 gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev;
2239 video_set_drvdata(&gspca_dev->vdev, gspca_dev);
2240 set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags);
2241 gspca_dev->module = module;
2242 gspca_dev->present = 1;
2243
2244 mutex_init(&gspca_dev->usb_lock);
2245 gspca_dev->vdev.lock = &gspca_dev->usb_lock;
2246 mutex_init(&gspca_dev->queue_lock);
2247 init_waitqueue_head(&gspca_dev->wq);
2248
2249 /* configure the subdriver and initialize the USB device */
2250 ret = sd_desc->config(gspca_dev, id);
2251 if (ret < 0)
2252 goto out;
2253 if (gspca_dev->cam.ctrls != NULL)
2254 ctrls_init(gspca_dev);
2255 ret = sd_desc->init(gspca_dev);
2256 if (ret < 0)
2257 goto out;
2258 if (sd_desc->init_controls)
2259 ret = sd_desc->init_controls(gspca_dev);
2260 if (ret < 0)
2261 goto out;
2262 gspca_set_default_mode(gspca_dev);
2263
2264 ret = gspca_input_connect(gspca_dev);
2265 if (ret)
2266 goto out;
2267
2268 /*
2269 * Don't take usb_lock for these ioctls. This improves latency if
2270 * usb_lock is taken for a long time, e.g. when changing a control
2271 * value, and a new frame is ready to be dequeued.
2272 */
2273 v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF);
2274 v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF);
2275 v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF);
2276 if (!gspca_dev->sd_desc->get_chip_ident)
2277 v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_CHIP_IDENT);
2278#ifdef CONFIG_VIDEO_ADV_DEBUG
2279 if (!gspca_dev->sd_desc->get_chip_ident ||
2280 !gspca_dev->sd_desc->get_register)
2281 v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER);
2282 if (!gspca_dev->sd_desc->get_chip_ident ||
2283 !gspca_dev->sd_desc->set_register)
2284 v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_S_REGISTER);
2285#endif
2286 if (!gspca_dev->sd_desc->get_jcomp)
2287 v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_G_JPEGCOMP);
2288 if (!gspca_dev->sd_desc->set_jcomp)
2289 v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_S_JPEGCOMP);
2290
2291 /* init video stuff */
2292 ret = video_register_device(&gspca_dev->vdev,
2293 VFL_TYPE_GRABBER,
2294 -1);
2295 if (ret < 0) {
2296 pr_err("video_register_device err %d\n", ret);
2297 goto out;
2298 }
2299
2300 usb_set_intfdata(intf, gspca_dev);
2301 PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
2302
2303 gspca_input_create_urb(gspca_dev);
2304
2305 return 0;
2306out:
2307#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2308 if (gspca_dev->input_dev)
2309 input_unregister_device(gspca_dev->input_dev);
2310#endif
2311 v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
2312 kfree(gspca_dev->usb_buf);
2313 kfree(gspca_dev);
2314 return ret;
2315}
2316EXPORT_SYMBOL(gspca_dev_probe2);
2317
2318/* same function as the previous one, but check the interface */
2319int gspca_dev_probe(struct usb_interface *intf,
2320 const struct usb_device_id *id,
2321 const struct sd_desc *sd_desc,
2322 int dev_size,
2323 struct module *module)
2324{
2325 struct usb_device *dev = interface_to_usbdev(intf);
2326
2327 /* we don't handle multi-config cameras */
2328 if (dev->descriptor.bNumConfigurations != 1) {
2329 pr_err("%04x:%04x too many config\n",
2330 id->idVendor, id->idProduct);
2331 return -ENODEV;
2332 }
2333
2334 /* the USB video interface must be the first one */
2335 if (dev->actconfig->desc.bNumInterfaces != 1
2336 && intf->cur_altsetting->desc.bInterfaceNumber != 0)
2337 return -ENODEV;
2338
2339 return gspca_dev_probe2(intf, id, sd_desc, dev_size, module);
2340}
2341EXPORT_SYMBOL(gspca_dev_probe);
2342
2343/*
2344 * USB disconnection
2345 *
2346 * This function must be called by the sub-driver
2347 * when the device disconnects, after the specific resources are freed.
2348 */
2349void gspca_disconnect(struct usb_interface *intf)
2350{
2351 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2352#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2353 struct input_dev *input_dev;
2354#endif
2355
2356 PDEBUG(D_PROBE, "%s disconnect",
2357 video_device_node_name(&gspca_dev->vdev));
2358
2359 mutex_lock(&gspca_dev->usb_lock);
2360
2361 usb_set_intfdata(intf, NULL);
2362 gspca_dev->dev = NULL;
2363 gspca_dev->present = 0;
2364 destroy_urbs(gspca_dev);
2365
2366#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2367 gspca_input_destroy_urb(gspca_dev);
2368 input_dev = gspca_dev->input_dev;
2369 if (input_dev) {
2370 gspca_dev->input_dev = NULL;
2371 input_unregister_device(input_dev);
2372 }
2373#endif
2374 /* Free subdriver's streaming resources / stop sd workqueue(s) */
2375 if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming)
2376 gspca_dev->sd_desc->stop0(gspca_dev);
2377 gspca_dev->streaming = 0;
2378 wake_up_interruptible(&gspca_dev->wq);
2379
2380 v4l2_device_disconnect(&gspca_dev->v4l2_dev);
2381 video_unregister_device(&gspca_dev->vdev);
2382
2383 mutex_unlock(&gspca_dev->usb_lock);
2384
2385 /* (this will call gspca_release() immediately or on last close) */
2386 v4l2_device_put(&gspca_dev->v4l2_dev);
2387}
2388EXPORT_SYMBOL(gspca_disconnect);
2389
2390#ifdef CONFIG_PM
2391int gspca_suspend(struct usb_interface *intf, pm_message_t message)
2392{
2393 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2394
2395 if (!gspca_dev->streaming)
2396 return 0;
2397 mutex_lock(&gspca_dev->usb_lock);
2398 gspca_dev->frozen = 1; /* avoid urb error messages */
2399 gspca_dev->usb_err = 0;
2400 if (gspca_dev->sd_desc->stopN)
2401 gspca_dev->sd_desc->stopN(gspca_dev);
2402 destroy_urbs(gspca_dev);
2403 gspca_input_destroy_urb(gspca_dev);
2404 gspca_set_alt0(gspca_dev);
2405 if (gspca_dev->sd_desc->stop0)
2406 gspca_dev->sd_desc->stop0(gspca_dev);
2407 mutex_unlock(&gspca_dev->usb_lock);
2408 return 0;
2409}
2410EXPORT_SYMBOL(gspca_suspend);
2411
2412int gspca_resume(struct usb_interface *intf)
2413{
2414 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2415 int streaming, ret = 0;
2416
2417 mutex_lock(&gspca_dev->usb_lock);
2418 gspca_dev->frozen = 0;
2419 gspca_dev->usb_err = 0;
2420 gspca_dev->sd_desc->init(gspca_dev);
2421 gspca_input_create_urb(gspca_dev);
2422 /*
2423 * Most subdrivers send all ctrl values on sd_start and thus
2424 * only write to the device registers on s_ctrl when streaming ->
2425 * Clear streaming to avoid setting all ctrls twice.
2426 */
2427 streaming = gspca_dev->streaming;
2428 gspca_dev->streaming = 0;
2429 if (streaming)
2430 ret = gspca_init_transfer(gspca_dev);
2431 mutex_unlock(&gspca_dev->usb_lock);
2432 return ret;
2433}
2434EXPORT_SYMBOL(gspca_resume);
2435#endif
2436
2437/* -- module insert / remove -- */
2438static int __init gspca_init(void)
2439{
2440 pr_info("v" GSPCA_VERSION " registered\n");
2441 return 0;
2442}
2443static void __exit gspca_exit(void)
2444{
2445}
2446
2447module_init(gspca_init);
2448module_exit(gspca_exit);
2449
2450#ifdef GSPCA_DEBUG
2451module_param_named(debug, gspca_debug, int, 0644);
2452MODULE_PARM_DESC(debug,
2453 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
2454 " 0x08:stream 0x10:frame 0x20:packet"
2455 " 0x0100: v4l2");
2456#endif
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
new file mode 100644
index 00000000000..dc688c7f5e4
--- /dev/null
+++ b/drivers/media/usb/gspca/gspca.h
@@ -0,0 +1,259 @@
1#ifndef GSPCAV2_H
2#define GSPCAV2_H
3
4#include <linux/module.h>
5#include <linux/kernel.h>
6#include <linux/usb.h>
7#include <linux/videodev2.h>
8#include <media/v4l2-common.h>
9#include <media/v4l2-ctrls.h>
10#include <media/v4l2-device.h>
11#include <linux/mutex.h>
12
13/* compilation option */
14/*#define GSPCA_DEBUG 1*/
15
16#ifdef GSPCA_DEBUG
17/* GSPCA our debug messages */
18extern int gspca_debug;
19#define PDEBUG(level, fmt, ...) \
20do { \
21 if (gspca_debug & (level)) \
22 pr_info(fmt, ##__VA_ARGS__); \
23} while (0)
24
25#define D_ERR 0x01
26#define D_PROBE 0x02
27#define D_CONF 0x04
28#define D_STREAM 0x08
29#define D_FRAM 0x10
30#define D_PACK 0x20
31#define D_USBI 0x00
32#define D_USBO 0x00
33#define D_V4L2 0x0100
34#else
35#define PDEBUG(level, fmt, ...)
36#endif
37
38#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
39/* image transfers */
40#define MAX_NURBS 4 /* max number of URBs */
41
42
43/* used to list framerates supported by a camera mode (resolution) */
44struct framerates {
45 const u8 *rates;
46 int nrates;
47};
48
49/* control definition */
50struct gspca_ctrl {
51 s16 val; /* current value */
52 s16 def; /* default value */
53 s16 min, max; /* minimum and maximum values */
54};
55
56/* device information - set at probe time */
57struct cam {
58 const struct v4l2_pix_format *cam_mode; /* size nmodes */
59 const struct framerates *mode_framerates; /* must have size nmodes,
60 * just like cam_mode */
61 struct gspca_ctrl *ctrls; /* control table - size nctrls */
62 /* may be NULL */
63 u32 bulk_size; /* buffer size when image transfer by bulk */
64 u32 input_flags; /* value for ENUM_INPUT status flags */
65 u8 nmodes; /* size of cam_mode */
66 u8 no_urb_create; /* don't create transfer URBs */
67 u8 bulk_nurbs; /* number of URBs in bulk mode
68 * - cannot be > MAX_NURBS
69 * - when 0 and bulk_size != 0 means
70 * 1 URB and submit done by subdriver */
71 u8 bulk; /* image transfer by 0:isoc / 1:bulk */
72 u8 npkt; /* number of packets in an ISOC message
73 * 0 is the default value: 32 packets */
74 u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc.
75 * code that the cam fills all image buffers to
76 * the max, even when using compression. */
77};
78
79struct gspca_dev;
80struct gspca_frame;
81
82/* subdriver operations */
83typedef int (*cam_op) (struct gspca_dev *);
84typedef void (*cam_v_op) (struct gspca_dev *);
85typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
86typedef int (*cam_jpg_op) (struct gspca_dev *,
87 struct v4l2_jpegcompression *);
88typedef int (*cam_reg_op) (struct gspca_dev *,
89 struct v4l2_dbg_register *);
90typedef int (*cam_ident_op) (struct gspca_dev *,
91 struct v4l2_dbg_chip_ident *);
92typedef void (*cam_streamparm_op) (struct gspca_dev *,
93 struct v4l2_streamparm *);
94typedef int (*cam_qmnu_op) (struct gspca_dev *,
95 struct v4l2_querymenu *);
96typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
97 u8 *data,
98 int len);
99typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
100 u8 *data,
101 int len);
102
103struct ctrl {
104 struct v4l2_queryctrl qctrl;
105 int (*set)(struct gspca_dev *, __s32);
106 int (*get)(struct gspca_dev *, __s32 *);
107 cam_v_op set_control;
108};
109
110/* subdriver description */
111struct sd_desc {
112/* information */
113 const char *name; /* sub-driver name */
114/* controls */
115 const struct ctrl *ctrls; /* static control definition */
116 int nctrls;
117/* mandatory operations */
118 cam_cf_op config; /* called on probe */
119 cam_op init; /* called on probe and resume */
120 cam_op init_controls; /* called on probe */
121 cam_op start; /* called on stream on after URBs creation */
122 cam_pkt_op pkt_scan;
123/* optional operations */
124 cam_op isoc_init; /* called on stream on before getting the EP */
125 cam_op isoc_nego; /* called when URB submit failed with NOSPC */
126 cam_v_op stopN; /* called on stream off - main alt */
127 cam_v_op stop0; /* called on stream off & disconnect - alt 0 */
128 cam_v_op dq_callback; /* called when a frame has been dequeued */
129 cam_jpg_op get_jcomp;
130 cam_jpg_op set_jcomp;
131 cam_qmnu_op querymenu;
132 cam_streamparm_op get_streamparm;
133 cam_streamparm_op set_streamparm;
134#ifdef CONFIG_VIDEO_ADV_DEBUG
135 cam_reg_op set_register;
136 cam_reg_op get_register;
137#endif
138 cam_ident_op get_chip_ident;
139#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
140 cam_int_pkt_op int_pkt_scan;
141 /* other_input makes the gspca core create gspca_dev->input even when
142 int_pkt_scan is NULL, for cams with non interrupt driven buttons */
143 u8 other_input;
144#endif
145};
146
147/* packet types when moving from iso buf to frame buf */
148enum gspca_packet_type {
149 DISCARD_PACKET,
150 FIRST_PACKET,
151 INTER_PACKET,
152 LAST_PACKET
153};
154
155struct gspca_frame {
156 __u8 *data; /* frame buffer */
157 int vma_use_count;
158 struct v4l2_buffer v4l2_buf;
159};
160
161struct gspca_dev {
162 struct video_device vdev; /* !! must be the first item */
163 struct module *module; /* subdriver handling the device */
164 struct v4l2_device v4l2_dev;
165 struct usb_device *dev;
166 struct file *capt_file; /* file doing video capture */
167 /* protected by queue_lock */
168#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
169 struct input_dev *input_dev;
170 char phys[64]; /* physical device path */
171#endif
172
173 struct cam cam; /* device information */
174 const struct sd_desc *sd_desc; /* subdriver description */
175 unsigned ctrl_dis; /* disabled controls (bit map) */
176 unsigned ctrl_inac; /* inactive controls (bit map) */
177 struct v4l2_ctrl_handler ctrl_handler;
178
179 /* autogain and exposure or gain control cluster, these are global as
180 the autogain/exposure functions in autogain_functions.c use them */
181 struct {
182 struct v4l2_ctrl *autogain;
183 struct v4l2_ctrl *exposure;
184 struct v4l2_ctrl *gain;
185 int exp_too_low_cnt, exp_too_high_cnt;
186 };
187
188#define USB_BUF_SZ 64
189 __u8 *usb_buf; /* buffer for USB exchanges */
190 struct urb *urb[MAX_NURBS];
191#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
192 struct urb *int_urb;
193#endif
194
195 __u8 *frbuf; /* buffer for nframes */
196 struct gspca_frame frame[GSPCA_MAX_FRAMES];
197 u8 *image; /* image beeing filled */
198 __u32 frsz; /* frame size */
199 u32 image_len; /* current length of image */
200 atomic_t fr_q; /* next frame to queue */
201 atomic_t fr_i; /* frame being filled */
202 signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
203 char nframes; /* number of frames */
204 u8 fr_o; /* next frame to dequeue */
205 __u8 last_packet_type;
206 __s8 empty_packet; /* if (-1) don't check empty packets */
207 __u8 streaming; /* protected by both mutexes (*) */
208
209 __u8 curr_mode; /* current camera mode */
210 __u32 pixfmt; /* current mode parameters */
211 __u16 width;
212 __u16 height;
213 __u32 sequence; /* frame sequence number */
214
215 wait_queue_head_t wq; /* wait queue */
216 struct mutex usb_lock; /* usb exchange protection */
217 struct mutex queue_lock; /* ISOC queue protection */
218 int usb_err; /* USB error - protected by usb_lock */
219 u16 pkt_size; /* ISOC packet size */
220#ifdef CONFIG_PM
221 char frozen; /* suspend - resume */
222#endif
223 char present; /* device connected */
224 char nbufread; /* number of buffers for read() */
225 char memory; /* memory type (V4L2_MEMORY_xxx) */
226 __u8 iface; /* USB interface number */
227 __u8 alt; /* USB alternate setting */
228 u8 audio; /* presence of audio device */
229
230 /* (*) These variables are proteced by both usb_lock and queue_lock,
231 that is any code setting them is holding *both*, which means that
232 any code getting them needs to hold at least one of them */
233};
234
235int gspca_dev_probe(struct usb_interface *intf,
236 const struct usb_device_id *id,
237 const struct sd_desc *sd_desc,
238 int dev_size,
239 struct module *module);
240int gspca_dev_probe2(struct usb_interface *intf,
241 const struct usb_device_id *id,
242 const struct sd_desc *sd_desc,
243 int dev_size,
244 struct module *module);
245void gspca_disconnect(struct usb_interface *intf);
246void gspca_frame_add(struct gspca_dev *gspca_dev,
247 enum gspca_packet_type packet_type,
248 const u8 *data,
249 int len);
250#ifdef CONFIG_PM
251int gspca_suspend(struct usb_interface *intf, pm_message_t message);
252int gspca_resume(struct usb_interface *intf);
253#endif
254int gspca_expo_autogain(struct gspca_dev *gspca_dev, int avg_lum,
255 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
256int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev,
257 int avg_lum, int desired_avg_lum, int deadzone);
258
259#endif /* GSPCAV2_H */
diff --git a/drivers/media/usb/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c
new file mode 100644
index 00000000000..26b99310d62
--- /dev/null
+++ b/drivers/media/usb/gspca/jeilinj.c
@@ -0,0 +1,548 @@
1/*
2 * Jeilinj subdriver
3 *
4 * Supports some Jeilin dual-mode cameras which use bulk transport and
5 * download raw JPEG data.
6 *
7 * Copyright (C) 2009 Theodore Kilgore
8 *
9 * Sportscam DV15 support and control settings are
10 * Copyright (C) 2011 Patrice Chotard
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29#define MODULE_NAME "jeilinj"
30
31#include <linux/slab.h>
32#include "gspca.h"
33#include "jpeg.h"
34
35MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
36MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
37MODULE_LICENSE("GPL");
38
39/* Default timeouts, in ms */
40#define JEILINJ_CMD_TIMEOUT 500
41#define JEILINJ_CMD_DELAY 160
42#define JEILINJ_DATA_TIMEOUT 1000
43
44/* Maximum transfer size to use. */
45#define JEILINJ_MAX_TRANSFER 0x200
46#define FRAME_HEADER_LEN 0x10
47#define FRAME_START 0xFFFFFFFF
48
49enum {
50 SAKAR_57379,
51 SPORTSCAM_DV15,
52};
53
54#define CAMQUALITY_MIN 0 /* highest cam quality */
55#define CAMQUALITY_MAX 97 /* lowest cam quality */
56
57/* Structure to hold all of our device specific stuff */
58struct sd {
59 struct gspca_dev gspca_dev; /* !! must be the first item */
60 int blocks_left;
61 const struct v4l2_pix_format *cap_mode;
62 struct v4l2_ctrl *freq;
63 struct v4l2_ctrl *jpegqual;
64 /* Driver stuff */
65 u8 type;
66 u8 quality; /* image quality */
67#define QUALITY_MIN 35
68#define QUALITY_MAX 85
69#define QUALITY_DEF 85
70 u8 jpeg_hdr[JPEG_HDR_SZ];
71};
72
73struct jlj_command {
74 unsigned char instruction[2];
75 unsigned char ack_wanted;
76 unsigned char delay;
77};
78
79/* AFAICT these cameras will only do 320x240. */
80static struct v4l2_pix_format jlj_mode[] = {
81 { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
82 .bytesperline = 320,
83 .sizeimage = 320 * 240,
84 .colorspace = V4L2_COLORSPACE_JPEG,
85 .priv = 0},
86 { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
87 .bytesperline = 640,
88 .sizeimage = 640 * 480,
89 .colorspace = V4L2_COLORSPACE_JPEG,
90 .priv = 0}
91};
92
93/*
94 * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
95 * and 0x82 for bulk transfer.
96 */
97
98/* All commands are two bytes only */
99static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
100{
101 int retval;
102
103 if (gspca_dev->usb_err < 0)
104 return;
105 memcpy(gspca_dev->usb_buf, command, 2);
106 retval = usb_bulk_msg(gspca_dev->dev,
107 usb_sndbulkpipe(gspca_dev->dev, 3),
108 gspca_dev->usb_buf, 2, NULL, 500);
109 if (retval < 0) {
110 pr_err("command write [%02x] error %d\n",
111 gspca_dev->usb_buf[0], retval);
112 gspca_dev->usb_err = retval;
113 }
114}
115
116/* Responses are one byte only */
117static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
118{
119 int retval;
120
121 if (gspca_dev->usb_err < 0)
122 return;
123 retval = usb_bulk_msg(gspca_dev->dev,
124 usb_rcvbulkpipe(gspca_dev->dev, 0x84),
125 gspca_dev->usb_buf, 1, NULL, 500);
126 response = gspca_dev->usb_buf[0];
127 if (retval < 0) {
128 pr_err("read command [%02x] error %d\n",
129 gspca_dev->usb_buf[0], retval);
130 gspca_dev->usb_err = retval;
131 }
132}
133
134static void setfreq(struct gspca_dev *gspca_dev, s32 val)
135{
136 u8 freq_commands[][2] = {
137 {0x71, 0x80},
138 {0x70, 0x07}
139 };
140
141 freq_commands[0][1] |= val >> 1;
142
143 jlj_write2(gspca_dev, freq_commands[0]);
144 jlj_write2(gspca_dev, freq_commands[1]);
145}
146
147static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
148{
149 u8 quality_commands[][2] = {
150 {0x71, 0x1E},
151 {0x70, 0x06}
152 };
153 u8 camquality;
154
155 /* adapt camera quality from jpeg quality */
156 camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
157 / (QUALITY_MAX - QUALITY_MIN);
158 quality_commands[0][1] += camquality;
159
160 jlj_write2(gspca_dev, quality_commands[0]);
161 jlj_write2(gspca_dev, quality_commands[1]);
162}
163
164static void setautogain(struct gspca_dev *gspca_dev, s32 val)
165{
166 u8 autogain_commands[][2] = {
167 {0x94, 0x02},
168 {0xcf, 0x00}
169 };
170
171 autogain_commands[1][1] = val << 4;
172
173 jlj_write2(gspca_dev, autogain_commands[0]);
174 jlj_write2(gspca_dev, autogain_commands[1]);
175}
176
177static void setred(struct gspca_dev *gspca_dev, s32 val)
178{
179 u8 setred_commands[][2] = {
180 {0x94, 0x02},
181 {0xe6, 0x00}
182 };
183
184 setred_commands[1][1] = val;
185
186 jlj_write2(gspca_dev, setred_commands[0]);
187 jlj_write2(gspca_dev, setred_commands[1]);
188}
189
190static void setgreen(struct gspca_dev *gspca_dev, s32 val)
191{
192 u8 setgreen_commands[][2] = {
193 {0x94, 0x02},
194 {0xe7, 0x00}
195 };
196
197 setgreen_commands[1][1] = val;
198
199 jlj_write2(gspca_dev, setgreen_commands[0]);
200 jlj_write2(gspca_dev, setgreen_commands[1]);
201}
202
203static void setblue(struct gspca_dev *gspca_dev, s32 val)
204{
205 u8 setblue_commands[][2] = {
206 {0x94, 0x02},
207 {0xe9, 0x00}
208 };
209
210 setblue_commands[1][1] = val;
211
212 jlj_write2(gspca_dev, setblue_commands[0]);
213 jlj_write2(gspca_dev, setblue_commands[1]);
214}
215
216static int jlj_start(struct gspca_dev *gspca_dev)
217{
218 int i;
219 int start_commands_size;
220 u8 response = 0xff;
221 struct sd *sd = (struct sd *) gspca_dev;
222 struct jlj_command start_commands[] = {
223 {{0x71, 0x81}, 0, 0},
224 {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
225 {{0x95, 0x70}, 1, 0},
226 {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
227 {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
228 {{0x95, 0x70}, 1, 0},
229 {{0x71, 0x00}, 0, 0}, /* start streaming ??*/
230 {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
231 {{0x95, 0x70}, 1, 0},
232#define SPORTSCAM_DV15_CMD_SIZE 9
233 {{0x94, 0x02}, 0, 0},
234 {{0xde, 0x24}, 0, 0},
235 {{0x94, 0x02}, 0, 0},
236 {{0xdd, 0xf0}, 0, 0},
237 {{0x94, 0x02}, 0, 0},
238 {{0xe3, 0x2c}, 0, 0},
239 {{0x94, 0x02}, 0, 0},
240 {{0xe4, 0x00}, 0, 0},
241 {{0x94, 0x02}, 0, 0},
242 {{0xe5, 0x00}, 0, 0},
243 {{0x94, 0x02}, 0, 0},
244 {{0xe6, 0x2c}, 0, 0},
245 {{0x94, 0x03}, 0, 0},
246 {{0xaa, 0x00}, 0, 0}
247 };
248
249 sd->blocks_left = 0;
250 /* Under Windows, USB spy shows that only the 9 first start
251 * commands are used for SPORTSCAM_DV15 webcam
252 */
253 if (sd->type == SPORTSCAM_DV15)
254 start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
255 else
256 start_commands_size = ARRAY_SIZE(start_commands);
257
258 for (i = 0; i < start_commands_size; i++) {
259 jlj_write2(gspca_dev, start_commands[i].instruction);
260 if (start_commands[i].delay)
261 msleep(start_commands[i].delay);
262 if (start_commands[i].ack_wanted)
263 jlj_read1(gspca_dev, response);
264 }
265 setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
266 msleep(2);
267 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
268 if (gspca_dev->usb_err < 0)
269 PDEBUG(D_ERR, "Start streaming command failed");
270 return gspca_dev->usb_err;
271}
272
273static void sd_pkt_scan(struct gspca_dev *gspca_dev,
274 u8 *data, int len)
275{
276 struct sd *sd = (struct sd *) gspca_dev;
277 int packet_type;
278 u32 header_marker;
279
280 PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0",
281 len, JEILINJ_MAX_TRANSFER);
282 if (len != JEILINJ_MAX_TRANSFER) {
283 PDEBUG(D_PACK, "bad length");
284 goto discard;
285 }
286 /* check if it's start of frame */
287 header_marker = ((u32 *)data)[0];
288 if (header_marker == FRAME_START) {
289 sd->blocks_left = data[0x0a] - 1;
290 PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left);
291 /* Start a new frame, and add the JPEG header, first thing */
292 gspca_frame_add(gspca_dev, FIRST_PACKET,
293 sd->jpeg_hdr, JPEG_HDR_SZ);
294 /* Toss line 0 of data block 0, keep the rest. */
295 gspca_frame_add(gspca_dev, INTER_PACKET,
296 data + FRAME_HEADER_LEN,
297 JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
298 } else if (sd->blocks_left > 0) {
299 PDEBUG(D_STREAM, "%d blocks remaining for frame",
300 sd->blocks_left);
301 sd->blocks_left -= 1;
302 if (sd->blocks_left == 0)
303 packet_type = LAST_PACKET;
304 else
305 packet_type = INTER_PACKET;
306 gspca_frame_add(gspca_dev, packet_type,
307 data, JEILINJ_MAX_TRANSFER);
308 } else
309 goto discard;
310 return;
311discard:
312 /* Discard data until a new frame starts. */
313 gspca_dev->last_packet_type = DISCARD_PACKET;
314}
315
316/* This function is called at probe time just before sd_init */
317static int sd_config(struct gspca_dev *gspca_dev,
318 const struct usb_device_id *id)
319{
320 struct cam *cam = &gspca_dev->cam;
321 struct sd *dev = (struct sd *) gspca_dev;
322
323 dev->type = id->driver_info;
324 dev->quality = QUALITY_DEF;
325
326 cam->cam_mode = jlj_mode;
327 cam->nmodes = ARRAY_SIZE(jlj_mode);
328 cam->bulk = 1;
329 cam->bulk_nurbs = 1;
330 cam->bulk_size = JEILINJ_MAX_TRANSFER;
331 return 0;
332}
333
334static void sd_stopN(struct gspca_dev *gspca_dev)
335{
336 int i;
337 u8 *buf;
338 static u8 stop_commands[][2] = {
339 {0x71, 0x00},
340 {0x70, 0x09},
341 {0x71, 0x80},
342 {0x70, 0x05}
343 };
344
345 for (;;) {
346 /* get the image remaining blocks */
347 usb_bulk_msg(gspca_dev->dev,
348 gspca_dev->urb[0]->pipe,
349 gspca_dev->urb[0]->transfer_buffer,
350 JEILINJ_MAX_TRANSFER, NULL,
351 JEILINJ_DATA_TIMEOUT);
352
353 /* search for 0xff 0xd9 (EOF for JPEG) */
354 i = 0;
355 buf = gspca_dev->urb[0]->transfer_buffer;
356 while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
357 ((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
358 i++;
359
360 if (i != (JEILINJ_MAX_TRANSFER - 1))
361 /* last remaining block found */
362 break;
363 }
364
365 for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
366 jlj_write2(gspca_dev, stop_commands[i]);
367}
368
369/* this function is called at probe and resume time */
370static int sd_init(struct gspca_dev *gspca_dev)
371{
372 return gspca_dev->usb_err;
373}
374
375/* Set up for getting frames. */
376static int sd_start(struct gspca_dev *gspca_dev)
377{
378 struct sd *dev = (struct sd *) gspca_dev;
379
380 /* create the JPEG header */
381 jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
382 0x21); /* JPEG 422 */
383 jpeg_set_qual(dev->jpeg_hdr, dev->quality);
384 PDEBUG(D_STREAM, "Start streaming at %dx%d",
385 gspca_dev->height, gspca_dev->width);
386 jlj_start(gspca_dev);
387 return gspca_dev->usb_err;
388}
389
390/* Table of supported USB devices */
391static const struct usb_device_id device_table[] = {
392 {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
393 {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
394 {}
395};
396
397MODULE_DEVICE_TABLE(usb, device_table);
398
399static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
400{
401 struct gspca_dev *gspca_dev =
402 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
403 struct sd *sd = (struct sd *)gspca_dev;
404
405 gspca_dev->usb_err = 0;
406
407 if (!gspca_dev->streaming)
408 return 0;
409
410 switch (ctrl->id) {
411 case V4L2_CID_POWER_LINE_FREQUENCY:
412 setfreq(gspca_dev, ctrl->val);
413 break;
414 case V4L2_CID_RED_BALANCE:
415 setred(gspca_dev, ctrl->val);
416 break;
417 case V4L2_CID_GAIN:
418 setgreen(gspca_dev, ctrl->val);
419 break;
420 case V4L2_CID_BLUE_BALANCE:
421 setblue(gspca_dev, ctrl->val);
422 break;
423 case V4L2_CID_AUTOGAIN:
424 setautogain(gspca_dev, ctrl->val);
425 break;
426 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
427 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
428 setcamquality(gspca_dev, ctrl->val);
429 break;
430 }
431 return gspca_dev->usb_err;
432}
433
434static const struct v4l2_ctrl_ops sd_ctrl_ops = {
435 .s_ctrl = sd_s_ctrl,
436};
437
438static int sd_init_controls(struct gspca_dev *gspca_dev)
439{
440 struct sd *sd = (struct sd *)gspca_dev;
441 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
442 static const struct v4l2_ctrl_config custom_autogain = {
443 .ops = &sd_ctrl_ops,
444 .id = V4L2_CID_AUTOGAIN,
445 .type = V4L2_CTRL_TYPE_INTEGER,
446 .name = "Automatic Gain (and Exposure)",
447 .max = 3,
448 .step = 1,
449 .def = 0,
450 };
451
452 gspca_dev->vdev.ctrl_handler = hdl;
453 v4l2_ctrl_handler_init(hdl, 6);
454 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
455 V4L2_CID_POWER_LINE_FREQUENCY,
456 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
457 V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
458 v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
459 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
460 V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
461 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
462 V4L2_CID_GAIN, 0, 3, 1, 2);
463 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
464 V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
465 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
466 V4L2_CID_JPEG_COMPRESSION_QUALITY,
467 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
468
469 if (hdl->error) {
470 pr_err("Could not initialize controls\n");
471 return hdl->error;
472 }
473 return 0;
474}
475
476static int sd_set_jcomp(struct gspca_dev *gspca_dev,
477 struct v4l2_jpegcompression *jcomp)
478{
479 struct sd *sd = (struct sd *) gspca_dev;
480
481 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
482 return 0;
483}
484
485static int sd_get_jcomp(struct gspca_dev *gspca_dev,
486 struct v4l2_jpegcompression *jcomp)
487{
488 struct sd *sd = (struct sd *) gspca_dev;
489
490 memset(jcomp, 0, sizeof *jcomp);
491 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
492 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
493 | V4L2_JPEG_MARKER_DQT;
494 return 0;
495}
496
497
498/* sub-driver description */
499static const struct sd_desc sd_desc_sakar_57379 = {
500 .name = MODULE_NAME,
501 .config = sd_config,
502 .init = sd_init,
503 .start = sd_start,
504 .stopN = sd_stopN,
505 .pkt_scan = sd_pkt_scan,
506};
507
508/* sub-driver description */
509static const struct sd_desc sd_desc_sportscam_dv15 = {
510 .name = MODULE_NAME,
511 .config = sd_config,
512 .init = sd_init,
513 .init_controls = sd_init_controls,
514 .start = sd_start,
515 .stopN = sd_stopN,
516 .pkt_scan = sd_pkt_scan,
517 .get_jcomp = sd_get_jcomp,
518 .set_jcomp = sd_set_jcomp,
519};
520
521static const struct sd_desc *sd_desc[2] = {
522 &sd_desc_sakar_57379,
523 &sd_desc_sportscam_dv15
524};
525
526/* -- device connect -- */
527static int sd_probe(struct usb_interface *intf,
528 const struct usb_device_id *id)
529{
530 return gspca_dev_probe(intf, id,
531 sd_desc[id->driver_info],
532 sizeof(struct sd),
533 THIS_MODULE);
534}
535
536static struct usb_driver sd_driver = {
537 .name = MODULE_NAME,
538 .id_table = device_table,
539 .probe = sd_probe,
540 .disconnect = gspca_disconnect,
541#ifdef CONFIG_PM
542 .suspend = gspca_suspend,
543 .resume = gspca_resume,
544 .reset_resume = gspca_resume,
545#endif
546};
547
548module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/jl2005bcd.c b/drivers/media/usb/gspca/jl2005bcd.c
new file mode 100644
index 00000000000..cf9d9fca5b8
--- /dev/null
+++ b/drivers/media/usb/gspca/jl2005bcd.c
@@ -0,0 +1,557 @@
1/*
2 * Jeilin JL2005B/C/D library
3 *
4 * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu>
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 "jl2005bcd"
22
23#include <linux/workqueue.h>
24#include <linux/slab.h>
25#include "gspca.h"
26
27
28MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
29MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* Default timeouts, in ms */
33#define JL2005C_CMD_TIMEOUT 500
34#define JL2005C_DATA_TIMEOUT 1000
35
36/* Maximum transfer size to use. */
37#define JL2005C_MAX_TRANSFER 0x200
38#define FRAME_HEADER_LEN 16
39
40
41/* specific webcam descriptor */
42struct sd {
43 struct gspca_dev gspca_dev; /* !! must be the first item */
44 unsigned char firmware_id[6];
45 const struct v4l2_pix_format *cap_mode;
46 /* Driver stuff */
47 struct work_struct work_struct;
48 struct workqueue_struct *work_thread;
49 u8 frame_brightness;
50 int block_size; /* block size of camera */
51 int vga; /* 1 if vga cam, 0 if cif cam */
52};
53
54
55/* Camera has two resolution settings. What they are depends on model. */
56static const struct v4l2_pix_format cif_mode[] = {
57 {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
58 .bytesperline = 176,
59 .sizeimage = 176 * 144,
60 .colorspace = V4L2_COLORSPACE_SRGB,
61 .priv = 0},
62 {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
63 .bytesperline = 352,
64 .sizeimage = 352 * 288,
65 .colorspace = V4L2_COLORSPACE_SRGB,
66 .priv = 0},
67};
68
69static const struct v4l2_pix_format vga_mode[] = {
70 {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
71 .bytesperline = 320,
72 .sizeimage = 320 * 240,
73 .colorspace = V4L2_COLORSPACE_SRGB,
74 .priv = 0},
75 {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
76 .bytesperline = 640,
77 .sizeimage = 640 * 480,
78 .colorspace = V4L2_COLORSPACE_SRGB,
79 .priv = 0},
80};
81
82/*
83 * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
84 * and 0x82 for bulk data transfer.
85 */
86
87/* All commands are two bytes only */
88static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
89{
90 int retval;
91
92 memcpy(gspca_dev->usb_buf, command, 2);
93 retval = usb_bulk_msg(gspca_dev->dev,
94 usb_sndbulkpipe(gspca_dev->dev, 3),
95 gspca_dev->usb_buf, 2, NULL, 500);
96 if (retval < 0)
97 pr_err("command write [%02x] error %d\n",
98 gspca_dev->usb_buf[0], retval);
99 return retval;
100}
101
102/* Response to a command is one byte in usb_buf[0], only if requested. */
103static int jl2005c_read1(struct gspca_dev *gspca_dev)
104{
105 int retval;
106
107 retval = usb_bulk_msg(gspca_dev->dev,
108 usb_rcvbulkpipe(gspca_dev->dev, 0x84),
109 gspca_dev->usb_buf, 1, NULL, 500);
110 if (retval < 0)
111 pr_err("read command [0x%02x] error %d\n",
112 gspca_dev->usb_buf[0], retval);
113 return retval;
114}
115
116/* Response appears in gspca_dev->usb_buf[0] */
117static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
118{
119 int retval;
120
121 static u8 instruction[2] = {0x95, 0x00};
122 /* put register to read in byte 1 */
123 instruction[1] = reg;
124 /* Send the read request */
125 retval = jl2005c_write2(gspca_dev, instruction);
126 if (retval < 0)
127 return retval;
128 retval = jl2005c_read1(gspca_dev);
129
130 return retval;
131}
132
133static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
134{
135 int i;
136 int retval;
137 int frame_brightness = 0;
138
139 static u8 instruction[2] = {0x7f, 0x01};
140
141 retval = jl2005c_write2(gspca_dev, instruction);
142 if (retval < 0)
143 return retval;
144
145 i = 0;
146 while (i < 20 && !frame_brightness) {
147 /* If we tried 20 times, give up. */
148 retval = jl2005c_read_reg(gspca_dev, 0x7e);
149 if (retval < 0)
150 return retval;
151 frame_brightness = gspca_dev->usb_buf[0];
152 retval = jl2005c_read_reg(gspca_dev, 0x7d);
153 if (retval < 0)
154 return retval;
155 i++;
156 }
157 PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]);
158 return retval;
159}
160
161static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
162 unsigned char value)
163{
164 int retval;
165 u8 instruction[2];
166
167 instruction[0] = reg;
168 instruction[1] = value;
169
170 retval = jl2005c_write2(gspca_dev, instruction);
171 if (retval < 0)
172 return retval;
173
174 return retval;
175}
176
177static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
178{
179 struct sd *sd = (struct sd *)gspca_dev;
180 int i = 0;
181 int retval = -1;
182 unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f};
183
184 PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id");
185 /* Read the first ID byte once for warmup */
186 retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
187 PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]);
188 if (retval < 0)
189 return retval;
190 /* Now actually get the ID string */
191 for (i = 0; i < 6; i++) {
192 retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
193 if (retval < 0)
194 return retval;
195 sd->firmware_id[i] = gspca_dev->usb_buf[0];
196 }
197 PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x",
198 sd->firmware_id[0],
199 sd->firmware_id[1],
200 sd->firmware_id[2],
201 sd->firmware_id[3],
202 sd->firmware_id[4],
203 sd->firmware_id[5]);
204 return 0;
205}
206
207static int jl2005c_stream_start_vga_lg
208 (struct gspca_dev *gspca_dev)
209{
210 int i;
211 int retval = -1;
212 static u8 instruction[][2] = {
213 {0x05, 0x00},
214 {0x7c, 0x00},
215 {0x7d, 0x18},
216 {0x02, 0x00},
217 {0x01, 0x00},
218 {0x04, 0x52},
219 };
220
221 for (i = 0; i < ARRAY_SIZE(instruction); i++) {
222 msleep(60);
223 retval = jl2005c_write2(gspca_dev, instruction[i]);
224 if (retval < 0)
225 return retval;
226 }
227 msleep(60);
228 return retval;
229}
230
231static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
232{
233 int i;
234 int retval = -1;
235 static u8 instruction[][2] = {
236 {0x06, 0x00},
237 {0x7c, 0x00},
238 {0x7d, 0x1a},
239 {0x02, 0x00},
240 {0x01, 0x00},
241 {0x04, 0x52},
242 };
243
244 for (i = 0; i < ARRAY_SIZE(instruction); i++) {
245 msleep(60);
246 retval = jl2005c_write2(gspca_dev, instruction[i]);
247 if (retval < 0)
248 return retval;
249 }
250 msleep(60);
251 return retval;
252}
253
254static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
255{
256 int i;
257 int retval = -1;
258 static u8 instruction[][2] = {
259 {0x05, 0x00},
260 {0x7c, 0x00},
261 {0x7d, 0x30},
262 {0x02, 0x00},
263 {0x01, 0x00},
264 {0x04, 0x42},
265 };
266
267 for (i = 0; i < ARRAY_SIZE(instruction); i++) {
268 msleep(60);
269 retval = jl2005c_write2(gspca_dev, instruction[i]);
270 if (retval < 0)
271 return retval;
272 }
273 msleep(60);
274 return retval;
275}
276
277static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
278{
279 int i;
280 int retval = -1;
281 static u8 instruction[][2] = {
282 {0x06, 0x00},
283 {0x7c, 0x00},
284 {0x7d, 0x32},
285 {0x02, 0x00},
286 {0x01, 0x00},
287 {0x04, 0x42},
288 };
289
290 for (i = 0; i < ARRAY_SIZE(instruction); i++) {
291 msleep(60);
292 retval = jl2005c_write2(gspca_dev, instruction[i]);
293 if (retval < 0)
294 return retval;
295 }
296 msleep(60);
297 return retval;
298}
299
300
301static int jl2005c_stop(struct gspca_dev *gspca_dev)
302{
303 int retval;
304
305 retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
306 return retval;
307}
308
309/* This function is called as a workqueue function and runs whenever the camera
310 * is streaming data. Because it is a workqueue function it is allowed to sleep
311 * so we can use synchronous USB calls. To avoid possible collisions with other
312 * threads attempting to use the camera's USB interface the gspca usb_lock is
313 * used when performing the one USB control operation inside the workqueue,
314 * which tells the camera to close the stream. In practice the only thing
315 * which needs to be protected against is the usb_set_interface call that
316 * gspca makes during stream_off. Otherwise the camera doesn't provide any
317 * controls that the user could try to change.
318 */
319static void jl2005c_dostream(struct work_struct *work)
320{
321 struct sd *dev = container_of(work, struct sd, work_struct);
322 struct gspca_dev *gspca_dev = &dev->gspca_dev;
323 int bytes_left = 0; /* bytes remaining in current frame. */
324 int data_len; /* size to use for the next read. */
325 int header_read = 0;
326 unsigned char header_sig[2] = {0x4a, 0x4c};
327 int act_len;
328 int packet_type;
329 int ret;
330 u8 *buffer;
331
332 buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
333 if (!buffer) {
334 pr_err("Couldn't allocate USB buffer\n");
335 goto quit_stream;
336 }
337
338 while (gspca_dev->dev && gspca_dev->streaming) {
339#ifdef CONFIG_PM
340 if (gspca_dev->frozen)
341 break;
342#endif
343 /* Check if this is a new frame. If so, start the frame first */
344 if (!header_read) {
345 mutex_lock(&gspca_dev->usb_lock);
346 ret = jl2005c_start_new_frame(gspca_dev);
347 mutex_unlock(&gspca_dev->usb_lock);
348 if (ret < 0)
349 goto quit_stream;
350 ret = usb_bulk_msg(gspca_dev->dev,
351 usb_rcvbulkpipe(gspca_dev->dev, 0x82),
352 buffer, JL2005C_MAX_TRANSFER, &act_len,
353 JL2005C_DATA_TIMEOUT);
354 PDEBUG(D_PACK,
355 "Got %d bytes out of %d for header",
356 act_len, JL2005C_MAX_TRANSFER);
357 if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
358 goto quit_stream;
359 /* Check whether we actually got the first blodk */
360 if (memcmp(header_sig, buffer, 2) != 0) {
361 pr_err("First block is not the first block\n");
362 goto quit_stream;
363 }
364 /* total size to fetch is byte 7, times blocksize
365 * of which we already got act_len */
366 bytes_left = buffer[0x07] * dev->block_size - act_len;
367 PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left);
368 /* We keep the header. It has other information, too.*/
369 packet_type = FIRST_PACKET;
370 gspca_frame_add(gspca_dev, packet_type,
371 buffer, act_len);
372 header_read = 1;
373 }
374 while (bytes_left > 0 && gspca_dev->dev) {
375 data_len = bytes_left > JL2005C_MAX_TRANSFER ?
376 JL2005C_MAX_TRANSFER : bytes_left;
377 ret = usb_bulk_msg(gspca_dev->dev,
378 usb_rcvbulkpipe(gspca_dev->dev, 0x82),
379 buffer, data_len, &act_len,
380 JL2005C_DATA_TIMEOUT);
381 if (ret < 0 || act_len < data_len)
382 goto quit_stream;
383 PDEBUG(D_PACK,
384 "Got %d bytes out of %d for frame",
385 data_len, bytes_left);
386 bytes_left -= data_len;
387 if (bytes_left == 0) {
388 packet_type = LAST_PACKET;
389 header_read = 0;
390 } else
391 packet_type = INTER_PACKET;
392 gspca_frame_add(gspca_dev, packet_type,
393 buffer, data_len);
394 }
395 }
396quit_stream:
397 if (gspca_dev->dev) {
398 mutex_lock(&gspca_dev->usb_lock);
399 jl2005c_stop(gspca_dev);
400 mutex_unlock(&gspca_dev->usb_lock);
401 }
402 kfree(buffer);
403}
404
405
406
407
408/* This function is called at probe time */
409static int sd_config(struct gspca_dev *gspca_dev,
410 const struct usb_device_id *id)
411{
412 struct cam *cam;
413 struct sd *sd = (struct sd *) gspca_dev;
414
415 cam = &gspca_dev->cam;
416 /* We don't use the buffer gspca allocates so make it small. */
417 cam->bulk_size = 64;
418 cam->bulk = 1;
419 /* For the rest, the camera needs to be detected */
420 jl2005c_get_firmware_id(gspca_dev);
421 /* Here are some known firmware IDs
422 * First some JL2005B cameras
423 * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam
424 * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B
425 * JL2005C cameras
426 * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512
427 * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly
428 * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz
429 *
430 * Based upon this scanty evidence, we can detect a CIF camera by
431 * testing byte 0 for 0x4x.
432 */
433 if ((sd->firmware_id[0] & 0xf0) == 0x40) {
434 cam->cam_mode = cif_mode;
435 cam->nmodes = ARRAY_SIZE(cif_mode);
436 sd->block_size = 0x80;
437 } else {
438 cam->cam_mode = vga_mode;
439 cam->nmodes = ARRAY_SIZE(vga_mode);
440 sd->block_size = 0x200;
441 }
442
443 INIT_WORK(&sd->work_struct, jl2005c_dostream);
444
445 return 0;
446}
447
448/* this function is called at probe and resume time */
449static int sd_init(struct gspca_dev *gspca_dev)
450{
451 return 0;
452}
453
454static int sd_start(struct gspca_dev *gspca_dev)
455{
456
457 struct sd *sd = (struct sd *) gspca_dev;
458 sd->cap_mode = gspca_dev->cam.cam_mode;
459
460 switch (gspca_dev->width) {
461 case 640:
462 PDEBUG(D_STREAM, "Start streaming at vga resolution");
463 jl2005c_stream_start_vga_lg(gspca_dev);
464 break;
465 case 320:
466 PDEBUG(D_STREAM, "Start streaming at qvga resolution");
467 jl2005c_stream_start_vga_small(gspca_dev);
468 break;
469 case 352:
470 PDEBUG(D_STREAM, "Start streaming at cif resolution");
471 jl2005c_stream_start_cif_lg(gspca_dev);
472 break;
473 case 176:
474 PDEBUG(D_STREAM, "Start streaming at qcif resolution");
475 jl2005c_stream_start_cif_small(gspca_dev);
476 break;
477 default:
478 pr_err("Unknown resolution specified\n");
479 return -1;
480 }
481
482 /* Start the workqueue function to do the streaming */
483 sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
484 queue_work(sd->work_thread, &sd->work_struct);
485
486 return 0;
487}
488
489/* called on streamoff with alt==0 and on disconnect */
490/* the usb_lock is held at entry - restore on exit */
491static void sd_stop0(struct gspca_dev *gspca_dev)
492{
493 struct sd *dev = (struct sd *) gspca_dev;
494
495 /* wait for the work queue to terminate */
496 mutex_unlock(&gspca_dev->usb_lock);
497 /* This waits for sq905c_dostream to finish */
498 destroy_workqueue(dev->work_thread);
499 dev->work_thread = NULL;
500 mutex_lock(&gspca_dev->usb_lock);
501}
502
503
504
505/* sub-driver description */
506static const struct sd_desc sd_desc = {
507 .name = MODULE_NAME,
508 .config = sd_config,
509 .init = sd_init,
510 .start = sd_start,
511 .stop0 = sd_stop0,
512};
513
514/* -- module initialisation -- */
515static const __devinitdata struct usb_device_id device_table[] = {
516 {USB_DEVICE(0x0979, 0x0227)},
517 {}
518};
519MODULE_DEVICE_TABLE(usb, device_table);
520
521/* -- device connect -- */
522static int sd_probe(struct usb_interface *intf,
523 const struct usb_device_id *id)
524{
525 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
526 THIS_MODULE);
527}
528
529static struct usb_driver sd_driver = {
530 .name = MODULE_NAME,
531 .id_table = device_table,
532 .probe = sd_probe,
533 .disconnect = gspca_disconnect,
534#ifdef CONFIG_PM
535 .suspend = gspca_suspend,
536 .resume = gspca_resume,
537 .reset_resume = gspca_resume,
538#endif
539};
540
541/* -- module insert / remove -- */
542static int __init sd_mod_init(void)
543{
544 int ret;
545
546 ret = usb_register(&sd_driver);
547 if (ret < 0)
548 return ret;
549 return 0;
550}
551static void __exit sd_mod_exit(void)
552{
553 usb_deregister(&sd_driver);
554}
555
556module_init(sd_mod_init);
557module_exit(sd_mod_exit);
diff --git a/drivers/media/usb/gspca/jpeg.h b/drivers/media/usb/gspca/jpeg.h
new file mode 100644
index 00000000000..ab54910418b
--- /dev/null
+++ b/drivers/media/usb/gspca/jpeg.h
@@ -0,0 +1,168 @@
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/*
28 * generation options
29 * CONEX_CAM Conexant if present
30 */
31
32/* JPEG header */
33static const u8 jpeg_head[] = {
34 0xff, 0xd8, /* jpeg */
35
36/* quantization table quality 50% */
37 0xff, 0xdb, 0x00, 0x84, /* DQT */
380,
39#define JPEG_QT0_OFFSET 7
40 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
41 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
42 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
43 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
44 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
45 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
46 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
47 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
481,
49#define JPEG_QT1_OFFSET 72
50 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
51 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
52 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
53 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
54 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
55 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
56 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
57 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
58
59/* huffman table */
60 0xff, 0xc4, 0x01, 0xa2,
61 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
62 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
64 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03,
65 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
66 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
67 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
68 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
69 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
70 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
71 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
72 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
73 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,
74 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
75 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
76 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,
77 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
78 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
79 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
80 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
81 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86,
82 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
83 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
84 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
85 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
86 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
87 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
88 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
89 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
90 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
91 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
92 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
93 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
94 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
95 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
96 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
97 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
98 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28,
99 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
100 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
101 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
102 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
103 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
104 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
105 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
106 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
107 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
108 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
109 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
110 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
111 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2,
112 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
113#ifdef CONEX_CAM
114/* the Conexant frames start with SOF0 */
115#define JPEG_HDR_SZ 556
116#else
117 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */
118 0x08, /* data precision */
119#define JPEG_HEIGHT_OFFSET 561
120 0x01, 0xe0, /* height */
121 0x02, 0x80, /* width */
122 0x03, /* component number */
123 0x01,
124 0x21, /* samples Y */
125 0x00, /* quant Y */
126 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */
127 0x03, 0x11, 0x01,
128
129 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */
130 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
131#define JPEG_HDR_SZ 589
132#endif
133};
134
135/* define the JPEG header */
136static void jpeg_define(u8 *jpeg_hdr,
137 int height,
138 int width,
139 int samplesY)
140{
141 memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
142#ifndef CONEX_CAM
143 jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
144 jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
145 jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
146 jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
147 jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY;
148#endif
149}
150
151/* set the JPEG quality */
152static void jpeg_set_qual(u8 *jpeg_hdr,
153 int quality)
154{
155 int i, sc;
156
157 if (quality < 50)
158 sc = 5000 / quality;
159 else
160 sc = 200 - quality * 2;
161 for (i = 0; i < 64; i++) {
162 jpeg_hdr[JPEG_QT0_OFFSET + i] =
163 (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
164 jpeg_hdr[JPEG_QT1_OFFSET + i] =
165 (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
166 }
167}
168#endif
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c
new file mode 100644
index 00000000000..40ad6687ee5
--- /dev/null
+++ b/drivers/media/usb/gspca/kinect.c
@@ -0,0 +1,408 @@
1/*
2 * kinect sensor device camera, gspca driver
3 *
4 * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
5 *
6 * Based on the OpenKinect project and libfreenect
7 * http://openkinect.org/wiki/Init_Analysis
8 *
9 * Special thanks to Steven Toth and kernellabs.com for sponsoring a Kinect
10 * sensor device which I tested the driver on.
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29#define MODULE_NAME "kinect"
30
31#include "gspca.h"
32
33#define CTRL_TIMEOUT 500
34
35MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
36MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
37MODULE_LICENSE("GPL");
38
39struct pkt_hdr {
40 uint8_t magic[2];
41 uint8_t pad;
42 uint8_t flag;
43 uint8_t unk1;
44 uint8_t seq;
45 uint8_t unk2;
46 uint8_t unk3;
47 uint32_t timestamp;
48};
49
50struct cam_hdr {
51 uint8_t magic[2];
52 uint16_t len;
53 uint16_t cmd;
54 uint16_t tag;
55};
56
57/* specific webcam descriptor */
58struct sd {
59 struct gspca_dev gspca_dev; /* !! must be the first item */
60 uint16_t cam_tag; /* a sequence number for packets */
61 uint8_t stream_flag; /* to identify different stream types */
62 uint8_t obuf[0x400]; /* output buffer for control commands */
63 uint8_t ibuf[0x200]; /* input buffer for control commands */
64};
65
66#define MODE_640x480 0x0001
67#define MODE_640x488 0x0002
68#define MODE_1280x1024 0x0004
69
70#define FORMAT_BAYER 0x0010
71#define FORMAT_UYVY 0x0020
72#define FORMAT_Y10B 0x0040
73
74#define FPS_HIGH 0x0100
75
76static const struct v4l2_pix_format video_camera_mode[] = {
77 {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
78 .bytesperline = 640,
79 .sizeimage = 640 * 480,
80 .colorspace = V4L2_COLORSPACE_SRGB,
81 .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH},
82 {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
83 .bytesperline = 640 * 2,
84 .sizeimage = 640 * 480 * 2,
85 .colorspace = V4L2_COLORSPACE_SRGB,
86 .priv = MODE_640x480 | FORMAT_UYVY},
87 {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
88 .bytesperline = 1280,
89 .sizeimage = 1280 * 1024,
90 .colorspace = V4L2_COLORSPACE_SRGB,
91 .priv = MODE_1280x1024 | FORMAT_BAYER},
92 {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
93 .bytesperline = 640 * 10 / 8,
94 .sizeimage = 640 * 488 * 10 / 8,
95 .colorspace = V4L2_COLORSPACE_SRGB,
96 .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH},
97 {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
98 .bytesperline = 1280 * 10 / 8,
99 .sizeimage = 1280 * 1024 * 10 / 8,
100 .colorspace = V4L2_COLORSPACE_SRGB,
101 .priv = MODE_1280x1024 | FORMAT_Y10B},
102};
103
104static int kinect_write(struct usb_device *udev, uint8_t *data,
105 uint16_t wLength)
106{
107 return usb_control_msg(udev,
108 usb_sndctrlpipe(udev, 0),
109 0x00,
110 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
111 0, 0, data, wLength, CTRL_TIMEOUT);
112}
113
114static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength)
115{
116 return usb_control_msg(udev,
117 usb_rcvctrlpipe(udev, 0),
118 0x00,
119 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
120 0, 0, data, wLength, CTRL_TIMEOUT);
121}
122
123static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
124 unsigned int cmd_len, void *replybuf, unsigned int reply_len)
125{
126 struct sd *sd = (struct sd *) gspca_dev;
127 struct usb_device *udev = gspca_dev->dev;
128 int res, actual_len;
129 uint8_t *obuf = sd->obuf;
130 uint8_t *ibuf = sd->ibuf;
131 struct cam_hdr *chdr = (void *)obuf;
132 struct cam_hdr *rhdr = (void *)ibuf;
133
134 if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
135 pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
136 return -1;
137 }
138
139 chdr->magic[0] = 0x47;
140 chdr->magic[1] = 0x4d;
141 chdr->cmd = cpu_to_le16(cmd);
142 chdr->tag = cpu_to_le16(sd->cam_tag);
143 chdr->len = cpu_to_le16(cmd_len / 2);
144
145 memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);
146
147 res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr));
148 PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
149 sd->cam_tag, cmd_len, res);
150 if (res < 0) {
151 pr_err("send_cmd: Output control transfer failed (%d)\n", res);
152 return res;
153 }
154
155 do {
156 actual_len = kinect_read(udev, ibuf, 0x200);
157 } while (actual_len == 0);
158 PDEBUG(D_USBO, "Control reply: %d", res);
159 if (actual_len < sizeof(*rhdr)) {
160 pr_err("send_cmd: Input control transfer failed (%d)\n", res);
161 return res;
162 }
163 actual_len -= sizeof(*rhdr);
164
165 if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
166 pr_err("send_cmd: Bad magic %02x %02x\n",
167 rhdr->magic[0], rhdr->magic[1]);
168 return -1;
169 }
170 if (rhdr->cmd != chdr->cmd) {
171 pr_err("send_cmd: Bad cmd %02x != %02x\n",
172 rhdr->cmd, chdr->cmd);
173 return -1;
174 }
175 if (rhdr->tag != chdr->tag) {
176 pr_err("send_cmd: Bad tag %04x != %04x\n",
177 rhdr->tag, chdr->tag);
178 return -1;
179 }
180 if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
181 pr_err("send_cmd: Bad len %04x != %04x\n",
182 cpu_to_le16(rhdr->len), (int)(actual_len/2));
183 return -1;
184 }
185
186 if (actual_len > reply_len) {
187 pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
188 reply_len, actual_len);
189 memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
190 } else {
191 memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
192 }
193
194 sd->cam_tag++;
195
196 return actual_len;
197}
198
199static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
200 uint16_t data)
201{
202 uint16_t reply[2];
203 uint16_t cmd[2];
204 int res;
205
206 cmd[0] = cpu_to_le16(reg);
207 cmd[1] = cpu_to_le16(data);
208
209 PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data);
210 res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4);
211 if (res < 0)
212 return res;
213 if (res != 2) {
214 pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
215 res, reply[0], reply[1]);
216 }
217 return 0;
218}
219
220/* this function is called at probe time */
221static int sd_config(struct gspca_dev *gspca_dev,
222 const struct usb_device_id *id)
223{
224 struct sd *sd = (struct sd *) gspca_dev;
225 struct cam *cam;
226
227 sd->cam_tag = 0;
228
229 /* Only video stream is supported for now,
230 * which has stream flag = 0x80 */
231 sd->stream_flag = 0x80;
232
233 cam = &gspca_dev->cam;
234
235 cam->cam_mode = video_camera_mode;
236 cam->nmodes = ARRAY_SIZE(video_camera_mode);
237
238#if 0
239 /* Setting those values is not needed for video stream */
240 cam->npkt = 15;
241 gspca_dev->pkt_size = 960 * 2;
242#endif
243
244 return 0;
245}
246
247/* this function is called at probe and resume time */
248static int sd_init(struct gspca_dev *gspca_dev)
249{
250 PDEBUG(D_PROBE, "Kinect Camera device.");
251
252 return 0;
253}
254
255static int sd_start(struct gspca_dev *gspca_dev)
256{
257 int mode;
258 uint8_t fmt_reg, fmt_val;
259 uint8_t res_reg, res_val;
260 uint8_t fps_reg, fps_val;
261 uint8_t mode_val;
262
263 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
264
265 if (mode & FORMAT_Y10B) {
266 fmt_reg = 0x19;
267 res_reg = 0x1a;
268 fps_reg = 0x1b;
269 mode_val = 0x03;
270 } else {
271 fmt_reg = 0x0c;
272 res_reg = 0x0d;
273 fps_reg = 0x0e;
274 mode_val = 0x01;
275 }
276
277 /* format */
278 if (mode & FORMAT_UYVY)
279 fmt_val = 0x05;
280 else
281 fmt_val = 0x00;
282
283 if (mode & MODE_1280x1024)
284 res_val = 0x02;
285 else
286 res_val = 0x01;
287
288 if (mode & FPS_HIGH)
289 fps_val = 0x1e;
290 else
291 fps_val = 0x0f;
292
293
294 /* turn off IR-reset function */
295 write_register(gspca_dev, 0x105, 0x00);
296
297 /* Reset video stream */
298 write_register(gspca_dev, 0x05, 0x00);
299
300 /* Due to some ridiculous condition in the firmware, we have to start
301 * and stop the depth stream before the camera will hand us 1280x1024
302 * IR. This is a stupid workaround, but we've yet to find a better
303 * solution.
304 *
305 * Thanks to Drew Fisher for figuring this out.
306 */
307 if (mode & (FORMAT_Y10B | MODE_1280x1024)) {
308 write_register(gspca_dev, 0x13, 0x01);
309 write_register(gspca_dev, 0x14, 0x1e);
310 write_register(gspca_dev, 0x06, 0x02);
311 write_register(gspca_dev, 0x06, 0x00);
312 }
313
314 write_register(gspca_dev, fmt_reg, fmt_val);
315 write_register(gspca_dev, res_reg, res_val);
316 write_register(gspca_dev, fps_reg, fps_val);
317
318 /* Start video stream */
319 write_register(gspca_dev, 0x05, mode_val);
320
321 /* disable Hflip */
322 write_register(gspca_dev, 0x47, 0x00);
323
324 return 0;
325}
326
327static void sd_stopN(struct gspca_dev *gspca_dev)
328{
329 /* reset video stream */
330 write_register(gspca_dev, 0x05, 0x00);
331}
332
333static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
334{
335 struct sd *sd = (struct sd *) gspca_dev;
336
337 struct pkt_hdr *hdr = (void *)__data;
338 uint8_t *data = __data + sizeof(*hdr);
339 int datalen = len - sizeof(*hdr);
340
341 uint8_t sof = sd->stream_flag | 1;
342 uint8_t mof = sd->stream_flag | 2;
343 uint8_t eof = sd->stream_flag | 5;
344
345 if (len < 12)
346 return;
347
348 if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
349 pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
350 sd->stream_flag, hdr->magic[0], hdr->magic[1]);
351 return;
352 }
353
354 if (hdr->flag == sof)
355 gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen);
356
357 else if (hdr->flag == mof)
358 gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen);
359
360 else if (hdr->flag == eof)
361 gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
362
363 else
364 pr_warn("Packet type not recognized...\n");
365}
366
367/* sub-driver description */
368static const struct sd_desc sd_desc = {
369 .name = MODULE_NAME,
370 .config = sd_config,
371 .init = sd_init,
372 .start = sd_start,
373 .stopN = sd_stopN,
374 .pkt_scan = sd_pkt_scan,
375 /*
376 .get_streamparm = sd_get_streamparm,
377 .set_streamparm = sd_set_streamparm,
378 */
379};
380
381/* -- module initialisation -- */
382static const struct usb_device_id device_table[] = {
383 {USB_DEVICE(0x045e, 0x02ae)},
384 {}
385};
386
387MODULE_DEVICE_TABLE(usb, device_table);
388
389/* -- device connect -- */
390static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
391{
392 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
393 THIS_MODULE);
394}
395
396static struct usb_driver sd_driver = {
397 .name = MODULE_NAME,
398 .id_table = device_table,
399 .probe = sd_probe,
400 .disconnect = gspca_disconnect,
401#ifdef CONFIG_PM
402 .suspend = gspca_suspend,
403 .resume = gspca_resume,
404 .reset_resume = gspca_resume,
405#endif
406};
407
408module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c
new file mode 100644
index 00000000000..bbf91e07e38
--- /dev/null
+++ b/drivers/media/usb/gspca/konica.c
@@ -0,0 +1,487 @@
1/*
2 * Driver for USB webcams based on Konica chipset. This
3 * chipset is used in Intel YC76 camera.
4 *
5 * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
6 *
7 * Based on the usbvideo v4l1 konicawc driver which is:
8 *
9 * Copyright (C) 2002 Simon Evans <spse@secret.org.uk>
10 *
11 * The code for making gspca work with a webcam with 2 isoc endpoints was
12 * taken from the benq gspca subdriver which is:
13 *
14 * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 */
30
31#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32
33#define MODULE_NAME "konica"
34
35#include <linux/input.h>
36#include "gspca.h"
37
38MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
39MODULE_DESCRIPTION("Konica chipset USB Camera Driver");
40MODULE_LICENSE("GPL");
41
42#define WHITEBAL_REG 0x01
43#define BRIGHTNESS_REG 0x02
44#define SHARPNESS_REG 0x03
45#define CONTRAST_REG 0x04
46#define SATURATION_REG 0x05
47
48/* specific webcam descriptor */
49struct sd {
50 struct gspca_dev gspca_dev; /* !! must be the first item */
51 struct urb *last_data_urb;
52 u8 snapshot_pressed;
53};
54
55
56/* .priv is what goes to register 8 for this mode, known working values:
57 0x00 -> 176x144, cropped
58 0x01 -> 176x144, cropped
59 0x02 -> 176x144, cropped
60 0x03 -> 176x144, cropped
61 0x04 -> 176x144, binned
62 0x05 -> 320x240
63 0x06 -> 320x240
64 0x07 -> 160x120, cropped
65 0x08 -> 160x120, cropped
66 0x09 -> 160x120, binned (note has 136 lines)
67 0x0a -> 160x120, binned (note has 136 lines)
68 0x0b -> 160x120, cropped
69*/
70static const struct v4l2_pix_format vga_mode[] = {
71 {160, 120, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
72 .bytesperline = 160,
73 .sizeimage = 160 * 136 * 3 / 2 + 960,
74 .colorspace = V4L2_COLORSPACE_SRGB,
75 .priv = 0x0a},
76 {176, 144, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
77 .bytesperline = 176,
78 .sizeimage = 176 * 144 * 3 / 2 + 960,
79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .priv = 0x04},
81 {320, 240, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
82 .bytesperline = 320,
83 .sizeimage = 320 * 240 * 3 / 2 + 960,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0x05},
86};
87
88static void sd_isoc_irq(struct urb *urb);
89
90static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
91{
92 struct usb_device *dev = gspca_dev->dev;
93 int ret;
94
95 if (gspca_dev->usb_err < 0)
96 return;
97 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
98 0x02,
99 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
100 value,
101 index,
102 NULL,
103 0,
104 1000);
105 if (ret < 0) {
106 pr_err("reg_w err writing %02x to %02x: %d\n",
107 value, index, ret);
108 gspca_dev->usb_err = ret;
109 }
110}
111
112static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index)
113{
114 struct usb_device *dev = gspca_dev->dev;
115 int ret;
116
117 if (gspca_dev->usb_err < 0)
118 return;
119 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
120 0x03,
121 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
122 value,
123 index,
124 gspca_dev->usb_buf,
125 2,
126 1000);
127 if (ret < 0) {
128 pr_err("reg_r err %d\n", ret);
129 gspca_dev->usb_err = ret;
130 }
131}
132
133static void konica_stream_on(struct gspca_dev *gspca_dev)
134{
135 reg_w(gspca_dev, 1, 0x0b);
136}
137
138static void konica_stream_off(struct gspca_dev *gspca_dev)
139{
140 reg_w(gspca_dev, 0, 0x0b);
141}
142
143/* this function is called at probe time */
144static int sd_config(struct gspca_dev *gspca_dev,
145 const struct usb_device_id *id)
146{
147 gspca_dev->cam.cam_mode = vga_mode;
148 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
149 gspca_dev->cam.no_urb_create = 1;
150
151 return 0;
152}
153
154/* this function is called at probe and resume time */
155static int sd_init(struct gspca_dev *gspca_dev)
156{
157 int i;
158
159 /*
160 * The konica needs a freaking large time to "boot" (approx 6.5 sec.),
161 * and does not want to be bothered while doing so :|
162 * Register 0x10 counts from 1 - 3, with 3 being "ready"
163 */
164 msleep(6000);
165 for (i = 0; i < 20; i++) {
166 reg_r(gspca_dev, 0, 0x10);
167 if (gspca_dev->usb_buf[0] == 3)
168 break;
169 msleep(100);
170 }
171 reg_w(gspca_dev, 0, 0x0d);
172
173 return gspca_dev->usb_err;
174}
175
176static int sd_start(struct gspca_dev *gspca_dev)
177{
178 struct sd *sd = (struct sd *) gspca_dev;
179 struct urb *urb;
180 int i, n, packet_size;
181 struct usb_host_interface *alt;
182 struct usb_interface *intf;
183
184 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
185 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
186 if (!alt) {
187 pr_err("Couldn't get altsetting\n");
188 return -EIO;
189 }
190
191 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
192
193 n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
194 reg_w(gspca_dev, n, 0x08);
195
196 konica_stream_on(gspca_dev);
197
198 if (gspca_dev->usb_err)
199 return gspca_dev->usb_err;
200
201 /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
202#if MAX_NURBS < 4
203#error "Not enough URBs in the gspca table"
204#endif
205#define SD_NPKT 32
206 for (n = 0; n < 4; n++) {
207 i = n & 1 ? 0 : 1;
208 packet_size =
209 le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
210 urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
211 if (!urb) {
212 pr_err("usb_alloc_urb failed\n");
213 return -ENOMEM;
214 }
215 gspca_dev->urb[n] = urb;
216 urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
217 packet_size * SD_NPKT,
218 GFP_KERNEL,
219 &urb->transfer_dma);
220 if (urb->transfer_buffer == NULL) {
221 pr_err("usb_buffer_alloc failed\n");
222 return -ENOMEM;
223 }
224
225 urb->dev = gspca_dev->dev;
226 urb->context = gspca_dev;
227 urb->transfer_buffer_length = packet_size * SD_NPKT;
228 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
229 n & 1 ? 0x81 : 0x82);
230 urb->transfer_flags = URB_ISO_ASAP
231 | URB_NO_TRANSFER_DMA_MAP;
232 urb->interval = 1;
233 urb->complete = sd_isoc_irq;
234 urb->number_of_packets = SD_NPKT;
235 for (i = 0; i < SD_NPKT; i++) {
236 urb->iso_frame_desc[i].length = packet_size;
237 urb->iso_frame_desc[i].offset = packet_size * i;
238 }
239 }
240
241 return 0;
242}
243
244static void sd_stopN(struct gspca_dev *gspca_dev)
245{
246 struct sd *sd = (struct sd *) gspca_dev;
247
248 konica_stream_off(gspca_dev);
249#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
250 /* Don't keep the button in the pressed state "forever" if it was
251 pressed when streaming is stopped */
252 if (sd->snapshot_pressed) {
253 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
254 input_sync(gspca_dev->input_dev);
255 sd->snapshot_pressed = 0;
256 }
257#endif
258}
259
260/* reception of an URB */
261static void sd_isoc_irq(struct urb *urb)
262{
263 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
264 struct sd *sd = (struct sd *) gspca_dev;
265 struct urb *data_urb, *status_urb;
266 u8 *data;
267 int i, st;
268
269 PDEBUG(D_PACK, "sd isoc irq");
270 if (!gspca_dev->streaming)
271 return;
272
273 if (urb->status != 0) {
274 if (urb->status == -ESHUTDOWN)
275 return; /* disconnection */
276#ifdef CONFIG_PM
277 if (gspca_dev->frozen)
278 return;
279#endif
280 PDEBUG(D_ERR, "urb status: %d", urb->status);
281 st = usb_submit_urb(urb, GFP_ATOMIC);
282 if (st < 0)
283 pr_err("resubmit urb error %d\n", st);
284 return;
285 }
286
287 /* if this is a data URB (ep 0x82), wait */
288 if (urb->transfer_buffer_length > 32) {
289 sd->last_data_urb = urb;
290 return;
291 }
292
293 status_urb = urb;
294 data_urb = sd->last_data_urb;
295 sd->last_data_urb = NULL;
296
297 if (!data_urb || data_urb->start_frame != status_urb->start_frame) {
298 PDEBUG(D_ERR|D_PACK, "lost sync on frames");
299 goto resubmit;
300 }
301
302 if (data_urb->number_of_packets != status_urb->number_of_packets) {
303 PDEBUG(D_ERR|D_PACK,
304 "no packets does not match, data: %d, status: %d",
305 data_urb->number_of_packets,
306 status_urb->number_of_packets);
307 goto resubmit;
308 }
309
310 for (i = 0; i < status_urb->number_of_packets; i++) {
311 if (data_urb->iso_frame_desc[i].status ||
312 status_urb->iso_frame_desc[i].status) {
313 PDEBUG(D_ERR|D_PACK,
314 "pkt %d data-status %d, status-status %d", i,
315 data_urb->iso_frame_desc[i].status,
316 status_urb->iso_frame_desc[i].status);
317 gspca_dev->last_packet_type = DISCARD_PACKET;
318 continue;
319 }
320
321 if (status_urb->iso_frame_desc[i].actual_length != 1) {
322 PDEBUG(D_ERR|D_PACK,
323 "bad status packet length %d",
324 status_urb->iso_frame_desc[i].actual_length);
325 gspca_dev->last_packet_type = DISCARD_PACKET;
326 continue;
327 }
328
329 st = *((u8 *)status_urb->transfer_buffer
330 + status_urb->iso_frame_desc[i].offset);
331
332 data = (u8 *)data_urb->transfer_buffer
333 + data_urb->iso_frame_desc[i].offset;
334
335 /* st: 0x80-0xff: frame start with frame number (ie 0-7f)
336 * otherwise:
337 * bit 0 0: keep packet
338 * 1: drop packet (padding data)
339 *
340 * bit 4 0 button not clicked
341 * 1 button clicked
342 * button is used to `take a picture' (in software)
343 */
344 if (st & 0x80) {
345 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
346 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
347 } else {
348#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
349 u8 button_state = st & 0x40 ? 1 : 0;
350 if (sd->snapshot_pressed != button_state) {
351 input_report_key(gspca_dev->input_dev,
352 KEY_CAMERA,
353 button_state);
354 input_sync(gspca_dev->input_dev);
355 sd->snapshot_pressed = button_state;
356 }
357#endif
358 if (st & 0x01)
359 continue;
360 }
361 gspca_frame_add(gspca_dev, INTER_PACKET, data,
362 data_urb->iso_frame_desc[i].actual_length);
363 }
364
365resubmit:
366 if (data_urb) {
367 st = usb_submit_urb(data_urb, GFP_ATOMIC);
368 if (st < 0)
369 PDEBUG(D_ERR|D_PACK,
370 "usb_submit_urb(data_urb) ret %d", st);
371 }
372 st = usb_submit_urb(status_urb, GFP_ATOMIC);
373 if (st < 0)
374 pr_err("usb_submit_urb(status_urb) ret %d\n", st);
375}
376
377static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
378{
379 struct gspca_dev *gspca_dev =
380 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
381
382 gspca_dev->usb_err = 0;
383
384 if (!gspca_dev->streaming)
385 return 0;
386
387 switch (ctrl->id) {
388 case V4L2_CID_BRIGHTNESS:
389 konica_stream_off(gspca_dev);
390 reg_w(gspca_dev, ctrl->val, BRIGHTNESS_REG);
391 konica_stream_on(gspca_dev);
392 break;
393 case V4L2_CID_CONTRAST:
394 konica_stream_off(gspca_dev);
395 reg_w(gspca_dev, ctrl->val, CONTRAST_REG);
396 konica_stream_on(gspca_dev);
397 break;
398 case V4L2_CID_SATURATION:
399 konica_stream_off(gspca_dev);
400 reg_w(gspca_dev, ctrl->val, SATURATION_REG);
401 konica_stream_on(gspca_dev);
402 break;
403 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
404 konica_stream_off(gspca_dev);
405 reg_w(gspca_dev, ctrl->val, WHITEBAL_REG);
406 konica_stream_on(gspca_dev);
407 break;
408 case V4L2_CID_SHARPNESS:
409 konica_stream_off(gspca_dev);
410 reg_w(gspca_dev, ctrl->val, SHARPNESS_REG);
411 konica_stream_on(gspca_dev);
412 break;
413 }
414 return gspca_dev->usb_err;
415}
416
417static const struct v4l2_ctrl_ops sd_ctrl_ops = {
418 .s_ctrl = sd_s_ctrl,
419};
420
421static int sd_init_controls(struct gspca_dev *gspca_dev)
422{
423 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
424
425 gspca_dev->vdev.ctrl_handler = hdl;
426 v4l2_ctrl_handler_init(hdl, 5);
427 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
428 V4L2_CID_BRIGHTNESS, 0, 9, 1, 4);
429 /* Needs to be verified */
430 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
431 V4L2_CID_CONTRAST, 0, 9, 1, 4);
432 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
433 V4L2_CID_SATURATION, 0, 9, 1, 4);
434 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
435 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
436 0, 33, 1, 25);
437 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
438 V4L2_CID_SHARPNESS, 0, 9, 1, 4);
439
440 if (hdl->error) {
441 pr_err("Could not initialize controls\n");
442 return hdl->error;
443 }
444 return 0;
445}
446
447/* sub-driver description */
448static const struct sd_desc sd_desc = {
449 .name = MODULE_NAME,
450 .config = sd_config,
451 .init = sd_init,
452 .init_controls = sd_init_controls,
453 .start = sd_start,
454 .stopN = sd_stopN,
455#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
456 .other_input = 1,
457#endif
458};
459
460/* -- module initialisation -- */
461static const struct usb_device_id device_table[] = {
462 {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */
463 {}
464};
465MODULE_DEVICE_TABLE(usb, device_table);
466
467/* -- device connect -- */
468static int sd_probe(struct usb_interface *intf,
469 const struct usb_device_id *id)
470{
471 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
472 THIS_MODULE);
473}
474
475static struct usb_driver sd_driver = {
476 .name = MODULE_NAME,
477 .id_table = device_table,
478 .probe = sd_probe,
479 .disconnect = gspca_disconnect,
480#ifdef CONFIG_PM
481 .suspend = gspca_suspend,
482 .resume = gspca_resume,
483 .reset_resume = gspca_resume,
484#endif
485};
486
487module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/m5602/Kconfig b/drivers/media/usb/gspca/m5602/Kconfig
new file mode 100644
index 00000000000..5a69016ed75
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/Kconfig
@@ -0,0 +1,11 @@
1config USB_M5602
2 tristate "ALi USB m5602 Camera Driver"
3 depends on VIDEO_V4L2 && USB_GSPCA
4 help
5 Say Y here if you want support for cameras based on the
6 ALi m5602 connected to various image sensors.
7
8 See <file:Documentation/video4linux/m5602.txt> for more info.
9
10 To compile this driver as a module, choose M here: the
11 module will be called gspca_m5602.
diff --git a/drivers/media/usb/gspca/m5602/Makefile b/drivers/media/usb/gspca/m5602/Makefile
new file mode 100644
index 00000000000..8e1fb5a1d2a
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/Makefile
@@ -0,0 +1,11 @@
1obj-$(CONFIG_USB_M5602) += gspca_m5602.o
2
3gspca_m5602-objs := m5602_core.o \
4 m5602_ov9650.o \
5 m5602_ov7660.o \
6 m5602_mt9m111.o \
7 m5602_po1030.o \
8 m5602_s5k83a.o \
9 m5602_s5k4aa.o
10
11ccflags-y += -I$(srctree)/drivers/media/usb/gspca
diff --git a/drivers/media/usb/gspca/m5602/m5602_bridge.h b/drivers/media/usb/gspca/m5602/m5602_bridge.h
new file mode 100644
index 00000000000..51af3ee3ab8
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_bridge.h
@@ -0,0 +1,163 @@
1/*
2 * USB Driver for ALi m5602 based webcams
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_BRIDGE_H_
20#define M5602_BRIDGE_H_
21
22#include <linux/slab.h>
23#include "gspca.h"
24
25#define MODULE_NAME "ALi m5602"
26
27/*****************************************************************************/
28
29#define M5602_XB_SENSOR_TYPE 0x00
30#define M5602_XB_SENSOR_CTRL 0x01
31#define M5602_XB_LINE_OF_FRAME_H 0x02
32#define M5602_XB_LINE_OF_FRAME_L 0x03
33#define M5602_XB_PIX_OF_LINE_H 0x04
34#define M5602_XB_PIX_OF_LINE_L 0x05
35#define M5602_XB_VSYNC_PARA 0x06
36#define M5602_XB_HSYNC_PARA 0x07
37#define M5602_XB_TEST_MODE_1 0x08
38#define M5602_XB_TEST_MODE_2 0x09
39#define M5602_XB_SIG_INI 0x0a
40#define M5602_XB_DS_PARA 0x0e
41#define M5602_XB_TRIG_PARA 0x0f
42#define M5602_XB_CLK_PD 0x10
43#define M5602_XB_MCU_CLK_CTRL 0x12
44#define M5602_XB_MCU_CLK_DIV 0x13
45#define M5602_XB_SEN_CLK_CTRL 0x14
46#define M5602_XB_SEN_CLK_DIV 0x15
47#define M5602_XB_AUD_CLK_CTRL 0x16
48#define M5602_XB_AUD_CLK_DIV 0x17
49#define M5602_OB_AC_LINK_STATE 0x22
50#define M5602_OB_PCM_SLOT_INDEX 0x24
51#define M5602_OB_GPIO_SLOT_INDEX 0x25
52#define M5602_OB_ACRX_STATUS_ADDRESS_H 0x28
53#define M5602_OB_ACRX_STATUS_DATA_L 0x29
54#define M5602_OB_ACRX_STATUS_DATA_H 0x2a
55#define M5602_OB_ACTX_COMMAND_ADDRESS 0x31
56#define M5602_OB_ACRX_COMMAND_DATA_L 0x32
57#define M5602_OB_ACTX_COMMAND_DATA_H 0X33
58#define M5602_XB_DEVCTR1 0x41
59#define M5602_XB_EPSETR0 0x42
60#define M5602_XB_EPAFCTR 0x47
61#define M5602_XB_EPBFCTR 0x49
62#define M5602_XB_EPEFCTR 0x4f
63#define M5602_XB_TEST_REG 0x53
64#define M5602_XB_ALT2SIZE 0x54
65#define M5602_XB_ALT3SIZE 0x55
66#define M5602_XB_OBSFRAME 0x56
67#define M5602_XB_PWR_CTL 0x59
68#define M5602_XB_ADC_CTRL 0x60
69#define M5602_XB_ADC_DATA 0x61
70#define M5602_XB_MISC_CTRL 0x62
71#define M5602_XB_SNAPSHOT 0x63
72#define M5602_XB_SCRATCH_1 0x64
73#define M5602_XB_SCRATCH_2 0x65
74#define M5602_XB_SCRATCH_3 0x66
75#define M5602_XB_SCRATCH_4 0x67
76#define M5602_XB_I2C_CTRL 0x68
77#define M5602_XB_I2C_CLK_DIV 0x69
78#define M5602_XB_I2C_DEV_ADDR 0x6a
79#define M5602_XB_I2C_REG_ADDR 0x6b
80#define M5602_XB_I2C_DATA 0x6c
81#define M5602_XB_I2C_STATUS 0x6d
82#define M5602_XB_GPIO_DAT_H 0x70
83#define M5602_XB_GPIO_DAT_L 0x71
84#define M5602_XB_GPIO_DIR_H 0x72
85#define M5602_XB_GPIO_DIR_L 0x73
86#define M5602_XB_GPIO_EN_H 0x74
87#define M5602_XB_GPIO_EN_L 0x75
88#define M5602_XB_GPIO_DAT 0x76
89#define M5602_XB_GPIO_DIR 0x77
90#define M5602_XB_SEN_CLK_CONTROL 0x80
91#define M5602_XB_SEN_CLK_DIVISION 0x81
92#define M5602_XB_CPR_CLK_CONTROL 0x82
93#define M5602_XB_CPR_CLK_DIVISION 0x83
94#define M5602_XB_MCU_CLK_CONTROL 0x84
95#define M5602_XB_MCU_CLK_DIVISION 0x85
96#define M5602_XB_DCT_CLK_CONTROL 0x86
97#define M5602_XB_DCT_CLK_DIVISION 0x87
98#define M5602_XB_EC_CLK_CONTROL 0x88
99#define M5602_XB_EC_CLK_DIVISION 0x89
100#define M5602_XB_LBUF_CLK_CONTROL 0x8a
101#define M5602_XB_LBUF_CLK_DIVISION 0x8b
102
103#define I2C_BUSY 0x80
104
105/*****************************************************************************/
106
107/* Driver info */
108#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project"
109#define DRIVER_DESC "ALi m5602 webcam driver"
110
111#define M5602_ISOC_ENDPOINT_ADDR 0x81
112#define M5602_INTR_ENDPOINT_ADDR 0x82
113
114#define M5602_URB_MSG_TIMEOUT 5000
115
116/*****************************************************************************/
117
118/* A skeleton used for sending messages to the m5602 bridge */
119static const unsigned char bridge_urb_skeleton[] = {
120 0x13, 0x00, 0x81, 0x00
121};
122
123/* A skeleton used for sending messages to the sensor */
124static const unsigned char sensor_urb_skeleton[] = {
125 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06,
126 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80,
127 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00,
128 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
129 0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
130 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
131};
132
133struct sd {
134 struct gspca_dev gspca_dev;
135
136 /* A pointer to the currently connected sensor */
137 const struct m5602_sensor *sensor;
138
139 struct sd_desc *desc;
140
141 /* Sensor private data */
142 void *sensor_priv;
143
144 /* The current frame's id, used to detect frame boundaries */
145 u8 frame_id;
146
147 /* The current frame count */
148 u32 frame_count;
149};
150
151int m5602_read_bridge(
152 struct sd *sd, const u8 address, u8 *i2c_data);
153
154int m5602_write_bridge(
155 struct sd *sd, const u8 address, const u8 i2c_data);
156
157int m5602_write_sensor(struct sd *sd, const u8 address,
158 u8 *i2c_data, const u8 len);
159
160int m5602_read_sensor(struct sd *sd, const u8 address,
161 u8 *i2c_data, const u8 len);
162
163#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c
new file mode 100644
index 00000000000..ed22638978c
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_core.c
@@ -0,0 +1,424 @@
1 /*
2 * USB Driver for ALi m5602 based webcams
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include "m5602_ov9650.h"
22#include "m5602_ov7660.h"
23#include "m5602_mt9m111.h"
24#include "m5602_po1030.h"
25#include "m5602_s5k83a.h"
26#include "m5602_s5k4aa.h"
27
28/* Kernel module parameters */
29int force_sensor;
30static bool dump_bridge;
31bool dump_sensor;
32
33static const struct usb_device_id m5602_table[] = {
34 {USB_DEVICE(0x0402, 0x5602)},
35 {}
36};
37
38MODULE_DEVICE_TABLE(usb, m5602_table);
39
40/* Reads a byte from the m5602 */
41int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
42{
43 int err;
44 struct usb_device *udev = sd->gspca_dev.dev;
45 __u8 *buf = sd->gspca_dev.usb_buf;
46
47 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
48 0x04, 0xc0, 0x14,
49 0x8100 + address, buf,
50 1, M5602_URB_MSG_TIMEOUT);
51 *i2c_data = buf[0];
52
53 PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x",
54 address, *i2c_data);
55
56 /* usb_control_msg(...) returns the number of bytes sent upon success,
57 mask that and return zero instead*/
58 return (err < 0) ? err : 0;
59}
60
61/* Writes a byte to the m5602 */
62int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
63{
64 int err;
65 struct usb_device *udev = sd->gspca_dev.dev;
66 __u8 *buf = sd->gspca_dev.usb_buf;
67
68 PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x",
69 address, i2c_data);
70
71 memcpy(buf, bridge_urb_skeleton,
72 sizeof(bridge_urb_skeleton));
73 buf[1] = address;
74 buf[3] = i2c_data;
75
76 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
77 0x04, 0x40, 0x19,
78 0x0000, buf,
79 4, M5602_URB_MSG_TIMEOUT);
80
81 /* usb_control_msg(...) returns the number of bytes sent upon success,
82 mask that and return zero instead */
83 return (err < 0) ? err : 0;
84}
85
86static int m5602_wait_for_i2c(struct sd *sd)
87{
88 int err;
89 u8 data;
90
91 do {
92 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data);
93 } while ((data & I2C_BUSY) && !err);
94 return err;
95}
96
97int m5602_read_sensor(struct sd *sd, const u8 address,
98 u8 *i2c_data, const u8 len)
99{
100 int err, i;
101
102 if (!len || len > sd->sensor->i2c_regW)
103 return -EINVAL;
104
105 err = m5602_wait_for_i2c(sd);
106 if (err < 0)
107 return err;
108
109 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
110 sd->sensor->i2c_slave_id);
111 if (err < 0)
112 return err;
113
114 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
115 if (err < 0)
116 return err;
117
118 /* Sensors with registers that are of only
119 one byte width are differently read */
120
121 /* FIXME: This works with the ov9650, but has issues with the po1030 */
122 if (sd->sensor->i2c_regW == 1) {
123 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1);
124 if (err < 0)
125 return err;
126
127 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
128 } else {
129 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
130 }
131
132 for (i = 0; (i < len) && !err; i++) {
133 err = m5602_wait_for_i2c(sd);
134 if (err < 0)
135 return err;
136
137 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
138
139 PDEBUG(D_CONF, "Reading sensor register "
140 "0x%x containing 0x%x ", address, *i2c_data);
141 }
142 return err;
143}
144
145int m5602_write_sensor(struct sd *sd, const u8 address,
146 u8 *i2c_data, const u8 len)
147{
148 int err, i;
149 u8 *p;
150 struct usb_device *udev = sd->gspca_dev.dev;
151 __u8 *buf = sd->gspca_dev.usb_buf;
152
153 /* No sensor with a data width larger than 16 bits has yet been seen */
154 if (len > sd->sensor->i2c_regW || !len)
155 return -EINVAL;
156
157 memcpy(buf, sensor_urb_skeleton,
158 sizeof(sensor_urb_skeleton));
159
160 buf[11] = sd->sensor->i2c_slave_id;
161 buf[15] = address;
162
163 /* Special case larger sensor writes */
164 p = buf + 16;
165
166 /* Copy a four byte write sequence for each byte to be written to */
167 for (i = 0; i < len; i++) {
168 memcpy(p, sensor_urb_skeleton + 16, 4);
169 p[3] = i2c_data[i];
170 p += 4;
171 PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
172 address, i2c_data[i]);
173 }
174
175 /* Copy the tailer */
176 memcpy(p, sensor_urb_skeleton + 20, 4);
177
178 /* Set the total length */
179 p[3] = 0x10 + len;
180
181 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
182 0x04, 0x40, 0x19,
183 0x0000, buf,
184 20 + len * 4, M5602_URB_MSG_TIMEOUT);
185
186 return (err < 0) ? err : 0;
187}
188
189/* Dump all the registers of the m5602 bridge,
190 unfortunately this breaks the camera until it's power cycled */
191static void m5602_dump_bridge(struct sd *sd)
192{
193 int i;
194 for (i = 0; i < 0x80; i++) {
195 unsigned char val = 0;
196 m5602_read_bridge(sd, i, &val);
197 pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
198 }
199 pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
200}
201
202static int m5602_probe_sensor(struct sd *sd)
203{
204 /* Try the po1030 */
205 sd->sensor = &po1030;
206 if (!sd->sensor->probe(sd))
207 return 0;
208
209 /* Try the mt9m111 sensor */
210 sd->sensor = &mt9m111;
211 if (!sd->sensor->probe(sd))
212 return 0;
213
214 /* Try the s5k4aa */
215 sd->sensor = &s5k4aa;
216 if (!sd->sensor->probe(sd))
217 return 0;
218
219 /* Try the ov9650 */
220 sd->sensor = &ov9650;
221 if (!sd->sensor->probe(sd))
222 return 0;
223
224 /* Try the ov7660 */
225 sd->sensor = &ov7660;
226 if (!sd->sensor->probe(sd))
227 return 0;
228
229 /* Try the s5k83a */
230 sd->sensor = &s5k83a;
231 if (!sd->sensor->probe(sd))
232 return 0;
233
234 /* More sensor probe function goes here */
235 pr_info("Failed to find a sensor\n");
236 sd->sensor = NULL;
237 return -ENODEV;
238}
239
240static int m5602_configure(struct gspca_dev *gspca_dev,
241 const struct usb_device_id *id);
242
243static int m5602_init(struct gspca_dev *gspca_dev)
244{
245 struct sd *sd = (struct sd *) gspca_dev;
246 int err;
247
248 PDEBUG(D_CONF, "Initializing ALi m5602 webcam");
249 /* Run the init sequence */
250 err = sd->sensor->init(sd);
251
252 return err;
253}
254
255static int m5602_start_transfer(struct gspca_dev *gspca_dev)
256{
257 struct sd *sd = (struct sd *) gspca_dev;
258 __u8 *buf = sd->gspca_dev.usb_buf;
259 int err;
260
261 /* Send start command to the camera */
262 const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
263
264 if (sd->sensor->start)
265 sd->sensor->start(sd);
266
267 memcpy(buf, buffer, sizeof(buffer));
268 err = usb_control_msg(gspca_dev->dev,
269 usb_sndctrlpipe(gspca_dev->dev, 0),
270 0x04, 0x40, 0x19, 0x0000, buf,
271 sizeof(buffer), M5602_URB_MSG_TIMEOUT);
272
273 PDEBUG(D_STREAM, "Transfer started");
274 return (err < 0) ? err : 0;
275}
276
277static void m5602_urb_complete(struct gspca_dev *gspca_dev,
278 u8 *data, int len)
279{
280 struct sd *sd = (struct sd *) gspca_dev;
281
282 if (len < 6) {
283 PDEBUG(D_PACK, "Packet is less than 6 bytes");
284 return;
285 }
286
287 /* Frame delimiter: ff xx xx xx ff ff */
288 if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
289 data[2] != sd->frame_id) {
290 PDEBUG(D_FRAM, "Frame delimiter detected");
291 sd->frame_id = data[2];
292
293 /* Remove the extra fluff appended on each header */
294 data += 6;
295 len -= 6;
296
297 /* Complete the last frame (if any) */
298 gspca_frame_add(gspca_dev, LAST_PACKET,
299 NULL, 0);
300 sd->frame_count++;
301
302 /* Create a new frame */
303 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
304
305 PDEBUG(D_FRAM, "Starting new frame %d",
306 sd->frame_count);
307
308 } else {
309 int cur_frame_len;
310
311 cur_frame_len = gspca_dev->image_len;
312 /* Remove urb header */
313 data += 4;
314 len -= 4;
315
316 if (cur_frame_len + len <= gspca_dev->frsz) {
317 PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
318 sd->frame_count, len);
319
320 gspca_frame_add(gspca_dev, INTER_PACKET,
321 data, len);
322 } else {
323 /* Add the remaining data up to frame size */
324 gspca_frame_add(gspca_dev, INTER_PACKET, data,
325 gspca_dev->frsz - cur_frame_len);
326 }
327 }
328}
329
330static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
331{
332 struct sd *sd = (struct sd *) gspca_dev;
333
334 /* Run the sensor specific end transfer sequence */
335 if (sd->sensor->stop)
336 sd->sensor->stop(sd);
337}
338
339/* sub-driver description, the ctrl and nctrl is filled at probe time */
340static struct sd_desc sd_desc = {
341 .name = MODULE_NAME,
342 .config = m5602_configure,
343 .init = m5602_init,
344 .start = m5602_start_transfer,
345 .stopN = m5602_stop_transfer,
346 .pkt_scan = m5602_urb_complete
347};
348
349/* this function is called at probe time */
350static int m5602_configure(struct gspca_dev *gspca_dev,
351 const struct usb_device_id *id)
352{
353 struct sd *sd = (struct sd *) gspca_dev;
354 struct cam *cam;
355 int err;
356
357 cam = &gspca_dev->cam;
358 sd->desc = &sd_desc;
359
360 if (dump_bridge)
361 m5602_dump_bridge(sd);
362
363 /* Probe sensor */
364 err = m5602_probe_sensor(sd);
365 if (err)
366 goto fail;
367
368 return 0;
369
370fail:
371 PDEBUG(D_ERR, "ALi m5602 webcam failed");
372 cam->cam_mode = NULL;
373 cam->nmodes = 0;
374
375 return err;
376}
377
378static int m5602_probe(struct usb_interface *intf,
379 const struct usb_device_id *id)
380{
381 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
382 THIS_MODULE);
383}
384
385static void m5602_disconnect(struct usb_interface *intf)
386{
387 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
388 struct sd *sd = (struct sd *) gspca_dev;
389
390 if (sd->sensor->disconnect)
391 sd->sensor->disconnect(sd);
392
393 gspca_disconnect(intf);
394}
395
396static struct usb_driver sd_driver = {
397 .name = MODULE_NAME,
398 .id_table = m5602_table,
399 .probe = m5602_probe,
400#ifdef CONFIG_PM
401 .suspend = gspca_suspend,
402 .resume = gspca_resume,
403 .reset_resume = gspca_resume,
404#endif
405 .disconnect = m5602_disconnect
406};
407
408module_usb_driver(sd_driver);
409
410MODULE_AUTHOR(DRIVER_AUTHOR);
411MODULE_DESCRIPTION(DRIVER_DESC);
412MODULE_LICENSE("GPL");
413module_param(force_sensor, int, S_IRUGO | S_IWUSR);
414MODULE_PARM_DESC(force_sensor,
415 "forces detection of a sensor, "
416 "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
417 "4 = MT9M111, 5 = PO1030, 6 = OV7660");
418
419module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
420MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
421
422module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
423MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
424 "at startup providing a sensor is found");
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
new file mode 100644
index 00000000000..6268aa24ec5
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
@@ -0,0 +1,647 @@
1/*
2 * Driver for the mt9m111 sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include "m5602_mt9m111.h"
22
23static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
24static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
25static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
26static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
27static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
28static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
29static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
30 __s32 val);
31static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
32 __s32 *val);
33static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
34static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
35static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
36static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
37static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
38static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
39
40static struct v4l2_pix_format mt9m111_modes[] = {
41 {
42 640,
43 480,
44 V4L2_PIX_FMT_SBGGR8,
45 V4L2_FIELD_NONE,
46 .sizeimage = 640 * 480,
47 .bytesperline = 640,
48 .colorspace = V4L2_COLORSPACE_SRGB,
49 .priv = 0
50 }
51};
52
53static const struct ctrl mt9m111_ctrls[] = {
54#define VFLIP_IDX 0
55 {
56 {
57 .id = V4L2_CID_VFLIP,
58 .type = V4L2_CTRL_TYPE_BOOLEAN,
59 .name = "vertical flip",
60 .minimum = 0,
61 .maximum = 1,
62 .step = 1,
63 .default_value = 0
64 },
65 .set = mt9m111_set_vflip,
66 .get = mt9m111_get_vflip
67 },
68#define HFLIP_IDX 1
69 {
70 {
71 .id = V4L2_CID_HFLIP,
72 .type = V4L2_CTRL_TYPE_BOOLEAN,
73 .name = "horizontal flip",
74 .minimum = 0,
75 .maximum = 1,
76 .step = 1,
77 .default_value = 0
78 },
79 .set = mt9m111_set_hflip,
80 .get = mt9m111_get_hflip
81 },
82#define GAIN_IDX 2
83 {
84 {
85 .id = V4L2_CID_GAIN,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "gain",
88 .minimum = 0,
89 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
90 .step = 1,
91 .default_value = MT9M111_DEFAULT_GAIN,
92 .flags = V4L2_CTRL_FLAG_SLIDER
93 },
94 .set = mt9m111_set_gain,
95 .get = mt9m111_get_gain
96 },
97#define AUTO_WHITE_BALANCE_IDX 3
98 {
99 {
100 .id = V4L2_CID_AUTO_WHITE_BALANCE,
101 .type = V4L2_CTRL_TYPE_BOOLEAN,
102 .name = "auto white balance",
103 .minimum = 0,
104 .maximum = 1,
105 .step = 1,
106 .default_value = 0,
107 },
108 .set = mt9m111_set_auto_white_balance,
109 .get = mt9m111_get_auto_white_balance
110 },
111#define GREEN_BALANCE_IDX 4
112 {
113 {
114 .id = M5602_V4L2_CID_GREEN_BALANCE,
115 .type = V4L2_CTRL_TYPE_INTEGER,
116 .name = "green balance",
117 .minimum = 0x00,
118 .maximum = 0x7ff,
119 .step = 0x1,
120 .default_value = MT9M111_GREEN_GAIN_DEFAULT,
121 .flags = V4L2_CTRL_FLAG_SLIDER
122 },
123 .set = mt9m111_set_green_balance,
124 .get = mt9m111_get_green_balance
125 },
126#define BLUE_BALANCE_IDX 5
127 {
128 {
129 .id = V4L2_CID_BLUE_BALANCE,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "blue balance",
132 .minimum = 0x00,
133 .maximum = 0x7ff,
134 .step = 0x1,
135 .default_value = MT9M111_BLUE_GAIN_DEFAULT,
136 .flags = V4L2_CTRL_FLAG_SLIDER
137 },
138 .set = mt9m111_set_blue_balance,
139 .get = mt9m111_get_blue_balance
140 },
141#define RED_BALANCE_IDX 5
142 {
143 {
144 .id = V4L2_CID_RED_BALANCE,
145 .type = V4L2_CTRL_TYPE_INTEGER,
146 .name = "red balance",
147 .minimum = 0x00,
148 .maximum = 0x7ff,
149 .step = 0x1,
150 .default_value = MT9M111_RED_GAIN_DEFAULT,
151 .flags = V4L2_CTRL_FLAG_SLIDER
152 },
153 .set = mt9m111_set_red_balance,
154 .get = mt9m111_get_red_balance
155 },
156};
157
158static void mt9m111_dump_registers(struct sd *sd);
159
160int mt9m111_probe(struct sd *sd)
161{
162 u8 data[2] = {0x00, 0x00};
163 int i;
164 s32 *sensor_settings;
165
166 if (force_sensor) {
167 if (force_sensor == MT9M111_SENSOR) {
168 pr_info("Forcing a %s sensor\n", mt9m111.name);
169 goto sensor_found;
170 }
171 /* If we want to force another sensor, don't try to probe this
172 * one */
173 return -ENODEV;
174 }
175
176 PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
177
178 /* Do the preinit */
179 for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
180 if (preinit_mt9m111[i][0] == BRIDGE) {
181 m5602_write_bridge(sd,
182 preinit_mt9m111[i][1],
183 preinit_mt9m111[i][2]);
184 } else {
185 data[0] = preinit_mt9m111[i][2];
186 data[1] = preinit_mt9m111[i][3];
187 m5602_write_sensor(sd,
188 preinit_mt9m111[i][1], data, 2);
189 }
190 }
191
192 if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
193 return -ENODEV;
194
195 if ((data[0] == 0x14) && (data[1] == 0x3a)) {
196 pr_info("Detected a mt9m111 sensor\n");
197 goto sensor_found;
198 }
199
200 return -ENODEV;
201
202sensor_found:
203 sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
204 GFP_KERNEL);
205 if (!sensor_settings)
206 return -ENOMEM;
207
208 sd->gspca_dev.cam.cam_mode = mt9m111_modes;
209 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
210 sd->desc->ctrls = mt9m111_ctrls;
211 sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
212
213 for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
214 sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
215 sd->sensor_priv = sensor_settings;
216
217 return 0;
218}
219
220int mt9m111_init(struct sd *sd)
221{
222 int i, err = 0;
223 s32 *sensor_settings = sd->sensor_priv;
224
225 /* Init the sensor */
226 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
227 u8 data[2];
228
229 if (init_mt9m111[i][0] == BRIDGE) {
230 err = m5602_write_bridge(sd,
231 init_mt9m111[i][1],
232 init_mt9m111[i][2]);
233 } else {
234 data[0] = init_mt9m111[i][2];
235 data[1] = init_mt9m111[i][3];
236 err = m5602_write_sensor(sd,
237 init_mt9m111[i][1], data, 2);
238 }
239 }
240
241 if (dump_sensor)
242 mt9m111_dump_registers(sd);
243
244 err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
245 if (err < 0)
246 return err;
247
248 err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
249 if (err < 0)
250 return err;
251
252 err = mt9m111_set_green_balance(&sd->gspca_dev,
253 sensor_settings[GREEN_BALANCE_IDX]);
254 if (err < 0)
255 return err;
256
257 err = mt9m111_set_blue_balance(&sd->gspca_dev,
258 sensor_settings[BLUE_BALANCE_IDX]);
259 if (err < 0)
260 return err;
261
262 err = mt9m111_set_red_balance(&sd->gspca_dev,
263 sensor_settings[RED_BALANCE_IDX]);
264 if (err < 0)
265 return err;
266
267 return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
268}
269
270int mt9m111_start(struct sd *sd)
271{
272 int i, err = 0;
273 u8 data[2];
274 struct cam *cam = &sd->gspca_dev.cam;
275 s32 *sensor_settings = sd->sensor_priv;
276
277 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
278 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
279
280 for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
281 if (start_mt9m111[i][0] == BRIDGE) {
282 err = m5602_write_bridge(sd,
283 start_mt9m111[i][1],
284 start_mt9m111[i][2]);
285 } else {
286 data[0] = start_mt9m111[i][2];
287 data[1] = start_mt9m111[i][3];
288 err = m5602_write_sensor(sd,
289 start_mt9m111[i][1], data, 2);
290 }
291 }
292 if (err < 0)
293 return err;
294
295 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
296 if (err < 0)
297 return err;
298
299 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
300 if (err < 0)
301 return err;
302
303 for (i = 0; i < 2 && !err; i++)
304 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
305 if (err < 0)
306 return err;
307
308 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
309 if (err < 0)
310 return err;
311
312 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
313 if (err < 0)
314 return err;
315
316 for (i = 0; i < 2 && !err; i++)
317 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
318 if (err < 0)
319 return err;
320
321 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
322 (width >> 8) & 0xff);
323 if (err < 0)
324 return err;
325
326 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
327 if (err < 0)
328 return err;
329
330 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
331 if (err < 0)
332 return err;
333
334 switch (width) {
335 case 640:
336 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
337 data[0] = MT9M111_RMB_OVER_SIZED;
338 data[1] = MT9M111_RMB_ROW_SKIP_2X |
339 MT9M111_RMB_COLUMN_SKIP_2X |
340 (sensor_settings[VFLIP_IDX] << 0) |
341 (sensor_settings[HFLIP_IDX] << 1);
342
343 err = m5602_write_sensor(sd,
344 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
345 break;
346
347 case 320:
348 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
349 data[0] = MT9M111_RMB_OVER_SIZED;
350 data[1] = MT9M111_RMB_ROW_SKIP_4X |
351 MT9M111_RMB_COLUMN_SKIP_4X |
352 (sensor_settings[VFLIP_IDX] << 0) |
353 (sensor_settings[HFLIP_IDX] << 1);
354 err = m5602_write_sensor(sd,
355 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
356 break;
357 }
358 return err;
359}
360
361void mt9m111_disconnect(struct sd *sd)
362{
363 sd->sensor = NULL;
364 kfree(sd->sensor_priv);
365}
366
367static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
368{
369 struct sd *sd = (struct sd *) gspca_dev;
370 s32 *sensor_settings = sd->sensor_priv;
371
372 *val = sensor_settings[VFLIP_IDX];
373 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
374
375 return 0;
376}
377
378static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
379{
380 int err;
381 u8 data[2] = {0x00, 0x00};
382 struct sd *sd = (struct sd *) gspca_dev;
383 s32 *sensor_settings = sd->sensor_priv;
384
385 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
386
387 sensor_settings[VFLIP_IDX] = val;
388
389 /* The mt9m111 is flipped by default */
390 val = !val;
391
392 /* Set the correct page map */
393 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
394 if (err < 0)
395 return err;
396
397 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
398 if (err < 0)
399 return err;
400
401 data[1] = (data[1] & 0xfe) | val;
402 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
403 data, 2);
404 return err;
405}
406
407static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
408{
409 struct sd *sd = (struct sd *) gspca_dev;
410 s32 *sensor_settings = sd->sensor_priv;
411
412 *val = sensor_settings[HFLIP_IDX];
413 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
414
415 return 0;
416}
417
418static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
419{
420 int err;
421 u8 data[2] = {0x00, 0x00};
422 struct sd *sd = (struct sd *) gspca_dev;
423 s32 *sensor_settings = sd->sensor_priv;
424
425 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
426
427 sensor_settings[HFLIP_IDX] = val;
428
429 /* The mt9m111 is flipped by default */
430 val = !val;
431
432 /* Set the correct page map */
433 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
434 if (err < 0)
435 return err;
436
437 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
438 if (err < 0)
439 return err;
440
441 data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
442 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
443 data, 2);
444 return err;
445}
446
447static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
448{
449 struct sd *sd = (struct sd *) gspca_dev;
450 s32 *sensor_settings = sd->sensor_priv;
451
452 *val = sensor_settings[GAIN_IDX];
453 PDEBUG(D_V4L2, "Read gain %d", *val);
454
455 return 0;
456}
457
458static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
459 __s32 val)
460{
461 struct sd *sd = (struct sd *) gspca_dev;
462 s32 *sensor_settings = sd->sensor_priv;
463 int err;
464 u8 data[2];
465
466 err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
467 if (err < 0)
468 return err;
469
470 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
471 data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
472
473 err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
474
475 PDEBUG(D_V4L2, "Set auto white balance %d", val);
476 return err;
477}
478
479static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
480 __s32 *val) {
481 struct sd *sd = (struct sd *) gspca_dev;
482 s32 *sensor_settings = sd->sensor_priv;
483
484 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
485 PDEBUG(D_V4L2, "Read auto white balance %d", *val);
486 return 0;
487}
488
489static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
490{
491 int err, tmp;
492 u8 data[2] = {0x00, 0x00};
493 struct sd *sd = (struct sd *) gspca_dev;
494 s32 *sensor_settings = sd->sensor_priv;
495
496 sensor_settings[GAIN_IDX] = val;
497
498 /* Set the correct page map */
499 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
500 if (err < 0)
501 return err;
502
503 if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
504 return -EINVAL;
505
506 if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
507 (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
508 tmp = (1 << 10) | (val << 9) |
509 (val << 8) | (val / 8);
510 else if ((val >= INITIAL_MAX_GAIN * 2) &&
511 (val < INITIAL_MAX_GAIN * 2 * 2))
512 tmp = (1 << 9) | (1 << 8) | (val / 4);
513 else if ((val >= INITIAL_MAX_GAIN) &&
514 (val < INITIAL_MAX_GAIN * 2))
515 tmp = (1 << 8) | (val / 2);
516 else
517 tmp = val;
518
519 data[1] = (tmp & 0xff);
520 data[0] = (tmp & 0xff00) >> 8;
521 PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
522 data[1], data[0]);
523
524 err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
525 data, 2);
526
527 return err;
528}
529
530static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
531{
532 int err;
533 u8 data[2];
534 struct sd *sd = (struct sd *) gspca_dev;
535 s32 *sensor_settings = sd->sensor_priv;
536
537 sensor_settings[GREEN_BALANCE_IDX] = val;
538 data[1] = (val & 0xff);
539 data[0] = (val & 0xff00) >> 8;
540
541 PDEBUG(D_V4L2, "Set green balance %d", val);
542 err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
543 data, 2);
544 if (err < 0)
545 return err;
546
547 return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
548 data, 2);
549}
550
551static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
552{
553 struct sd *sd = (struct sd *) gspca_dev;
554 s32 *sensor_settings = sd->sensor_priv;
555
556 *val = sensor_settings[GREEN_BALANCE_IDX];
557 PDEBUG(D_V4L2, "Read green balance %d", *val);
558 return 0;
559}
560
561static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
562{
563 u8 data[2];
564 struct sd *sd = (struct sd *) gspca_dev;
565 s32 *sensor_settings = sd->sensor_priv;
566
567 sensor_settings[BLUE_BALANCE_IDX] = val;
568 data[1] = (val & 0xff);
569 data[0] = (val & 0xff00) >> 8;
570
571 PDEBUG(D_V4L2, "Set blue balance %d", val);
572
573 return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
574 data, 2);
575}
576
577static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
578{
579 struct sd *sd = (struct sd *) gspca_dev;
580 s32 *sensor_settings = sd->sensor_priv;
581
582 *val = sensor_settings[BLUE_BALANCE_IDX];
583 PDEBUG(D_V4L2, "Read blue balance %d", *val);
584 return 0;
585}
586
587static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
588{
589 u8 data[2];
590 struct sd *sd = (struct sd *) gspca_dev;
591 s32 *sensor_settings = sd->sensor_priv;
592
593 sensor_settings[RED_BALANCE_IDX] = val;
594 data[1] = (val & 0xff);
595 data[0] = (val & 0xff00) >> 8;
596
597 PDEBUG(D_V4L2, "Set red balance %d", val);
598
599 return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
600 data, 2);
601}
602
603static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
604{
605 struct sd *sd = (struct sd *) gspca_dev;
606 s32 *sensor_settings = sd->sensor_priv;
607
608 *val = sensor_settings[RED_BALANCE_IDX];
609 PDEBUG(D_V4L2, "Read red balance %d", *val);
610 return 0;
611}
612
613static void mt9m111_dump_registers(struct sd *sd)
614{
615 u8 address, value[2] = {0x00, 0x00};
616
617 pr_info("Dumping the mt9m111 register state\n");
618
619 pr_info("Dumping the mt9m111 sensor core registers\n");
620 value[1] = MT9M111_SENSOR_CORE;
621 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
622 for (address = 0; address < 0xff; address++) {
623 m5602_read_sensor(sd, address, value, 2);
624 pr_info("register 0x%x contains 0x%x%x\n",
625 address, value[0], value[1]);
626 }
627
628 pr_info("Dumping the mt9m111 color pipeline registers\n");
629 value[1] = MT9M111_COLORPIPE;
630 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
631 for (address = 0; address < 0xff; address++) {
632 m5602_read_sensor(sd, address, value, 2);
633 pr_info("register 0x%x contains 0x%x%x\n",
634 address, value[0], value[1]);
635 }
636
637 pr_info("Dumping the mt9m111 camera control registers\n");
638 value[1] = MT9M111_CAMERA_CONTROL;
639 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
640 for (address = 0; address < 0xff; address++) {
641 m5602_read_sensor(sd, address, value, 2);
642 pr_info("register 0x%x contains 0x%x%x\n",
643 address, value[0], value[1]);
644 }
645
646 pr_info("mt9m111 register state dump complete\n");
647}
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.h b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
new file mode 100644
index 00000000000..8c672b5c8c6
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
@@ -0,0 +1,271 @@
1/*
2 * Driver for the mt9m111 sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * Some defines taken from the mt9m111 sensor driver
14 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation, version 2.
19 *
20 */
21
22#ifndef M5602_MT9M111_H_
23#define M5602_MT9M111_H_
24
25#include "m5602_sensor.h"
26
27/*****************************************************************************/
28
29#define MT9M111_SC_CHIPVER 0x00
30#define MT9M111_SC_ROWSTART 0x01
31#define MT9M111_SC_COLSTART 0x02
32#define MT9M111_SC_WINDOW_HEIGHT 0x03
33#define MT9M111_SC_WINDOW_WIDTH 0x04
34#define MT9M111_SC_HBLANK_CONTEXT_B 0x05
35#define MT9M111_SC_VBLANK_CONTEXT_B 0x06
36#define MT9M111_SC_HBLANK_CONTEXT_A 0x07
37#define MT9M111_SC_VBLANK_CONTEXT_A 0x08
38#define MT9M111_SC_SHUTTER_WIDTH 0x09
39#define MT9M111_SC_ROW_SPEED 0x0a
40#define MT9M111_SC_EXTRA_DELAY 0x0b
41#define MT9M111_SC_SHUTTER_DELAY 0x0c
42#define MT9M111_SC_RESET 0x0d
43#define MT9M111_SC_R_MODE_CONTEXT_B 0x20
44#define MT9M111_SC_R_MODE_CONTEXT_A 0x21
45#define MT9M111_SC_FLASH_CONTROL 0x23
46#define MT9M111_SC_GREEN_1_GAIN 0x2b
47#define MT9M111_SC_BLUE_GAIN 0x2c
48#define MT9M111_SC_RED_GAIN 0x2d
49#define MT9M111_SC_GREEN_2_GAIN 0x2e
50#define MT9M111_SC_GLOBAL_GAIN 0x2f
51
52#define MT9M111_CONTEXT_CONTROL 0xc8
53#define MT9M111_PAGE_MAP 0xf0
54#define MT9M111_BYTEWISE_ADDRESS 0xf1
55
56#define MT9M111_CP_OPERATING_MODE_CTL 0x06
57#define MT9M111_CP_LUMA_OFFSET 0x34
58#define MT9M111_CP_LUMA_CLIP 0x35
59#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a
60#define MT9M111_CP_LENS_CORRECTION_1 0x3b
61#define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c
62#define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d
63#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b
64#define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3
65
66#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65
67#define MT9M111_CC_AWB_PARAMETER_7 0x28
68
69#define MT9M111_SENSOR_CORE 0x00
70#define MT9M111_COLORPIPE 0x01
71#define MT9M111_CAMERA_CONTROL 0x02
72
73#define MT9M111_RESET (1 << 0)
74#define MT9M111_RESTART (1 << 1)
75#define MT9M111_ANALOG_STANDBY (1 << 2)
76#define MT9M111_CHIP_ENABLE (1 << 3)
77#define MT9M111_CHIP_DISABLE (0 << 3)
78#define MT9M111_OUTPUT_DISABLE (1 << 4)
79#define MT9M111_SHOW_BAD_FRAMES (1 << 0)
80#define MT9M111_RESTART_BAD_FRAMES (1 << 1)
81#define MT9M111_SYNCHRONIZE_CHANGES (1 << 7)
82
83#define MT9M111_RMB_OVER_SIZED (1 << 0)
84#define MT9M111_RMB_MIRROR_ROWS (1 << 0)
85#define MT9M111_RMB_MIRROR_COLS (1 << 1)
86#define MT9M111_RMB_ROW_SKIP_2X (1 << 2)
87#define MT9M111_RMB_COLUMN_SKIP_2X (1 << 3)
88#define MT9M111_RMB_ROW_SKIP_4X (1 << 4)
89#define MT9M111_RMB_COLUMN_SKIP_4X (1 << 5)
90
91#define MT9M111_COLOR_MATRIX_BYPASS (1 << 4)
92#define MT9M111_SEL_CONTEXT_B (1 << 3)
93
94#define MT9M111_TRISTATE_PIN_IN_STANDBY (1 << 1)
95#define MT9M111_SOC_SOFT_STANDBY (1 << 0)
96
97#define MT9M111_2D_DEFECT_CORRECTION_ENABLE (1 << 0)
98
99#define INITIAL_MAX_GAIN 64
100#define MT9M111_DEFAULT_GAIN 283
101#define MT9M111_GREEN_GAIN_DEFAULT 0x20
102#define MT9M111_BLUE_GAIN_DEFAULT 0x20
103#define MT9M111_RED_GAIN_DEFAULT 0x20
104
105/*****************************************************************************/
106
107/* Kernel module parameters */
108extern int force_sensor;
109extern bool dump_sensor;
110
111int mt9m111_probe(struct sd *sd);
112int mt9m111_init(struct sd *sd);
113int mt9m111_start(struct sd *sd);
114void mt9m111_disconnect(struct sd *sd);
115
116static const struct m5602_sensor mt9m111 = {
117 .name = "MT9M111",
118
119 .i2c_slave_id = 0xba,
120 .i2c_regW = 2,
121
122 .probe = mt9m111_probe,
123 .init = mt9m111_init,
124 .disconnect = mt9m111_disconnect,
125 .start = mt9m111_start,
126};
127
128static const unsigned char preinit_mt9m111[][4] = {
129 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
130 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
131 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
132 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
133 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
134 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
135 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
136 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
137
138 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
139 {SENSOR, MT9M111_SC_RESET,
140 MT9M111_RESET |
141 MT9M111_RESTART |
142 MT9M111_ANALOG_STANDBY |
143 MT9M111_CHIP_DISABLE,
144 MT9M111_SHOW_BAD_FRAMES |
145 MT9M111_RESTART_BAD_FRAMES |
146 MT9M111_SYNCHRONIZE_CHANGES},
147
148 {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
149 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
150 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
151 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
152 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
153 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
154 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
155 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
156
157 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
158 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
159 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
160 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
161 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
162 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
163
164 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
165};
166
167static const unsigned char init_mt9m111[][4] = {
168 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
169 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
170 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
171 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
172 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
173 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
174
175 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
176 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
177 {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
178 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
179 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
180 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
181 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
182 {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
183 {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
184 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
185
186 {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
187 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
188 {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
189 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
190 {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
191 MT9M111_CP_OPERATING_MODE_CTL},
192 {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
193 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
194 MT9M111_2D_DEFECT_CORRECTION_ENABLE},
195 {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
196 MT9M111_2D_DEFECT_CORRECTION_ENABLE},
197 {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
198 {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
199 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
200 {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
201 {SENSOR, 0xcd, 0x00, 0x0e},
202 {SENSOR, 0xd0, 0x00, 0x40},
203
204 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
205 {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
206 {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
207
208 {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
209 {SENSOR, 0x33, 0x03, 0x49},
210 {SENSOR, 0x34, 0xc0, 0x19},
211 {SENSOR, 0x3f, 0x20, 0x20},
212 {SENSOR, 0x40, 0x20, 0x20},
213 {SENSOR, 0x5a, 0xc0, 0x0a},
214 {SENSOR, 0x70, 0x7b, 0x0a},
215 {SENSOR, 0x71, 0xff, 0x00},
216 {SENSOR, 0x72, 0x19, 0x0e},
217 {SENSOR, 0x73, 0x18, 0x0f},
218 {SENSOR, 0x74, 0x57, 0x32},
219 {SENSOR, 0x75, 0x56, 0x34},
220 {SENSOR, 0x76, 0x73, 0x35},
221 {SENSOR, 0x77, 0x30, 0x12},
222 {SENSOR, 0x78, 0x79, 0x02},
223 {SENSOR, 0x79, 0x75, 0x06},
224 {SENSOR, 0x7a, 0x77, 0x0a},
225 {SENSOR, 0x7b, 0x78, 0x09},
226 {SENSOR, 0x7c, 0x7d, 0x06},
227 {SENSOR, 0x7d, 0x31, 0x10},
228 {SENSOR, 0x7e, 0x00, 0x7e},
229 {SENSOR, 0x80, 0x59, 0x04},
230 {SENSOR, 0x81, 0x59, 0x04},
231 {SENSOR, 0x82, 0x57, 0x0a},
232 {SENSOR, 0x83, 0x58, 0x0b},
233 {SENSOR, 0x84, 0x47, 0x0c},
234 {SENSOR, 0x85, 0x48, 0x0e},
235 {SENSOR, 0x86, 0x5b, 0x02},
236 {SENSOR, 0x87, 0x00, 0x5c},
237 {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
238 {SENSOR, 0x60, 0x00, 0x80},
239 {SENSOR, 0x61, 0x00, 0x00},
240 {SENSOR, 0x62, 0x00, 0x00},
241 {SENSOR, 0x63, 0x00, 0x00},
242 {SENSOR, 0x64, 0x00, 0x00},
243
244 {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
245 {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
246 {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
247 {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
248 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
249 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
250 {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
251 {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
252 {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
253 {SENSOR, 0x30, 0x04, 0x00},
254 /* Set number of blank rows chosen to 400 */
255 {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
256};
257
258static const unsigned char start_mt9m111[][4] = {
259 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
260 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
261 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
262 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
263 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
264 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
265 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
266 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
267 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
268 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
269 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
270};
271#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.c b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
new file mode 100644
index 00000000000..9a14835c128
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
@@ -0,0 +1,488 @@
1/*
2 * Driver for the ov7660 sensor
3 *
4 * Copyright (C) 2009 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include "m5602_ov7660.h"
22
23static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
25static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
26 __s32 *val);
27static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
28 __s32 val);
29static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
30static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
31static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
32static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
33static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
35static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
36static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
37
38static const struct ctrl ov7660_ctrls[] = {
39#define GAIN_IDX 1
40 {
41 {
42 .id = V4L2_CID_GAIN,
43 .type = V4L2_CTRL_TYPE_INTEGER,
44 .name = "gain",
45 .minimum = 0x00,
46 .maximum = 0xff,
47 .step = 0x1,
48 .default_value = OV7660_DEFAULT_GAIN,
49 .flags = V4L2_CTRL_FLAG_SLIDER
50 },
51 .set = ov7660_set_gain,
52 .get = ov7660_get_gain
53 },
54#define BLUE_BALANCE_IDX 2
55#define RED_BALANCE_IDX 3
56#define AUTO_WHITE_BALANCE_IDX 4
57 {
58 {
59 .id = V4L2_CID_AUTO_WHITE_BALANCE,
60 .type = V4L2_CTRL_TYPE_BOOLEAN,
61 .name = "auto white balance",
62 .minimum = 0,
63 .maximum = 1,
64 .step = 1,
65 .default_value = 1
66 },
67 .set = ov7660_set_auto_white_balance,
68 .get = ov7660_get_auto_white_balance
69 },
70#define AUTO_GAIN_CTRL_IDX 5
71 {
72 {
73 .id = V4L2_CID_AUTOGAIN,
74 .type = V4L2_CTRL_TYPE_BOOLEAN,
75 .name = "auto gain control",
76 .minimum = 0,
77 .maximum = 1,
78 .step = 1,
79 .default_value = 1
80 },
81 .set = ov7660_set_auto_gain,
82 .get = ov7660_get_auto_gain
83 },
84#define AUTO_EXPOSURE_IDX 6
85 {
86 {
87 .id = V4L2_CID_EXPOSURE_AUTO,
88 .type = V4L2_CTRL_TYPE_BOOLEAN,
89 .name = "auto exposure",
90 .minimum = 0,
91 .maximum = 1,
92 .step = 1,
93 .default_value = 1
94 },
95 .set = ov7660_set_auto_exposure,
96 .get = ov7660_get_auto_exposure
97 },
98#define HFLIP_IDX 7
99 {
100 {
101 .id = V4L2_CID_HFLIP,
102 .type = V4L2_CTRL_TYPE_BOOLEAN,
103 .name = "horizontal flip",
104 .minimum = 0,
105 .maximum = 1,
106 .step = 1,
107 .default_value = 0
108 },
109 .set = ov7660_set_hflip,
110 .get = ov7660_get_hflip
111 },
112#define VFLIP_IDX 8
113 {
114 {
115 .id = V4L2_CID_VFLIP,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "vertical flip",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121 .default_value = 0
122 },
123 .set = ov7660_set_vflip,
124 .get = ov7660_get_vflip
125 },
126
127};
128
129static struct v4l2_pix_format ov7660_modes[] = {
130 {
131 640,
132 480,
133 V4L2_PIX_FMT_SBGGR8,
134 V4L2_FIELD_NONE,
135 .sizeimage =
136 640 * 480,
137 .bytesperline = 640,
138 .colorspace = V4L2_COLORSPACE_SRGB,
139 .priv = 0
140 }
141};
142
143static void ov7660_dump_registers(struct sd *sd);
144
145int ov7660_probe(struct sd *sd)
146{
147 int err = 0, i;
148 u8 prod_id = 0, ver_id = 0;
149
150 s32 *sensor_settings;
151
152 if (force_sensor) {
153 if (force_sensor == OV7660_SENSOR) {
154 pr_info("Forcing an %s sensor\n", ov7660.name);
155 goto sensor_found;
156 }
157 /* If we want to force another sensor,
158 don't try to probe this one */
159 return -ENODEV;
160 }
161
162 /* Do the preinit */
163 for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
164 u8 data[2];
165
166 if (preinit_ov7660[i][0] == BRIDGE) {
167 err = m5602_write_bridge(sd,
168 preinit_ov7660[i][1],
169 preinit_ov7660[i][2]);
170 } else {
171 data[0] = preinit_ov7660[i][2];
172 err = m5602_write_sensor(sd,
173 preinit_ov7660[i][1], data, 1);
174 }
175 }
176 if (err < 0)
177 return err;
178
179 if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
180 return -ENODEV;
181
182 if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
183 return -ENODEV;
184
185 pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
186
187 if ((prod_id == 0x76) && (ver_id == 0x60)) {
188 pr_info("Detected a ov7660 sensor\n");
189 goto sensor_found;
190 }
191 return -ENODEV;
192
193sensor_found:
194 sensor_settings = kmalloc(
195 ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
196 if (!sensor_settings)
197 return -ENOMEM;
198
199 sd->gspca_dev.cam.cam_mode = ov7660_modes;
200 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
201 sd->desc->ctrls = ov7660_ctrls;
202 sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
203
204 for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
205 sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
206 sd->sensor_priv = sensor_settings;
207
208 return 0;
209}
210
211int ov7660_init(struct sd *sd)
212{
213 int i, err = 0;
214 s32 *sensor_settings = sd->sensor_priv;
215
216 /* Init the sensor */
217 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
218 u8 data[2];
219
220 if (init_ov7660[i][0] == BRIDGE) {
221 err = m5602_write_bridge(sd,
222 init_ov7660[i][1],
223 init_ov7660[i][2]);
224 } else {
225 data[0] = init_ov7660[i][2];
226 err = m5602_write_sensor(sd,
227 init_ov7660[i][1], data, 1);
228 }
229 }
230
231 if (dump_sensor)
232 ov7660_dump_registers(sd);
233
234 err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
235 if (err < 0)
236 return err;
237
238 err = ov7660_set_auto_white_balance(&sd->gspca_dev,
239 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
240 if (err < 0)
241 return err;
242
243 err = ov7660_set_auto_gain(&sd->gspca_dev,
244 sensor_settings[AUTO_GAIN_CTRL_IDX]);
245 if (err < 0)
246 return err;
247
248 err = ov7660_set_auto_exposure(&sd->gspca_dev,
249 sensor_settings[AUTO_EXPOSURE_IDX]);
250 if (err < 0)
251 return err;
252 err = ov7660_set_hflip(&sd->gspca_dev,
253 sensor_settings[HFLIP_IDX]);
254 if (err < 0)
255 return err;
256
257 err = ov7660_set_vflip(&sd->gspca_dev,
258 sensor_settings[VFLIP_IDX]);
259
260 return err;
261}
262
263int ov7660_start(struct sd *sd)
264{
265 return 0;
266}
267
268int ov7660_stop(struct sd *sd)
269{
270 return 0;
271}
272
273void ov7660_disconnect(struct sd *sd)
274{
275 ov7660_stop(sd);
276
277 sd->sensor = NULL;
278 kfree(sd->sensor_priv);
279}
280
281static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
282{
283 struct sd *sd = (struct sd *) gspca_dev;
284 s32 *sensor_settings = sd->sensor_priv;
285
286 *val = sensor_settings[GAIN_IDX];
287 PDEBUG(D_V4L2, "Read gain %d", *val);
288 return 0;
289}
290
291static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
292{
293 int err;
294 u8 i2c_data;
295 struct sd *sd = (struct sd *) gspca_dev;
296 s32 *sensor_settings = sd->sensor_priv;
297
298 PDEBUG(D_V4L2, "Setting gain to %d", val);
299
300 sensor_settings[GAIN_IDX] = val;
301
302 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
303 return err;
304}
305
306
307static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
308 __s32 *val)
309{
310 struct sd *sd = (struct sd *) gspca_dev;
311 s32 *sensor_settings = sd->sensor_priv;
312
313 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
314 return 0;
315}
316
317static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
318 __s32 val)
319{
320 int err;
321 u8 i2c_data;
322 struct sd *sd = (struct sd *) gspca_dev;
323 s32 *sensor_settings = sd->sensor_priv;
324
325 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
326
327 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
328 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
329 if (err < 0)
330 return err;
331
332 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
333 err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
334
335 return err;
336}
337
338static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
339{
340 struct sd *sd = (struct sd *) gspca_dev;
341 s32 *sensor_settings = sd->sensor_priv;
342
343 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
344 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
345 return 0;
346}
347
348static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
349{
350 int err;
351 u8 i2c_data;
352 struct sd *sd = (struct sd *) gspca_dev;
353 s32 *sensor_settings = sd->sensor_priv;
354
355 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
356
357 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
358 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
359 if (err < 0)
360 return err;
361
362 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
363
364 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
365}
366
367static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
368{
369 struct sd *sd = (struct sd *) gspca_dev;
370 s32 *sensor_settings = sd->sensor_priv;
371
372 *val = sensor_settings[AUTO_EXPOSURE_IDX];
373 PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
374 return 0;
375}
376
377static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
378 __s32 val)
379{
380 int err;
381 u8 i2c_data;
382 struct sd *sd = (struct sd *) gspca_dev;
383 s32 *sensor_settings = sd->sensor_priv;
384
385 PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
386
387 sensor_settings[AUTO_EXPOSURE_IDX] = val;
388 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
389 if (err < 0)
390 return err;
391
392 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
393
394 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
395}
396
397static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
398{
399 struct sd *sd = (struct sd *) gspca_dev;
400 s32 *sensor_settings = sd->sensor_priv;
401
402 *val = sensor_settings[HFLIP_IDX];
403 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
404 return 0;
405}
406
407static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
408{
409 int err;
410 u8 i2c_data;
411 struct sd *sd = (struct sd *) gspca_dev;
412 s32 *sensor_settings = sd->sensor_priv;
413
414 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
415
416 sensor_settings[HFLIP_IDX] = val;
417
418 i2c_data = ((val & 0x01) << 5) |
419 (sensor_settings[VFLIP_IDX] << 4);
420
421 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
422
423 return err;
424}
425
426static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
427{
428 struct sd *sd = (struct sd *) gspca_dev;
429 s32 *sensor_settings = sd->sensor_priv;
430
431 *val = sensor_settings[VFLIP_IDX];
432 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
433
434 return 0;
435}
436
437static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
438{
439 int err;
440 u8 i2c_data;
441 struct sd *sd = (struct sd *) gspca_dev;
442 s32 *sensor_settings = sd->sensor_priv;
443
444 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
445 sensor_settings[VFLIP_IDX] = val;
446
447 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
448 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
449 if (err < 0)
450 return err;
451
452 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
453 if (gspca_dev->streaming)
454 err = ov7660_start(sd);
455
456 return err;
457}
458
459static void ov7660_dump_registers(struct sd *sd)
460{
461 int address;
462 pr_info("Dumping the ov7660 register state\n");
463 for (address = 0; address < 0xa9; address++) {
464 u8 value;
465 m5602_read_sensor(sd, address, &value, 1);
466 pr_info("register 0x%x contains 0x%x\n", address, value);
467 }
468
469 pr_info("ov7660 register state dump complete\n");
470
471 pr_info("Probing for which registers that are read/write\n");
472 for (address = 0; address < 0xff; address++) {
473 u8 old_value, ctrl_value;
474 u8 test_value[2] = {0xff, 0xff};
475
476 m5602_read_sensor(sd, address, &old_value, 1);
477 m5602_write_sensor(sd, address, test_value, 1);
478 m5602_read_sensor(sd, address, &ctrl_value, 1);
479
480 if (ctrl_value == test_value[0])
481 pr_info("register 0x%x is writeable\n", address);
482 else
483 pr_info("register 0x%x is read only\n", address);
484
485 /* Restore original value */
486 m5602_write_sensor(sd, address, &old_value, 1);
487 }
488}
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.h b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
new file mode 100644
index 00000000000..2b6a13b508f
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
@@ -0,0 +1,260 @@
1/*
2 * Driver for the ov7660 sensor
3 *
4 * Copyright (C) 2009 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_OV7660_H_
20#define M5602_OV7660_H_
21
22#include "m5602_sensor.h"
23
24#define OV7660_GAIN 0x00
25#define OV7660_BLUE_GAIN 0x01
26#define OV7660_RED_GAIN 0x02
27#define OV7660_VREF 0x03
28#define OV7660_COM1 0x04
29#define OV7660_BAVE 0x05
30#define OV7660_GEAVE 0x06
31#define OV7660_AECHH 0x07
32#define OV7660_RAVE 0x08
33#define OV7660_COM2 0x09
34#define OV7660_PID 0x0a
35#define OV7660_VER 0x0b
36#define OV7660_COM3 0x0c
37#define OV7660_COM4 0x0d
38#define OV7660_COM5 0x0e
39#define OV7660_COM6 0x0f
40#define OV7660_AECH 0x10
41#define OV7660_CLKRC 0x11
42#define OV7660_COM7 0x12
43#define OV7660_COM8 0x13
44#define OV7660_COM9 0x14
45#define OV7660_COM10 0x15
46#define OV7660_RSVD16 0x16
47#define OV7660_HSTART 0x17
48#define OV7660_HSTOP 0x18
49#define OV7660_VSTART 0x19
50#define OV7660_VSTOP 0x1a
51#define OV7660_PSHFT 0x1b
52#define OV7660_MIDH 0x1c
53#define OV7660_MIDL 0x1d
54#define OV7660_MVFP 0x1e
55#define OV7660_LAEC 0x1f
56#define OV7660_BOS 0x20
57#define OV7660_GBOS 0x21
58#define OV7660_GROS 0x22
59#define OV7660_ROS 0x23
60#define OV7660_AEW 0x24
61#define OV7660_AEB 0x25
62#define OV7660_VPT 0x26
63#define OV7660_BBIAS 0x27
64#define OV7660_GbBIAS 0x28
65#define OV7660_RSVD29 0x29
66#define OV7660_RBIAS 0x2c
67#define OV7660_HREF 0x32
68#define OV7660_ADC 0x37
69#define OV7660_OFON 0x39
70#define OV7660_TSLB 0x3a
71#define OV7660_COM12 0x3c
72#define OV7660_COM13 0x3d
73#define OV7660_LCC1 0x62
74#define OV7660_LCC2 0x63
75#define OV7660_LCC3 0x64
76#define OV7660_LCC4 0x65
77#define OV7660_LCC5 0x66
78#define OV7660_HV 0x69
79#define OV7660_RSVDA1 0xa1
80
81#define OV7660_DEFAULT_GAIN 0x0e
82#define OV7660_DEFAULT_RED_GAIN 0x80
83#define OV7660_DEFAULT_BLUE_GAIN 0x80
84#define OV7660_DEFAULT_SATURATION 0x00
85#define OV7660_DEFAULT_EXPOSURE 0x20
86
87/* Kernel module parameters */
88extern int force_sensor;
89extern bool dump_sensor;
90
91int ov7660_probe(struct sd *sd);
92int ov7660_init(struct sd *sd);
93int ov7660_start(struct sd *sd);
94int ov7660_stop(struct sd *sd);
95void ov7660_disconnect(struct sd *sd);
96
97static const struct m5602_sensor ov7660 = {
98 .name = "ov7660",
99 .i2c_slave_id = 0x42,
100 .i2c_regW = 1,
101 .probe = ov7660_probe,
102 .init = ov7660_init,
103 .start = ov7660_start,
104 .stop = ov7660_stop,
105 .disconnect = ov7660_disconnect,
106};
107
108static const unsigned char preinit_ov7660[][4] = {
109 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
110 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
111 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
112 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
113 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
114 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
115 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
116 {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
117 {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
118 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
119 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
120
121 {SENSOR, OV7660_OFON, 0x0c},
122 {SENSOR, OV7660_COM2, 0x11},
123 {SENSOR, OV7660_COM7, 0x05},
124
125 {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
126 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
127 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
128 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
129 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
130 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
131 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
132 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
133 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
134 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
135 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
136 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
137 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
138 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
139 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}
140};
141
142static const unsigned char init_ov7660[][4] = {
143 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
144 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
145 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
146 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
147 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
148 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
149 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
150 {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
151 {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
152 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
153 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
154 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
155 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
156 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
157 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
158 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
159 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
160 {SENSOR, OV7660_COM7, 0x80},
161 {SENSOR, OV7660_CLKRC, 0x80},
162 {SENSOR, OV7660_COM9, 0x4c},
163 {SENSOR, OV7660_OFON, 0x43},
164 {SENSOR, OV7660_COM12, 0x28},
165 {SENSOR, OV7660_COM8, 0x00},
166 {SENSOR, OV7660_COM10, 0x40},
167 {SENSOR, OV7660_HSTART, 0x0c},
168 {SENSOR, OV7660_HSTOP, 0x61},
169 {SENSOR, OV7660_HREF, 0xa4},
170 {SENSOR, OV7660_PSHFT, 0x0b},
171 {SENSOR, OV7660_VSTART, 0x01},
172 {SENSOR, OV7660_VSTOP, 0x7a},
173 {SENSOR, OV7660_VSTOP, 0x00},
174 {SENSOR, OV7660_COM7, 0x05},
175 {SENSOR, OV7660_COM6, 0x42},
176 {SENSOR, OV7660_BBIAS, 0x94},
177 {SENSOR, OV7660_GbBIAS, 0x94},
178 {SENSOR, OV7660_RSVD29, 0x94},
179 {SENSOR, OV7660_RBIAS, 0x94},
180 {SENSOR, OV7660_COM1, 0x00},
181 {SENSOR, OV7660_AECH, 0x00},
182 {SENSOR, OV7660_AECHH, 0x00},
183 {SENSOR, OV7660_ADC, 0x05},
184 {SENSOR, OV7660_COM13, 0x00},
185 {SENSOR, OV7660_RSVDA1, 0x23},
186 {SENSOR, OV7660_TSLB, 0x0d},
187 {SENSOR, OV7660_HV, 0x80},
188 {SENSOR, OV7660_LCC1, 0x00},
189 {SENSOR, OV7660_LCC2, 0x00},
190 {SENSOR, OV7660_LCC3, 0x10},
191 {SENSOR, OV7660_LCC4, 0x40},
192 {SENSOR, OV7660_LCC5, 0x01},
193
194 {SENSOR, OV7660_AECH, 0x20},
195 {SENSOR, OV7660_COM1, 0x00},
196 {SENSOR, OV7660_OFON, 0x0c},
197 {SENSOR, OV7660_COM2, 0x11},
198 {SENSOR, OV7660_COM7, 0x05},
199 {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
200 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
201 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
202 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
203 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
204 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
205 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
206 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
207 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
208 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
209 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
210 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
211 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
212 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
213 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
214 {SENSOR, OV7660_AECH, 0x5f},
215 {SENSOR, OV7660_COM1, 0x03},
216 {SENSOR, OV7660_OFON, 0x0c},
217 {SENSOR, OV7660_COM2, 0x11},
218 {SENSOR, OV7660_COM7, 0x05},
219 {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
220 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
221 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
222 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
223 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
224 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
225 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
226 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
227 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
228 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
229 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
230 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
231 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
232 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
233 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
234
235 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
236 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
237 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
238 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
239 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
240 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
241 {BRIDGE, M5602_XB_SIG_INI, 0x01},
242 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
243 {BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
244 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
245 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
246 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
247 {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
248 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
249 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
250 {BRIDGE, M5602_XB_SIG_INI, 0x00},
251 {BRIDGE, M5602_XB_SIG_INI, 0x02},
252 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
253 {BRIDGE, M5602_XB_HSYNC_PARA, 0x27},
254 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
255 {BRIDGE, M5602_XB_HSYNC_PARA, 0xa7},
256 {BRIDGE, M5602_XB_SIG_INI, 0x00},
257 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
258 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
259};
260#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.c b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
new file mode 100644
index 00000000000..2114a8b90ec
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
@@ -0,0 +1,881 @@
1/*
2 * Driver for the ov9650 sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include "m5602_ov9650.h"
22
23static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
24static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
25static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
27static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
29static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
30static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
31static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
35static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
36 __s32 *val);
37static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
38 __s32 val);
39static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
40static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
41static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
42static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
43
44/* Vertically and horizontally flips the image if matched, needed for machines
45 where the sensor is mounted upside down */
46static
47 const
48 struct dmi_system_id ov9650_flip_dmi_table[] = {
49 {
50 .ident = "ASUS A6Ja",
51 .matches = {
52 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
53 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
54 }
55 },
56 {
57 .ident = "ASUS A6JC",
58 .matches = {
59 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
60 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
61 }
62 },
63 {
64 .ident = "ASUS A6K",
65 .matches = {
66 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
67 DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
68 }
69 },
70 {
71 .ident = "ASUS A6Kt",
72 .matches = {
73 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
74 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
75 }
76 },
77 {
78 .ident = "ASUS A6VA",
79 .matches = {
80 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
81 DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
82 }
83 },
84 {
85
86 .ident = "ASUS A6VC",
87 .matches = {
88 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
89 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
90 }
91 },
92 {
93 .ident = "ASUS A6VM",
94 .matches = {
95 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
96 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
97 }
98 },
99 {
100 .ident = "ASUS A7V",
101 .matches = {
102 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
103 DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
104 }
105 },
106 {
107 .ident = "Alienware Aurora m9700",
108 .matches = {
109 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
110 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
111 }
112 },
113 {}
114};
115
116static const struct ctrl ov9650_ctrls[] = {
117#define EXPOSURE_IDX 0
118 {
119 {
120 .id = V4L2_CID_EXPOSURE,
121 .type = V4L2_CTRL_TYPE_INTEGER,
122 .name = "exposure",
123 .minimum = 0x00,
124 .maximum = 0x1ff,
125 .step = 0x4,
126 .default_value = EXPOSURE_DEFAULT,
127 .flags = V4L2_CTRL_FLAG_SLIDER
128 },
129 .set = ov9650_set_exposure,
130 .get = ov9650_get_exposure
131 },
132#define GAIN_IDX 1
133 {
134 {
135 .id = V4L2_CID_GAIN,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "gain",
138 .minimum = 0x00,
139 .maximum = 0x3ff,
140 .step = 0x1,
141 .default_value = GAIN_DEFAULT,
142 .flags = V4L2_CTRL_FLAG_SLIDER
143 },
144 .set = ov9650_set_gain,
145 .get = ov9650_get_gain
146 },
147#define RED_BALANCE_IDX 2
148 {
149 {
150 .id = V4L2_CID_RED_BALANCE,
151 .type = V4L2_CTRL_TYPE_INTEGER,
152 .name = "red balance",
153 .minimum = 0x00,
154 .maximum = 0xff,
155 .step = 0x1,
156 .default_value = RED_GAIN_DEFAULT,
157 .flags = V4L2_CTRL_FLAG_SLIDER
158 },
159 .set = ov9650_set_red_balance,
160 .get = ov9650_get_red_balance
161 },
162#define BLUE_BALANCE_IDX 3
163 {
164 {
165 .id = V4L2_CID_BLUE_BALANCE,
166 .type = V4L2_CTRL_TYPE_INTEGER,
167 .name = "blue balance",
168 .minimum = 0x00,
169 .maximum = 0xff,
170 .step = 0x1,
171 .default_value = BLUE_GAIN_DEFAULT,
172 .flags = V4L2_CTRL_FLAG_SLIDER
173 },
174 .set = ov9650_set_blue_balance,
175 .get = ov9650_get_blue_balance
176 },
177#define HFLIP_IDX 4
178 {
179 {
180 .id = V4L2_CID_HFLIP,
181 .type = V4L2_CTRL_TYPE_BOOLEAN,
182 .name = "horizontal flip",
183 .minimum = 0,
184 .maximum = 1,
185 .step = 1,
186 .default_value = 0
187 },
188 .set = ov9650_set_hflip,
189 .get = ov9650_get_hflip
190 },
191#define VFLIP_IDX 5
192 {
193 {
194 .id = V4L2_CID_VFLIP,
195 .type = V4L2_CTRL_TYPE_BOOLEAN,
196 .name = "vertical flip",
197 .minimum = 0,
198 .maximum = 1,
199 .step = 1,
200 .default_value = 0
201 },
202 .set = ov9650_set_vflip,
203 .get = ov9650_get_vflip
204 },
205#define AUTO_WHITE_BALANCE_IDX 6
206 {
207 {
208 .id = V4L2_CID_AUTO_WHITE_BALANCE,
209 .type = V4L2_CTRL_TYPE_BOOLEAN,
210 .name = "auto white balance",
211 .minimum = 0,
212 .maximum = 1,
213 .step = 1,
214 .default_value = 1
215 },
216 .set = ov9650_set_auto_white_balance,
217 .get = ov9650_get_auto_white_balance
218 },
219#define AUTO_GAIN_CTRL_IDX 7
220 {
221 {
222 .id = V4L2_CID_AUTOGAIN,
223 .type = V4L2_CTRL_TYPE_BOOLEAN,
224 .name = "auto gain control",
225 .minimum = 0,
226 .maximum = 1,
227 .step = 1,
228 .default_value = 1
229 },
230 .set = ov9650_set_auto_gain,
231 .get = ov9650_get_auto_gain
232 },
233#define AUTO_EXPOSURE_IDX 8
234 {
235 {
236 .id = V4L2_CID_EXPOSURE_AUTO,
237 .type = V4L2_CTRL_TYPE_BOOLEAN,
238 .name = "auto exposure",
239 .minimum = 0,
240 .maximum = 1,
241 .step = 1,
242 .default_value = 1
243 },
244 .set = ov9650_set_auto_exposure,
245 .get = ov9650_get_auto_exposure
246 }
247
248};
249
250static struct v4l2_pix_format ov9650_modes[] = {
251 {
252 176,
253 144,
254 V4L2_PIX_FMT_SBGGR8,
255 V4L2_FIELD_NONE,
256 .sizeimage =
257 176 * 144,
258 .bytesperline = 176,
259 .colorspace = V4L2_COLORSPACE_SRGB,
260 .priv = 9
261 }, {
262 320,
263 240,
264 V4L2_PIX_FMT_SBGGR8,
265 V4L2_FIELD_NONE,
266 .sizeimage =
267 320 * 240,
268 .bytesperline = 320,
269 .colorspace = V4L2_COLORSPACE_SRGB,
270 .priv = 8
271 }, {
272 352,
273 288,
274 V4L2_PIX_FMT_SBGGR8,
275 V4L2_FIELD_NONE,
276 .sizeimage =
277 352 * 288,
278 .bytesperline = 352,
279 .colorspace = V4L2_COLORSPACE_SRGB,
280 .priv = 9
281 }, {
282 640,
283 480,
284 V4L2_PIX_FMT_SBGGR8,
285 V4L2_FIELD_NONE,
286 .sizeimage =
287 640 * 480,
288 .bytesperline = 640,
289 .colorspace = V4L2_COLORSPACE_SRGB,
290 .priv = 9
291 }
292};
293
294static void ov9650_dump_registers(struct sd *sd);
295
296int ov9650_probe(struct sd *sd)
297{
298 int err = 0;
299 u8 prod_id = 0, ver_id = 0, i;
300 s32 *sensor_settings;
301
302 if (force_sensor) {
303 if (force_sensor == OV9650_SENSOR) {
304 pr_info("Forcing an %s sensor\n", ov9650.name);
305 goto sensor_found;
306 }
307 /* If we want to force another sensor,
308 don't try to probe this one */
309 return -ENODEV;
310 }
311
312 PDEBUG(D_PROBE, "Probing for an ov9650 sensor");
313
314 /* Run the pre-init before probing the sensor */
315 for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
316 u8 data = preinit_ov9650[i][2];
317 if (preinit_ov9650[i][0] == SENSOR)
318 err = m5602_write_sensor(sd,
319 preinit_ov9650[i][1], &data, 1);
320 else
321 err = m5602_write_bridge(sd,
322 preinit_ov9650[i][1], data);
323 }
324
325 if (err < 0)
326 return err;
327
328 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
329 return -ENODEV;
330
331 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
332 return -ENODEV;
333
334 if ((prod_id == 0x96) && (ver_id == 0x52)) {
335 pr_info("Detected an ov9650 sensor\n");
336 goto sensor_found;
337 }
338 return -ENODEV;
339
340sensor_found:
341 sensor_settings = kmalloc(
342 ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
343 if (!sensor_settings)
344 return -ENOMEM;
345
346 sd->gspca_dev.cam.cam_mode = ov9650_modes;
347 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
348 sd->desc->ctrls = ov9650_ctrls;
349 sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
350
351 for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
352 sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
353 sd->sensor_priv = sensor_settings;
354 return 0;
355}
356
357int ov9650_init(struct sd *sd)
358{
359 int i, err = 0;
360 u8 data;
361 s32 *sensor_settings = sd->sensor_priv;
362
363 if (dump_sensor)
364 ov9650_dump_registers(sd);
365
366 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
367 data = init_ov9650[i][2];
368 if (init_ov9650[i][0] == SENSOR)
369 err = m5602_write_sensor(sd, init_ov9650[i][1],
370 &data, 1);
371 else
372 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
373 }
374
375 err = ov9650_set_exposure(&sd->gspca_dev,
376 sensor_settings[EXPOSURE_IDX]);
377 if (err < 0)
378 return err;
379
380 err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
381 if (err < 0)
382 return err;
383
384 err = ov9650_set_red_balance(&sd->gspca_dev,
385 sensor_settings[RED_BALANCE_IDX]);
386 if (err < 0)
387 return err;
388
389 err = ov9650_set_blue_balance(&sd->gspca_dev,
390 sensor_settings[BLUE_BALANCE_IDX]);
391 if (err < 0)
392 return err;
393
394 err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
395 if (err < 0)
396 return err;
397
398 err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
399 if (err < 0)
400 return err;
401
402 err = ov9650_set_auto_exposure(&sd->gspca_dev,
403 sensor_settings[AUTO_EXPOSURE_IDX]);
404 if (err < 0)
405 return err;
406
407 err = ov9650_set_auto_white_balance(&sd->gspca_dev,
408 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
409 if (err < 0)
410 return err;
411
412 err = ov9650_set_auto_gain(&sd->gspca_dev,
413 sensor_settings[AUTO_GAIN_CTRL_IDX]);
414 return err;
415}
416
417int ov9650_start(struct sd *sd)
418{
419 u8 data;
420 int i, err = 0;
421 struct cam *cam = &sd->gspca_dev.cam;
422 s32 *sensor_settings = sd->sensor_priv;
423
424 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
425 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
426 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
427 int hor_offs = OV9650_LEFT_OFFSET;
428
429 if ((!dmi_check_system(ov9650_flip_dmi_table) &&
430 sensor_settings[VFLIP_IDX]) ||
431 (dmi_check_system(ov9650_flip_dmi_table) &&
432 !sensor_settings[VFLIP_IDX]))
433 ver_offs--;
434
435 if (width <= 320)
436 hor_offs /= 2;
437
438 /* Synthesize the vsync/hsync setup */
439 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
440 if (res_init_ov9650[i][0] == BRIDGE)
441 err = m5602_write_bridge(sd, res_init_ov9650[i][1],
442 res_init_ov9650[i][2]);
443 else if (res_init_ov9650[i][0] == SENSOR) {
444 data = res_init_ov9650[i][2];
445 err = m5602_write_sensor(sd,
446 res_init_ov9650[i][1], &data, 1);
447 }
448 }
449 if (err < 0)
450 return err;
451
452 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
453 ((ver_offs >> 8) & 0xff));
454 if (err < 0)
455 return err;
456
457 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
458 if (err < 0)
459 return err;
460
461 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
462 if (err < 0)
463 return err;
464
465 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
466 if (err < 0)
467 return err;
468
469 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
470 if (err < 0)
471 return err;
472
473 for (i = 0; i < 2 && !err; i++)
474 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
475 if (err < 0)
476 return err;
477
478 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
479 if (err < 0)
480 return err;
481
482 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
483 if (err < 0)
484 return err;
485
486 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
487 (hor_offs >> 8) & 0xff);
488 if (err < 0)
489 return err;
490
491 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
492 if (err < 0)
493 return err;
494
495 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
496 ((width + hor_offs) >> 8) & 0xff);
497 if (err < 0)
498 return err;
499
500 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
501 ((width + hor_offs) & 0xff));
502 if (err < 0)
503 return err;
504
505 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
506 if (err < 0)
507 return err;
508
509 switch (width) {
510 case 640:
511 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
512
513 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
514 OV9650_RAW_RGB_SELECT;
515 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
516 break;
517
518 case 352:
519 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
520
521 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
522 OV9650_RAW_RGB_SELECT;
523 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
524 break;
525
526 case 320:
527 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
528
529 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
530 OV9650_RAW_RGB_SELECT;
531 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
532 break;
533
534 case 176:
535 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
536
537 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
538 OV9650_RAW_RGB_SELECT;
539 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
540 break;
541 }
542 return err;
543}
544
545int ov9650_stop(struct sd *sd)
546{
547 u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
548 return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
549}
550
551void ov9650_disconnect(struct sd *sd)
552{
553 ov9650_stop(sd);
554
555 sd->sensor = NULL;
556 kfree(sd->sensor_priv);
557}
558
559static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 s32 *sensor_settings = sd->sensor_priv;
563
564 *val = sensor_settings[EXPOSURE_IDX];
565 PDEBUG(D_V4L2, "Read exposure %d", *val);
566 return 0;
567}
568
569static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
570{
571 struct sd *sd = (struct sd *) gspca_dev;
572 s32 *sensor_settings = sd->sensor_priv;
573 u8 i2c_data;
574 int err;
575
576 PDEBUG(D_V4L2, "Set exposure to %d", val);
577
578 sensor_settings[EXPOSURE_IDX] = val;
579 /* The 6 MSBs */
580 i2c_data = (val >> 10) & 0x3f;
581 err = m5602_write_sensor(sd, OV9650_AECHM,
582 &i2c_data, 1);
583 if (err < 0)
584 return err;
585
586 /* The 8 middle bits */
587 i2c_data = (val >> 2) & 0xff;
588 err = m5602_write_sensor(sd, OV9650_AECH,
589 &i2c_data, 1);
590 if (err < 0)
591 return err;
592
593 /* The 2 LSBs */
594 i2c_data = val & 0x03;
595 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
596 return err;
597}
598
599static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
600{
601 struct sd *sd = (struct sd *) gspca_dev;
602 s32 *sensor_settings = sd->sensor_priv;
603
604 *val = sensor_settings[GAIN_IDX];
605 PDEBUG(D_V4L2, "Read gain %d", *val);
606 return 0;
607}
608
609static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
610{
611 int err;
612 u8 i2c_data;
613 struct sd *sd = (struct sd *) gspca_dev;
614 s32 *sensor_settings = sd->sensor_priv;
615
616 PDEBUG(D_V4L2, "Setting gain to %d", val);
617
618 sensor_settings[GAIN_IDX] = val;
619
620 /* The 2 MSB */
621 /* Read the OV9650_VREF register first to avoid
622 corrupting the VREF high and low bits */
623 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
624 if (err < 0)
625 return err;
626
627 /* Mask away all uninteresting bits */
628 i2c_data = ((val & 0x0300) >> 2) |
629 (i2c_data & 0x3f);
630 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
631 if (err < 0)
632 return err;
633
634 /* The 8 LSBs */
635 i2c_data = val & 0xff;
636 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
637 return err;
638}
639
640static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643 s32 *sensor_settings = sd->sensor_priv;
644
645 *val = sensor_settings[RED_BALANCE_IDX];
646 PDEBUG(D_V4L2, "Read red gain %d", *val);
647 return 0;
648}
649
650static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
651{
652 int err;
653 u8 i2c_data;
654 struct sd *sd = (struct sd *) gspca_dev;
655 s32 *sensor_settings = sd->sensor_priv;
656
657 PDEBUG(D_V4L2, "Set red gain to %d", val);
658
659 sensor_settings[RED_BALANCE_IDX] = val;
660
661 i2c_data = val & 0xff;
662 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
663 return err;
664}
665
666static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
667{
668 struct sd *sd = (struct sd *) gspca_dev;
669 s32 *sensor_settings = sd->sensor_priv;
670
671 *val = sensor_settings[BLUE_BALANCE_IDX];
672 PDEBUG(D_V4L2, "Read blue gain %d", *val);
673
674 return 0;
675}
676
677static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
678{
679 int err;
680 u8 i2c_data;
681 struct sd *sd = (struct sd *) gspca_dev;
682 s32 *sensor_settings = sd->sensor_priv;
683
684 PDEBUG(D_V4L2, "Set blue gain to %d", val);
685
686 sensor_settings[BLUE_BALANCE_IDX] = val;
687
688 i2c_data = val & 0xff;
689 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
690 return err;
691}
692
693static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696 s32 *sensor_settings = sd->sensor_priv;
697
698 *val = sensor_settings[HFLIP_IDX];
699 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
700 return 0;
701}
702
703static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
704{
705 int err;
706 u8 i2c_data;
707 struct sd *sd = (struct sd *) gspca_dev;
708 s32 *sensor_settings = sd->sensor_priv;
709
710 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
711
712 sensor_settings[HFLIP_IDX] = val;
713
714 if (!dmi_check_system(ov9650_flip_dmi_table))
715 i2c_data = ((val & 0x01) << 5) |
716 (sensor_settings[VFLIP_IDX] << 4);
717 else
718 i2c_data = ((val & 0x01) << 5) |
719 (!sensor_settings[VFLIP_IDX] << 4);
720
721 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
722
723 return err;
724}
725
726static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729 s32 *sensor_settings = sd->sensor_priv;
730
731 *val = sensor_settings[VFLIP_IDX];
732 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
733
734 return 0;
735}
736
737static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
738{
739 int err;
740 u8 i2c_data;
741 struct sd *sd = (struct sd *) gspca_dev;
742 s32 *sensor_settings = sd->sensor_priv;
743
744 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
745 sensor_settings[VFLIP_IDX] = val;
746
747 if (dmi_check_system(ov9650_flip_dmi_table))
748 val = !val;
749
750 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
751 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
752 if (err < 0)
753 return err;
754
755 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
756 if (gspca_dev->streaming)
757 err = ov9650_start(sd);
758
759 return err;
760}
761
762static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
765 s32 *sensor_settings = sd->sensor_priv;
766
767 *val = sensor_settings[AUTO_EXPOSURE_IDX];
768 PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
769 return 0;
770}
771
772static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
773 __s32 val)
774{
775 int err;
776 u8 i2c_data;
777 struct sd *sd = (struct sd *) gspca_dev;
778 s32 *sensor_settings = sd->sensor_priv;
779
780 PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
781
782 sensor_settings[AUTO_EXPOSURE_IDX] = val;
783 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
784 if (err < 0)
785 return err;
786
787 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
788
789 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
790}
791
792static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
793 __s32 *val)
794{
795 struct sd *sd = (struct sd *) gspca_dev;
796 s32 *sensor_settings = sd->sensor_priv;
797
798 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
799 return 0;
800}
801
802static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
803 __s32 val)
804{
805 int err;
806 u8 i2c_data;
807 struct sd *sd = (struct sd *) gspca_dev;
808 s32 *sensor_settings = sd->sensor_priv;
809
810 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
811
812 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
813 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
814 if (err < 0)
815 return err;
816
817 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
818 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
819
820 return err;
821}
822
823static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826 s32 *sensor_settings = sd->sensor_priv;
827
828 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
829 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
830 return 0;
831}
832
833static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
834{
835 int err;
836 u8 i2c_data;
837 struct sd *sd = (struct sd *) gspca_dev;
838 s32 *sensor_settings = sd->sensor_priv;
839
840 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
841
842 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
843 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
844 if (err < 0)
845 return err;
846
847 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
848
849 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
850}
851
852static void ov9650_dump_registers(struct sd *sd)
853{
854 int address;
855 pr_info("Dumping the ov9650 register state\n");
856 for (address = 0; address < 0xa9; address++) {
857 u8 value;
858 m5602_read_sensor(sd, address, &value, 1);
859 pr_info("register 0x%x contains 0x%x\n", address, value);
860 }
861
862 pr_info("ov9650 register state dump complete\n");
863
864 pr_info("Probing for which registers that are read/write\n");
865 for (address = 0; address < 0xff; address++) {
866 u8 old_value, ctrl_value;
867 u8 test_value[2] = {0xff, 0xff};
868
869 m5602_read_sensor(sd, address, &old_value, 1);
870 m5602_write_sensor(sd, address, test_value, 1);
871 m5602_read_sensor(sd, address, &ctrl_value, 1);
872
873 if (ctrl_value == test_value[0])
874 pr_info("register 0x%x is writeable\n", address);
875 else
876 pr_info("register 0x%x is read only\n", address);
877
878 /* Restore original value */
879 m5602_write_sensor(sd, address, &old_value, 1);
880 }
881}
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.h b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
new file mode 100644
index 00000000000..f7aa5bf6898
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
@@ -0,0 +1,307 @@
1/*
2 * Driver for the ov9650 sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_OV9650_H_
20#define M5602_OV9650_H_
21
22#include <linux/dmi.h>
23#include "m5602_sensor.h"
24
25/*****************************************************************************/
26
27#define OV9650_GAIN 0x00
28#define OV9650_BLUE 0x01
29#define OV9650_RED 0x02
30#define OV9650_VREF 0x03
31#define OV9650_COM1 0x04
32#define OV9650_BAVE 0x05
33#define OV9650_GEAVE 0x06
34#define OV9650_RSVD7 0x07
35#define OV9650_COM2 0x09
36#define OV9650_PID 0x0a
37#define OV9650_VER 0x0b
38#define OV9650_COM3 0x0c
39#define OV9650_COM4 0x0d
40#define OV9650_COM5 0x0e
41#define OV9650_COM6 0x0f
42#define OV9650_AECH 0x10
43#define OV9650_CLKRC 0x11
44#define OV9650_COM7 0x12
45#define OV9650_COM8 0x13
46#define OV9650_COM9 0x14
47#define OV9650_COM10 0x15
48#define OV9650_RSVD16 0x16
49#define OV9650_HSTART 0x17
50#define OV9650_HSTOP 0x18
51#define OV9650_VSTRT 0x19
52#define OV9650_VSTOP 0x1a
53#define OV9650_PSHFT 0x1b
54#define OV9650_MVFP 0x1e
55#define OV9650_AEW 0x24
56#define OV9650_AEB 0x25
57#define OV9650_VPT 0x26
58#define OV9650_BBIAS 0x27
59#define OV9650_GbBIAS 0x28
60#define OV9650_Gr_COM 0x29
61#define OV9650_RBIAS 0x2c
62#define OV9650_HREF 0x32
63#define OV9650_CHLF 0x33
64#define OV9650_ARBLM 0x34
65#define OV9650_RSVD35 0x35
66#define OV9650_RSVD36 0x36
67#define OV9650_ADC 0x37
68#define OV9650_ACOM38 0x38
69#define OV9650_OFON 0x39
70#define OV9650_TSLB 0x3a
71#define OV9650_COM12 0x3c
72#define OV9650_COM13 0x3d
73#define OV9650_COM15 0x40
74#define OV9650_COM16 0x41
75#define OV9650_LCC1 0x62
76#define OV9650_LCC2 0x63
77#define OV9650_LCC3 0x64
78#define OV9650_LCC4 0x65
79#define OV9650_LCC5 0x66
80#define OV9650_HV 0x69
81#define OV9650_DBLV 0x6b
82#define OV9650_COM21 0x8b
83#define OV9650_COM22 0x8c
84#define OV9650_COM24 0x8e
85#define OV9650_DBLC1 0x8f
86#define OV9650_RSVD94 0x94
87#define OV9650_RSVD95 0x95
88#define OV9650_RSVD96 0x96
89#define OV9650_LCCFB 0x9d
90#define OV9650_LCCFR 0x9e
91#define OV9650_AECHM 0xa1
92#define OV9650_COM26 0xa5
93#define OV9650_ACOMA8 0xa8
94#define OV9650_ACOMA9 0xa9
95
96#define OV9650_REGISTER_RESET (1 << 7)
97#define OV9650_VGA_SELECT (1 << 6)
98#define OV9650_CIF_SELECT (1 << 5)
99#define OV9650_QVGA_SELECT (1 << 4)
100#define OV9650_QCIF_SELECT (1 << 3)
101#define OV9650_RGB_SELECT (1 << 2)
102#define OV9650_RAW_RGB_SELECT (1 << 0)
103
104#define OV9650_FAST_AGC_AEC (1 << 7)
105#define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6)
106#define OV9650_BANDING (1 << 5)
107#define OV9650_AGC_EN (1 << 2)
108#define OV9650_AWB_EN (1 << 1)
109#define OV9650_AEC_EN (1 << 0)
110
111#define OV9650_VARIOPIXEL (1 << 2)
112#define OV9650_SYSTEM_CLK_SEL (1 << 7)
113#define OV9650_SLAM_MODE (1 << 4)
114
115#define OV9650_QVGA_VARIOPIXEL (1 << 7)
116
117#define OV9650_VFLIP (1 << 4)
118#define OV9650_HFLIP (1 << 5)
119
120#define OV9650_SOFT_SLEEP (1 << 4)
121#define OV9650_OUTPUT_DRIVE_2X (1 << 0)
122
123#define OV9650_DENOISE_ENABLE (1 << 5)
124#define OV9650_WHITE_PIXEL_ENABLE (1 << 1)
125#define OV9650_WHITE_PIXEL_OPTION (1 << 0)
126
127#define OV9650_LEFT_OFFSET 0x62
128
129#define GAIN_DEFAULT 0x14
130#define RED_GAIN_DEFAULT 0x70
131#define BLUE_GAIN_DEFAULT 0x20
132#define EXPOSURE_DEFAULT 0x1ff
133
134/*****************************************************************************/
135
136/* Kernel module parameters */
137extern int force_sensor;
138extern bool dump_sensor;
139
140int ov9650_probe(struct sd *sd);
141int ov9650_init(struct sd *sd);
142int ov9650_start(struct sd *sd);
143int ov9650_stop(struct sd *sd);
144void ov9650_disconnect(struct sd *sd);
145
146static const struct m5602_sensor ov9650 = {
147 .name = "OV9650",
148 .i2c_slave_id = 0x60,
149 .i2c_regW = 1,
150 .probe = ov9650_probe,
151 .init = ov9650_init,
152 .start = ov9650_start,
153 .stop = ov9650_stop,
154 .disconnect = ov9650_disconnect,
155};
156
157static const unsigned char preinit_ov9650[][3] = {
158 /* [INITCAM] */
159 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
160 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
161 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
162 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
163 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
164 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
165
166 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
167 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
168 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
169 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
170 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
171 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
172 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
173 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
174 /* Reset chip */
175 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
176 /* Enable double clock */
177 {SENSOR, OV9650_CLKRC, 0x80},
178 /* Do something out of spec with the power */
179 {SENSOR, OV9650_OFON, 0x40}
180};
181
182static const unsigned char init_ov9650[][3] = {
183 /* [INITCAM] */
184 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
185 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
186 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
187 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
188 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
189 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
190
191 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
192 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
193 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
194 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
195 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
196 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
197 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
198 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
199
200 /* Reset chip */
201 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
202 /* One extra reset is needed in order to make the sensor behave
203 properly when resuming from ram, could be a timing issue */
204 {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
205
206 /* Enable double clock */
207 {SENSOR, OV9650_CLKRC, 0x80},
208 /* Do something out of spec with the power */
209 {SENSOR, OV9650_OFON, 0x40},
210
211 /* Set fast AGC/AEC algorithm with unlimited step size */
212 {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
213 OV9650_AEC_UNLIM_STEP_SIZE},
214
215 {SENSOR, OV9650_CHLF, 0x10},
216 {SENSOR, OV9650_ARBLM, 0xbf},
217 {SENSOR, OV9650_ACOM38, 0x81},
218 /* Turn off color matrix coefficient double option */
219 {SENSOR, OV9650_COM16, 0x00},
220 /* Enable color matrix for RGB/YUV, Delay Y channel,
221 set output Y/UV delay to 1 */
222 {SENSOR, OV9650_COM13, 0x19},
223 /* Enable digital BLC, Set output mode to U Y V Y */
224 {SENSOR, OV9650_TSLB, 0x0c},
225 /* Limit the AGC/AEC stable upper region */
226 {SENSOR, OV9650_COM24, 0x00},
227 /* Enable HREF and some out of spec things */
228 {SENSOR, OV9650_COM12, 0x73},
229 /* Set all DBLC offset signs to positive and
230 do some out of spec stuff */
231 {SENSOR, OV9650_DBLC1, 0xdf},
232 {SENSOR, OV9650_COM21, 0x06},
233 {SENSOR, OV9650_RSVD35, 0x91},
234 /* Necessary, no camera stream without it */
235 {SENSOR, OV9650_RSVD16, 0x06},
236 {SENSOR, OV9650_RSVD94, 0x99},
237 {SENSOR, OV9650_RSVD95, 0x99},
238 {SENSOR, OV9650_RSVD96, 0x04},
239 /* Enable full range output */
240 {SENSOR, OV9650_COM15, 0x0},
241 /* Enable HREF at optical black, enable ADBLC bias,
242 enable ADBLC, reset timings at format change */
243 {SENSOR, OV9650_COM6, 0x4b},
244 /* Subtract 32 from the B channel bias */
245 {SENSOR, OV9650_BBIAS, 0xa0},
246 /* Subtract 32 from the Gb channel bias */
247 {SENSOR, OV9650_GbBIAS, 0xa0},
248 /* Do not bypass the analog BLC and to some out of spec stuff */
249 {SENSOR, OV9650_Gr_COM, 0x00},
250 /* Subtract 32 from the R channel bias */
251 {SENSOR, OV9650_RBIAS, 0xa0},
252 /* Subtract 32 from the R channel bias */
253 {SENSOR, OV9650_RBIAS, 0x0},
254 {SENSOR, OV9650_COM26, 0x80},
255 {SENSOR, OV9650_ACOMA9, 0x98},
256 /* Set the AGC/AEC stable region upper limit */
257 {SENSOR, OV9650_AEW, 0x68},
258 /* Set the AGC/AEC stable region lower limit */
259 {SENSOR, OV9650_AEB, 0x5c},
260 /* Set the high and low limit nibbles to 3 */
261 {SENSOR, OV9650_VPT, 0xc3},
262 /* Set the Automatic Gain Ceiling (AGC) to 128x,
263 drop VSYNC at frame drop,
264 limit exposure timing,
265 drop frame when the AEC step is larger than the exposure gap */
266 {SENSOR, OV9650_COM9, 0x6e},
267 /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
268 and set PWDN to SLVS (slave mode vertical sync) */
269 {SENSOR, OV9650_COM10, 0x42},
270 /* Set horizontal column start high to default value */
271 {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
272 /* Set horizontal column end */
273 {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
274 /* Complementing register to the two writes above */
275 {SENSOR, OV9650_HREF, 0xb2},
276 /* Set vertical row start high bits */
277 {SENSOR, OV9650_VSTRT, 0x02},
278 /* Set vertical row end low bits */
279 {SENSOR, OV9650_VSTOP, 0x7e},
280 /* Set complementing vertical frame control */
281 {SENSOR, OV9650_VREF, 0x10},
282 {SENSOR, OV9650_ADC, 0x04},
283 {SENSOR, OV9650_HV, 0x40},
284
285 /* Enable denoise, and white-pixel erase */
286 {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
287 OV9650_WHITE_PIXEL_ENABLE |
288 OV9650_WHITE_PIXEL_OPTION},
289
290 /* Enable VARIOPIXEL */
291 {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
292 {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
293
294 /* Put the sensor in soft sleep mode */
295 {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
296};
297
298static const unsigned char res_init_ov9650[][3] = {
299 {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
300
301 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
302 {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
303 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
304 {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
305 {BRIDGE, M5602_XB_SIG_INI, 0x01}
306};
307#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c
new file mode 100644
index 00000000000..b8771698cbc
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_po1030.c
@@ -0,0 +1,763 @@
1/*
2 * Driver for the po1030 sensor
3 *
4 * Copyright (c) 2008 Erik Andrén
5 * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include "m5602_po1030.h"
22
23static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
24static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
25static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
27static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
29static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
30static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
31static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
32static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
33static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
35static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
36static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
37static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
38 __s32 val);
39static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
40 __s32 *val);
41static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
42 __s32 val);
43static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
44 __s32 *val);
45
46static struct v4l2_pix_format po1030_modes[] = {
47 {
48 640,
49 480,
50 V4L2_PIX_FMT_SBGGR8,
51 V4L2_FIELD_NONE,
52 .sizeimage = 640 * 480,
53 .bytesperline = 640,
54 .colorspace = V4L2_COLORSPACE_SRGB,
55 .priv = 2
56 }
57};
58
59static const struct ctrl po1030_ctrls[] = {
60#define GAIN_IDX 0
61 {
62 {
63 .id = V4L2_CID_GAIN,
64 .type = V4L2_CTRL_TYPE_INTEGER,
65 .name = "gain",
66 .minimum = 0x00,
67 .maximum = 0x4f,
68 .step = 0x1,
69 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
70 .flags = V4L2_CTRL_FLAG_SLIDER
71 },
72 .set = po1030_set_gain,
73 .get = po1030_get_gain
74 },
75#define EXPOSURE_IDX 1
76 {
77 {
78 .id = V4L2_CID_EXPOSURE,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "exposure",
81 .minimum = 0x00,
82 .maximum = 0x02ff,
83 .step = 0x1,
84 .default_value = PO1030_EXPOSURE_DEFAULT,
85 .flags = V4L2_CTRL_FLAG_SLIDER
86 },
87 .set = po1030_set_exposure,
88 .get = po1030_get_exposure
89 },
90#define RED_BALANCE_IDX 2
91 {
92 {
93 .id = V4L2_CID_RED_BALANCE,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "red balance",
96 .minimum = 0x00,
97 .maximum = 0xff,
98 .step = 0x1,
99 .default_value = PO1030_RED_GAIN_DEFAULT,
100 .flags = V4L2_CTRL_FLAG_SLIDER
101 },
102 .set = po1030_set_red_balance,
103 .get = po1030_get_red_balance
104 },
105#define BLUE_BALANCE_IDX 3
106 {
107 {
108 .id = V4L2_CID_BLUE_BALANCE,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "blue balance",
111 .minimum = 0x00,
112 .maximum = 0xff,
113 .step = 0x1,
114 .default_value = PO1030_BLUE_GAIN_DEFAULT,
115 .flags = V4L2_CTRL_FLAG_SLIDER
116 },
117 .set = po1030_set_blue_balance,
118 .get = po1030_get_blue_balance
119 },
120#define HFLIP_IDX 4
121 {
122 {
123 .id = V4L2_CID_HFLIP,
124 .type = V4L2_CTRL_TYPE_BOOLEAN,
125 .name = "horizontal flip",
126 .minimum = 0,
127 .maximum = 1,
128 .step = 1,
129 .default_value = 0,
130 },
131 .set = po1030_set_hflip,
132 .get = po1030_get_hflip
133 },
134#define VFLIP_IDX 5
135 {
136 {
137 .id = V4L2_CID_VFLIP,
138 .type = V4L2_CTRL_TYPE_BOOLEAN,
139 .name = "vertical flip",
140 .minimum = 0,
141 .maximum = 1,
142 .step = 1,
143 .default_value = 0,
144 },
145 .set = po1030_set_vflip,
146 .get = po1030_get_vflip
147 },
148#define AUTO_WHITE_BALANCE_IDX 6
149 {
150 {
151 .id = V4L2_CID_AUTO_WHITE_BALANCE,
152 .type = V4L2_CTRL_TYPE_BOOLEAN,
153 .name = "auto white balance",
154 .minimum = 0,
155 .maximum = 1,
156 .step = 1,
157 .default_value = 0,
158 },
159 .set = po1030_set_auto_white_balance,
160 .get = po1030_get_auto_white_balance
161 },
162#define AUTO_EXPOSURE_IDX 7
163 {
164 {
165 .id = V4L2_CID_EXPOSURE_AUTO,
166 .type = V4L2_CTRL_TYPE_BOOLEAN,
167 .name = "auto exposure",
168 .minimum = 0,
169 .maximum = 1,
170 .step = 1,
171 .default_value = 0,
172 },
173 .set = po1030_set_auto_exposure,
174 .get = po1030_get_auto_exposure
175 },
176#define GREEN_BALANCE_IDX 8
177 {
178 {
179 .id = M5602_V4L2_CID_GREEN_BALANCE,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "green balance",
182 .minimum = 0x00,
183 .maximum = 0xff,
184 .step = 0x1,
185 .default_value = PO1030_GREEN_GAIN_DEFAULT,
186 .flags = V4L2_CTRL_FLAG_SLIDER
187 },
188 .set = po1030_set_green_balance,
189 .get = po1030_get_green_balance
190 },
191};
192
193static void po1030_dump_registers(struct sd *sd);
194
195int po1030_probe(struct sd *sd)
196{
197 u8 dev_id_h = 0, i;
198 s32 *sensor_settings;
199
200 if (force_sensor) {
201 if (force_sensor == PO1030_SENSOR) {
202 pr_info("Forcing a %s sensor\n", po1030.name);
203 goto sensor_found;
204 }
205 /* If we want to force another sensor, don't try to probe this
206 * one */
207 return -ENODEV;
208 }
209
210 PDEBUG(D_PROBE, "Probing for a po1030 sensor");
211
212 /* Run the pre-init to actually probe the unit */
213 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
214 u8 data = preinit_po1030[i][2];
215 if (preinit_po1030[i][0] == SENSOR)
216 m5602_write_sensor(sd,
217 preinit_po1030[i][1], &data, 1);
218 else
219 m5602_write_bridge(sd, preinit_po1030[i][1], data);
220 }
221
222 if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
223 return -ENODEV;
224
225 if (dev_id_h == 0x30) {
226 pr_info("Detected a po1030 sensor\n");
227 goto sensor_found;
228 }
229 return -ENODEV;
230
231sensor_found:
232 sensor_settings = kmalloc(
233 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
234 if (!sensor_settings)
235 return -ENOMEM;
236
237 sd->gspca_dev.cam.cam_mode = po1030_modes;
238 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
239 sd->desc->ctrls = po1030_ctrls;
240 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
241
242 for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
243 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
244 sd->sensor_priv = sensor_settings;
245
246 return 0;
247}
248
249int po1030_init(struct sd *sd)
250{
251 s32 *sensor_settings = sd->sensor_priv;
252 int i, err = 0;
253
254 /* Init the sensor */
255 for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
256 u8 data[2] = {0x00, 0x00};
257
258 switch (init_po1030[i][0]) {
259 case BRIDGE:
260 err = m5602_write_bridge(sd,
261 init_po1030[i][1],
262 init_po1030[i][2]);
263 break;
264
265 case SENSOR:
266 data[0] = init_po1030[i][2];
267 err = m5602_write_sensor(sd,
268 init_po1030[i][1], data, 1);
269 break;
270
271 default:
272 pr_info("Invalid stream command, exiting init\n");
273 return -EINVAL;
274 }
275 }
276 if (err < 0)
277 return err;
278
279 if (dump_sensor)
280 po1030_dump_registers(sd);
281
282 err = po1030_set_exposure(&sd->gspca_dev,
283 sensor_settings[EXPOSURE_IDX]);
284 if (err < 0)
285 return err;
286
287 err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
288 if (err < 0)
289 return err;
290
291 err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
292 if (err < 0)
293 return err;
294
295 err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
296 if (err < 0)
297 return err;
298
299 err = po1030_set_red_balance(&sd->gspca_dev,
300 sensor_settings[RED_BALANCE_IDX]);
301 if (err < 0)
302 return err;
303
304 err = po1030_set_blue_balance(&sd->gspca_dev,
305 sensor_settings[BLUE_BALANCE_IDX]);
306 if (err < 0)
307 return err;
308
309 err = po1030_set_green_balance(&sd->gspca_dev,
310 sensor_settings[GREEN_BALANCE_IDX]);
311 if (err < 0)
312 return err;
313
314 err = po1030_set_auto_white_balance(&sd->gspca_dev,
315 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
316 if (err < 0)
317 return err;
318
319 err = po1030_set_auto_exposure(&sd->gspca_dev,
320 sensor_settings[AUTO_EXPOSURE_IDX]);
321 return err;
322}
323
324int po1030_start(struct sd *sd)
325{
326 struct cam *cam = &sd->gspca_dev.cam;
327 int i, err = 0;
328 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
329 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
330 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
331 u8 data;
332
333 switch (width) {
334 case 320:
335 data = PO1030_SUBSAMPLING;
336 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
337 if (err < 0)
338 return err;
339
340 data = ((width + 3) >> 8) & 0xff;
341 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
342 if (err < 0)
343 return err;
344
345 data = (width + 3) & 0xff;
346 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
347 if (err < 0)
348 return err;
349
350 data = ((height + 1) >> 8) & 0xff;
351 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
352 if (err < 0)
353 return err;
354
355 data = (height + 1) & 0xff;
356 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
357
358 height += 6;
359 width -= 1;
360 break;
361
362 case 640:
363 data = 0;
364 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
365 if (err < 0)
366 return err;
367
368 data = ((width + 7) >> 8) & 0xff;
369 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
370 if (err < 0)
371 return err;
372
373 data = (width + 7) & 0xff;
374 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
375 if (err < 0)
376 return err;
377
378 data = ((height + 3) >> 8) & 0xff;
379 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
380 if (err < 0)
381 return err;
382
383 data = (height + 3) & 0xff;
384 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
385
386 height += 12;
387 width -= 2;
388 break;
389 }
390 err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
391 if (err < 0)
392 return err;
393
394 err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
395 if (err < 0)
396 return err;
397
398 err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
399 if (err < 0)
400 return err;
401
402 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
403 if (err < 0)
404 return err;
405
406 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
407 ((ver_offs >> 8) & 0xff));
408 if (err < 0)
409 return err;
410
411 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
412 if (err < 0)
413 return err;
414
415 for (i = 0; i < 2 && !err; i++)
416 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
417 if (err < 0)
418 return err;
419
420 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
421 if (err < 0)
422 return err;
423
424 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
425 if (err < 0)
426 return err;
427
428 for (i = 0; i < 2 && !err; i++)
429 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
430
431 for (i = 0; i < 2 && !err; i++)
432 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
433
434 for (i = 0; i < 2 && !err; i++)
435 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
436 if (err < 0)
437 return err;
438
439 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
440 if (err < 0)
441 return err;
442
443 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
444 if (err < 0)
445 return err;
446
447 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
448 return err;
449}
450
451static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
452{
453 struct sd *sd = (struct sd *) gspca_dev;
454 s32 *sensor_settings = sd->sensor_priv;
455
456 *val = sensor_settings[EXPOSURE_IDX];
457 PDEBUG(D_V4L2, "Exposure read as %d", *val);
458 return 0;
459}
460
461static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
462{
463 struct sd *sd = (struct sd *) gspca_dev;
464 s32 *sensor_settings = sd->sensor_priv;
465 u8 i2c_data;
466 int err;
467
468 sensor_settings[EXPOSURE_IDX] = val;
469 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
470
471 i2c_data = ((val & 0xff00) >> 8);
472 PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
473 i2c_data);
474
475 err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
476 &i2c_data, 1);
477 if (err < 0)
478 return err;
479
480 i2c_data = (val & 0xff);
481 PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
482 i2c_data);
483 err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
484 &i2c_data, 1);
485
486 return err;
487}
488
489static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
490{
491 struct sd *sd = (struct sd *) gspca_dev;
492 s32 *sensor_settings = sd->sensor_priv;
493
494 *val = sensor_settings[GAIN_IDX];
495 PDEBUG(D_V4L2, "Read global gain %d", *val);
496 return 0;
497}
498
499static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
500{
501 struct sd *sd = (struct sd *) gspca_dev;
502 s32 *sensor_settings = sd->sensor_priv;
503 u8 i2c_data;
504 int err;
505
506 sensor_settings[GAIN_IDX] = val;
507
508 i2c_data = val & 0xff;
509 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
510 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
511 &i2c_data, 1);
512 return err;
513}
514
515static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
516{
517 struct sd *sd = (struct sd *) gspca_dev;
518 s32 *sensor_settings = sd->sensor_priv;
519
520 *val = sensor_settings[HFLIP_IDX];
521 PDEBUG(D_V4L2, "Read hflip %d", *val);
522
523 return 0;
524}
525
526static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
527{
528 struct sd *sd = (struct sd *) gspca_dev;
529 s32 *sensor_settings = sd->sensor_priv;
530 u8 i2c_data;
531 int err;
532
533 sensor_settings[HFLIP_IDX] = val;
534
535 PDEBUG(D_V4L2, "Set hflip %d", val);
536 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
537 if (err < 0)
538 return err;
539
540 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
541
542 err = m5602_write_sensor(sd, PO1030_CONTROL2,
543 &i2c_data, 1);
544
545 return err;
546}
547
548static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
549{
550 struct sd *sd = (struct sd *) gspca_dev;
551 s32 *sensor_settings = sd->sensor_priv;
552
553 *val = sensor_settings[VFLIP_IDX];
554 PDEBUG(D_V4L2, "Read vflip %d", *val);
555
556 return 0;
557}
558
559static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 s32 *sensor_settings = sd->sensor_priv;
563 u8 i2c_data;
564 int err;
565
566 sensor_settings[VFLIP_IDX] = val;
567
568 PDEBUG(D_V4L2, "Set vflip %d", val);
569 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
570 if (err < 0)
571 return err;
572
573 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
574
575 err = m5602_write_sensor(sd, PO1030_CONTROL2,
576 &i2c_data, 1);
577
578 return err;
579}
580
581static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
582{
583 struct sd *sd = (struct sd *) gspca_dev;
584 s32 *sensor_settings = sd->sensor_priv;
585
586 *val = sensor_settings[RED_BALANCE_IDX];
587 PDEBUG(D_V4L2, "Read red gain %d", *val);
588 return 0;
589}
590
591static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
592{
593 struct sd *sd = (struct sd *) gspca_dev;
594 s32 *sensor_settings = sd->sensor_priv;
595 u8 i2c_data;
596 int err;
597
598 sensor_settings[RED_BALANCE_IDX] = val;
599
600 i2c_data = val & 0xff;
601 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
602 err = m5602_write_sensor(sd, PO1030_RED_GAIN,
603 &i2c_data, 1);
604 return err;
605}
606
607static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
608{
609 struct sd *sd = (struct sd *) gspca_dev;
610 s32 *sensor_settings = sd->sensor_priv;
611
612 *val = sensor_settings[BLUE_BALANCE_IDX];
613 PDEBUG(D_V4L2, "Read blue gain %d", *val);
614
615 return 0;
616}
617
618static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 s32 *sensor_settings = sd->sensor_priv;
622 u8 i2c_data;
623 int err;
624
625 sensor_settings[BLUE_BALANCE_IDX] = val;
626
627 i2c_data = val & 0xff;
628 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
629 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
630 &i2c_data, 1);
631
632 return err;
633}
634
635static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
636{
637 struct sd *sd = (struct sd *) gspca_dev;
638 s32 *sensor_settings = sd->sensor_priv;
639
640 *val = sensor_settings[GREEN_BALANCE_IDX];
641 PDEBUG(D_V4L2, "Read green gain %d", *val);
642
643 return 0;
644}
645
646static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
647{
648 struct sd *sd = (struct sd *) gspca_dev;
649 s32 *sensor_settings = sd->sensor_priv;
650 u8 i2c_data;
651 int err;
652
653 sensor_settings[GREEN_BALANCE_IDX] = val;
654 i2c_data = val & 0xff;
655 PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
656
657 err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
658 &i2c_data, 1);
659 if (err < 0)
660 return err;
661
662 return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
663 &i2c_data, 1);
664}
665
666static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
667 __s32 *val)
668{
669 struct sd *sd = (struct sd *) gspca_dev;
670 s32 *sensor_settings = sd->sensor_priv;
671
672 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
673 PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
674
675 return 0;
676}
677
678static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
679 __s32 val)
680{
681 struct sd *sd = (struct sd *) gspca_dev;
682 s32 *sensor_settings = sd->sensor_priv;
683 u8 i2c_data;
684 int err;
685
686 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
687
688 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
689 if (err < 0)
690 return err;
691
692 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
693 i2c_data = (i2c_data & 0xfe) | (val & 0x01);
694 err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
695 return err;
696}
697
698static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
699 __s32 *val)
700{
701 struct sd *sd = (struct sd *) gspca_dev;
702 s32 *sensor_settings = sd->sensor_priv;
703
704 *val = sensor_settings[AUTO_EXPOSURE_IDX];
705 PDEBUG(D_V4L2, "Auto exposure is %d", *val);
706 return 0;
707}
708
709static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
710 __s32 val)
711{
712 struct sd *sd = (struct sd *) gspca_dev;
713 s32 *sensor_settings = sd->sensor_priv;
714 u8 i2c_data;
715 int err;
716
717 sensor_settings[AUTO_EXPOSURE_IDX] = val;
718 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
719 if (err < 0)
720 return err;
721
722 PDEBUG(D_V4L2, "Set auto exposure to %d", val);
723 i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
724 return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
725}
726
727void po1030_disconnect(struct sd *sd)
728{
729 sd->sensor = NULL;
730 kfree(sd->sensor_priv);
731}
732
733static void po1030_dump_registers(struct sd *sd)
734{
735 int address;
736 u8 value = 0;
737
738 pr_info("Dumping the po1030 sensor core registers\n");
739 for (address = 0; address < 0x7f; address++) {
740 m5602_read_sensor(sd, address, &value, 1);
741 pr_info("register 0x%x contains 0x%x\n", address, value);
742 }
743
744 pr_info("po1030 register state dump complete\n");
745
746 pr_info("Probing for which registers that are read/write\n");
747 for (address = 0; address < 0xff; address++) {
748 u8 old_value, ctrl_value;
749 u8 test_value[2] = {0xff, 0xff};
750
751 m5602_read_sensor(sd, address, &old_value, 1);
752 m5602_write_sensor(sd, address, test_value, 1);
753 m5602_read_sensor(sd, address, &ctrl_value, 1);
754
755 if (ctrl_value == test_value[0])
756 pr_info("register 0x%x is writeable\n", address);
757 else
758 pr_info("register 0x%x is read only\n", address);
759
760 /* Restore original value */
761 m5602_write_sensor(sd, address, &old_value, 1);
762 }
763}
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.h b/drivers/media/usb/gspca/m5602/m5602_po1030.h
new file mode 100644
index 00000000000..81a2bcb88fe
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_po1030.h
@@ -0,0 +1,272 @@
1/*
2 * Driver for the po1030 sensor.
3 *
4 * Copyright (c) 2008 Erik Andrén
5 * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * Register defines taken from Pascal Stangs Procyon Armlib
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation, version 2.
18 *
19 */
20
21#ifndef M5602_PO1030_H_
22#define M5602_PO1030_H_
23
24#include "m5602_sensor.h"
25
26/*****************************************************************************/
27
28#define PO1030_DEVID_H 0x00
29#define PO1030_DEVID_L 0x01
30#define PO1030_FRAMEWIDTH_H 0x04
31#define PO1030_FRAMEWIDTH_L 0x05
32#define PO1030_FRAMEHEIGHT_H 0x06
33#define PO1030_FRAMEHEIGHT_L 0x07
34#define PO1030_WINDOWX_H 0x08
35#define PO1030_WINDOWX_L 0x09
36#define PO1030_WINDOWY_H 0x0a
37#define PO1030_WINDOWY_L 0x0b
38#define PO1030_WINDOWWIDTH_H 0x0c
39#define PO1030_WINDOWWIDTH_L 0x0d
40#define PO1030_WINDOWHEIGHT_H 0x0e
41#define PO1030_WINDOWHEIGHT_L 0x0f
42
43#define PO1030_GLOBALIBIAS 0x12
44#define PO1030_PIXELIBIAS 0x13
45
46#define PO1030_GLOBALGAIN 0x15
47#define PO1030_RED_GAIN 0x16
48#define PO1030_GREEN_1_GAIN 0x17
49#define PO1030_BLUE_GAIN 0x18
50#define PO1030_GREEN_2_GAIN 0x19
51
52#define PO1030_INTEGLINES_H 0x1a
53#define PO1030_INTEGLINES_M 0x1b
54#define PO1030_INTEGLINES_L 0x1c
55
56#define PO1030_CONTROL1 0x1d
57#define PO1030_CONTROL2 0x1e
58#define PO1030_CONTROL3 0x1f
59#define PO1030_CONTROL4 0x20
60
61#define PO1030_PERIOD50_H 0x23
62#define PO1030_PERIOD50_L 0x24
63#define PO1030_PERIOD60_H 0x25
64#define PO1030_PERIOD60_L 0x26
65#define PO1030_REGCLK167 0x27
66#define PO1030_FLICKER_DELTA50 0x28
67#define PO1030_FLICKERDELTA60 0x29
68
69#define PO1030_ADCOFFSET 0x2c
70
71/* Gamma Correction Coeffs */
72#define PO1030_GC0 0x2d
73#define PO1030_GC1 0x2e
74#define PO1030_GC2 0x2f
75#define PO1030_GC3 0x30
76#define PO1030_GC4 0x31
77#define PO1030_GC5 0x32
78#define PO1030_GC6 0x33
79#define PO1030_GC7 0x34
80
81/* Color Transform Matrix */
82#define PO1030_CT0 0x35
83#define PO1030_CT1 0x36
84#define PO1030_CT2 0x37
85#define PO1030_CT3 0x38
86#define PO1030_CT4 0x39
87#define PO1030_CT5 0x3a
88#define PO1030_CT6 0x3b
89#define PO1030_CT7 0x3c
90#define PO1030_CT8 0x3d
91
92#define PO1030_AUTOCTRL1 0x3e
93#define PO1030_AUTOCTRL2 0x3f
94
95#define PO1030_YTARGET 0x40
96#define PO1030_GLOBALGAINMIN 0x41
97#define PO1030_GLOBALGAINMAX 0x42
98
99#define PO1030_AWB_RED_TUNING 0x47
100#define PO1030_AWB_BLUE_TUNING 0x48
101
102/* Output format control */
103#define PO1030_OUTFORMCTRL1 0x5a
104#define PO1030_OUTFORMCTRL2 0x5b
105#define PO1030_OUTFORMCTRL3 0x5c
106#define PO1030_OUTFORMCTRL4 0x5d
107#define PO1030_OUTFORMCTRL5 0x5e
108
109#define PO1030_EDGE_ENH_OFF 0x5f
110#define PO1030_EGA 0x60
111
112#define PO1030_Cb_U_GAIN 0x63
113#define PO1030_Cr_V_GAIN 0x64
114
115#define PO1030_YCONTRAST 0x74
116#define PO1030_YSATURATION 0x75
117
118#define PO1030_HFLIP (1 << 7)
119#define PO1030_VFLIP (1 << 6)
120
121#define PO1030_HREF_ENABLE (1 << 6)
122
123#define PO1030_RAW_RGB_BAYER 0x4
124
125#define PO1030_FRAME_EQUAL (1 << 3)
126#define PO1030_AUTO_SUBSAMPLING (1 << 4)
127
128#define PO1030_WEIGHT_WIN_2X (1 << 3)
129
130#define PO1030_SHUTTER_MODE (1 << 6)
131#define PO1030_AUTO_SUBSAMPLING (1 << 4)
132#define PO1030_FRAME_EQUAL (1 << 3)
133
134#define PO1030_SENSOR_RESET (1 << 5)
135
136#define PO1030_SUBSAMPLING (1 << 6)
137
138/*****************************************************************************/
139
140#define PO1030_GLOBAL_GAIN_DEFAULT 0x12
141#define PO1030_EXPOSURE_DEFAULT 0x0085
142#define PO1030_BLUE_GAIN_DEFAULT 0x36
143#define PO1030_RED_GAIN_DEFAULT 0x36
144#define PO1030_GREEN_GAIN_DEFAULT 0x40
145
146/*****************************************************************************/
147
148/* Kernel module parameters */
149extern int force_sensor;
150extern bool dump_sensor;
151
152int po1030_probe(struct sd *sd);
153int po1030_init(struct sd *sd);
154int po1030_start(struct sd *sd);
155void po1030_disconnect(struct sd *sd);
156
157static const struct m5602_sensor po1030 = {
158 .name = "PO1030",
159
160 .i2c_slave_id = 0xdc,
161 .i2c_regW = 1,
162
163 .probe = po1030_probe,
164 .init = po1030_init,
165 .start = po1030_start,
166 .disconnect = po1030_disconnect,
167};
168
169static const unsigned char preinit_po1030[][3] = {
170 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
171 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
172 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
173 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
174 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
175 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
176 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
177 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
178 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
179 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
180 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
181 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
182 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
183
184 {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
185
186 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
187 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
188 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
189 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
190 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
191 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
192 {BRIDGE, M5602_XB_GPIO_DAT, 0x00}
193};
194
195static const unsigned char init_po1030[][3] = {
196 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
197 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
198 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
199 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
200 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
201 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
202 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
203
204 {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
205
206 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
207 {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
208 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
209 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
210 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
211 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
212 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
213 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
214 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
215 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
216
217 {SENSOR, PO1030_AUTOCTRL2, 0x04},
218
219 {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER},
220 {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X},
221
222 {SENSOR, PO1030_CONTROL2, 0x03},
223 {SENSOR, 0x21, 0x90},
224 {SENSOR, PO1030_YTARGET, 0x60},
225 {SENSOR, 0x59, 0x13},
226 {SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE},
227 {SENSOR, PO1030_EDGE_ENH_OFF, 0x00},
228 {SENSOR, PO1030_EGA, 0x80},
229 {SENSOR, 0x78, 0x14},
230 {SENSOR, 0x6f, 0x01},
231 {SENSOR, PO1030_GLOBALGAINMAX, 0x14},
232 {SENSOR, PO1030_Cb_U_GAIN, 0x38},
233 {SENSOR, PO1030_Cr_V_GAIN, 0x38},
234 {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE |
235 PO1030_AUTO_SUBSAMPLING |
236 PO1030_FRAME_EQUAL},
237 {SENSOR, PO1030_GC0, 0x10},
238 {SENSOR, PO1030_GC1, 0x20},
239 {SENSOR, PO1030_GC2, 0x40},
240 {SENSOR, PO1030_GC3, 0x60},
241 {SENSOR, PO1030_GC4, 0x80},
242 {SENSOR, PO1030_GC5, 0xa0},
243 {SENSOR, PO1030_GC6, 0xc0},
244 {SENSOR, PO1030_GC7, 0xff},
245
246 /* Set the width to 751 */
247 {SENSOR, PO1030_FRAMEWIDTH_H, 0x02},
248 {SENSOR, PO1030_FRAMEWIDTH_L, 0xef},
249
250 /* Set the height to 540 */
251 {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02},
252 {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c},
253
254 /* Set the x window to 1 */
255 {SENSOR, PO1030_WINDOWX_H, 0x00},
256 {SENSOR, PO1030_WINDOWX_L, 0x01},
257
258 /* Set the y window to 1 */
259 {SENSOR, PO1030_WINDOWY_H, 0x00},
260 {SENSOR, PO1030_WINDOWY_L, 0x01},
261
262 /* with a very low lighted environment increase the exposure but
263 * decrease the FPS (Frame Per Second) */
264 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
265 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
266
267 {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
268 {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
269 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
270 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
271};
272#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
new file mode 100644
index 00000000000..cc8ec3f7e8d
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
@@ -0,0 +1,726 @@
1/*
2 * Driver for the s5k4aa sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include "m5602_s5k4aa.h"
22
23static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
24static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
25static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
26static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
27static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
28static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
29static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
30static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
31static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
32static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
33static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
34static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
35
36static
37 const
38 struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
39 {
40 .ident = "BRUNEINIT",
41 .matches = {
42 DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
43 DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
44 DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
45 }
46 }, {
47 .ident = "Fujitsu-Siemens Amilo Xa 2528",
48 .matches = {
49 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
50 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
51 }
52 }, {
53 .ident = "Fujitsu-Siemens Amilo Xi 2428",
54 .matches = {
55 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
56 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
57 }
58 }, {
59 .ident = "Fujitsu-Siemens Amilo Xi 2528",
60 .matches = {
61 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
62 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
63 }
64 }, {
65 .ident = "Fujitsu-Siemens Amilo Xi 2550",
66 .matches = {
67 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
68 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
69 }
70 }, {
71 .ident = "Fujitsu-Siemens Amilo Pa 2548",
72 .matches = {
73 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
74 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
75 }
76 }, {
77 .ident = "MSI GX700",
78 .matches = {
79 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
80 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
81 DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
82 }
83 }, {
84 .ident = "MSI GX700",
85 .matches = {
86 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
87 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
88 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
89 }
90 }, {
91 .ident = "MSI GX700",
92 .matches = {
93 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
94 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
95 DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
96 }
97 }, {
98 .ident = "MSI GX700/GX705/EX700",
99 .matches = {
100 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
101 DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
102 }
103 }, {
104 .ident = "MSI L735",
105 .matches = {
106 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
107 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
108 }
109 }, {
110 .ident = "Lenovo Y300",
111 .matches = {
112 DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
113 DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
114 }
115 },
116 { }
117};
118
119static struct v4l2_pix_format s5k4aa_modes[] = {
120 {
121 640,
122 480,
123 V4L2_PIX_FMT_SBGGR8,
124 V4L2_FIELD_NONE,
125 .sizeimage =
126 640 * 480,
127 .bytesperline = 640,
128 .colorspace = V4L2_COLORSPACE_SRGB,
129 .priv = 0
130 },
131 {
132 1280,
133 1024,
134 V4L2_PIX_FMT_SBGGR8,
135 V4L2_FIELD_NONE,
136 .sizeimage =
137 1280 * 1024,
138 .bytesperline = 1280,
139 .colorspace = V4L2_COLORSPACE_SRGB,
140 .priv = 0
141 }
142};
143
144static const struct ctrl s5k4aa_ctrls[] = {
145#define VFLIP_IDX 0
146 {
147 {
148 .id = V4L2_CID_VFLIP,
149 .type = V4L2_CTRL_TYPE_BOOLEAN,
150 .name = "vertical flip",
151 .minimum = 0,
152 .maximum = 1,
153 .step = 1,
154 .default_value = 0
155 },
156 .set = s5k4aa_set_vflip,
157 .get = s5k4aa_get_vflip
158 },
159#define HFLIP_IDX 1
160 {
161 {
162 .id = V4L2_CID_HFLIP,
163 .type = V4L2_CTRL_TYPE_BOOLEAN,
164 .name = "horizontal flip",
165 .minimum = 0,
166 .maximum = 1,
167 .step = 1,
168 .default_value = 0
169 },
170 .set = s5k4aa_set_hflip,
171 .get = s5k4aa_get_hflip
172 },
173#define GAIN_IDX 2
174 {
175 {
176 .id = V4L2_CID_GAIN,
177 .type = V4L2_CTRL_TYPE_INTEGER,
178 .name = "Gain",
179 .minimum = 0,
180 .maximum = 127,
181 .step = 1,
182 .default_value = S5K4AA_DEFAULT_GAIN,
183 .flags = V4L2_CTRL_FLAG_SLIDER
184 },
185 .set = s5k4aa_set_gain,
186 .get = s5k4aa_get_gain
187 },
188#define EXPOSURE_IDX 3
189 {
190 {
191 .id = V4L2_CID_EXPOSURE,
192 .type = V4L2_CTRL_TYPE_INTEGER,
193 .name = "Exposure",
194 .minimum = 13,
195 .maximum = 0xfff,
196 .step = 1,
197 .default_value = 0x100,
198 .flags = V4L2_CTRL_FLAG_SLIDER
199 },
200 .set = s5k4aa_set_exposure,
201 .get = s5k4aa_get_exposure
202 },
203#define NOISE_SUPP_IDX 4
204 {
205 {
206 .id = V4L2_CID_PRIVATE_BASE,
207 .type = V4L2_CTRL_TYPE_BOOLEAN,
208 .name = "Noise suppression (smoothing)",
209 .minimum = 0,
210 .maximum = 1,
211 .step = 1,
212 .default_value = 1,
213 },
214 .set = s5k4aa_set_noise,
215 .get = s5k4aa_get_noise
216 },
217#define BRIGHTNESS_IDX 5
218 {
219 {
220 .id = V4L2_CID_BRIGHTNESS,
221 .type = V4L2_CTRL_TYPE_INTEGER,
222 .name = "Brightness",
223 .minimum = 0,
224 .maximum = 0x1f,
225 .step = 1,
226 .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
227 },
228 .set = s5k4aa_set_brightness,
229 .get = s5k4aa_get_brightness
230 },
231
232};
233
234static void s5k4aa_dump_registers(struct sd *sd);
235
236int s5k4aa_probe(struct sd *sd)
237{
238 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
239 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
240 int i, err = 0;
241 s32 *sensor_settings;
242
243 if (force_sensor) {
244 if (force_sensor == S5K4AA_SENSOR) {
245 pr_info("Forcing a %s sensor\n", s5k4aa.name);
246 goto sensor_found;
247 }
248 /* If we want to force another sensor, don't try to probe this
249 * one */
250 return -ENODEV;
251 }
252
253 PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
254
255 /* Preinit the sensor */
256 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
257 u8 data[2] = {0x00, 0x00};
258
259 switch (preinit_s5k4aa[i][0]) {
260 case BRIDGE:
261 err = m5602_write_bridge(sd,
262 preinit_s5k4aa[i][1],
263 preinit_s5k4aa[i][2]);
264 break;
265
266 case SENSOR:
267 data[0] = preinit_s5k4aa[i][2];
268 err = m5602_write_sensor(sd,
269 preinit_s5k4aa[i][1],
270 data, 1);
271 break;
272
273 case SENSOR_LONG:
274 data[0] = preinit_s5k4aa[i][2];
275 data[1] = preinit_s5k4aa[i][3];
276 err = m5602_write_sensor(sd,
277 preinit_s5k4aa[i][1],
278 data, 2);
279 break;
280 default:
281 pr_info("Invalid stream command, exiting init\n");
282 return -EINVAL;
283 }
284 }
285
286 /* Test some registers, but we don't know their exact meaning yet */
287 if (m5602_read_sensor(sd, 0x00, prod_id, 2))
288 return -ENODEV;
289 if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
290 return -ENODEV;
291 if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
292 return -ENODEV;
293
294 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
295 return -ENODEV;
296 else
297 pr_info("Detected a s5k4aa sensor\n");
298
299sensor_found:
300 sensor_settings = kmalloc(
301 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
302 if (!sensor_settings)
303 return -ENOMEM;
304
305 sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
306 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
307 sd->desc->ctrls = s5k4aa_ctrls;
308 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
309
310 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
311 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
312 sd->sensor_priv = sensor_settings;
313
314 return 0;
315}
316
317int s5k4aa_start(struct sd *sd)
318{
319 int i, err = 0;
320 u8 data[2];
321 struct cam *cam = &sd->gspca_dev.cam;
322 s32 *sensor_settings = sd->sensor_priv;
323
324 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
325 case 1280:
326 PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
327
328 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
329 switch (SXGA_s5k4aa[i][0]) {
330 case BRIDGE:
331 err = m5602_write_bridge(sd,
332 SXGA_s5k4aa[i][1],
333 SXGA_s5k4aa[i][2]);
334 break;
335
336 case SENSOR:
337 data[0] = SXGA_s5k4aa[i][2];
338 err = m5602_write_sensor(sd,
339 SXGA_s5k4aa[i][1],
340 data, 1);
341 break;
342
343 case SENSOR_LONG:
344 data[0] = SXGA_s5k4aa[i][2];
345 data[1] = SXGA_s5k4aa[i][3];
346 err = m5602_write_sensor(sd,
347 SXGA_s5k4aa[i][1],
348 data, 2);
349 break;
350
351 default:
352 pr_err("Invalid stream command, exiting init\n");
353 return -EINVAL;
354 }
355 }
356 err = s5k4aa_set_noise(&sd->gspca_dev, 0);
357 if (err < 0)
358 return err;
359 break;
360
361 case 640:
362 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
363
364 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
365 switch (VGA_s5k4aa[i][0]) {
366 case BRIDGE:
367 err = m5602_write_bridge(sd,
368 VGA_s5k4aa[i][1],
369 VGA_s5k4aa[i][2]);
370 break;
371
372 case SENSOR:
373 data[0] = VGA_s5k4aa[i][2];
374 err = m5602_write_sensor(sd,
375 VGA_s5k4aa[i][1],
376 data, 1);
377 break;
378
379 case SENSOR_LONG:
380 data[0] = VGA_s5k4aa[i][2];
381 data[1] = VGA_s5k4aa[i][3];
382 err = m5602_write_sensor(sd,
383 VGA_s5k4aa[i][1],
384 data, 2);
385 break;
386
387 default:
388 pr_err("Invalid stream command, exiting init\n");
389 return -EINVAL;
390 }
391 }
392 err = s5k4aa_set_noise(&sd->gspca_dev, 1);
393 if (err < 0)
394 return err;
395 break;
396 }
397 if (err < 0)
398 return err;
399
400 err = s5k4aa_set_exposure(&sd->gspca_dev,
401 sensor_settings[EXPOSURE_IDX]);
402 if (err < 0)
403 return err;
404
405 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
406 if (err < 0)
407 return err;
408
409 err = s5k4aa_set_brightness(&sd->gspca_dev,
410 sensor_settings[BRIGHTNESS_IDX]);
411 if (err < 0)
412 return err;
413
414 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
415 if (err < 0)
416 return err;
417
418 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
419 if (err < 0)
420 return err;
421
422 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
423}
424
425int s5k4aa_init(struct sd *sd)
426{
427 int i, err = 0;
428
429 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
430 u8 data[2] = {0x00, 0x00};
431
432 switch (init_s5k4aa[i][0]) {
433 case BRIDGE:
434 err = m5602_write_bridge(sd,
435 init_s5k4aa[i][1],
436 init_s5k4aa[i][2]);
437 break;
438
439 case SENSOR:
440 data[0] = init_s5k4aa[i][2];
441 err = m5602_write_sensor(sd,
442 init_s5k4aa[i][1], data, 1);
443 break;
444
445 case SENSOR_LONG:
446 data[0] = init_s5k4aa[i][2];
447 data[1] = init_s5k4aa[i][3];
448 err = m5602_write_sensor(sd,
449 init_s5k4aa[i][1], data, 2);
450 break;
451 default:
452 pr_info("Invalid stream command, exiting init\n");
453 return -EINVAL;
454 }
455 }
456
457 if (dump_sensor)
458 s5k4aa_dump_registers(sd);
459
460 return err;
461}
462
463static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
464{
465 struct sd *sd = (struct sd *) gspca_dev;
466 s32 *sensor_settings = sd->sensor_priv;
467
468 *val = sensor_settings[EXPOSURE_IDX];
469 PDEBUG(D_V4L2, "Read exposure %d", *val);
470
471 return 0;
472}
473
474static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
475{
476 struct sd *sd = (struct sd *) gspca_dev;
477 s32 *sensor_settings = sd->sensor_priv;
478 u8 data = S5K4AA_PAGE_MAP_2;
479 int err;
480
481 sensor_settings[EXPOSURE_IDX] = val;
482 PDEBUG(D_V4L2, "Set exposure to %d", val);
483 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
484 if (err < 0)
485 return err;
486 data = (val >> 8) & 0xff;
487 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
488 if (err < 0)
489 return err;
490 data = val & 0xff;
491 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
492
493 return err;
494}
495
496static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
497{
498 struct sd *sd = (struct sd *) gspca_dev;
499 s32 *sensor_settings = sd->sensor_priv;
500
501 *val = sensor_settings[VFLIP_IDX];
502 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
503
504 return 0;
505}
506
507static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
508{
509 struct sd *sd = (struct sd *) gspca_dev;
510 s32 *sensor_settings = sd->sensor_priv;
511 u8 data = S5K4AA_PAGE_MAP_2;
512 int err;
513
514 sensor_settings[VFLIP_IDX] = val;
515
516 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
517 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
518 if (err < 0)
519 return err;
520
521 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
522 if (err < 0)
523 return err;
524
525 if (dmi_check_system(s5k4aa_vflip_dmi_table))
526 val = !val;
527
528 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
529 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
530 if (err < 0)
531 return err;
532
533 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
534 if (err < 0)
535 return err;
536 if (val)
537 data &= 0xfe;
538 else
539 data |= 0x01;
540 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
541 return err;
542}
543
544static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
545{
546 struct sd *sd = (struct sd *) gspca_dev;
547 s32 *sensor_settings = sd->sensor_priv;
548
549 *val = sensor_settings[HFLIP_IDX];
550 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
551
552 return 0;
553}
554
555static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
556{
557 struct sd *sd = (struct sd *) gspca_dev;
558 s32 *sensor_settings = sd->sensor_priv;
559 u8 data = S5K4AA_PAGE_MAP_2;
560 int err;
561
562 sensor_settings[HFLIP_IDX] = val;
563
564 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
565 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
566 if (err < 0)
567 return err;
568
569 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
570 if (err < 0)
571 return err;
572
573 if (dmi_check_system(s5k4aa_vflip_dmi_table))
574 val = !val;
575
576 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
577 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
578 if (err < 0)
579 return err;
580
581 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
582 if (err < 0)
583 return err;
584 if (val)
585 data &= 0xfe;
586 else
587 data |= 0x01;
588 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
589 return err;
590}
591
592static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
593{
594 struct sd *sd = (struct sd *) gspca_dev;
595 s32 *sensor_settings = sd->sensor_priv;
596
597 *val = sensor_settings[GAIN_IDX];
598 PDEBUG(D_V4L2, "Read gain %d", *val);
599 return 0;
600}
601
602static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
603{
604 struct sd *sd = (struct sd *) gspca_dev;
605 s32 *sensor_settings = sd->sensor_priv;
606 u8 data = S5K4AA_PAGE_MAP_2;
607 int err;
608
609 sensor_settings[GAIN_IDX] = val;
610
611 PDEBUG(D_V4L2, "Set gain to %d", val);
612 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
613 if (err < 0)
614 return err;
615
616 data = val & 0xff;
617 err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
618
619 return err;
620}
621
622static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625 s32 *sensor_settings = sd->sensor_priv;
626
627 *val = sensor_settings[BRIGHTNESS_IDX];
628 PDEBUG(D_V4L2, "Read brightness %d", *val);
629 return 0;
630}
631
632static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
633{
634 struct sd *sd = (struct sd *) gspca_dev;
635 s32 *sensor_settings = sd->sensor_priv;
636 u8 data = S5K4AA_PAGE_MAP_2;
637 int err;
638
639 sensor_settings[BRIGHTNESS_IDX] = val;
640
641 PDEBUG(D_V4L2, "Set brightness to %d", val);
642 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
643 if (err < 0)
644 return err;
645
646 data = val & 0xff;
647 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
648}
649
650static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
653 s32 *sensor_settings = sd->sensor_priv;
654
655 *val = sensor_settings[NOISE_SUPP_IDX];
656 PDEBUG(D_V4L2, "Read noise %d", *val);
657 return 0;
658}
659
660static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
661{
662 struct sd *sd = (struct sd *) gspca_dev;
663 s32 *sensor_settings = sd->sensor_priv;
664 u8 data = S5K4AA_PAGE_MAP_2;
665 int err;
666
667 sensor_settings[NOISE_SUPP_IDX] = val;
668
669 PDEBUG(D_V4L2, "Set noise to %d", val);
670 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
671 if (err < 0)
672 return err;
673
674 data = val & 0x01;
675 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
676}
677
678void s5k4aa_disconnect(struct sd *sd)
679{
680 sd->sensor = NULL;
681 kfree(sd->sensor_priv);
682}
683
684static void s5k4aa_dump_registers(struct sd *sd)
685{
686 int address;
687 u8 page, old_page;
688 m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
689 for (page = 0; page < 16; page++) {
690 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
691 pr_info("Dumping the s5k4aa register state for page 0x%x\n",
692 page);
693 for (address = 0; address <= 0xff; address++) {
694 u8 value = 0;
695 m5602_read_sensor(sd, address, &value, 1);
696 pr_info("register 0x%x contains 0x%x\n",
697 address, value);
698 }
699 }
700 pr_info("s5k4aa register state dump complete\n");
701
702 for (page = 0; page < 16; page++) {
703 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
704 pr_info("Probing for which registers that are read/write for page 0x%x\n",
705 page);
706 for (address = 0; address <= 0xff; address++) {
707 u8 old_value, ctrl_value, test_value = 0xff;
708
709 m5602_read_sensor(sd, address, &old_value, 1);
710 m5602_write_sensor(sd, address, &test_value, 1);
711 m5602_read_sensor(sd, address, &ctrl_value, 1);
712
713 if (ctrl_value == test_value)
714 pr_info("register 0x%x is writeable\n",
715 address);
716 else
717 pr_info("register 0x%x is read only\n",
718 address);
719
720 /* Restore original value */
721 m5602_write_sensor(sd, address, &old_value, 1);
722 }
723 }
724 pr_info("Read/write register probing complete\n");
725 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
726}
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
new file mode 100644
index 00000000000..8e0035e731c
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
@@ -0,0 +1,283 @@
1/*
2 * Driver for the s5k4aa sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_S5K4AA_H_
20#define M5602_S5K4AA_H_
21
22#include <linux/dmi.h>
23
24#include "m5602_sensor.h"
25
26/*****************************************************************************/
27
28#define S5K4AA_PAGE_MAP 0xec
29
30#define S5K4AA_PAGE_MAP_0 0x00
31#define S5K4AA_PAGE_MAP_1 0x01
32#define S5K4AA_PAGE_MAP_2 0x02
33
34/* Sensor register definitions for page 0x02 */
35#define S5K4AA_READ_MODE 0x03
36#define S5K4AA_ROWSTART_HI 0x04
37#define S5K4AA_ROWSTART_LO 0x05
38#define S5K4AA_COLSTART_HI 0x06
39#define S5K4AA_COLSTART_LO 0x07
40#define S5K4AA_WINDOW_HEIGHT_HI 0x08
41#define S5K4AA_WINDOW_HEIGHT_LO 0x09
42#define S5K4AA_WINDOW_WIDTH_HI 0x0a
43#define S5K4AA_WINDOW_WIDTH_LO 0x0b
44#define S5K4AA_GLOBAL_GAIN__ 0x0f
45/* sync lost, if too low, reduces frame rate if too high */
46#define S5K4AA_H_BLANK_HI__ 0x1d
47#define S5K4AA_H_BLANK_LO__ 0x1e
48#define S5K4AA_EXPOSURE_HI 0x17
49#define S5K4AA_EXPOSURE_LO 0x18
50#define S5K4AA_BRIGHTNESS 0x1f /* (digital?) gain : 5 bits */
51#define S5K4AA_GAIN 0x20 /* (analogue?) gain : 7 bits */
52#define S5K4AA_NOISE_SUPP 0x37
53
54#define S5K4AA_RM_ROW_SKIP_4X 0x08
55#define S5K4AA_RM_ROW_SKIP_2X 0x04
56#define S5K4AA_RM_COL_SKIP_4X 0x02
57#define S5K4AA_RM_COL_SKIP_2X 0x01
58#define S5K4AA_RM_H_FLIP 0x40
59#define S5K4AA_RM_V_FLIP 0x80
60
61#define S5K4AA_DEFAULT_GAIN 0x5f
62#define S5K4AA_DEFAULT_BRIGHTNESS 0x10
63
64/*****************************************************************************/
65
66/* Kernel module parameters */
67extern int force_sensor;
68extern bool dump_sensor;
69
70int s5k4aa_probe(struct sd *sd);
71int s5k4aa_init(struct sd *sd);
72int s5k4aa_start(struct sd *sd);
73void s5k4aa_disconnect(struct sd *sd);
74
75static const struct m5602_sensor s5k4aa = {
76 .name = "S5K4AA",
77 .i2c_slave_id = 0x5a,
78 .i2c_regW = 2,
79
80 .probe = s5k4aa_probe,
81 .init = s5k4aa_init,
82 .start = s5k4aa_start,
83 .disconnect = s5k4aa_disconnect,
84};
85
86static const unsigned char preinit_s5k4aa[][4] = {
87 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
88 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
89 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
90 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
91 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
92 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
93 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
94
95 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
96 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
97 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
98 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
99 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
100 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
101 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
102 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
103 {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
104 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
105 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
106 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
107 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
108 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
109 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
110 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
111
112 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
113 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
114 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
115 {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
116 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
117 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
118 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
119 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
120 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
121 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
122 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
123 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
124 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
125
126 {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
127};
128
129static const unsigned char init_s5k4aa[][4] = {
130 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
131 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
132 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
133 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
134 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
135 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
136 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
137
138 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
139 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
140 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
141 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
142 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
143 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
144 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
145 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
146 {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
147 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
148 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
149 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
150 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
151 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
152 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
153 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
154
155 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
156 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
157 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
158 {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
159 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
160 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
161 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
162 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
163 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
164 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
165 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
166 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
167 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
168
169 {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
170 {SENSOR, 0x36, 0x01, 0x00},
171 {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
172 {SENSOR, 0x7b, 0xff, 0x00},
173 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
174 {SENSOR, 0x0c, 0x05, 0x00},
175 {SENSOR, 0x02, 0x0e, 0x00},
176 {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
177 {SENSOR, 0x37, 0x00, 0x00},
178};
179
180static const unsigned char VGA_s5k4aa[][4] = {
181 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
182 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
183 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
184 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
185 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
186 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
187 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
188 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
189 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
190 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
191 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
192 /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
193 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
194 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
195 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
196 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
197 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
198 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
199 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
200 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
201 /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
202 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
203 {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
204 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
205 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
206 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
207
208 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
209 {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
210 | S5K4AA_RM_COL_SKIP_2X, 0x00},
211 /* 0x37 : Fix image stability when light is too bright and improves
212 * image quality in 640x480, but worsens it in 1280x1024 */
213 {SENSOR, 0x37, 0x01, 0x00},
214 /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
215 {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
216 {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00},
217 {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
218 {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
219 /* window_height_hi, window_height_lo : 960 = 0x03c0 */
220 {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
221 {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
222 /* window_width_hi, window_width_lo : 1280 = 0x0500 */
223 {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
224 {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
225 {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
226 {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
227 {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
228 {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
229 {SENSOR, 0x11, 0x04, 0x00},
230 {SENSOR, 0x12, 0xc3, 0x00},
231 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
232 {SENSOR, 0x02, 0x0e, 0x00},
233};
234
235static const unsigned char SXGA_s5k4aa[][4] = {
236 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
237 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
238 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
239 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
240 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
241 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
242 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
243 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
244 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
245 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
246 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
247 /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */
248 {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
249 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
250 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
251 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
252 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
253 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
254 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
255 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
256 /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */
257 {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
258 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
259 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
260 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
261 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
262
263 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
264 {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00},
265 {SENSOR, 0x37, 0x01, 0x00},
266 {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
267 {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00},
268 {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
269 {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00},
270 {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00},
271 {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00},
272 {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
273 {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
274 {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00},
275 {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00},
276 {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
277 {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
278 {SENSOR, 0x11, 0x04, 0x00},
279 {SENSOR, 0x12, 0xc3, 0x00},
280 {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
281 {SENSOR, 0x02, 0x0e, 0x00},
282};
283#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
new file mode 100644
index 00000000000..1de743a02b0
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
@@ -0,0 +1,605 @@
1/*
2 * Driver for the s5k83a sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/kthread.h>
22#include "m5602_s5k83a.h"
23
24static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
25static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
27static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
28static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
29static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
30static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
31static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
32static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
33static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
34
35static struct v4l2_pix_format s5k83a_modes[] = {
36 {
37 640,
38 480,
39 V4L2_PIX_FMT_SBGGR8,
40 V4L2_FIELD_NONE,
41 .sizeimage =
42 640 * 480,
43 .bytesperline = 640,
44 .colorspace = V4L2_COLORSPACE_SRGB,
45 .priv = 0
46 }
47};
48
49static const struct ctrl s5k83a_ctrls[] = {
50#define GAIN_IDX 0
51 {
52 {
53 .id = V4L2_CID_GAIN,
54 .type = V4L2_CTRL_TYPE_INTEGER,
55 .name = "gain",
56 .minimum = 0x00,
57 .maximum = 0xff,
58 .step = 0x01,
59 .default_value = S5K83A_DEFAULT_GAIN,
60 .flags = V4L2_CTRL_FLAG_SLIDER
61 },
62 .set = s5k83a_set_gain,
63 .get = s5k83a_get_gain
64
65 },
66#define BRIGHTNESS_IDX 1
67 {
68 {
69 .id = V4L2_CID_BRIGHTNESS,
70 .type = V4L2_CTRL_TYPE_INTEGER,
71 .name = "brightness",
72 .minimum = 0x00,
73 .maximum = 0xff,
74 .step = 0x01,
75 .default_value = S5K83A_DEFAULT_BRIGHTNESS,
76 .flags = V4L2_CTRL_FLAG_SLIDER
77 },
78 .set = s5k83a_set_brightness,
79 .get = s5k83a_get_brightness,
80 },
81#define EXPOSURE_IDX 2
82 {
83 {
84 .id = V4L2_CID_EXPOSURE,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "exposure",
87 .minimum = 0x00,
88 .maximum = S5K83A_MAXIMUM_EXPOSURE,
89 .step = 0x01,
90 .default_value = S5K83A_DEFAULT_EXPOSURE,
91 .flags = V4L2_CTRL_FLAG_SLIDER
92 },
93 .set = s5k83a_set_exposure,
94 .get = s5k83a_get_exposure
95 },
96#define HFLIP_IDX 3
97 {
98 {
99 .id = V4L2_CID_HFLIP,
100 .type = V4L2_CTRL_TYPE_BOOLEAN,
101 .name = "horizontal flip",
102 .minimum = 0,
103 .maximum = 1,
104 .step = 1,
105 .default_value = 0
106 },
107 .set = s5k83a_set_hflip,
108 .get = s5k83a_get_hflip
109 },
110#define VFLIP_IDX 4
111 {
112 {
113 .id = V4L2_CID_VFLIP,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 .name = "vertical flip",
116 .minimum = 0,
117 .maximum = 1,
118 .step = 1,
119 .default_value = 0
120 },
121 .set = s5k83a_set_vflip,
122 .get = s5k83a_get_vflip
123 }
124};
125
126static void s5k83a_dump_registers(struct sd *sd);
127static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
128static int s5k83a_set_led_indication(struct sd *sd, u8 val);
129static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
130 __s32 vflip, __s32 hflip);
131
132int s5k83a_probe(struct sd *sd)
133{
134 struct s5k83a_priv *sens_priv;
135 u8 prod_id = 0, ver_id = 0;
136 int i, err = 0;
137
138 if (force_sensor) {
139 if (force_sensor == S5K83A_SENSOR) {
140 pr_info("Forcing a %s sensor\n", s5k83a.name);
141 goto sensor_found;
142 }
143 /* If we want to force another sensor, don't try to probe this
144 * one */
145 return -ENODEV;
146 }
147
148 PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
149
150 /* Preinit the sensor */
151 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
152 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
153 if (preinit_s5k83a[i][0] == SENSOR)
154 err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
155 data, 2);
156 else
157 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
158 data[0]);
159 }
160
161 /* We don't know what register (if any) that contain the product id
162 * Just pick the first addresses that seem to produce the same results
163 * on multiple machines */
164 if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
165 return -ENODEV;
166
167 if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
168 return -ENODEV;
169
170 if ((prod_id == 0xff) || (ver_id == 0xff))
171 return -ENODEV;
172 else
173 pr_info("Detected a s5k83a sensor\n");
174
175sensor_found:
176 sens_priv = kmalloc(
177 sizeof(struct s5k83a_priv), GFP_KERNEL);
178 if (!sens_priv)
179 return -ENOMEM;
180
181 sens_priv->settings =
182 kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
183 if (!sens_priv->settings) {
184 kfree(sens_priv);
185 return -ENOMEM;
186 }
187
188 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
189 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
190 sd->desc->ctrls = s5k83a_ctrls;
191 sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
192
193 /* null the pointer! thread is't running now */
194 sens_priv->rotation_thread = NULL;
195
196 for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
197 sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
198
199 sd->sensor_priv = sens_priv;
200 return 0;
201}
202
203int s5k83a_init(struct sd *sd)
204{
205 int i, err = 0;
206 s32 *sensor_settings =
207 ((struct s5k83a_priv *) sd->sensor_priv)->settings;
208
209 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
210 u8 data[2] = {0x00, 0x00};
211
212 switch (init_s5k83a[i][0]) {
213 case BRIDGE:
214 err = m5602_write_bridge(sd,
215 init_s5k83a[i][1],
216 init_s5k83a[i][2]);
217 break;
218
219 case SENSOR:
220 data[0] = init_s5k83a[i][2];
221 err = m5602_write_sensor(sd,
222 init_s5k83a[i][1], data, 1);
223 break;
224
225 case SENSOR_LONG:
226 data[0] = init_s5k83a[i][2];
227 data[1] = init_s5k83a[i][3];
228 err = m5602_write_sensor(sd,
229 init_s5k83a[i][1], data, 2);
230 break;
231 default:
232 pr_info("Invalid stream command, exiting init\n");
233 return -EINVAL;
234 }
235 }
236
237 if (dump_sensor)
238 s5k83a_dump_registers(sd);
239
240 err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
241 if (err < 0)
242 return err;
243
244 err = s5k83a_set_brightness(&sd->gspca_dev,
245 sensor_settings[BRIGHTNESS_IDX]);
246 if (err < 0)
247 return err;
248
249 err = s5k83a_set_exposure(&sd->gspca_dev,
250 sensor_settings[EXPOSURE_IDX]);
251 if (err < 0)
252 return err;
253
254 err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
255 if (err < 0)
256 return err;
257
258 err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
259
260 return err;
261}
262
263static int rotation_thread_function(void *data)
264{
265 struct sd *sd = (struct sd *) data;
266 struct s5k83a_priv *sens_priv = sd->sensor_priv;
267 u8 reg, previous_rotation = 0;
268 __s32 vflip, hflip;
269
270 set_current_state(TASK_INTERRUPTIBLE);
271 while (!schedule_timeout(100)) {
272 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
273 break;
274
275 s5k83a_get_rotation(sd, &reg);
276 if (previous_rotation != reg) {
277 previous_rotation = reg;
278 pr_info("Camera was flipped\n");
279
280 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
281 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
282
283 if (reg) {
284 vflip = !vflip;
285 hflip = !hflip;
286 }
287 s5k83a_set_flip_real((struct gspca_dev *) sd,
288 vflip, hflip);
289 }
290
291 mutex_unlock(&sd->gspca_dev.usb_lock);
292 set_current_state(TASK_INTERRUPTIBLE);
293 }
294
295 /* return to "front" flip */
296 if (previous_rotation) {
297 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
298 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
299 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
300 }
301
302 sens_priv->rotation_thread = NULL;
303 return 0;
304}
305
306int s5k83a_start(struct sd *sd)
307{
308 int i, err = 0;
309 struct s5k83a_priv *sens_priv = sd->sensor_priv;
310
311 /* Create another thread, polling the GPIO ports of the camera to check
312 if it got rotated. This is how the windows driver does it so we have
313 to assume that there is no better way of accomplishing this */
314 sens_priv->rotation_thread = kthread_create(rotation_thread_function,
315 sd, "rotation thread");
316 wake_up_process(sens_priv->rotation_thread);
317
318 /* Preinit the sensor */
319 for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
320 u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
321 if (start_s5k83a[i][0] == SENSOR)
322 err = m5602_write_sensor(sd, start_s5k83a[i][1],
323 data, 2);
324 else
325 err = m5602_write_bridge(sd, start_s5k83a[i][1],
326 data[0]);
327 }
328 if (err < 0)
329 return err;
330
331 return s5k83a_set_led_indication(sd, 1);
332}
333
334int s5k83a_stop(struct sd *sd)
335{
336 struct s5k83a_priv *sens_priv = sd->sensor_priv;
337
338 if (sens_priv->rotation_thread)
339 kthread_stop(sens_priv->rotation_thread);
340
341 return s5k83a_set_led_indication(sd, 0);
342}
343
344void s5k83a_disconnect(struct sd *sd)
345{
346 struct s5k83a_priv *sens_priv = sd->sensor_priv;
347
348 s5k83a_stop(sd);
349
350 sd->sensor = NULL;
351 kfree(sens_priv->settings);
352 kfree(sens_priv);
353}
354
355static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
356{
357 struct sd *sd = (struct sd *) gspca_dev;
358 struct s5k83a_priv *sens_priv = sd->sensor_priv;
359
360 *val = sens_priv->settings[GAIN_IDX];
361 return 0;
362}
363
364static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
365{
366 int err;
367 u8 data[2];
368 struct sd *sd = (struct sd *) gspca_dev;
369 struct s5k83a_priv *sens_priv = sd->sensor_priv;
370
371 sens_priv->settings[GAIN_IDX] = val;
372
373 data[0] = 0x00;
374 data[1] = 0x20;
375 err = m5602_write_sensor(sd, 0x14, data, 2);
376 if (err < 0)
377 return err;
378
379 data[0] = 0x01;
380 data[1] = 0x00;
381 err = m5602_write_sensor(sd, 0x0d, data, 2);
382 if (err < 0)
383 return err;
384
385 /* FIXME: This is not sane, we need to figure out the composition
386 of these registers */
387 data[0] = val >> 3; /* gain, high 5 bits */
388 data[1] = val >> 1; /* gain, high 7 bits */
389 err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
390
391 return err;
392}
393
394static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
395{
396 struct sd *sd = (struct sd *) gspca_dev;
397 struct s5k83a_priv *sens_priv = sd->sensor_priv;
398
399 *val = sens_priv->settings[BRIGHTNESS_IDX];
400 return 0;
401}
402
403static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
404{
405 int err;
406 u8 data[1];
407 struct sd *sd = (struct sd *) gspca_dev;
408 struct s5k83a_priv *sens_priv = sd->sensor_priv;
409
410 sens_priv->settings[BRIGHTNESS_IDX] = val;
411 data[0] = val;
412 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
413 return err;
414}
415
416static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
417{
418 struct sd *sd = (struct sd *) gspca_dev;
419 struct s5k83a_priv *sens_priv = sd->sensor_priv;
420
421 *val = sens_priv->settings[EXPOSURE_IDX];
422 return 0;
423}
424
425static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
426{
427 int err;
428 u8 data[2];
429 struct sd *sd = (struct sd *) gspca_dev;
430 struct s5k83a_priv *sens_priv = sd->sensor_priv;
431
432 sens_priv->settings[EXPOSURE_IDX] = val;
433 data[0] = 0;
434 data[1] = val;
435 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
436 return err;
437}
438
439static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
440{
441 struct sd *sd = (struct sd *) gspca_dev;
442 struct s5k83a_priv *sens_priv = sd->sensor_priv;
443
444 *val = sens_priv->settings[VFLIP_IDX];
445 return 0;
446}
447
448static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
449 __s32 vflip, __s32 hflip)
450{
451 int err;
452 u8 data[1];
453 struct sd *sd = (struct sd *) gspca_dev;
454
455 data[0] = 0x05;
456 err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
457 if (err < 0)
458 return err;
459
460 /* six bit is vflip, seven is hflip */
461 data[0] = S5K83A_FLIP_MASK;
462 data[0] = (vflip) ? data[0] | 0x40 : data[0];
463 data[0] = (hflip) ? data[0] | 0x80 : data[0];
464
465 err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
466 if (err < 0)
467 return err;
468
469 data[0] = (vflip) ? 0x0b : 0x0a;
470 err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
471 if (err < 0)
472 return err;
473
474 data[0] = (hflip) ? 0x0a : 0x0b;
475 err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
476 return err;
477}
478
479static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
480{
481 int err;
482 u8 reg;
483 __s32 hflip;
484 struct sd *sd = (struct sd *) gspca_dev;
485 struct s5k83a_priv *sens_priv = sd->sensor_priv;
486
487 sens_priv->settings[VFLIP_IDX] = val;
488
489 s5k83a_get_hflip(gspca_dev, &hflip);
490
491 err = s5k83a_get_rotation(sd, &reg);
492 if (err < 0)
493 return err;
494 if (reg) {
495 val = !val;
496 hflip = !hflip;
497 }
498
499 err = s5k83a_set_flip_real(gspca_dev, val, hflip);
500 return err;
501}
502
503static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
504{
505 struct sd *sd = (struct sd *) gspca_dev;
506 struct s5k83a_priv *sens_priv = sd->sensor_priv;
507
508 *val = sens_priv->settings[HFLIP_IDX];
509 return 0;
510}
511
512static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
513{
514 int err;
515 u8 reg;
516 __s32 vflip;
517 struct sd *sd = (struct sd *) gspca_dev;
518 struct s5k83a_priv *sens_priv = sd->sensor_priv;
519
520 sens_priv->settings[HFLIP_IDX] = val;
521
522 s5k83a_get_vflip(gspca_dev, &vflip);
523
524 err = s5k83a_get_rotation(sd, &reg);
525 if (err < 0)
526 return err;
527 if (reg) {
528 val = !val;
529 vflip = !vflip;
530 }
531
532 err = s5k83a_set_flip_real(gspca_dev, vflip, val);
533 return err;
534}
535
536static int s5k83a_set_led_indication(struct sd *sd, u8 val)
537{
538 int err = 0;
539 u8 data[1];
540
541 err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
542 if (err < 0)
543 return err;
544
545 if (val)
546 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
547 else
548 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
549
550 err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
551
552 return err;
553}
554
555/* Get camera rotation on Acer notebooks */
556static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
557{
558 int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
559 *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
560 return err;
561}
562
563static void s5k83a_dump_registers(struct sd *sd)
564{
565 int address;
566 u8 page, old_page;
567 m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
568
569 for (page = 0; page < 16; page++) {
570 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
571 pr_info("Dumping the s5k83a register state for page 0x%x\n",
572 page);
573 for (address = 0; address <= 0xff; address++) {
574 u8 val = 0;
575 m5602_read_sensor(sd, address, &val, 1);
576 pr_info("register 0x%x contains 0x%x\n", address, val);
577 }
578 }
579 pr_info("s5k83a register state dump complete\n");
580
581 for (page = 0; page < 16; page++) {
582 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
583 pr_info("Probing for which registers that are read/write for page 0x%x\n",
584 page);
585 for (address = 0; address <= 0xff; address++) {
586 u8 old_val, ctrl_val, test_val = 0xff;
587
588 m5602_read_sensor(sd, address, &old_val, 1);
589 m5602_write_sensor(sd, address, &test_val, 1);
590 m5602_read_sensor(sd, address, &ctrl_val, 1);
591
592 if (ctrl_val == test_val)
593 pr_info("register 0x%x is writeable\n",
594 address);
595 else
596 pr_info("register 0x%x is read only\n",
597 address);
598
599 /* Restore original val */
600 m5602_write_sensor(sd, address, &old_val, 1);
601 }
602 }
603 pr_info("Read/write register probing complete\n");
604 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
605}
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.h b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
new file mode 100644
index 00000000000..79952247b53
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
@@ -0,0 +1,193 @@
1/*
2 * Driver for the s5k83a sensor
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_S5K83A_H_
20#define M5602_S5K83A_H_
21
22#include "m5602_sensor.h"
23
24#define S5K83A_FLIP 0x01
25#define S5K83A_HFLIP_TUNE 0x03
26#define S5K83A_VFLIP_TUNE 0x05
27#define S5K83A_BRIGHTNESS 0x0a
28#define S5K83A_EXPOSURE 0x18
29#define S5K83A_GAIN 0x1b
30#define S5K83A_PAGE_MAP 0xec
31
32#define S5K83A_DEFAULT_GAIN 0x71
33#define S5K83A_DEFAULT_BRIGHTNESS 0x7e
34#define S5K83A_DEFAULT_EXPOSURE 0x00
35#define S5K83A_MAXIMUM_EXPOSURE 0x3c
36#define S5K83A_FLIP_MASK 0x10
37#define S5K83A_GPIO_LED_MASK 0x10
38#define S5K83A_GPIO_ROTATION_MASK 0x40
39
40/*****************************************************************************/
41
42/* Kernel module parameters */
43extern int force_sensor;
44extern bool dump_sensor;
45
46int s5k83a_probe(struct sd *sd);
47int s5k83a_init(struct sd *sd);
48int s5k83a_start(struct sd *sd);
49int s5k83a_stop(struct sd *sd);
50void s5k83a_disconnect(struct sd *sd);
51
52static const struct m5602_sensor s5k83a = {
53 .name = "S5K83A",
54 .probe = s5k83a_probe,
55 .init = s5k83a_init,
56 .start = s5k83a_start,
57 .stop = s5k83a_stop,
58 .disconnect = s5k83a_disconnect,
59 .i2c_slave_id = 0x5a,
60 .i2c_regW = 2,
61};
62
63struct s5k83a_priv {
64 /* We use another thread periodically
65 probing the orientation of the camera */
66 struct task_struct *rotation_thread;
67 s32 *settings;
68};
69
70static const unsigned char preinit_s5k83a[][4] = {
71 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
72 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
73 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
74 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
75 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
76 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
77 {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
78
79 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
80 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
81 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
82 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
83 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
84 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
85 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
86 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
87 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
88 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
89 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
90 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
91 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
92 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
93 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
94 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
95 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
96 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
97 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
98 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
99 {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
100 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
101 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
102 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
103 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
104 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
105};
106
107/* This could probably be considerably shortened.
108 I don't have the hardware to experiment with it, patches welcome
109*/
110static const unsigned char init_s5k83a[][4] = {
111 /* The following sequence is useless after a clean boot
112 but is necessary after resume from suspend */
113 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
114 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
115 {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
116 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
117 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
118 {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
119 {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
120 {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
121 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
122 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
123 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
124 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
125 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
126 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
127 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
128 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
129 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
130 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
131 {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
132 {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
133 {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
134 {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
135 {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
136 {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
137 {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
138
139 {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
140 {SENSOR, 0xaf, 0x01, 0x00},
141 {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
142 {SENSOR, 0x7b, 0xff, 0x00},
143 {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
144 {SENSOR, 0x01, 0x50, 0x00},
145 {SENSOR, 0x12, 0x20, 0x00},
146 {SENSOR, 0x17, 0x40, 0x00},
147 {SENSOR, 0x1c, 0x00, 0x00},
148 {SENSOR, 0x02, 0x70, 0x00},
149 {SENSOR, 0x03, 0x0b, 0x00},
150 {SENSOR, 0x04, 0xf0, 0x00},
151 {SENSOR, 0x05, 0x0b, 0x00},
152 {SENSOR, 0x06, 0x71, 0x00},
153 {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
154 {SENSOR, 0x08, 0x02, 0x00},
155 {SENSOR, 0x09, 0x88, 0x00}, /* 648 */
156 {SENSOR, 0x14, 0x00, 0x00},
157 {SENSOR, 0x15, 0x20, 0x00}, /* 32 */
158 {SENSOR, 0x19, 0x00, 0x00},
159 {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
160 {SENSOR, 0x0f, 0x02, 0x00},
161 {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
162 /* normal colors
163 (this is value after boot, but after tries can be different) */
164 {SENSOR, 0x00, 0x06, 0x00},
165};
166
167static const unsigned char start_s5k83a[][4] = {
168 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
169 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
170 {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
171 {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
172 {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
173 {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
174 {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
175 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
176 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
177 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
178 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
179 {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
180 {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
181 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
182 {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
183 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
184 {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
185 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
186 {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
187 {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
188 {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
189 {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
190 {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
191 {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
192};
193#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_sensor.h b/drivers/media/usb/gspca/m5602/m5602_sensor.h
new file mode 100644
index 00000000000..edff4f1f586
--- /dev/null
+++ b/drivers/media/usb/gspca/m5602/m5602_sensor.h
@@ -0,0 +1,70 @@
1/*
2 * USB Driver for ALi m5602 based webcams
3 *
4 * Copyright (C) 2008 Erik Andrén
5 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
6 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
7 *
8 * Portions of code to USB interface and ALi driver software,
9 * Copyright (c) 2006 Willem Duinker
10 * v4l2 interface modeled after the V4L2 driver
11 * for SN9C10x PC Camera Controllers
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 *
17 */
18
19#ifndef M5602_SENSOR_H_
20#define M5602_SENSOR_H_
21
22#include "m5602_bridge.h"
23
24#define M5602_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 0)
25#define M5602_V4L2_CID_NOISE_SUPPRESION (V4L2_CID_PRIVATE_BASE + 1)
26
27/* Enumerates all supported sensors */
28enum sensors {
29 OV9650_SENSOR = 1,
30 S5K83A_SENSOR = 2,
31 S5K4AA_SENSOR = 3,
32 MT9M111_SENSOR = 4,
33 PO1030_SENSOR = 5,
34 OV7660_SENSOR = 6,
35};
36
37/* Enumerates all possible instruction types */
38enum instruction {
39 BRIDGE,
40 SENSOR,
41 SENSOR_LONG
42};
43
44struct m5602_sensor {
45 /* Defines the name of a sensor */
46 char name[32];
47
48 /* What i2c address the sensor is connected to */
49 u8 i2c_slave_id;
50
51 /* Width of each i2c register (in bytes) */
52 u8 i2c_regW;
53
54 /* Probes if the sensor is connected */
55 int (*probe)(struct sd *sd);
56
57 /* Performs a initialization sequence */
58 int (*init)(struct sd *sd);
59
60 /* Executed when the camera starts to send data */
61 int (*start)(struct sd *sd);
62
63 /* Executed when the camera ends to send data */
64 int (*stop)(struct sd *sd);
65
66 /* Executed when the device is disconnected */
67 void (*disconnect)(struct sd *sd);
68};
69
70#endif
diff --git a/drivers/media/usb/gspca/mars.c b/drivers/media/usb/gspca/mars.c
new file mode 100644
index 00000000000..ff2c5abf115
--- /dev/null
+++ b/drivers/media/usb/gspca/mars.c
@@ -0,0 +1,439 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "mars"
25
26#include "gspca.h"
27#include "jpeg.h"
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33#define QUALITY 50
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 struct v4l2_ctrl *brightness;
40 struct v4l2_ctrl *saturation;
41 struct v4l2_ctrl *sharpness;
42 struct v4l2_ctrl *gamma;
43 struct { /* illuminator control cluster */
44 struct v4l2_ctrl *illum_top;
45 struct v4l2_ctrl *illum_bottom;
46 };
47 u8 jpeg_hdr[JPEG_HDR_SZ];
48};
49
50/* V4L2 controls supported by the driver */
51static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
52static void setcolors(struct gspca_dev *gspca_dev, s32 val);
53static void setgamma(struct gspca_dev *gspca_dev, s32 val);
54static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
55
56static const struct v4l2_pix_format vga_mode[] = {
57 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
58 .bytesperline = 320,
59 .sizeimage = 320 * 240 * 3 / 8 + 590,
60 .colorspace = V4L2_COLORSPACE_JPEG,
61 .priv = 2},
62 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
63 .bytesperline = 640,
64 .sizeimage = 640 * 480 * 3 / 8 + 590,
65 .colorspace = V4L2_COLORSPACE_JPEG,
66 .priv = 1},
67};
68
69static const __u8 mi_data[0x20] = {
70/* 01 02 03 04 05 06 07 08 */
71 0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
72/* 09 0a 0b 0c 0d 0e 0f 10 */
73 0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
74/* 11 12 13 14 15 16 17 18 */
75 0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
76/* 19 1a 1b 1c 1d 1e 1f 20 */
77 0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
78};
79
80/* write <len> bytes from gspca_dev->usb_buf */
81static void reg_w(struct gspca_dev *gspca_dev,
82 int len)
83{
84 int alen, ret;
85
86 if (gspca_dev->usb_err < 0)
87 return;
88
89 ret = usb_bulk_msg(gspca_dev->dev,
90 usb_sndbulkpipe(gspca_dev->dev, 4),
91 gspca_dev->usb_buf,
92 len,
93 &alen,
94 500); /* timeout in milliseconds */
95 if (ret < 0) {
96 pr_err("reg write [%02x] error %d\n",
97 gspca_dev->usb_buf[0], ret);
98 gspca_dev->usb_err = ret;
99 }
100}
101
102static void mi_w(struct gspca_dev *gspca_dev,
103 u8 addr,
104 u8 value)
105{
106 gspca_dev->usb_buf[0] = 0x1f;
107 gspca_dev->usb_buf[1] = 0; /* control byte */
108 gspca_dev->usb_buf[2] = addr;
109 gspca_dev->usb_buf[3] = value;
110
111 reg_w(gspca_dev, 4);
112}
113
114static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
115{
116 gspca_dev->usb_buf[0] = 0x61;
117 gspca_dev->usb_buf[1] = val;
118 reg_w(gspca_dev, 2);
119}
120
121static void setcolors(struct gspca_dev *gspca_dev, s32 val)
122{
123 gspca_dev->usb_buf[0] = 0x5f;
124 gspca_dev->usb_buf[1] = val << 3;
125 gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
126 reg_w(gspca_dev, 3);
127}
128
129static void setgamma(struct gspca_dev *gspca_dev, s32 val)
130{
131 gspca_dev->usb_buf[0] = 0x06;
132 gspca_dev->usb_buf[1] = val * 0x40;
133 reg_w(gspca_dev, 2);
134}
135
136static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
137{
138 gspca_dev->usb_buf[0] = 0x67;
139 gspca_dev->usb_buf[1] = val * 4 + 3;
140 reg_w(gspca_dev, 2);
141}
142
143static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
144{
145 /* both are off if not streaming */
146 gspca_dev->usb_buf[0] = 0x22;
147 if (top)
148 gspca_dev->usb_buf[1] = 0x76;
149 else if (bottom)
150 gspca_dev->usb_buf[1] = 0x7a;
151 else
152 gspca_dev->usb_buf[1] = 0x7e;
153 reg_w(gspca_dev, 2);
154}
155
156static int mars_s_ctrl(struct v4l2_ctrl *ctrl)
157{
158 struct gspca_dev *gspca_dev =
159 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
160 struct sd *sd = (struct sd *)gspca_dev;
161
162 gspca_dev->usb_err = 0;
163
164 if (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
165 /* only one can be on at a time */
166 if (ctrl->is_new && ctrl->val)
167 sd->illum_bottom->val = 0;
168 if (sd->illum_bottom->is_new && sd->illum_bottom->val)
169 sd->illum_top->val = 0;
170 }
171
172 if (!gspca_dev->streaming)
173 return 0;
174
175 switch (ctrl->id) {
176 case V4L2_CID_BRIGHTNESS:
177 setbrightness(gspca_dev, ctrl->val);
178 break;
179 case V4L2_CID_SATURATION:
180 setcolors(gspca_dev, ctrl->val);
181 break;
182 case V4L2_CID_GAMMA:
183 setgamma(gspca_dev, ctrl->val);
184 break;
185 case V4L2_CID_ILLUMINATORS_1:
186 setilluminators(gspca_dev, sd->illum_top->val,
187 sd->illum_bottom->val);
188 break;
189 case V4L2_CID_SHARPNESS:
190 setsharpness(gspca_dev, ctrl->val);
191 break;
192 default:
193 return -EINVAL;
194 }
195 return gspca_dev->usb_err;
196}
197
198static const struct v4l2_ctrl_ops mars_ctrl_ops = {
199 .s_ctrl = mars_s_ctrl,
200};
201
202/* this function is called at probe time */
203static int sd_init_controls(struct gspca_dev *gspca_dev)
204{
205 struct sd *sd = (struct sd *) gspca_dev;
206 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
207
208 gspca_dev->vdev.ctrl_handler = hdl;
209 v4l2_ctrl_handler_init(hdl, 6);
210 sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
211 V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
212 sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
213 V4L2_CID_SATURATION, 0, 255, 1, 200);
214 sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
215 V4L2_CID_GAMMA, 0, 3, 1, 1);
216 sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
217 V4L2_CID_SHARPNESS, 0, 2, 1, 1);
218 sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
219 V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
220 sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
221 sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
222 V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
223 sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
224 if (hdl->error) {
225 pr_err("Could not initialize controls\n");
226 return hdl->error;
227 }
228 v4l2_ctrl_cluster(2, &sd->illum_top);
229 return 0;
230}
231
232/* this function is called at probe time */
233static int sd_config(struct gspca_dev *gspca_dev,
234 const struct usb_device_id *id)
235{
236 struct cam *cam;
237
238 cam = &gspca_dev->cam;
239 cam->cam_mode = vga_mode;
240 cam->nmodes = ARRAY_SIZE(vga_mode);
241 return 0;
242}
243
244/* this function is called at probe and resume time */
245static int sd_init(struct gspca_dev *gspca_dev)
246{
247 return 0;
248}
249
250static int sd_start(struct gspca_dev *gspca_dev)
251{
252 struct sd *sd = (struct sd *) gspca_dev;
253 u8 *data;
254 int i;
255
256 /* create the JPEG header */
257 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
258 0x21); /* JPEG 422 */
259 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
260
261 data = gspca_dev->usb_buf;
262
263 data[0] = 0x01; /* address */
264 data[1] = 0x01;
265 reg_w(gspca_dev, 2);
266
267 /*
268 Initialize the MR97113 chip register
269 */
270 data[0] = 0x00; /* address */
271 data[1] = 0x0c | 0x01; /* reg 0 */
272 data[2] = 0x01; /* reg 1 */
273 data[3] = gspca_dev->width / 8; /* h_size , reg 2 */
274 data[4] = gspca_dev->height / 8; /* v_size , reg 3 */
275 data[5] = 0x30; /* reg 4, MI, PAS5101 :
276 * 0x30 for 24mhz , 0x28 for 12mhz */
277 data[6] = 0x02; /* reg 5, H start - was 0x04 */
278 data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40; /* reg 0x06: gamma */
279 data[8] = 0x01; /* reg 7, V start - was 0x03 */
280/* if (h_size == 320 ) */
281/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
282/* else */
283 data[9] = 0x52; /* reg 8, 24MHz, no scale down */
284/*jfm: from win trace*/
285 data[10] = 0x18;
286
287 reg_w(gspca_dev, 11);
288
289 data[0] = 0x23; /* address */
290 data[1] = 0x09; /* reg 35, append frame header */
291
292 reg_w(gspca_dev, 2);
293
294 data[0] = 0x3c; /* address */
295/* if (gspca_dev->width == 1280) */
296/* data[1] = 200; * reg 60, pc-cam frame size
297 * (unit: 4KB) 800KB */
298/* else */
299 data[1] = 50; /* 50 reg 60, pc-cam frame size
300 * (unit: 4KB) 200KB */
301 reg_w(gspca_dev, 2);
302
303 /* auto dark-gain */
304 data[0] = 0x5e; /* address */
305 data[1] = 0; /* reg 94, Y Gain (auto) */
306/*jfm: from win trace*/
307 /* reg 0x5f/0x60 (LE) = saturation */
308 /* h (60): xxxx x100
309 * l (5f): xxxx x000 */
310 data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
311 data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
312 data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */
313 data[5] = 0x00;
314
315 reg_w(gspca_dev, 6);
316
317 data[0] = 0x67;
318/*jfm: from win trace*/
319 data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
320 data[2] = 0x14;
321 reg_w(gspca_dev, 3);
322
323 data[0] = 0x69;
324 data[1] = 0x2f;
325 data[2] = 0x28;
326 data[3] = 0x42;
327 reg_w(gspca_dev, 4);
328
329 data[0] = 0x63;
330 data[1] = 0x07;
331 reg_w(gspca_dev, 2);
332/*jfm: win trace - many writes here to reg 0x64*/
333
334 /* initialize the MI sensor */
335 for (i = 0; i < sizeof mi_data; i++)
336 mi_w(gspca_dev, i + 1, mi_data[i]);
337
338 data[0] = 0x00;
339 data[1] = 0x4d; /* ISOC transferring enable... */
340 reg_w(gspca_dev, 2);
341
342 setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
343 v4l2_ctrl_g_ctrl(sd->illum_bottom));
344
345 return gspca_dev->usb_err;
346}
347
348static void sd_stopN(struct gspca_dev *gspca_dev)
349{
350 struct sd *sd = (struct sd *) gspca_dev;
351
352 if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
353 v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
354 setilluminators(gspca_dev, false, false);
355 msleep(20);
356 }
357
358 gspca_dev->usb_buf[0] = 1;
359 gspca_dev->usb_buf[1] = 0;
360 reg_w(gspca_dev, 2);
361}
362
363static void sd_pkt_scan(struct gspca_dev *gspca_dev,
364 u8 *data, /* isoc packet */
365 int len) /* iso packet length */
366{
367 struct sd *sd = (struct sd *) gspca_dev;
368 int p;
369
370 if (len < 6) {
371/* gspca_dev->last_packet_type = DISCARD_PACKET; */
372 return;
373 }
374 for (p = 0; p < len - 6; p++) {
375 if (data[0 + p] == 0xff
376 && data[1 + p] == 0xff
377 && data[2 + p] == 0x00
378 && data[3 + p] == 0xff
379 && data[4 + p] == 0x96) {
380 if (data[5 + p] == 0x64
381 || data[5 + p] == 0x65
382 || data[5 + p] == 0x66
383 || data[5 + p] == 0x67) {
384 PDEBUG(D_PACK, "sof offset: %d len: %d",
385 p, len);
386 gspca_frame_add(gspca_dev, LAST_PACKET,
387 data, p);
388
389 /* put the JPEG header */
390 gspca_frame_add(gspca_dev, FIRST_PACKET,
391 sd->jpeg_hdr, JPEG_HDR_SZ);
392 data += p + 16;
393 len -= p + 16;
394 break;
395 }
396 }
397 }
398 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
399}
400
401/* sub-driver description */
402static const struct sd_desc sd_desc = {
403 .name = MODULE_NAME,
404 .config = sd_config,
405 .init = sd_init,
406 .init_controls = sd_init_controls,
407 .start = sd_start,
408 .stopN = sd_stopN,
409 .pkt_scan = sd_pkt_scan,
410};
411
412/* -- module initialisation -- */
413static const struct usb_device_id device_table[] = {
414 {USB_DEVICE(0x093a, 0x050f)},
415 {}
416};
417MODULE_DEVICE_TABLE(usb, device_table);
418
419/* -- device connect -- */
420static int sd_probe(struct usb_interface *intf,
421 const struct usb_device_id *id)
422{
423 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
424 THIS_MODULE);
425}
426
427static struct usb_driver sd_driver = {
428 .name = MODULE_NAME,
429 .id_table = device_table,
430 .probe = sd_probe,
431 .disconnect = gspca_disconnect,
432#ifdef CONFIG_PM
433 .suspend = gspca_suspend,
434 .resume = gspca_resume,
435 .reset_resume = gspca_resume,
436#endif
437};
438
439module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/mr97310a.c b/drivers/media/usb/gspca/mr97310a.c
new file mode 100644
index 00000000000..8f4714df599
--- /dev/null
+++ b/drivers/media/usb/gspca/mr97310a.c
@@ -0,0 +1,1091 @@
1/*
2 * Mars MR97310A library
3 *
4 * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
5 * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
6 *
7 * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
8 * and for the routines for detecting and classifying these various cameras,
9 * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
10 *
11 * Support for the control settings for the CIF cameras is
12 * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and
13 * Thomas Kaiser <thomas@kaiser-linux.li>
14 *
15 * Support for the control settings for the VGA cameras is
16 * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
17 *
18 * Several previously unsupported cameras are owned and have been tested by
19 * Hans de Goede <hdegoede@redhat.com> and
20 * Thomas Kaiser <thomas@kaiser-linux.li> and
21 * Theodore Kilgore <kilgota@auburn.edu> and
22 * Edmond Rodriguez <erodrig_97@yahoo.com> and
23 * Aurelien Jacobs <aurel@gnuage.org>
24 *
25 * The MR97311A support in gspca/mars.c has been helpful in understanding some
26 * of the registers in these cameras.
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * any later version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 */
42
43#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
44
45#define MODULE_NAME "mr97310a"
46
47#include "gspca.h"
48
49#define CAM_TYPE_CIF 0
50#define CAM_TYPE_VGA 1
51
52#define MR97310A_BRIGHTNESS_DEFAULT 0
53
54#define MR97310A_EXPOSURE_MIN 0
55#define MR97310A_EXPOSURE_MAX 4095
56#define MR97310A_EXPOSURE_DEFAULT 1000
57
58#define MR97310A_GAIN_MIN 0
59#define MR97310A_GAIN_MAX 31
60#define MR97310A_GAIN_DEFAULT 25
61
62#define MR97310A_CONTRAST_MIN 0
63#define MR97310A_CONTRAST_MAX 31
64#define MR97310A_CONTRAST_DEFAULT 23
65
66#define MR97310A_CS_GAIN_MIN 0
67#define MR97310A_CS_GAIN_MAX 0x7ff
68#define MR97310A_CS_GAIN_DEFAULT 0x110
69
70#define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000)
71#define MR97310A_MIN_CLOCKDIV_MIN 3
72#define MR97310A_MIN_CLOCKDIV_MAX 8
73#define MR97310A_MIN_CLOCKDIV_DEFAULT 3
74
75MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
76 "Theodore Kilgore <kilgota@auburn.edu>");
77MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
78MODULE_LICENSE("GPL");
79
80/* global parameters */
81static int force_sensor_type = -1;
82module_param(force_sensor_type, int, 0644);
83MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
84
85/* specific webcam descriptor */
86struct sd {
87 struct gspca_dev gspca_dev; /* !! must be the first item */
88 struct { /* exposure/min_clockdiv control cluster */
89 struct v4l2_ctrl *exposure;
90 struct v4l2_ctrl *min_clockdiv;
91 };
92 u8 sof_read;
93 u8 cam_type; /* 0 is CIF and 1 is VGA */
94 u8 sensor_type; /* We use 0 and 1 here, too. */
95 u8 do_lcd_stop;
96 u8 adj_colors;
97};
98
99struct sensor_w_data {
100 u8 reg;
101 u8 flags;
102 u8 data[16];
103 int len;
104};
105
106static void sd_stopN(struct gspca_dev *gspca_dev);
107
108static const struct v4l2_pix_format vga_mode[] = {
109 {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
110 .bytesperline = 160,
111 .sizeimage = 160 * 120,
112 .colorspace = V4L2_COLORSPACE_SRGB,
113 .priv = 4},
114 {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
115 .bytesperline = 176,
116 .sizeimage = 176 * 144,
117 .colorspace = V4L2_COLORSPACE_SRGB,
118 .priv = 3},
119 {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
120 .bytesperline = 320,
121 .sizeimage = 320 * 240,
122 .colorspace = V4L2_COLORSPACE_SRGB,
123 .priv = 2},
124 {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
125 .bytesperline = 352,
126 .sizeimage = 352 * 288,
127 .colorspace = V4L2_COLORSPACE_SRGB,
128 .priv = 1},
129 {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
130 .bytesperline = 640,
131 .sizeimage = 640 * 480,
132 .colorspace = V4L2_COLORSPACE_SRGB,
133 .priv = 0},
134};
135
136/* the bytes to write are in gspca_dev->usb_buf */
137static int mr_write(struct gspca_dev *gspca_dev, int len)
138{
139 int rc;
140
141 rc = usb_bulk_msg(gspca_dev->dev,
142 usb_sndbulkpipe(gspca_dev->dev, 4),
143 gspca_dev->usb_buf, len, NULL, 500);
144 if (rc < 0)
145 pr_err("reg write [%02x] error %d\n",
146 gspca_dev->usb_buf[0], rc);
147 return rc;
148}
149
150/* the bytes are read into gspca_dev->usb_buf */
151static int mr_read(struct gspca_dev *gspca_dev, int len)
152{
153 int rc;
154
155 rc = usb_bulk_msg(gspca_dev->dev,
156 usb_rcvbulkpipe(gspca_dev->dev, 3),
157 gspca_dev->usb_buf, len, NULL, 500);
158 if (rc < 0)
159 pr_err("reg read [%02x] error %d\n",
160 gspca_dev->usb_buf[0], rc);
161 return rc;
162}
163
164static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
165 const u8 *data, int len)
166{
167 gspca_dev->usb_buf[0] = 0x1f;
168 gspca_dev->usb_buf[1] = flags;
169 gspca_dev->usb_buf[2] = reg;
170 memcpy(gspca_dev->usb_buf + 3, data, len);
171
172 return mr_write(gspca_dev, len + 3);
173}
174
175static int sensor_write_regs(struct gspca_dev *gspca_dev,
176 const struct sensor_w_data *data, int len)
177{
178 int i, rc;
179
180 for (i = 0; i < len; i++) {
181 rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
182 data[i].data, data[i].len);
183 if (rc < 0)
184 return rc;
185 }
186
187 return 0;
188}
189
190static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
191{
192 struct sd *sd = (struct sd *) gspca_dev;
193 u8 buf, confirm_reg;
194 int rc;
195
196 buf = data;
197 if (sd->cam_type == CAM_TYPE_CIF) {
198 rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
199 confirm_reg = sd->sensor_type ? 0x13 : 0x11;
200 } else {
201 rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
202 confirm_reg = 0x11;
203 }
204 if (rc < 0)
205 return rc;
206
207 buf = 0x01;
208 rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
209 if (rc < 0)
210 return rc;
211
212 return 0;
213}
214
215static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
216{
217 int err_code;
218
219 gspca_dev->usb_buf[0] = reg;
220 err_code = mr_write(gspca_dev, 1);
221 if (err_code < 0)
222 return err_code;
223
224 err_code = mr_read(gspca_dev, 16);
225 if (err_code < 0)
226 return err_code;
227
228 if (verbose)
229 PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,
230 gspca_dev->usb_buf[0],
231 gspca_dev->usb_buf[1],
232 gspca_dev->usb_buf[2]);
233
234 return 0;
235}
236
237static int zero_the_pointer(struct gspca_dev *gspca_dev)
238{
239 __u8 *data = gspca_dev->usb_buf;
240 int err_code;
241 u8 status = 0;
242 int tries = 0;
243
244 err_code = cam_get_response16(gspca_dev, 0x21, 0);
245 if (err_code < 0)
246 return err_code;
247
248 data[0] = 0x19;
249 data[1] = 0x51;
250 err_code = mr_write(gspca_dev, 2);
251 if (err_code < 0)
252 return err_code;
253
254 err_code = cam_get_response16(gspca_dev, 0x21, 0);
255 if (err_code < 0)
256 return err_code;
257
258 data[0] = 0x19;
259 data[1] = 0xba;
260 err_code = mr_write(gspca_dev, 2);
261 if (err_code < 0)
262 return err_code;
263
264 err_code = cam_get_response16(gspca_dev, 0x21, 0);
265 if (err_code < 0)
266 return err_code;
267
268 data[0] = 0x19;
269 data[1] = 0x00;
270 err_code = mr_write(gspca_dev, 2);
271 if (err_code < 0)
272 return err_code;
273
274 err_code = cam_get_response16(gspca_dev, 0x21, 0);
275 if (err_code < 0)
276 return err_code;
277
278 data[0] = 0x19;
279 data[1] = 0x00;
280 err_code = mr_write(gspca_dev, 2);
281 if (err_code < 0)
282 return err_code;
283
284 while (status != 0x0a && tries < 256) {
285 err_code = cam_get_response16(gspca_dev, 0x21, 0);
286 status = data[0];
287 tries++;
288 if (err_code < 0)
289 return err_code;
290 }
291 if (status != 0x0a)
292 PDEBUG(D_ERR, "status is %02x", status);
293
294 tries = 0;
295 while (tries < 4) {
296 data[0] = 0x19;
297 data[1] = 0x00;
298 err_code = mr_write(gspca_dev, 2);
299 if (err_code < 0)
300 return err_code;
301
302 err_code = cam_get_response16(gspca_dev, 0x21, 0);
303 status = data[0];
304 tries++;
305 if (err_code < 0)
306 return err_code;
307 }
308
309 data[0] = 0x19;
310 err_code = mr_write(gspca_dev, 1);
311 if (err_code < 0)
312 return err_code;
313
314 err_code = mr_read(gspca_dev, 16);
315 if (err_code < 0)
316 return err_code;
317
318 return 0;
319}
320
321static int stream_start(struct gspca_dev *gspca_dev)
322{
323 gspca_dev->usb_buf[0] = 0x01;
324 gspca_dev->usb_buf[1] = 0x01;
325 return mr_write(gspca_dev, 2);
326}
327
328static void stream_stop(struct gspca_dev *gspca_dev)
329{
330 gspca_dev->usb_buf[0] = 0x01;
331 gspca_dev->usb_buf[1] = 0x00;
332 if (mr_write(gspca_dev, 2) < 0)
333 PDEBUG(D_ERR, "Stream Stop failed");
334}
335
336static void lcd_stop(struct gspca_dev *gspca_dev)
337{
338 gspca_dev->usb_buf[0] = 0x19;
339 gspca_dev->usb_buf[1] = 0x54;
340 if (mr_write(gspca_dev, 2) < 0)
341 PDEBUG(D_ERR, "LCD Stop failed");
342}
343
344static int isoc_enable(struct gspca_dev *gspca_dev)
345{
346 gspca_dev->usb_buf[0] = 0x00;
347 gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */
348 return mr_write(gspca_dev, 2);
349}
350
351/* This function is called at probe time */
352static int sd_config(struct gspca_dev *gspca_dev,
353 const struct usb_device_id *id)
354{
355 struct sd *sd = (struct sd *) gspca_dev;
356 struct cam *cam;
357 int err_code;
358
359 cam = &gspca_dev->cam;
360 cam->cam_mode = vga_mode;
361 cam->nmodes = ARRAY_SIZE(vga_mode);
362 sd->do_lcd_stop = 0;
363
364 /* Several of the supported CIF cameras share the same USB ID but
365 * require different initializations and different control settings.
366 * The same is true of the VGA cameras. Therefore, we are forced
367 * to start the initialization process in order to determine which
368 * camera is present. Some of the supported cameras require the
369 * memory pointer to be set to 0 as the very first item of business
370 * or else they will not stream. So we do that immediately.
371 */
372 err_code = zero_the_pointer(gspca_dev);
373 if (err_code < 0)
374 return err_code;
375
376 err_code = stream_start(gspca_dev);
377 if (err_code < 0)
378 return err_code;
379
380 /* Now, the query for sensor type. */
381 err_code = cam_get_response16(gspca_dev, 0x07, 1);
382 if (err_code < 0)
383 return err_code;
384
385 if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
386 sd->cam_type = CAM_TYPE_CIF;
387 cam->nmodes--;
388 /*
389 * All but one of the known CIF cameras share the same USB ID,
390 * but two different init routines are in use, and the control
391 * settings are different, too. We need to detect which camera
392 * of the two known varieties is connected!
393 *
394 * A list of known CIF cameras follows. They all report either
395 * 0200 for type 0 or 0300 for type 1.
396 * If you have another to report, please do
397 *
398 * Name sd->sensor_type reported by
399 *
400 * Sakar 56379 Spy-shot 0 T. Kilgore
401 * Innovage 0 T. Kilgore
402 * Vivitar Mini 0 H. De Goede
403 * Vivitar Mini 0 E. Rodriguez
404 * Vivitar Mini 1 T. Kilgore
405 * Elta-Media 8212dc 1 T. Kaiser
406 * Philips dig. keych. 1 T. Kilgore
407 * Trust Spyc@m 100 1 A. Jacobs
408 */
409 switch (gspca_dev->usb_buf[0]) {
410 case 2:
411 sd->sensor_type = 0;
412 break;
413 case 3:
414 sd->sensor_type = 1;
415 break;
416 default:
417 pr_err("Unknown CIF Sensor id : %02x\n",
418 gspca_dev->usb_buf[1]);
419 return -ENODEV;
420 }
421 PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
422 sd->sensor_type);
423 } else {
424 sd->cam_type = CAM_TYPE_VGA;
425
426 /*
427 * Here is a table of the responses to the query for sensor
428 * type, from the known MR97310A VGA cameras. Six different
429 * cameras of which five share the same USB ID.
430 *
431 * Name gspca_dev->usb_buf[] sd->sensor_type
432 * sd->do_lcd_stop
433 * Aiptek Pencam VGA+ 0300 0 1
434 * ION digital 0300 0 1
435 * Argus DC-1620 0450 1 0
436 * Argus QuickClix 0420 1 1
437 * Sakar 77379 Digital 0350 0 1
438 * Sakar 1638x CyberPix 0120 0 2
439 *
440 * Based upon these results, we assume default settings
441 * and then correct as necessary, as follows.
442 *
443 */
444
445 sd->sensor_type = 1;
446 sd->do_lcd_stop = 0;
447 sd->adj_colors = 0;
448 if (gspca_dev->usb_buf[0] == 0x01) {
449 sd->sensor_type = 2;
450 } else if ((gspca_dev->usb_buf[0] != 0x03) &&
451 (gspca_dev->usb_buf[0] != 0x04)) {
452 pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
453 gspca_dev->usb_buf[0]);
454 pr_err("Defaults assumed, may not work\n");
455 pr_err("Please report this\n");
456 }
457 /* Sakar Digital color needs to be adjusted. */
458 if ((gspca_dev->usb_buf[0] == 0x03) &&
459 (gspca_dev->usb_buf[1] == 0x50))
460 sd->adj_colors = 1;
461 if (gspca_dev->usb_buf[0] == 0x04) {
462 sd->do_lcd_stop = 1;
463 switch (gspca_dev->usb_buf[1]) {
464 case 0x50:
465 sd->sensor_type = 0;
466 PDEBUG(D_PROBE, "sensor_type corrected to 0");
467 break;
468 case 0x20:
469 /* Nothing to do here. */
470 break;
471 default:
472 pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
473 gspca_dev->usb_buf[1]);
474 pr_err("Defaults assumed, may not work\n");
475 pr_err("Please report this\n");
476 }
477 }
478 PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
479 sd->sensor_type);
480 }
481 /* Stop streaming as we've started it only to probe the sensor type. */
482 sd_stopN(gspca_dev);
483
484 if (force_sensor_type != -1) {
485 sd->sensor_type = !!force_sensor_type;
486 PDEBUG(D_PROBE, "Forcing sensor type to: %d",
487 sd->sensor_type);
488 }
489
490 return 0;
491}
492
493/* this function is called at probe and resume time */
494static int sd_init(struct gspca_dev *gspca_dev)
495{
496 return 0;
497}
498
499static int start_cif_cam(struct gspca_dev *gspca_dev)
500{
501 struct sd *sd = (struct sd *) gspca_dev;
502 __u8 *data = gspca_dev->usb_buf;
503 int err_code;
504 static const __u8 startup_string[] = {
505 0x00,
506 0x0d,
507 0x01,
508 0x00, /* Hsize/8 for 352 or 320 */
509 0x00, /* Vsize/4 for 288 or 240 */
510 0x13, /* or 0xbb, depends on sensor */
511 0x00, /* Hstart, depends on res. */
512 0x00, /* reserved ? */
513 0x00, /* Vstart, depends on res. and sensor */
514 0x50, /* 0x54 to get 176 or 160 */
515 0xc0
516 };
517
518 /* Note: Some of the above descriptions guessed from MR97113A driver */
519
520 memcpy(data, startup_string, 11);
521 if (sd->sensor_type)
522 data[5] = 0xbb;
523
524 switch (gspca_dev->width) {
525 case 160:
526 data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
527 /* fall thru */
528 case 320:
529 default:
530 data[3] = 0x28; /* reg 2, H size/8 */
531 data[4] = 0x3c; /* reg 3, V size/4 */
532 data[6] = 0x14; /* reg 5, H start */
533 data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */
534 break;
535 case 176:
536 data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */
537 /* fall thru */
538 case 352:
539 data[3] = 0x2c; /* reg 2, H size/8 */
540 data[4] = 0x48; /* reg 3, V size/4 */
541 data[6] = 0x06; /* reg 5, H start */
542 data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */
543 break;
544 }
545 err_code = mr_write(gspca_dev, 11);
546 if (err_code < 0)
547 return err_code;
548
549 if (!sd->sensor_type) {
550 static const struct sensor_w_data cif_sensor0_init_data[] = {
551 {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
552 0x0f, 0x14, 0x0f, 0x10}, 8},
553 {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
554 {0x12, 0x00, {0x07}, 1},
555 {0x1f, 0x00, {0x06}, 1},
556 {0x27, 0x00, {0x04}, 1},
557 {0x29, 0x00, {0x0c}, 1},
558 {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
559 {0x50, 0x00, {0x60}, 1},
560 {0x60, 0x00, {0x06}, 1},
561 {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
562 {0x72, 0x00, {0x1e, 0x56}, 2},
563 {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
564 0x31, 0x80, 0x00}, 9},
565 {0x11, 0x00, {0x01}, 1},
566 {0, 0, {0}, 0}
567 };
568 err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
569 ARRAY_SIZE(cif_sensor0_init_data));
570 } else { /* sd->sensor_type = 1 */
571 static const struct sensor_w_data cif_sensor1_init_data[] = {
572 /* Reg 3,4, 7,8 get set by the controls */
573 {0x02, 0x00, {0x10}, 1},
574 {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
575 {0x06, 0x01, {0x00}, 1},
576 {0x09, 0x02, {0x0e}, 1},
577 {0x0a, 0x02, {0x05}, 1},
578 {0x0b, 0x02, {0x05}, 1},
579 {0x0c, 0x02, {0x0f}, 1},
580 {0x0d, 0x02, {0x07}, 1},
581 {0x0e, 0x02, {0x0c}, 1},
582 {0x0f, 0x00, {0x00}, 1},
583 {0x10, 0x00, {0x06}, 1},
584 {0x11, 0x00, {0x07}, 1},
585 {0x12, 0x00, {0x00}, 1},
586 {0x13, 0x00, {0x01}, 1},
587 {0, 0, {0}, 0}
588 };
589 /* Without this command the cam won't work with USB-UHCI */
590 gspca_dev->usb_buf[0] = 0x0a;
591 gspca_dev->usb_buf[1] = 0x00;
592 err_code = mr_write(gspca_dev, 2);
593 if (err_code < 0)
594 return err_code;
595 err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
596 ARRAY_SIZE(cif_sensor1_init_data));
597 }
598 return err_code;
599}
600
601static int start_vga_cam(struct gspca_dev *gspca_dev)
602{
603 struct sd *sd = (struct sd *) gspca_dev;
604 __u8 *data = gspca_dev->usb_buf;
605 int err_code;
606 static const __u8 startup_string[] =
607 {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
608 0x00, 0x50, 0xc0};
609 /* What some of these mean is explained in start_cif_cam(), above */
610
611 memcpy(data, startup_string, 11);
612 if (!sd->sensor_type) {
613 data[5] = 0x00;
614 data[10] = 0x91;
615 }
616 if (sd->sensor_type == 2) {
617 data[5] = 0x00;
618 data[10] = 0x18;
619 }
620
621 switch (gspca_dev->width) {
622 case 160:
623 data[9] |= 0x0c; /* reg 8, 4:1 scale down */
624 /* fall thru */
625 case 320:
626 data[9] |= 0x04; /* reg 8, 2:1 scale down */
627 /* fall thru */
628 case 640:
629 default:
630 data[3] = 0x50; /* reg 2, H size/8 */
631 data[4] = 0x78; /* reg 3, V size/4 */
632 data[6] = 0x04; /* reg 5, H start */
633 data[8] = 0x03; /* reg 7, V start */
634 if (sd->sensor_type == 2) {
635 data[6] = 2;
636 data[8] = 1;
637 }
638 if (sd->do_lcd_stop)
639 data[8] = 0x04; /* Bayer tile shifted */
640 break;
641
642 case 176:
643 data[9] |= 0x04; /* reg 8, 2:1 scale down */
644 /* fall thru */
645 case 352:
646 data[3] = 0x2c; /* reg 2, H size */
647 data[4] = 0x48; /* reg 3, V size */
648 data[6] = 0x94; /* reg 5, H start */
649 data[8] = 0x63; /* reg 7, V start */
650 if (sd->do_lcd_stop)
651 data[8] = 0x64; /* Bayer tile shifted */
652 break;
653 }
654
655 err_code = mr_write(gspca_dev, 11);
656 if (err_code < 0)
657 return err_code;
658
659 if (!sd->sensor_type) {
660 static const struct sensor_w_data vga_sensor0_init_data[] = {
661 {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
662 {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
663 {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
664 {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
665 {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
666 {0, 0, {0}, 0}
667 };
668 err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
669 ARRAY_SIZE(vga_sensor0_init_data));
670 } else if (sd->sensor_type == 1) {
671 static const struct sensor_w_data color_adj[] = {
672 {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
673 /* adjusted blue, green, red gain correct
674 too much blue from the Sakar Digital */
675 0x05, 0x01, 0x04}, 8}
676 };
677
678 static const struct sensor_w_data color_no_adj[] = {
679 {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
680 /* default blue, green, red gain settings */
681 0x07, 0x00, 0x01}, 8}
682 };
683
684 static const struct sensor_w_data vga_sensor1_init_data[] = {
685 {0x11, 0x04, {0x01}, 1},
686 {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
687 /* These settings may be better for some cameras */
688 /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
689 0x00, 0x0a}, 7},
690 {0x11, 0x04, {0x01}, 1},
691 {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
692 {0x11, 0x04, {0x01}, 1},
693 {0, 0, {0}, 0}
694 };
695
696 if (sd->adj_colors)
697 err_code = sensor_write_regs(gspca_dev, color_adj,
698 ARRAY_SIZE(color_adj));
699 else
700 err_code = sensor_write_regs(gspca_dev, color_no_adj,
701 ARRAY_SIZE(color_no_adj));
702
703 if (err_code < 0)
704 return err_code;
705
706 err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
707 ARRAY_SIZE(vga_sensor1_init_data));
708 } else { /* sensor type == 2 */
709 static const struct sensor_w_data vga_sensor2_init_data[] = {
710
711 {0x01, 0x00, {0x48}, 1},
712 {0x02, 0x00, {0x22}, 1},
713 /* Reg 3 msb and 4 is lsb of the exposure setting*/
714 {0x05, 0x00, {0x10}, 1},
715 {0x06, 0x00, {0x00}, 1},
716 {0x07, 0x00, {0x00}, 1},
717 {0x08, 0x00, {0x00}, 1},
718 {0x09, 0x00, {0x00}, 1},
719 /* The following are used in the gain control
720 * which is BTW completely borked in the OEM driver
721 * The values for each color go from 0 to 0x7ff
722 *{0x0a, 0x00, {0x01}, 1}, green1 gain msb
723 *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb
724 *{0x0c, 0x00, {0x01}, 1}, red gain msb
725 *{0x0d, 0x00, {0x10}, 1}, red gain lsb
726 *{0x0e, 0x00, {0x01}, 1}, blue gain msb
727 *{0x0f, 0x00, {0x10}, 1}, blue gain lsb
728 *{0x10, 0x00, {0x01}, 1}, green2 gain msb
729 *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
730 */
731 {0x12, 0x00, {0x00}, 1},
732 {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
733 {0x14, 0x00, {0x00}, 1},
734 {0x15, 0x00, {0x06}, 1},
735 {0x16, 0x00, {0x01}, 1},
736 {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
737 {0x18, 0x00, {0x02}, 1},
738 {0x19, 0x00, {0x82}, 1}, /* don't mess with */
739 {0x1a, 0x00, {0x00}, 1},
740 {0x1b, 0x00, {0x20}, 1},
741 /* {0x1c, 0x00, {0x17}, 1}, contrast control */
742 {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
743 {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
744 {0x1f, 0x00, {0x0c}, 1},
745 {0x20, 0x00, {0x00}, 1},
746 {0, 0, {0}, 0}
747 };
748 err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
749 ARRAY_SIZE(vga_sensor2_init_data));
750 }
751 return err_code;
752}
753
754static int sd_start(struct gspca_dev *gspca_dev)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757 int err_code;
758
759 sd->sof_read = 0;
760
761 /* Some of the VGA cameras require the memory pointer
762 * to be set to 0 again. We have been forced to start the
763 * stream in sd_config() to detect the hardware, and closed it.
764 * Thus, we need here to do a completely fresh and clean start. */
765 err_code = zero_the_pointer(gspca_dev);
766 if (err_code < 0)
767 return err_code;
768
769 err_code = stream_start(gspca_dev);
770 if (err_code < 0)
771 return err_code;
772
773 if (sd->cam_type == CAM_TYPE_CIF) {
774 err_code = start_cif_cam(gspca_dev);
775 } else {
776 err_code = start_vga_cam(gspca_dev);
777 }
778 if (err_code < 0)
779 return err_code;
780
781 return isoc_enable(gspca_dev);
782}
783
784static void sd_stopN(struct gspca_dev *gspca_dev)
785{
786 struct sd *sd = (struct sd *) gspca_dev;
787
788 stream_stop(gspca_dev);
789 /* Not all the cams need this, but even if not, probably a good idea */
790 zero_the_pointer(gspca_dev);
791 if (sd->do_lcd_stop)
792 lcd_stop(gspca_dev);
793}
794
795static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
796{
797 struct sd *sd = (struct sd *) gspca_dev;
798 u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */
799 u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
800 static const u8 quick_clix_table[] =
801 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
802 { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15};
803 if (sd->cam_type == CAM_TYPE_VGA) {
804 sign_reg += 4;
805 value_reg += 4;
806 }
807
808 /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
809 if (val > 0) {
810 sensor_write1(gspca_dev, sign_reg, 0x00);
811 } else {
812 sensor_write1(gspca_dev, sign_reg, 0x01);
813 val = 257 - val;
814 }
815 /* Use lookup table for funky Argus QuickClix brightness */
816 if (sd->do_lcd_stop)
817 val = quick_clix_table[val];
818
819 sensor_write1(gspca_dev, value_reg, val);
820}
821
822static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv)
823{
824 struct sd *sd = (struct sd *) gspca_dev;
825 int exposure = MR97310A_EXPOSURE_DEFAULT;
826 u8 buf[2];
827
828 if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
829 /* This cam does not like exposure settings < 300,
830 so scale 0 - 4095 to 300 - 4095 */
831 exposure = (expo * 9267) / 10000 + 300;
832 sensor_write1(gspca_dev, 3, exposure >> 4);
833 sensor_write1(gspca_dev, 4, exposure & 0x0f);
834 } else if (sd->sensor_type == 2) {
835 exposure = expo;
836 exposure >>= 3;
837 sensor_write1(gspca_dev, 3, exposure >> 8);
838 sensor_write1(gspca_dev, 4, exposure & 0xff);
839 } else {
840 /* We have both a clock divider and an exposure register.
841 We first calculate the clock divider, as that determines
842 the maximum exposure and then we calculate the exposure
843 register setting (which goes from 0 - 511).
844
845 Note our 0 - 4095 exposure is mapped to 0 - 511
846 milliseconds exposure time */
847 u8 clockdiv = (60 * expo + 7999) / 8000;
848
849 /* Limit framerate to not exceed usb bandwidth */
850 if (clockdiv < min_clockdiv && gspca_dev->width >= 320)
851 clockdiv = min_clockdiv;
852 else if (clockdiv < 2)
853 clockdiv = 2;
854
855 if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
856 clockdiv = 4;
857
858 /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
859 exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
860 exposure = (60 * 511 * expo) / (8000 * clockdiv);
861 if (exposure > 511)
862 exposure = 511;
863
864 /* exposure register value is reversed! */
865 exposure = 511 - exposure;
866
867 buf[0] = exposure & 0xff;
868 buf[1] = exposure >> 8;
869 sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
870 sensor_write1(gspca_dev, 0x02, clockdiv);
871 }
872}
873
874static void setgain(struct gspca_dev *gspca_dev, s32 val)
875{
876 struct sd *sd = (struct sd *) gspca_dev;
877 u8 gainreg;
878
879 if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
880 sensor_write1(gspca_dev, 0x0e, val);
881 else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
882 for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
883 sensor_write1(gspca_dev, gainreg, val >> 8);
884 sensor_write1(gspca_dev, gainreg + 1, val & 0xff);
885 }
886 else
887 sensor_write1(gspca_dev, 0x10, val);
888}
889
890static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
891{
892 sensor_write1(gspca_dev, 0x1c, val);
893}
894
895static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
896{
897 struct gspca_dev *gspca_dev =
898 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
899 struct sd *sd = (struct sd *)gspca_dev;
900
901 gspca_dev->usb_err = 0;
902
903 if (!gspca_dev->streaming)
904 return 0;
905
906 switch (ctrl->id) {
907 case V4L2_CID_BRIGHTNESS:
908 setbrightness(gspca_dev, ctrl->val);
909 break;
910 case V4L2_CID_CONTRAST:
911 setcontrast(gspca_dev, ctrl->val);
912 break;
913 case V4L2_CID_EXPOSURE:
914 setexposure(gspca_dev, sd->exposure->val,
915 sd->min_clockdiv ? sd->min_clockdiv->val : 0);
916 break;
917 case V4L2_CID_GAIN:
918 setgain(gspca_dev, ctrl->val);
919 break;
920 }
921 return gspca_dev->usb_err;
922}
923
924static const struct v4l2_ctrl_ops sd_ctrl_ops = {
925 .s_ctrl = sd_s_ctrl,
926};
927
928static int sd_init_controls(struct gspca_dev *gspca_dev)
929{
930 struct sd *sd = (struct sd *)gspca_dev;
931 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
932 static const struct v4l2_ctrl_config clockdiv = {
933 .ops = &sd_ctrl_ops,
934 .id = MR97310A_CID_CLOCKDIV,
935 .type = V4L2_CTRL_TYPE_INTEGER,
936 .name = "Minimum Clock Divider",
937 .min = MR97310A_MIN_CLOCKDIV_MIN,
938 .max = MR97310A_MIN_CLOCKDIV_MAX,
939 .step = 1,
940 .def = MR97310A_MIN_CLOCKDIV_DEFAULT,
941 };
942 bool has_brightness = false;
943 bool has_argus_brightness = false;
944 bool has_contrast = false;
945 bool has_gain = false;
946 bool has_cs_gain = false;
947 bool has_exposure = false;
948 bool has_clockdiv = false;
949
950 gspca_dev->vdev.ctrl_handler = hdl;
951 v4l2_ctrl_handler_init(hdl, 4);
952
953 /* Setup controls depending on camera type */
954 if (sd->cam_type == CAM_TYPE_CIF) {
955 /* No brightness for sensor_type 0 */
956 if (sd->sensor_type == 0)
957 has_exposure = has_gain = has_clockdiv = true;
958 else
959 has_exposure = has_gain = has_brightness = true;
960 } else {
961 /* All controls need to be disabled if VGA sensor_type is 0 */
962 if (sd->sensor_type == 0)
963 ; /* no controls! */
964 else if (sd->sensor_type == 2)
965 has_exposure = has_cs_gain = has_contrast = true;
966 else if (sd->do_lcd_stop)
967 has_exposure = has_gain = has_argus_brightness =
968 has_clockdiv = true;
969 else
970 has_exposure = has_gain = has_brightness =
971 has_clockdiv = true;
972 }
973
974 /* Separate brightness control description for Argus QuickClix as it has
975 * different limits from the other mr97310a cameras, and separate gain
976 * control for Sakar CyberPix camera. */
977 /*
978 * This control is disabled for CIF type 1 and VGA type 0 cameras.
979 * It does not quite act linearly for the Argus QuickClix camera,
980 * but it does control brightness. The values are 0 - 15 only, and
981 * the table above makes them act consecutively.
982 */
983 if (has_brightness)
984 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
985 V4L2_CID_BRIGHTNESS, -254, 255, 1,
986 MR97310A_BRIGHTNESS_DEFAULT);
987 else if (has_argus_brightness)
988 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
989 V4L2_CID_BRIGHTNESS, 0, 15, 1,
990 MR97310A_BRIGHTNESS_DEFAULT);
991 if (has_contrast)
992 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
993 V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN,
994 MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT);
995 if (has_gain)
996 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
997 V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX,
998 1, MR97310A_GAIN_DEFAULT);
999 else if (has_cs_gain)
1000 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN,
1001 MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX,
1002 1, MR97310A_CS_GAIN_DEFAULT);
1003 if (has_exposure)
1004 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1005 V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN,
1006 MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT);
1007 if (has_clockdiv)
1008 sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL);
1009
1010 if (hdl->error) {
1011 pr_err("Could not initialize controls\n");
1012 return hdl->error;
1013 }
1014 if (has_exposure && has_clockdiv)
1015 v4l2_ctrl_cluster(2, &sd->exposure);
1016 return 0;
1017}
1018
1019/* Include pac common sof detection functions */
1020#include "pac_common.h"
1021
1022static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1023 u8 *data, /* isoc packet */
1024 int len) /* iso packet length */
1025{
1026 struct sd *sd = (struct sd *) gspca_dev;
1027 unsigned char *sof;
1028
1029 sof = pac_find_sof(&sd->sof_read, data, len);
1030 if (sof) {
1031 int n;
1032
1033 /* finish decoding current frame */
1034 n = sof - data;
1035 if (n > sizeof pac_sof_marker)
1036 n -= sizeof pac_sof_marker;
1037 else
1038 n = 0;
1039 gspca_frame_add(gspca_dev, LAST_PACKET,
1040 data, n);
1041 /* Start next frame. */
1042 gspca_frame_add(gspca_dev, FIRST_PACKET,
1043 pac_sof_marker, sizeof pac_sof_marker);
1044 len -= sof - data;
1045 data = sof;
1046 }
1047 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1048}
1049
1050/* sub-driver description */
1051static const struct sd_desc sd_desc = {
1052 .name = MODULE_NAME,
1053 .config = sd_config,
1054 .init = sd_init,
1055 .init_controls = sd_init_controls,
1056 .start = sd_start,
1057 .stopN = sd_stopN,
1058 .pkt_scan = sd_pkt_scan,
1059};
1060
1061/* -- module initialisation -- */
1062static const struct usb_device_id device_table[] = {
1063 {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */
1064 {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */
1065 {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */
1066 {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */
1067 {}
1068};
1069MODULE_DEVICE_TABLE(usb, device_table);
1070
1071/* -- device connect -- */
1072static int sd_probe(struct usb_interface *intf,
1073 const struct usb_device_id *id)
1074{
1075 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1076 THIS_MODULE);
1077}
1078
1079static struct usb_driver sd_driver = {
1080 .name = MODULE_NAME,
1081 .id_table = device_table,
1082 .probe = sd_probe,
1083 .disconnect = gspca_disconnect,
1084#ifdef CONFIG_PM
1085 .suspend = gspca_suspend,
1086 .resume = gspca_resume,
1087 .reset_resume = gspca_resume,
1088#endif
1089};
1090
1091module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/nw80x.c b/drivers/media/usb/gspca/nw80x.c
new file mode 100644
index 00000000000..44c9964b1b3
--- /dev/null
+++ b/drivers/media/usb/gspca/nw80x.c
@@ -0,0 +1,2110 @@
1/*
2 * DivIO nw80x subdriver
3 *
4 * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
5 * Copyright (C) 2003 Sylvain Munaut <tnt@246tNt.com>
6 * Kjell Claesson <keyson@users.sourceforge.net>
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#define MODULE_NAME "nw80x"
26
27#include "gspca.h"
28
29MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
30MODULE_DESCRIPTION("NW80x USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33static int webcam;
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 u32 ae_res;
40 s8 ag_cnt;
41#define AG_CNT_START 13
42 u8 exp_too_low_cnt;
43 u8 exp_too_high_cnt;
44
45 u8 bridge;
46 u8 webcam;
47};
48
49enum bridges {
50 BRIDGE_NW800, /* and et31x110 */
51 BRIDGE_NW801,
52 BRIDGE_NW802,
53};
54enum webcams {
55 Generic800,
56 SpaceCam, /* Trust 120 SpaceCam */
57 SpaceCam2, /* other Trust 120 SpaceCam */
58 Cvideopro, /* Conceptronic Video Pro */
59 Dlink350c,
60 DS3303u,
61 Kr651us,
62 Kritter,
63 Mustek300,
64 Proscope,
65 Twinkle,
66 DvcV6,
67 P35u,
68 Generic802,
69 NWEBCAMS /* number of webcams */
70};
71
72static const u8 webcam_chip[NWEBCAMS] = {
73 [Generic800] = BRIDGE_NW800, /* 06a5:0000
74 * Typhoon Webcam 100 USB */
75
76 [SpaceCam] = BRIDGE_NW800, /* 06a5:d800
77 * Trust SpaceCam120 or SpaceCam100 PORTABLE */
78
79 [SpaceCam2] = BRIDGE_NW800, /* 06a5:d800 - pas106
80 * other Trust SpaceCam120 or SpaceCam100 PORTABLE */
81
82 [Cvideopro] = BRIDGE_NW802, /* 06a5:d001
83 * Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' */
84
85 [Dlink350c] = BRIDGE_NW802, /* 06a5:d001
86 * D-Link NetQam Pro 250plus */
87
88 [DS3303u] = BRIDGE_NW801, /* 06a5:d001
89 * Plustek Opticam 500U or ProLink DS3303u */
90
91 [Kr651us] = BRIDGE_NW802, /* 06a5:d001
92 * Panasonic GP-KR651US */
93
94 [Kritter] = BRIDGE_NW802, /* 06a5:d001
95 * iRez Kritter cam */
96
97 [Mustek300] = BRIDGE_NW802, /* 055f:d001
98 * Mustek Wcam 300 mini */
99
100 [Proscope] = BRIDGE_NW802, /* 06a5:d001
101 * Scalar USB Microscope (ProScope) */
102
103 [Twinkle] = BRIDGE_NW800, /* 06a5:d800 - hv7121b? (seems pas106)
104 * Divio Chicony TwinkleCam
105 * DSB-C110 */
106
107 [DvcV6] = BRIDGE_NW802, /* 0502:d001
108 * DVC V6 */
109
110 [P35u] = BRIDGE_NW801, /* 052b:d001, 06a5:d001 and 06be:d001
111 * EZCam Pro p35u */
112
113 [Generic802] = BRIDGE_NW802,
114};
115/*
116 * other webcams:
117 * - nw801 046d:d001
118 * Logitech QuickCam Pro (dark focus ring)
119 * - nw801 0728:d001
120 * AVerMedia Camguard
121 * - nw??? 06a5:d001
122 * D-Link NetQam Pro 250plus
123 * - nw800 065a:d800
124 * Showcam NGS webcam
125 * - nw??? ????:????
126 * Sceptre svc300
127 */
128
129/*
130 * registers
131 * nw800/et31x110 nw801 nw802
132 * 0000..009e 0000..00a1 0000..009e
133 * 0200..0211 id id
134 * 0300..0302 id id
135 * 0400..0406 (inex) 0400..0406
136 * 0500..0505 0500..0506 (inex)
137 * 0600..061a 0600..0601 0600..0601
138 * 0800..0814 id id
139 * 1000..109c 1000..10a1 1000..109a
140 */
141
142/* resolutions
143 * nw800: 320x240, 352x288
144 * nw801/802: 320x240, 640x480
145 */
146static const struct v4l2_pix_format cif_mode[] = {
147 {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
148 .bytesperline = 320,
149 .sizeimage = 320 * 240 * 4 / 8,
150 .colorspace = V4L2_COLORSPACE_JPEG},
151 {352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
152 .bytesperline = 352,
153 .sizeimage = 352 * 288 * 4 / 8,
154 .colorspace = V4L2_COLORSPACE_JPEG}
155};
156static const struct v4l2_pix_format vga_mode[] = {
157 {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
158 .bytesperline = 320,
159 .sizeimage = 320 * 240 * 4 / 8,
160 .colorspace = V4L2_COLORSPACE_JPEG},
161 {640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
162 .bytesperline = 640,
163 .sizeimage = 640 * 480 * 3 / 8,
164 .colorspace = V4L2_COLORSPACE_JPEG},
165};
166
167/*
168 * The sequences below contain:
169 * - 1st and 2nd bytes: either
170 * - register number (BE)
171 * - I2C0 + i2c address
172 * - 3rd byte: data length (=0 for end of sequence)
173 * - n bytes: data
174 */
175#define I2C0 0xff
176
177static const u8 nw800_init[] = {
178 0x04, 0x05, 0x01, 0x61,
179 0x04, 0x04, 0x01, 0x01,
180 0x04, 0x06, 0x01, 0x04,
181 0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
182 0x05, 0x05, 0x01, 0x00,
183 0, 0, 0
184};
185static const u8 nw800_start[] = {
186 0x04, 0x06, 0x01, 0xc0,
187 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
188 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
189 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
190 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
191 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
192 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
193 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
194 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
195 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
196 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
197 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
198 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
199 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
200 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
202 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
203 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
205 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
206 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
207 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
208 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
209 0x40, 0x20,
210 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
211 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
212 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
213 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00,
217 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
222 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
225 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
226 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
227 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
228 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
229 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
230 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
231 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
232 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
233 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
234 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
235 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
236 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
238 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
239 0x01, 0x60, 0x01, 0x00, 0x00,
240
241 0x04, 0x04, 0x01, 0xff,
242 0x04, 0x06, 0x01, 0xc4,
243
244 0x04, 0x06, 0x01, 0xc0,
245 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
246 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
247 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
248 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
249 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
250 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
251 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
252 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
253 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
254 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
255 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
256 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
257 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
258 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
260 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
261 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
263 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
264 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
265 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
266 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
267 0x40, 0x20,
268 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
269 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
270 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
271 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00,
275 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x00,
278 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
280 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
283 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
284 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
285 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
286 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
287 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
288 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
289 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
290 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
291 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
292 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
293 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
294 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
296 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
297 0x01, 0x60, 0x01, 0x00, 0x00,
298
299 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
300 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
301 0x40,
302 0x00, 0x80, 0x01, 0xa0,
303 0x10, 0x1a, 0x01, 0x00,
304 0x00, 0x91, 0x02, 0x6c, 0x01,
305 0x00, 0x03, 0x02, 0xc8, 0x01,
306 0x10, 0x1a, 0x01, 0x00,
307 0x10, 0x00, 0x01, 0x83,
308 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
309 0x20, 0x01, 0x60, 0x01,
310 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
311 0x10, 0x1b, 0x02, 0x69, 0x00,
312 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
313 0x05, 0x02, 0x01, 0x02,
314 0x06, 0x00, 0x02, 0x04, 0xd9,
315 0x05, 0x05, 0x01, 0x20,
316 0x05, 0x05, 0x01, 0x21,
317 0x10, 0x0e, 0x01, 0x08,
318 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
319 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
320 0xea,
321 0x10, 0x03, 0x01, 0x00,
322 0x10, 0x0f, 0x02, 0x13, 0x13,
323 0x10, 0x03, 0x01, 0x14,
324 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
325 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
326 0xea,
327 0x10, 0x0b, 0x01, 0x14,
328 0x10, 0x0d, 0x01, 0x20,
329 0x10, 0x0c, 0x01, 0x34,
330 0x04, 0x06, 0x01, 0xc3,
331 0x04, 0x04, 0x01, 0x00,
332 0x05, 0x02, 0x01, 0x02,
333 0x06, 0x00, 0x02, 0x00, 0x48,
334 0x05, 0x05, 0x01, 0x20,
335 0x05, 0x05, 0x01, 0x21,
336 0, 0, 0
337};
338
339/* 06a5:d001 - nw801 - Panasonic
340 * P35u */
341static const u8 nw801_start_1[] = {
342 0x05, 0x06, 0x01, 0x04,
343 0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
344 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
345 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
346 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
347 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
348 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
349 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
350 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
351 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
352 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
353 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
354 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
355 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
356 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
358 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
359 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00,
361 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
362 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
363 0x36, 0x00,
364 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
365 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
366 0x40, 0x20,
367 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
368 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x06, 0x00, 0x02, 0x09, 0x99,
370 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a,
375 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02,
378 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
379 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06,
380 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
381 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
382 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4,
383 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf,
384 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
385 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
386 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
387 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
388 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
389 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
390 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02,
392 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
393 0xf0, 0x00,
394 0, 0, 0,
395};
396static const u8 nw801_start_qvga[] = {
397 0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
398 0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78,
399 0x02, 0x0f, 0x01, 0x6b,
400 0x10, 0x1a, 0x01, 0x15,
401 0x00, 0x00, 0x01, 0x1e,
402 0x10, 0x00, 0x01, 0x2f,
403 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
404 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
405 /* AE window */
406 0, 0, 0,
407};
408static const u8 nw801_start_vga[] = {
409 0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00,
410 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0,
411 0x02, 0x0f, 0x01, 0xd5,
412 0x10, 0x1a, 0x01, 0x15,
413 0x00, 0x00, 0x01, 0x0e,
414 0x10, 0x00, 0x01, 0x22,
415 0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
416 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
417 0, 0, 0,
418};
419static const u8 nw801_start_2[] = {
420 0x10, 0x04, 0x01, 0x1a,
421 0x10, 0x19, 0x01, 0x09, /* clock */
422 0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01,
423 /* .. gain .. */
424 0x00, 0x03, 0x02, 0x92, 0x03,
425 0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07,
426 0x00, 0x7b, 0x01, 0xcf,
427 0x10, 0x94, 0x01, 0x07,
428 0x05, 0x05, 0x01, 0x01,
429 0x05, 0x04, 0x01, 0x01,
430 0x10, 0x0e, 0x01, 0x08,
431 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
432 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
433 0xf0,
434 0x10, 0x03, 0x01, 0x00,
435 0x10, 0x0f, 0x02, 0x0c, 0x0c,
436 0x10, 0x03, 0x01, 0x08,
437 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
438 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
439 0xf0,
440 0x10, 0x0b, 0x01, 0x0b,
441 0x10, 0x0d, 0x01, 0x0b,
442 0x10, 0x0c, 0x01, 0x1f,
443 0x05, 0x06, 0x01, 0x03,
444 0, 0, 0
445};
446
447/* nw802 (sharp IR3Y38M?) */
448static const u8 nw802_start[] = {
449 0x04, 0x06, 0x01, 0x04,
450 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d,
451 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
452 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
453 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
454 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
455 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
456 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
457 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
458 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
459 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
460 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
461 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
462 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
463 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
464 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
465 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
466 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
468 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
469 0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00,
470 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
471 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
472 0x40, 0x20,
473 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
474 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
475 0x06, 0x00, 0x02, 0x09, 0x99,
476 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
478 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00,
480 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
481 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14,
483 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
484 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
485 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
486 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
487 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
488 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
489 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
490 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
491 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
492 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
493 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
494 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
495 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82,
497 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
498 0x01, 0xf0, 0x00,
499 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
500 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
501 0x40,
502 0x10, 0x1a, 0x01, 0x00,
503 0x10, 0x00, 0x01, 0xad,
504 0x00, 0x00, 0x01, 0x08,
505 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
506 0x10, 0x1b, 0x02, 0x00, 0x00,
507 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
508 0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
509 0x10, 0x0e, 0x01, 0x27,
510 0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
511 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
512 0xd8,
513 0x10, 0x03, 0x01, 0x00,
514 0x10, 0x0f, 0x02, 0x14, 0x14,
515 0x10, 0x03, 0x01, 0x0c,
516 0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74,
517 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1,
518 0xff,
519/* 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
520 * 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
521 * 0xd8, */
522 0x10, 0x0b, 0x01, 0x10,
523 0x10, 0x0d, 0x01, 0x11,
524 0x10, 0x0c, 0x01, 0x1c,
525 0x04, 0x06, 0x01, 0x03,
526 0x04, 0x04, 0x01, 0x00,
527 0, 0, 0
528};
529/* et31x110 - Trust 120 SpaceCam */
530static const u8 spacecam_init[] = {
531 0x04, 0x05, 0x01, 0x01,
532 0x04, 0x04, 0x01, 0x01,
533 0x04, 0x06, 0x01, 0x04,
534 0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
535 0x05, 0x05, 0x01, 0x00,
536 0, 0, 0
537};
538static const u8 spacecam_start[] = {
539 0x04, 0x06, 0x01, 0x44,
540 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
541 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
542 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
543 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
544 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
545 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
546 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
547 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
548 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
549 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
550 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
551 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
552 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
553 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
555 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
556 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
558 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
559 0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00,
560 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
561 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
562 0x40, 0x20,
563 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
564 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00,
570 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
575 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
578 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
579 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
580 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
581 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
582 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
583 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
584 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
585 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
586 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
587 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
588 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
589 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
591 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
592 0x01, 0x60, 0x01, 0x00, 0x00,
593 0x04, 0x06, 0x01, 0xc0,
594 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
595 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
596 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
597 0x40,
598 0x00, 0x80, 0x01, 0xa0,
599 0x10, 0x1a, 0x01, 0x00,
600 0x00, 0x91, 0x02, 0x32, 0x01,
601 0x00, 0x03, 0x02, 0x08, 0x02,
602 0x10, 0x00, 0x01, 0x83,
603 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
604 0x20, 0x01, 0x60, 0x01,
605 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
606 0x10, 0x0e, 0x01, 0x08,
607 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
608 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
609 0xf9,
610 0x10, 0x03, 0x01, 0x00,
611 0x10, 0x0f, 0x02, 0x13, 0x13,
612 0x10, 0x03, 0x01, 0x06,
613 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
614 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
615 0xf9,
616 0x10, 0x0b, 0x01, 0x08,
617 0x10, 0x0d, 0x01, 0x10,
618 0x10, 0x0c, 0x01, 0x1f,
619 0x04, 0x06, 0x01, 0xc3,
620 0x04, 0x05, 0x01, 0x40,
621 0x04, 0x04, 0x01, 0x40,
622 0, 0, 0
623};
624/* et31x110 - pas106 - other Trust SpaceCam120 */
625static const u8 spacecam2_start[] = {
626 0x04, 0x06, 0x01, 0x44,
627 0x04, 0x06, 0x01, 0x00,
628 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
629 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
630 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
631 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
632 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
633 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
634 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
635 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
636 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
637 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
638 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
639 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
640 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
641 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
643 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
644 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
646 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
647 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
648 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
649 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
650 0x40, 0x20,
651 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
652 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
653 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00,
658 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
663 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
666 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
667 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
668 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
669 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
670 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
671 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
672 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
673 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
674 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
675 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
676 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
677 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
679 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
680 0x01, 0x60, 0x01, 0x00, 0x00,
681 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
682 0x04, 0x04, 0x01, 0x40,
683 0x04, 0x04, 0x01, 0x00,
684 I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05,
685 0x00, 0x00, 0x05, 0x05,
686 I2C0, 0x40, 0x02, 0x11, 0x06,
687 I2C0, 0x40, 0x02, 0x14, 0x00,
688 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
689 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
690 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
691 0x40,
692 I2C0, 0x40, 0x02, 0x02, 0x0c, /* pixel clock */
693 I2C0, 0x40, 0x02, 0x0f, 0x00,
694 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
695 0x10, 0x00, 0x01, 0x01,
696 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
697 0x20, 0x01, 0x60, 0x01,
698 I2C0, 0x40, 0x02, 0x05, 0x0f, /* exposure */
699 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
700 I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00,
701 /* gains */
702 I2C0, 0x40, 0x03, 0x12, 0x04, 0x01,
703 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
704 0x10, 0x0e, 0x01, 0x08,
705 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
706 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
707 0xf9,
708 0x10, 0x03, 0x01, 0x00,
709 0x10, 0x0f, 0x02, 0x13, 0x13,
710 0x10, 0x03, 0x01, 0x06,
711 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
712 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
713 0xf9,
714 0x10, 0x0b, 0x01, 0x11,
715 0x10, 0x0d, 0x01, 0x10,
716 0x10, 0x0c, 0x01, 0x14,
717 0x04, 0x06, 0x01, 0x03,
718 0x04, 0x05, 0x01, 0x61,
719 0x04, 0x04, 0x01, 0x00,
720 0, 0, 0
721};
722
723/* nw802 - Conceptronic Video Pro */
724static const u8 cvideopro_start[] = {
725 0x04, 0x06, 0x01, 0x04,
726 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
727 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
728 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
729 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
730 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
731 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
732 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
733 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
734 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
735 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
736 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
737 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
738 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
739 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
741 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
742 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
743 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
744 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
745 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
746 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
747 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
748 0x40, 0x20,
749 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
750 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
751 0x06, 0x00, 0x02, 0x09, 0x99,
752 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00, 0x00, 0x00,
755 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
756 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
757 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
759 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
760 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
761 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
762 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
763 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
764 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
765 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
766 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
767 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
768 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
769 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
770 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
771 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
772 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
773 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
774 0x01, 0xf0, 0x00,
775 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
776 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
777 0x40,
778 0x10, 0x1a, 0x01, 0x03,
779 0x10, 0x00, 0x01, 0xac,
780 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
781 0x10, 0x1b, 0x02, 0x3b, 0x01,
782 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
783 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
784 0x10, 0x1d, 0x02, 0x40, 0x06,
785 0x10, 0x0e, 0x01, 0x08,
786 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
787 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
788 0xdc,
789 0x10, 0x03, 0x01, 0x00,
790 0x10, 0x0f, 0x02, 0x12, 0x12,
791 0x10, 0x03, 0x01, 0x0c,
792 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
793 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
794 0xdc,
795 0x10, 0x0b, 0x01, 0x09,
796 0x10, 0x0d, 0x01, 0x10,
797 0x10, 0x0c, 0x01, 0x2f,
798 0x04, 0x06, 0x01, 0x03,
799 0x04, 0x04, 0x01, 0x00,
800 0, 0, 0
801};
802
803/* nw802 - D-link dru-350c cam */
804static const u8 dlink_start[] = {
805 0x04, 0x06, 0x01, 0x04,
806 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
807 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
808 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
809 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
810 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
811 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
812 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
813 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
814 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
815 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
816 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
817 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
818 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
819 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
820 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
821 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
822 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
823 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
824 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
825 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
826 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
827 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
828 0x40, 0x20,
829 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
830 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
831 0x06, 0x00, 0x02, 0x09, 0x99,
832 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x00,
835 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
837 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
839 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
840 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
841 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
842 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
843 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
844 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
845 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
846 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
847 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
848 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
849 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
850 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
851 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82,
853 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
854 0x01, 0xf0, 0x00,
855 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
856 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
857 0x40,
858 0x10, 0x1a, 0x01, 0x00,
859 0x10, 0x00, 0x01, 0xad,
860 0x00, 0x00, 0x01, 0x08,
861 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
862 0x10, 0x1b, 0x02, 0x00, 0x00,
863 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
864 0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
865 0x10, 0x0e, 0x01, 0x20,
866 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
867 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
868 0xea,
869 0x10, 0x03, 0x01, 0x00,
870 0x10, 0x0f, 0x02, 0x11, 0x11,
871 0x10, 0x03, 0x01, 0x10,
872 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
873 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
874 0xea,
875 0x10, 0x0b, 0x01, 0x19,
876 0x10, 0x0d, 0x01, 0x10,
877 0x10, 0x0c, 0x01, 0x1e,
878 0x04, 0x06, 0x01, 0x03,
879 0x04, 0x04, 0x01, 0x00,
880 0, 0, 0
881};
882
883/* 06a5:d001 - nw801 - Sony
884 * Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */
885/*fixme: 320x240 only*/
886static const u8 ds3303_start[] = {
887 0x05, 0x06, 0x01, 0x04,
888 0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
889 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
890 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
891 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
892 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
893 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
894 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
895 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
896 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
897 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
898 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
899 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
900 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
901 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
902 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
903 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
904 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00,
906 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
907 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
908 0x36, 0x00,
909 0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
910 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50,
911 0x40, 0x20,
912 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
913 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
914 0x06, 0x00, 0x02, 0x09, 0x99,
915 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
917 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
920 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
921 0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00,
922 0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20,
923 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00,
924 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03,
925 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
926 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
927 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88,
928 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb,
929 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
930 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
931 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
932 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
933 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
934 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
935 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01,
936 0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02,
937 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
938 0xf0, 0x00,
939
940 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
941 0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81,
942 0x40,
943 0x10, 0x1a, 0x01, 0x15,
944 0x10, 0x00, 0x01, 0x2f,
945 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
946 0x10, 0x1b, 0x02, 0x00, 0x00,
947 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
948 0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
949 0x10, 0x24, 0x02, 0x40, 0x06,
950 0x10, 0x0e, 0x01, 0x08,
951 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
952 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
953 0xf9,
954 0x10, 0x03, 0x01, 0x00,
955 0x10, 0x0f, 0x02, 0x16, 0x16,
956 0x10, 0x03, 0x01, 0x0c,
957 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
958 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
959 0xf9,
960 0x10, 0x0b, 0x01, 0x26,
961 0x10, 0x0d, 0x01, 0x10,
962 0x10, 0x0c, 0x01, 0x1c,
963 0x05, 0x06, 0x01, 0x03,
964 0x05, 0x04, 0x01, 0x00,
965 0, 0, 0
966};
967
968/* 06a5:d001 - nw802 - Panasonic
969 * GP-KR651US (Philips TDA8786) */
970static const u8 kr651_start_1[] = {
971 0x04, 0x06, 0x01, 0x04,
972 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48,
973 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
974 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
975 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
976 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
977 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
978 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
979 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
980 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
981 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
982 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
983 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
984 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
985 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
987 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
988 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
989 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
990 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
991 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
992 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
993 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
994 0x40, 0x20,
995 0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
996 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
997 0x06, 0x00, 0x02, 0x09, 0x99,
998 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1000 0x00, 0x00, 0x00, 0x00, 0x00,
1001 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1002 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1003 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
1005 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1006 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1007 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1008 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1009 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1010 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1011 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1012 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1013 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1014 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1015 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1016 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1017 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
1019 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1020 0x01, 0xf0, 0x00,
1021 0, 0, 0
1022};
1023static const u8 kr651_start_qvga[] = {
1024 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
1025 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
1026 0x40,
1027 0x10, 0x1a, 0x01, 0x03,
1028 0x10, 0x00, 0x01, 0xac,
1029 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1030 0x10, 0x1b, 0x02, 0x00, 0x00,
1031 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
1032 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
1033 0x10, 0x1d, 0x02, 0x28, 0x01,
1034 0, 0, 0
1035};
1036static const u8 kr651_start_vga[] = {
1037 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
1038 0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98,
1039 0x80,
1040 0x10, 0x1a, 0x01, 0x03,
1041 0x10, 0x00, 0x01, 0xa0,
1042 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
1043 0x10, 0x1b, 0x02, 0x00, 0x00,
1044 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
1045 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
1046 0x10, 0x1d, 0x02, 0x68, 0x00,
1047};
1048static const u8 kr651_start_2[] = {
1049 0x10, 0x0e, 0x01, 0x08,
1050 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
1051 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
1052 0xdc,
1053 0x10, 0x03, 0x01, 0x00,
1054 0x10, 0x0f, 0x02, 0x0c, 0x0c,
1055 0x10, 0x03, 0x01, 0x0c,
1056 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
1057 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
1058 0xdc,
1059 0x10, 0x0b, 0x01, 0x10,
1060 0x10, 0x0d, 0x01, 0x10,
1061 0x10, 0x0c, 0x01, 0x2d,
1062 0x04, 0x06, 0x01, 0x03,
1063 0x04, 0x04, 0x01, 0x00,
1064 0, 0, 0
1065};
1066
1067/* nw802 - iRez Kritter cam */
1068static const u8 kritter_start[] = {
1069 0x04, 0x06, 0x01, 0x06,
1070 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48,
1071 0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19,
1072 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1073 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28,
1074 0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
1075 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1076 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
1077 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1078 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
1079 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1080 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
1081 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1082 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
1083 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1084 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
1085 0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30,
1086 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
1087 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1088 0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
1089 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
1090 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1091 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1092 0x40, 0x20,
1093 0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
1094 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
1095 0x06, 0x00, 0x02, 0x09, 0x99,
1096 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0x00, 0x00, 0x00,
1099 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1101 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1102 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
1103 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1104 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1105 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1106 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1107 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1108 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1109 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1110 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1111 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1112 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1113 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1114 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1115 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82,
1117 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1118 0x01, 0xf0, 0x00,
1119 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
1120 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
1121 0x40,
1122 0x10, 0x1a, 0x01, 0x03,
1123 0x10, 0x00, 0x01, 0xaf,
1124 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1125 0x10, 0x1b, 0x02, 0x3b, 0x01,
1126 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
1127 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
1128 0x10, 0x1d, 0x02, 0x00, 0x00,
1129 0x10, 0x0e, 0x01, 0x08,
1130 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
1131 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
1132 0xcb,
1133 0x10, 0x03, 0x01, 0x00,
1134 0x10, 0x0f, 0x02, 0x0d, 0x0d,
1135 0x10, 0x03, 0x01, 0x02,
1136 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
1137 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
1138 0xcb,
1139 0x10, 0x0b, 0x01, 0x17,
1140 0x10, 0x0d, 0x01, 0x10,
1141 0x10, 0x0c, 0x01, 0x1e,
1142 0x04, 0x06, 0x01, 0x03,
1143 0x04, 0x04, 0x01, 0x00,
1144 0, 0, 0
1145};
1146
1147/* nw802 - Mustek Wcam 300 mini */
1148static const u8 mustek_start[] = {
1149 0x04, 0x06, 0x01, 0x04,
1150 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
1151 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
1152 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1153 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
1154 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
1155 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
1156 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
1157 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
1158 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1159 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1160 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1161 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1162 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
1163 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1164 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
1165 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
1166 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1168 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
1169 0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06,
1170 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1171 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1172 0x40, 0x20,
1173 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1174 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
1175 0x06, 0x00, 0x02, 0x09, 0x99,
1176 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x00, 0x00, 0x00, 0x00, 0x00,
1179 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00,
1180 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1181 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1182 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
1183 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
1184 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1185 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1186 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1187 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1188 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1189 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1190 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1191 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1192 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1193 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1194 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1195 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1196 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82,
1197 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1198 0x01, 0xf0, 0x00,
1199 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
1200 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
1201 0x40,
1202 0x10, 0x1a, 0x01, 0x00,
1203 0x10, 0x00, 0x01, 0xad,
1204 0x00, 0x00, 0x01, 0x08,
1205 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1206 0x10, 0x1b, 0x02, 0x00, 0x00,
1207 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1208 0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
1209 0x10, 0x0e, 0x01, 0x0f,
1210 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
1211 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
1212 0xff,
1213 0x10, 0x0f, 0x02, 0x11, 0x11,
1214 0x10, 0x03, 0x01, 0x0c,
1215 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
1216 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
1217 0xff,
1218 0x10, 0x0b, 0x01, 0x1c,
1219 0x10, 0x0d, 0x01, 0x1a,
1220 0x10, 0x0c, 0x01, 0x34,
1221 0x04, 0x05, 0x01, 0x61,
1222 0x04, 0x04, 0x01, 0x40,
1223 0x04, 0x06, 0x01, 0x03,
1224 0, 0, 0
1225};
1226
1227/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */
1228static const u8 proscope_init[] = {
1229 0x04, 0x05, 0x01, 0x21,
1230 0x04, 0x04, 0x01, 0x01,
1231 0, 0, 0
1232};
1233static const u8 proscope_start_1[] = {
1234 0x04, 0x06, 0x01, 0x04,
1235 0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04,
1236 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
1237 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1238 0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4,
1239 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
1240 0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86,
1241 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
1242 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
1243 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6,
1244 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1245 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1246 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1247 0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34,
1248 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1249 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8,
1250 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
1251 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1253 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94,
1254 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
1255 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1256 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1257 0x40, 0x20,
1258 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1259 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
1260 0x06, 0x00, 0x02, 0x09, 0x99,
1261 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
1266 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
1267 0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01,
1268 0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
1269 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1270 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1271 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1272 0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f,
1273 0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4,
1274 0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1275 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1276 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1277 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1278 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1279 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1280 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f,
1281 0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82,
1282 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1283 0x01, 0xf0, 0x00,
1284 0, 0, 0
1285};
1286static const u8 proscope_start_qvga[] = {
1287 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
1288 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
1289 0x40,
1290 0x10, 0x1a, 0x01, 0x06,
1291 0x00, 0x03, 0x02, 0xf9, 0x02,
1292 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1293 0x10, 0x1b, 0x02, 0x00, 0x00,
1294 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1295 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
1296 0x10, 0x0e, 0x01, 0x10,
1297 0, 0, 0
1298};
1299static const u8 proscope_start_vga[] = {
1300 0x00, 0x03, 0x02, 0xf9, 0x02,
1301 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
1302 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
1303 0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00,
1304 0x80,
1305 0x10, 0x1a, 0x01, 0x06,
1306 0x10, 0x00, 0x01, 0xa1,
1307 0x10, 0x1b, 0x02, 0x00, 0x00,
1308 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
1309 0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
1310 0x10, 0x0e, 0x01, 0x10,
1311 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
1312 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
1313 0xf9,
1314 0x10, 0x03, 0x01, 0x00,
1315 0, 0, 0
1316};
1317static const u8 proscope_start_2[] = {
1318 0x10, 0x0f, 0x02, 0x0c, 0x0c,
1319 0x10, 0x03, 0x01, 0x0c,
1320 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
1321 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
1322 0xf9,
1323 0x10, 0x0b, 0x01, 0x0b,
1324 0x10, 0x0d, 0x01, 0x10,
1325 0x10, 0x0c, 0x01, 0x1b,
1326 0x04, 0x06, 0x01, 0x03,
1327 0x04, 0x05, 0x01, 0x21,
1328 0x04, 0x04, 0x01, 0x00,
1329 0, 0, 0
1330};
1331
1332/* nw800 - hv7121b? (seems pas106) - Divio Chicony TwinkleCam */
1333static const u8 twinkle_start[] = {
1334 0x04, 0x06, 0x01, 0x44,
1335 0x04, 0x06, 0x01, 0x00,
1336 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
1337 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
1338 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1339 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
1340 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
1341 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
1342 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
1343 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
1344 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1345 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1346 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1347 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1348 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
1349 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1350 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
1351 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
1352 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
1353 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
1354 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
1355 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
1356 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1357 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1358 0x40, 0x20,
1359 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1360 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
1361 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
1362 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1365 0x00, 0x00, 0x00,
1366 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1368 0x00, 0x00, 0x00, 0x00, 0x00,
1369 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08,
1371 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1372 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
1373 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1374 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1375 0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06,
1376 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80,
1377 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1378 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1379 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1380 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1381 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1382 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1383 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1384 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1385 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
1387 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
1388 0x01, 0x60, 0x01, 0x00, 0x00,
1389
1390 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
1391 0x04, 0x04, 0x01, 0x10,
1392 0x04, 0x04, 0x01, 0x00,
1393 0x04, 0x05, 0x01, 0x61,
1394 0x04, 0x04, 0x01, 0x01,
1395 I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00,
1396 0x00, 0x00, 0x00, 0x0a,
1397 I2C0, 0x40, 0x02, 0x11, 0x06,
1398 I2C0, 0x40, 0x02, 0x14, 0x00,
1399 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
1400 I2C0, 0x40, 0x02, 0x07, 0x01,
1401 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
1402 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
1403 0x40,
1404 I2C0, 0x40, 0x02, 0x02, 0x0c,
1405 I2C0, 0x40, 0x02, 0x13, 0x01,
1406 0x10, 0x00, 0x01, 0x01,
1407 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
1408 0x20, 0x01, 0x60, 0x01,
1409 I2C0, 0x40, 0x02, 0x05, 0x0f,
1410 I2C0, 0x40, 0x02, 0x13, 0x01,
1411 I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17,
1412 I2C0, 0x40, 0x03, 0x12, 0x00, 0x01,
1413 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
1414 I2C0, 0x40, 0x02, 0x12, 0x00,
1415 I2C0, 0x40, 0x02, 0x0e, 0x00,
1416 I2C0, 0x40, 0x02, 0x11, 0x06,
1417 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
1418 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
1419 0xf9,
1420 0x10, 0x03, 0x01, 0x00,
1421 0x10, 0x0f, 0x02, 0x0c, 0x0c,
1422 0x10, 0x03, 0x01, 0x06,
1423 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
1424 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
1425 0xf9,
1426 0x10, 0x0b, 0x01, 0x19,
1427 0x10, 0x0d, 0x01, 0x10,
1428 0x10, 0x0c, 0x01, 0x0d,
1429 0x04, 0x06, 0x01, 0x03,
1430 0x04, 0x05, 0x01, 0x61,
1431 0x04, 0x04, 0x01, 0x41,
1432 0, 0, 0
1433};
1434
1435/* nw802 dvc-v6 */
1436static const u8 dvcv6_start[] = {
1437 0x04, 0x06, 0x01, 0x06,
1438 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
1439 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
1440 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1441 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
1442 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
1443 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1444 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
1445 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1446 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
1447 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1448 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
1449 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1450 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
1451 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
1453 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
1454 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
1455 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1456 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
1457 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
1458 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1459 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1460 0x40, 0x20,
1461 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1462 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
1463 0x06, 0x00, 0x02, 0x09, 0x99,
1464 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466 0x00, 0x00, 0x00, 0x00, 0x00,
1467 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1468 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1469 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1470 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
1471 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1472 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1473 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1474 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1475 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1476 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1477 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1478 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1479 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1480 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1481 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1482 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1483 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
1485 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1486 0x01, 0xf0, 0x00,
1487 0x00, 0x03, 0x02, 0x94, 0x03,
1488 0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07,
1489 0x00, 0x7b, 0x02, 0xe0, 0x00,
1490 0x10, 0x8d, 0x01, 0x00,
1491 0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02,
1492 0x00, 0x91, 0x02, 0x0b, 0x02,
1493 0x10, 0x00, 0x01, 0xaf,
1494 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00,
1495 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
1496 0x40,
1497 0x10, 0x1a, 0x01, 0x02,
1498 0x10, 0x00, 0x01, 0xaf,
1499 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1500 0x10, 0x1b, 0x02, 0x07, 0x01,
1501 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
1502 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
1503 0x10, 0x1d, 0x02, 0x40, 0x06,
1504 0x10, 0x0e, 0x01, 0x08,
1505 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
1506 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
1507 0xdc,
1508 0x10, 0x03, 0x01, 0x00,
1509 0x10, 0x0f, 0x02, 0x12, 0x12,
1510 0x10, 0x03, 0x01, 0x11,
1511 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
1512 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
1513 0xdc,
1514 0x10, 0x0b, 0x01, 0x16,
1515 0x10, 0x0d, 0x01, 0x10,
1516 0x10, 0x0c, 0x01, 0x1a,
1517 0x04, 0x06, 0x01, 0x03,
1518 0x04, 0x04, 0x01, 0x00,
1519};
1520
1521static const u8 *webcam_start[] = {
1522 [Generic800] = nw800_start,
1523 [SpaceCam] = spacecam_start,
1524 [SpaceCam2] = spacecam2_start,
1525 [Cvideopro] = cvideopro_start,
1526 [Dlink350c] = dlink_start,
1527 [DS3303u] = ds3303_start,
1528 [Kr651us] = kr651_start_1,
1529 [Kritter] = kritter_start,
1530 [Mustek300] = mustek_start,
1531 [Proscope] = proscope_start_1,
1532 [Twinkle] = twinkle_start,
1533 [DvcV6] = dvcv6_start,
1534 [P35u] = nw801_start_1,
1535 [Generic802] = nw802_start,
1536};
1537
1538/* -- write a register -- */
1539static void reg_w(struct gspca_dev *gspca_dev,
1540 u16 index,
1541 const u8 *data,
1542 int len)
1543{
1544 struct usb_device *dev = gspca_dev->dev;
1545 int ret;
1546
1547 if (gspca_dev->usb_err < 0)
1548 return;
1549 if (len == 1)
1550 PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data);
1551 else
1552 PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...",
1553 index, *data, data[1]);
1554 memcpy(gspca_dev->usb_buf, data, len);
1555 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1556 0x00,
1557 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1558 0x00, /* value */
1559 index,
1560 gspca_dev->usb_buf,
1561 len,
1562 500);
1563 if (ret < 0) {
1564 pr_err("reg_w err %d\n", ret);
1565 gspca_dev->usb_err = ret;
1566 }
1567}
1568
1569/* -- read registers in usb_buf -- */
1570static void reg_r(struct gspca_dev *gspca_dev,
1571 u16 index,
1572 int len)
1573{
1574 struct usb_device *dev = gspca_dev->dev;
1575 int ret;
1576
1577 if (gspca_dev->usb_err < 0)
1578 return;
1579 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1580 0x00,
1581 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1582 0x00, index,
1583 gspca_dev->usb_buf, len, 500);
1584 if (ret < 0) {
1585 pr_err("reg_r err %d\n", ret);
1586 gspca_dev->usb_err = ret;
1587 return;
1588 }
1589 if (len == 1)
1590 PDEBUG(D_USBI, "GET 00 0000 %04x %02x",
1591 index, gspca_dev->usb_buf[0]);
1592 else
1593 PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..",
1594 index, gspca_dev->usb_buf[0],
1595 gspca_dev->usb_buf[1]);
1596}
1597
1598static void i2c_w(struct gspca_dev *gspca_dev,
1599 u8 i2c_addr,
1600 const u8 *data,
1601 int len)
1602{
1603 u8 val[2];
1604 int i;
1605
1606 reg_w(gspca_dev, 0x0600, data + 1, len - 1);
1607 reg_w(gspca_dev, 0x0600, data, len);
1608 val[0] = len;
1609 val[1] = i2c_addr;
1610 reg_w(gspca_dev, 0x0502, val, 2);
1611 val[0] = 0x01;
1612 reg_w(gspca_dev, 0x0501, val, 1);
1613 for (i = 5; --i >= 0; ) {
1614 msleep(4);
1615 reg_r(gspca_dev, 0x0505, 1);
1616 if (gspca_dev->usb_err < 0)
1617 return;
1618 if (gspca_dev->usb_buf[0] == 0)
1619 return;
1620 }
1621 gspca_dev->usb_err = -ETIME;
1622}
1623
1624static void reg_w_buf(struct gspca_dev *gspca_dev,
1625 const u8 *cmd)
1626{
1627 u16 reg;
1628 int len;
1629
1630 for (;;) {
1631 reg = *cmd++ << 8;
1632 reg += *cmd++;
1633 len = *cmd++;
1634 if (len == 0)
1635 break;
1636 if (cmd[-3] != I2C0)
1637 reg_w(gspca_dev, reg, cmd, len);
1638 else
1639 i2c_w(gspca_dev, reg, cmd, len);
1640 cmd += len;
1641 }
1642}
1643
1644static int swap_bits(int v)
1645{
1646 int r, i;
1647
1648 r = 0;
1649 for (i = 0; i < 8; i++) {
1650 r <<= 1;
1651 if (v & 1)
1652 r++;
1653 v >>= 1;
1654 }
1655 return r;
1656}
1657
1658static void setgain(struct gspca_dev *gspca_dev, u8 val)
1659{
1660 struct sd *sd = (struct sd *) gspca_dev;
1661 u8 v[2];
1662
1663 switch (sd->webcam) {
1664 case P35u:
1665 reg_w(gspca_dev, 0x1026, &val, 1);
1666 break;
1667 case Kr651us:
1668 /* 0 - 253 */
1669 val = swap_bits(val);
1670 v[0] = val << 3;
1671 v[1] = val >> 5;
1672 reg_w(gspca_dev, 0x101d, v, 2); /* SIF reg0/1 (AGC) */
1673 break;
1674 }
1675}
1676
1677static void setexposure(struct gspca_dev *gspca_dev, s32 val)
1678{
1679 struct sd *sd = (struct sd *) gspca_dev;
1680 u8 v[2];
1681
1682 switch (sd->webcam) {
1683 case P35u:
1684 v[0] = ((9 - val) << 3) | 0x01;
1685 reg_w(gspca_dev, 0x1019, v, 1);
1686 break;
1687 case Cvideopro:
1688 case DvcV6:
1689 case Kritter:
1690 case Kr651us:
1691 v[0] = val;
1692 v[1] = val >> 8;
1693 reg_w(gspca_dev, 0x101b, v, 2);
1694 break;
1695 }
1696}
1697
1698static void setautogain(struct gspca_dev *gspca_dev, s32 val)
1699{
1700 struct sd *sd = (struct sd *) gspca_dev;
1701 int w, h;
1702
1703 if (!val) {
1704 sd->ag_cnt = -1;
1705 return;
1706 }
1707 sd->ag_cnt = AG_CNT_START;
1708
1709 reg_r(gspca_dev, 0x1004, 1);
1710 if (gspca_dev->usb_buf[0] & 0x04) { /* if AE_FULL_FRM */
1711 sd->ae_res = gspca_dev->width * gspca_dev->height;
1712 } else { /* get the AE window size */
1713 reg_r(gspca_dev, 0x1011, 8);
1714 w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]
1715 - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2];
1716 h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4]
1717 - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6];
1718 sd->ae_res = h * w;
1719 if (sd->ae_res == 0)
1720 sd->ae_res = gspca_dev->width * gspca_dev->height;
1721 }
1722}
1723
1724static int nw802_test_reg(struct gspca_dev *gspca_dev,
1725 u16 index,
1726 u8 value)
1727{
1728 /* write the value */
1729 reg_w(gspca_dev, index, &value, 1);
1730
1731 /* read it */
1732 reg_r(gspca_dev, index, 1);
1733
1734 return gspca_dev->usb_buf[0] == value;
1735}
1736
1737/* this function is called at probe time */
1738static int sd_config(struct gspca_dev *gspca_dev,
1739 const struct usb_device_id *id)
1740{
1741 struct sd *sd = (struct sd *) gspca_dev;
1742
1743 if ((unsigned) webcam >= NWEBCAMS)
1744 webcam = 0;
1745 sd->webcam = webcam;
1746 gspca_dev->cam.needs_full_bandwidth = 1;
1747 sd->ag_cnt = -1;
1748
1749 /*
1750 * Autodetect sequence inspired from some log.
1751 * We try to detect what registers exist or not.
1752 * If 0x0500 does not exist => NW802
1753 * If it does, test 0x109b. If it doesn't exist,
1754 * then it's a NW801. Else, a NW800
1755 * If a et31x110 (nw800 and 06a5:d800)
1756 * get the sensor ID
1757 */
1758 if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) {
1759 sd->bridge = BRIDGE_NW802;
1760 if (sd->webcam == Generic800)
1761 sd->webcam = Generic802;
1762 } else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) {
1763 sd->bridge = BRIDGE_NW801;
1764 if (sd->webcam == Generic800)
1765 sd->webcam = P35u;
1766 } else if (id->idVendor == 0x06a5 && id->idProduct == 0xd800) {
1767 reg_r(gspca_dev, 0x0403, 1); /* GPIO */
1768 PDEBUG(D_PROBE, "et31x110 sensor type %02x",
1769 gspca_dev->usb_buf[0]);
1770 switch (gspca_dev->usb_buf[0] >> 1) {
1771 case 0x00: /* ?? */
1772 if (sd->webcam == Generic800)
1773 sd->webcam = SpaceCam;
1774 break;
1775 case 0x01: /* Hynix? */
1776 if (sd->webcam == Generic800)
1777 sd->webcam = Twinkle;
1778 break;
1779 case 0x0a: /* Pixart */
1780 if (sd->webcam == Generic800)
1781 sd->webcam = SpaceCam2;
1782 break;
1783 }
1784 }
1785 if (webcam_chip[sd->webcam] != sd->bridge) {
1786 pr_err("Bad webcam type %d for NW80%d\n",
1787 sd->webcam, sd->bridge);
1788 gspca_dev->usb_err = -ENODEV;
1789 return gspca_dev->usb_err;
1790 }
1791 PDEBUG(D_PROBE, "Bridge nw80%d - type: %d", sd->bridge, sd->webcam);
1792
1793 if (sd->bridge == BRIDGE_NW800) {
1794 switch (sd->webcam) {
1795 case DS3303u:
1796 gspca_dev->cam.cam_mode = cif_mode; /* qvga */
1797 break;
1798 default:
1799 gspca_dev->cam.cam_mode = &cif_mode[1]; /* cif */
1800 break;
1801 }
1802 gspca_dev->cam.nmodes = 1;
1803 } else {
1804 gspca_dev->cam.cam_mode = vga_mode;
1805 switch (sd->webcam) {
1806 case Kr651us:
1807 case Proscope:
1808 case P35u:
1809 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
1810 break;
1811 default:
1812 gspca_dev->cam.nmodes = 1; /* qvga only */
1813 break;
1814 }
1815 }
1816
1817 return gspca_dev->usb_err;
1818}
1819
1820/* this function is called at probe and resume time */
1821static int sd_init(struct gspca_dev *gspca_dev)
1822{
1823 struct sd *sd = (struct sd *) gspca_dev;
1824
1825 switch (sd->bridge) {
1826 case BRIDGE_NW800:
1827 switch (sd->webcam) {
1828 case SpaceCam:
1829 reg_w_buf(gspca_dev, spacecam_init);
1830 break;
1831 default:
1832 reg_w_buf(gspca_dev, nw800_init);
1833 break;
1834 }
1835 break;
1836 default:
1837 switch (sd->webcam) {
1838 case Mustek300:
1839 case P35u:
1840 case Proscope:
1841 reg_w_buf(gspca_dev, proscope_init);
1842 break;
1843 }
1844 break;
1845 }
1846 return gspca_dev->usb_err;
1847}
1848
1849/* -- start the camera -- */
1850static int sd_start(struct gspca_dev *gspca_dev)
1851{
1852 struct sd *sd = (struct sd *) gspca_dev;
1853 const u8 *cmd;
1854
1855 cmd = webcam_start[sd->webcam];
1856 reg_w_buf(gspca_dev, cmd);
1857 switch (sd->webcam) {
1858 case P35u:
1859 if (gspca_dev->width == 320)
1860 reg_w_buf(gspca_dev, nw801_start_qvga);
1861 else
1862 reg_w_buf(gspca_dev, nw801_start_vga);
1863 reg_w_buf(gspca_dev, nw801_start_2);
1864 break;
1865 case Kr651us:
1866 if (gspca_dev->width == 320)
1867 reg_w_buf(gspca_dev, kr651_start_qvga);
1868 else
1869 reg_w_buf(gspca_dev, kr651_start_vga);
1870 reg_w_buf(gspca_dev, kr651_start_2);
1871 break;
1872 case Proscope:
1873 if (gspca_dev->width == 320)
1874 reg_w_buf(gspca_dev, proscope_start_qvga);
1875 else
1876 reg_w_buf(gspca_dev, proscope_start_vga);
1877 reg_w_buf(gspca_dev, proscope_start_2);
1878 break;
1879 }
1880
1881 sd->exp_too_high_cnt = 0;
1882 sd->exp_too_low_cnt = 0;
1883 return gspca_dev->usb_err;
1884}
1885
1886static void sd_stopN(struct gspca_dev *gspca_dev)
1887{
1888 struct sd *sd = (struct sd *) gspca_dev;
1889 u8 value;
1890
1891 /* 'go' off */
1892 if (sd->bridge != BRIDGE_NW801) {
1893 value = 0x02;
1894 reg_w(gspca_dev, 0x0406, &value, 1);
1895 }
1896
1897 /* LED off */
1898 switch (sd->webcam) {
1899 case Cvideopro:
1900 case Kr651us:
1901 case DvcV6:
1902 case Kritter:
1903 value = 0xff;
1904 break;
1905 case Dlink350c:
1906 value = 0x21;
1907 break;
1908 case SpaceCam:
1909 case SpaceCam2:
1910 case Proscope:
1911 case Twinkle:
1912 value = 0x01;
1913 break;
1914 default:
1915 return;
1916 }
1917 reg_w(gspca_dev, 0x0404, &value, 1);
1918}
1919
1920static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1921 u8 *data, /* isoc packet */
1922 int len) /* iso packet length */
1923{
1924 /*
1925 * frame header = '00 00 hh ww ss xx ff ff'
1926 * with:
1927 * - 'hh': height / 4
1928 * - 'ww': width / 4
1929 * - 'ss': frame sequence number c0..dd
1930 */
1931 if (data[0] == 0x00 && data[1] == 0x00
1932 && data[6] == 0xff && data[7] == 0xff) {
1933 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1934 gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8);
1935 } else {
1936 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1937 }
1938}
1939
1940static void do_autogain(struct gspca_dev *gspca_dev)
1941{
1942 struct sd *sd = (struct sd *) gspca_dev;
1943 int luma;
1944
1945 if (sd->ag_cnt < 0)
1946 return;
1947 if (--sd->ag_cnt >= 0)
1948 return;
1949 sd->ag_cnt = AG_CNT_START;
1950
1951 /* get the average luma */
1952 reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4);
1953 luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16)
1954 + (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
1955 luma /= sd->ae_res;
1956
1957 switch (sd->webcam) {
1958 case P35u:
1959 gspca_coarse_grained_expo_autogain(gspca_dev, luma, 100, 5);
1960 break;
1961 default:
1962 gspca_expo_autogain(gspca_dev, luma, 100, 5, 230, 0);
1963 break;
1964 }
1965}
1966
1967
1968static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1969{
1970 struct gspca_dev *gspca_dev =
1971 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1972
1973 gspca_dev->usb_err = 0;
1974
1975 if (!gspca_dev->streaming)
1976 return 0;
1977
1978 switch (ctrl->id) {
1979 /* autogain/gain/exposure control cluster */
1980 case V4L2_CID_AUTOGAIN:
1981 if (ctrl->is_new)
1982 setautogain(gspca_dev, ctrl->val);
1983 if (!ctrl->val) {
1984 if (gspca_dev->gain->is_new)
1985 setgain(gspca_dev, gspca_dev->gain->val);
1986 if (gspca_dev->exposure->is_new)
1987 setexposure(gspca_dev,
1988 gspca_dev->exposure->val);
1989 }
1990 break;
1991 /* Some webcams only have exposure, so handle that separately from the
1992 autogain/gain/exposure cluster in the previous case. */
1993 case V4L2_CID_EXPOSURE:
1994 setexposure(gspca_dev, gspca_dev->exposure->val);
1995 break;
1996 }
1997 return gspca_dev->usb_err;
1998}
1999
2000static const struct v4l2_ctrl_ops sd_ctrl_ops = {
2001 .s_ctrl = sd_s_ctrl,
2002};
2003
2004static int sd_init_controls(struct gspca_dev *gspca_dev)
2005{
2006 struct sd *sd = (struct sd *)gspca_dev;
2007 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
2008
2009 gspca_dev->vdev.ctrl_handler = hdl;
2010 v4l2_ctrl_handler_init(hdl, 3);
2011 switch (sd->webcam) {
2012 case P35u:
2013 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2014 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
2015 /* For P35u choose coarse expo auto gain function gain minimum,
2016 * to avoid a large settings jump the first auto adjustment */
2017 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2018 V4L2_CID_GAIN, 0, 127, 1, 127 / 5 * 2);
2019 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2020 V4L2_CID_EXPOSURE, 0, 9, 1, 9);
2021 break;
2022 case Kr651us:
2023 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2024 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
2025 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2026 V4L2_CID_GAIN, 0, 253, 1, 128);
2027 /* fall through */
2028 case Cvideopro:
2029 case DvcV6:
2030 case Kritter:
2031 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2032 V4L2_CID_EXPOSURE, 0, 315, 1, 150);
2033 break;
2034 default:
2035 break;
2036 }
2037
2038 if (hdl->error) {
2039 pr_err("Could not initialize controls\n");
2040 return hdl->error;
2041 }
2042 if (gspca_dev->autogain)
2043 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
2044 return 0;
2045}
2046
2047/* sub-driver description */
2048static const struct sd_desc sd_desc = {
2049 .name = MODULE_NAME,
2050 .config = sd_config,
2051 .init = sd_init,
2052 .init_controls = sd_init_controls,
2053 .start = sd_start,
2054 .stopN = sd_stopN,
2055 .pkt_scan = sd_pkt_scan,
2056 .dq_callback = do_autogain,
2057};
2058
2059/* -- module initialisation -- */
2060static const struct usb_device_id device_table[] = {
2061 {USB_DEVICE(0x046d, 0xd001)},
2062 {USB_DEVICE(0x0502, 0xd001)},
2063 {USB_DEVICE(0x052b, 0xd001)},
2064 {USB_DEVICE(0x055f, 0xd001)},
2065 {USB_DEVICE(0x06a5, 0x0000)},
2066 {USB_DEVICE(0x06a5, 0xd001)},
2067 {USB_DEVICE(0x06a5, 0xd800)},
2068 {USB_DEVICE(0x06be, 0xd001)},
2069 {USB_DEVICE(0x0728, 0xd001)},
2070 {}
2071};
2072MODULE_DEVICE_TABLE(usb, device_table);
2073
2074/* -- device connect -- */
2075static int sd_probe(struct usb_interface *intf,
2076 const struct usb_device_id *id)
2077{
2078 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2079 THIS_MODULE);
2080}
2081
2082static struct usb_driver sd_driver = {
2083 .name = MODULE_NAME,
2084 .id_table = device_table,
2085 .probe = sd_probe,
2086 .disconnect = gspca_disconnect,
2087#ifdef CONFIG_PM
2088 .suspend = gspca_suspend,
2089 .resume = gspca_resume,
2090 .reset_resume = gspca_resume,
2091#endif
2092};
2093
2094module_usb_driver(sd_driver);
2095
2096module_param(webcam, int, 0644);
2097MODULE_PARM_DESC(webcam,
2098 "Webcam type\n"
2099 "0: generic\n"
2100 "1: Trust 120 SpaceCam\n"
2101 "2: other Trust 120 SpaceCam\n"
2102 "3: Conceptronic Video Pro\n"
2103 "4: D-link dru-350c\n"
2104 "5: Plustek Opticam 500U\n"
2105 "6: Panasonic GP-KR651US\n"
2106 "7: iRez Kritter\n"
2107 "8: Mustek Wcam 300 mini\n"
2108 "9: Scalar USB Microscope M2 (Proscope)\n"
2109 "10: Divio Chicony TwinkleCam\n"
2110 "11: DVC-V6\n");
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c
new file mode 100644
index 00000000000..bfc7cefa59f
--- /dev/null
+++ b/drivers/media/usb/gspca/ov519.c
@@ -0,0 +1,4991 @@
1/**
2 * OV519 driver
3 *
4 * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr>
5 * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
6 *
7 * This module is adapted from the ov51x-jpeg package, which itself
8 * was adapted from the ov511 driver.
9 *
10 * Original copyright for the ov511 driver is:
11 *
12 * Copyright (c) 1999-2006 Mark W. McClelland
13 * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach
14 * Many improvements by Bret Wallach <bwallac1@san.rr.com>
15 * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
16 * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
17 * Changes by Claudio Matsuoka <claudio@conectiva.com>
18 *
19 * ov51x-jpeg original copyright is:
20 *
21 * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org>
22 * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.com>
23 *
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 *
38 */
39
40#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
41
42#define MODULE_NAME "ov519"
43
44#include <linux/input.h>
45#include "gspca.h"
46
47/* The jpeg_hdr is used by w996Xcf only */
48/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */
49#define CONEX_CAM
50#include "jpeg.h"
51
52MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
53MODULE_DESCRIPTION("OV519 USB Camera Driver");
54MODULE_LICENSE("GPL");
55
56/* global parameters */
57static int frame_rate;
58
59/* Number of times to retry a failed I2C transaction. Increase this if you
60 * are getting "Failed to read sensor ID..." */
61static int i2c_detect_tries = 10;
62
63/* ov519 device descriptor */
64struct sd {
65 struct gspca_dev gspca_dev; /* !! must be the first item */
66
67 struct v4l2_ctrl *jpegqual;
68 struct v4l2_ctrl *freq;
69 struct { /* h/vflip control cluster */
70 struct v4l2_ctrl *hflip;
71 struct v4l2_ctrl *vflip;
72 };
73 struct { /* autobrightness/brightness control cluster */
74 struct v4l2_ctrl *autobright;
75 struct v4l2_ctrl *brightness;
76 };
77
78 u8 packet_nr;
79
80 char bridge;
81#define BRIDGE_OV511 0
82#define BRIDGE_OV511PLUS 1
83#define BRIDGE_OV518 2
84#define BRIDGE_OV518PLUS 3
85#define BRIDGE_OV519 4 /* = ov530 */
86#define BRIDGE_OVFX2 5
87#define BRIDGE_W9968CF 6
88#define BRIDGE_MASK 7
89
90 char invert_led;
91#define BRIDGE_INVERT_LED 8
92
93 char snapshot_pressed;
94 char snapshot_needs_reset;
95
96 /* Determined by sensor type */
97 u8 sif;
98
99#define QUALITY_MIN 50
100#define QUALITY_MAX 70
101#define QUALITY_DEF 50
102
103 u8 stopped; /* Streaming is temporarily paused */
104 u8 first_frame;
105
106 u8 frame_rate; /* current Framerate */
107 u8 clockdiv; /* clockdiv override */
108
109 s8 sensor; /* Type of image sensor chip (SEN_*) */
110
111 u8 sensor_addr;
112 u16 sensor_width;
113 u16 sensor_height;
114 s16 sensor_reg_cache[256];
115
116 u8 jpeg_hdr[JPEG_HDR_SZ];
117};
118enum sensors {
119 SEN_OV2610,
120 SEN_OV2610AE,
121 SEN_OV3610,
122 SEN_OV6620,
123 SEN_OV6630,
124 SEN_OV66308AF,
125 SEN_OV7610,
126 SEN_OV7620,
127 SEN_OV7620AE,
128 SEN_OV7640,
129 SEN_OV7648,
130 SEN_OV7660,
131 SEN_OV7670,
132 SEN_OV76BE,
133 SEN_OV8610,
134 SEN_OV9600,
135};
136
137/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
138 the ov sensors which is already present here. When we have the time we
139 really should move the sensor drivers to v4l2 sub drivers. */
140#include "w996Xcf.c"
141
142/* table of the disabled controls */
143struct ctrl_valid {
144 int has_brightness:1;
145 int has_contrast:1;
146 int has_exposure:1;
147 int has_autogain:1;
148 int has_sat:1;
149 int has_hvflip:1;
150 int has_autobright:1;
151 int has_freq:1;
152};
153
154static const struct ctrl_valid valid_controls[] = {
155 [SEN_OV2610] = {
156 .has_exposure = 1,
157 .has_autogain = 1,
158 },
159 [SEN_OV2610AE] = {
160 .has_exposure = 1,
161 .has_autogain = 1,
162 },
163 [SEN_OV3610] = {
164 /* No controls */
165 },
166 [SEN_OV6620] = {
167 .has_brightness = 1,
168 .has_contrast = 1,
169 .has_sat = 1,
170 .has_autobright = 1,
171 .has_freq = 1,
172 },
173 [SEN_OV6630] = {
174 .has_brightness = 1,
175 .has_contrast = 1,
176 .has_sat = 1,
177 .has_autobright = 1,
178 .has_freq = 1,
179 },
180 [SEN_OV66308AF] = {
181 .has_brightness = 1,
182 .has_contrast = 1,
183 .has_sat = 1,
184 .has_autobright = 1,
185 .has_freq = 1,
186 },
187 [SEN_OV7610] = {
188 .has_brightness = 1,
189 .has_contrast = 1,
190 .has_sat = 1,
191 .has_autobright = 1,
192 .has_freq = 1,
193 },
194 [SEN_OV7620] = {
195 .has_brightness = 1,
196 .has_contrast = 1,
197 .has_sat = 1,
198 .has_autobright = 1,
199 .has_freq = 1,
200 },
201 [SEN_OV7620AE] = {
202 .has_brightness = 1,
203 .has_contrast = 1,
204 .has_sat = 1,
205 .has_autobright = 1,
206 .has_freq = 1,
207 },
208 [SEN_OV7640] = {
209 .has_brightness = 1,
210 .has_sat = 1,
211 .has_freq = 1,
212 },
213 [SEN_OV7648] = {
214 .has_brightness = 1,
215 .has_sat = 1,
216 .has_freq = 1,
217 },
218 [SEN_OV7660] = {
219 .has_brightness = 1,
220 .has_contrast = 1,
221 .has_sat = 1,
222 .has_hvflip = 1,
223 .has_freq = 1,
224 },
225 [SEN_OV7670] = {
226 .has_brightness = 1,
227 .has_contrast = 1,
228 .has_hvflip = 1,
229 .has_freq = 1,
230 },
231 [SEN_OV76BE] = {
232 .has_brightness = 1,
233 .has_contrast = 1,
234 .has_sat = 1,
235 .has_autobright = 1,
236 .has_freq = 1,
237 },
238 [SEN_OV8610] = {
239 .has_brightness = 1,
240 .has_contrast = 1,
241 .has_sat = 1,
242 .has_autobright = 1,
243 },
244 [SEN_OV9600] = {
245 .has_exposure = 1,
246 .has_autogain = 1,
247 },
248};
249
250static const struct v4l2_pix_format ov519_vga_mode[] = {
251 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
252 .bytesperline = 320,
253 .sizeimage = 320 * 240 * 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};
262static const struct v4l2_pix_format ov519_sif_mode[] = {
263 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
264 .bytesperline = 160,
265 .sizeimage = 160 * 120 * 3 / 8 + 590,
266 .colorspace = V4L2_COLORSPACE_JPEG,
267 .priv = 3},
268 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
269 .bytesperline = 176,
270 .sizeimage = 176 * 144 * 3 / 8 + 590,
271 .colorspace = V4L2_COLORSPACE_JPEG,
272 .priv = 1},
273 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
274 .bytesperline = 320,
275 .sizeimage = 320 * 240 * 3 / 8 + 590,
276 .colorspace = V4L2_COLORSPACE_JPEG,
277 .priv = 2},
278 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
279 .bytesperline = 352,
280 .sizeimage = 352 * 288 * 3 / 8 + 590,
281 .colorspace = V4L2_COLORSPACE_JPEG,
282 .priv = 0},
283};
284
285/* Note some of the sizeimage values for the ov511 / ov518 may seem
286 larger then necessary, however they need to be this big as the ov511 /
287 ov518 always fills the entire isoc frame, using 0 padding bytes when
288 it doesn't have any data. So with low framerates the amount of data
289 transferred can become quite large (libv4l will remove all the 0 padding
290 in userspace). */
291static const struct v4l2_pix_format ov518_vga_mode[] = {
292 {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
293 .bytesperline = 320,
294 .sizeimage = 320 * 240 * 3,
295 .colorspace = V4L2_COLORSPACE_JPEG,
296 .priv = 1},
297 {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
298 .bytesperline = 640,
299 .sizeimage = 640 * 480 * 2,
300 .colorspace = V4L2_COLORSPACE_JPEG,
301 .priv = 0},
302};
303static const struct v4l2_pix_format ov518_sif_mode[] = {
304 {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
305 .bytesperline = 160,
306 .sizeimage = 70000,
307 .colorspace = V4L2_COLORSPACE_JPEG,
308 .priv = 3},
309 {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
310 .bytesperline = 176,
311 .sizeimage = 70000,
312 .colorspace = V4L2_COLORSPACE_JPEG,
313 .priv = 1},
314 {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
315 .bytesperline = 320,
316 .sizeimage = 320 * 240 * 3,
317 .colorspace = V4L2_COLORSPACE_JPEG,
318 .priv = 2},
319 {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
320 .bytesperline = 352,
321 .sizeimage = 352 * 288 * 3,
322 .colorspace = V4L2_COLORSPACE_JPEG,
323 .priv = 0},
324};
325
326static const struct v4l2_pix_format ov511_vga_mode[] = {
327 {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
328 .bytesperline = 320,
329 .sizeimage = 320 * 240 * 3,
330 .colorspace = V4L2_COLORSPACE_JPEG,
331 .priv = 1},
332 {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
333 .bytesperline = 640,
334 .sizeimage = 640 * 480 * 2,
335 .colorspace = V4L2_COLORSPACE_JPEG,
336 .priv = 0},
337};
338static const struct v4l2_pix_format ov511_sif_mode[] = {
339 {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
340 .bytesperline = 160,
341 .sizeimage = 70000,
342 .colorspace = V4L2_COLORSPACE_JPEG,
343 .priv = 3},
344 {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
345 .bytesperline = 176,
346 .sizeimage = 70000,
347 .colorspace = V4L2_COLORSPACE_JPEG,
348 .priv = 1},
349 {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
350 .bytesperline = 320,
351 .sizeimage = 320 * 240 * 3,
352 .colorspace = V4L2_COLORSPACE_JPEG,
353 .priv = 2},
354 {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
355 .bytesperline = 352,
356 .sizeimage = 352 * 288 * 3,
357 .colorspace = V4L2_COLORSPACE_JPEG,
358 .priv = 0},
359};
360
361static const struct v4l2_pix_format ovfx2_vga_mode[] = {
362 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
363 .bytesperline = 320,
364 .sizeimage = 320 * 240,
365 .colorspace = V4L2_COLORSPACE_SRGB,
366 .priv = 1},
367 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
368 .bytesperline = 640,
369 .sizeimage = 640 * 480,
370 .colorspace = V4L2_COLORSPACE_SRGB,
371 .priv = 0},
372};
373static const struct v4l2_pix_format ovfx2_cif_mode[] = {
374 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
375 .bytesperline = 160,
376 .sizeimage = 160 * 120,
377 .colorspace = V4L2_COLORSPACE_SRGB,
378 .priv = 3},
379 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
380 .bytesperline = 176,
381 .sizeimage = 176 * 144,
382 .colorspace = V4L2_COLORSPACE_SRGB,
383 .priv = 1},
384 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
385 .bytesperline = 320,
386 .sizeimage = 320 * 240,
387 .colorspace = V4L2_COLORSPACE_SRGB,
388 .priv = 2},
389 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
390 .bytesperline = 352,
391 .sizeimage = 352 * 288,
392 .colorspace = V4L2_COLORSPACE_SRGB,
393 .priv = 0},
394};
395static const struct v4l2_pix_format ovfx2_ov2610_mode[] = {
396 {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
397 .bytesperline = 800,
398 .sizeimage = 800 * 600,
399 .colorspace = V4L2_COLORSPACE_SRGB,
400 .priv = 1},
401 {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
402 .bytesperline = 1600,
403 .sizeimage = 1600 * 1200,
404 .colorspace = V4L2_COLORSPACE_SRGB},
405};
406static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
407 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
408 .bytesperline = 640,
409 .sizeimage = 640 * 480,
410 .colorspace = V4L2_COLORSPACE_SRGB,
411 .priv = 1},
412 {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
413 .bytesperline = 800,
414 .sizeimage = 800 * 600,
415 .colorspace = V4L2_COLORSPACE_SRGB,
416 .priv = 1},
417 {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
418 .bytesperline = 1024,
419 .sizeimage = 1024 * 768,
420 .colorspace = V4L2_COLORSPACE_SRGB,
421 .priv = 1},
422 {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
423 .bytesperline = 1600,
424 .sizeimage = 1600 * 1200,
425 .colorspace = V4L2_COLORSPACE_SRGB,
426 .priv = 0},
427 {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
428 .bytesperline = 2048,
429 .sizeimage = 2048 * 1536,
430 .colorspace = V4L2_COLORSPACE_SRGB,
431 .priv = 0},
432};
433static const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
434 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
435 .bytesperline = 640,
436 .sizeimage = 640 * 480,
437 .colorspace = V4L2_COLORSPACE_SRGB,
438 .priv = 1},
439 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
440 .bytesperline = 1280,
441 .sizeimage = 1280 * 1024,
442 .colorspace = V4L2_COLORSPACE_SRGB},
443};
444
445/* Registers common to OV511 / OV518 */
446#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */
447#define R51x_SYS_RESET 0x50
448 /* Reset type flags */
449 #define OV511_RESET_OMNICE 0x08
450#define R51x_SYS_INIT 0x53
451#define R51x_SYS_SNAP 0x52
452#define R51x_SYS_CUST_ID 0x5f
453#define R51x_COMP_LUT_BEGIN 0x80
454
455/* OV511 Camera interface register numbers */
456#define R511_CAM_DELAY 0x10
457#define R511_CAM_EDGE 0x11
458#define R511_CAM_PXCNT 0x12
459#define R511_CAM_LNCNT 0x13
460#define R511_CAM_PXDIV 0x14
461#define R511_CAM_LNDIV 0x15
462#define R511_CAM_UV_EN 0x16
463#define R511_CAM_LINE_MODE 0x17
464#define R511_CAM_OPTS 0x18
465
466#define R511_SNAP_FRAME 0x19
467#define R511_SNAP_PXCNT 0x1a
468#define R511_SNAP_LNCNT 0x1b
469#define R511_SNAP_PXDIV 0x1c
470#define R511_SNAP_LNDIV 0x1d
471#define R511_SNAP_UV_EN 0x1e
472#define R511_SNAP_OPTS 0x1f
473
474#define R511_DRAM_FLOW_CTL 0x20
475#define R511_FIFO_OPTS 0x31
476#define R511_I2C_CTL 0x40
477#define R511_SYS_LED_CTL 0x55 /* OV511+ only */
478#define R511_COMP_EN 0x78
479#define R511_COMP_LUT_EN 0x79
480
481/* OV518 Camera interface register numbers */
482#define R518_GPIO_OUT 0x56 /* OV518(+) only */
483#define R518_GPIO_CTL 0x57 /* OV518(+) only */
484
485/* OV519 Camera interface register numbers */
486#define OV519_R10_H_SIZE 0x10
487#define OV519_R11_V_SIZE 0x11
488#define OV519_R12_X_OFFSETL 0x12
489#define OV519_R13_X_OFFSETH 0x13
490#define OV519_R14_Y_OFFSETL 0x14
491#define OV519_R15_Y_OFFSETH 0x15
492#define OV519_R16_DIVIDER 0x16
493#define OV519_R20_DFR 0x20
494#define OV519_R25_FORMAT 0x25
495
496/* OV519 System Controller register numbers */
497#define OV519_R51_RESET1 0x51
498#define OV519_R54_EN_CLK1 0x54
499#define OV519_R57_SNAPSHOT 0x57
500
501#define OV519_GPIO_DATA_OUT0 0x71
502#define OV519_GPIO_IO_CTRL0 0x72
503
504/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */
505
506/*
507 * The FX2 chip does not give us a zero length read at end of frame.
508 * It does, however, give a short read at the end of a frame, if
509 * necessary, rather than run two frames together.
510 *
511 * By choosing the right bulk transfer size, we are guaranteed to always
512 * get a short read for the last read of each frame. Frame sizes are
513 * always a composite number (width * height, or a multiple) so if we
514 * choose a prime number, we are guaranteed that the last read of a
515 * frame will be short.
516 *
517 * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB,
518 * otherwise EOVERFLOW "babbling" errors occur. I have not been able
519 * to figure out why. [PMiller]
520 *
521 * The constant (13 * 4096) is the largest "prime enough" number less than 64KB.
522 *
523 * It isn't enough to know the number of bytes per frame, in case we
524 * have data dropouts or buffer overruns (even though the FX2 double
525 * buffers, there are some pretty strict real time constraints for
526 * isochronous transfer for larger frame sizes).
527 */
528/*jfm: this value does not work for 800x600 - see isoc_init */
529#define OVFX2_BULK_SIZE (13 * 4096)
530
531/* I2C registers */
532#define R51x_I2C_W_SID 0x41
533#define R51x_I2C_SADDR_3 0x42
534#define R51x_I2C_SADDR_2 0x43
535#define R51x_I2C_R_SID 0x44
536#define R51x_I2C_DATA 0x45
537#define R518_I2C_CTL 0x47 /* OV518(+) only */
538#define OVFX2_I2C_ADDR 0x00
539
540/* I2C ADDRESSES */
541#define OV7xx0_SID 0x42
542#define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */
543#define OV8xx0_SID 0xa0
544#define OV6xx0_SID 0xc0
545
546/* OV7610 registers */
547#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
548#define OV7610_REG_BLUE 0x01 /* blue channel balance */
549#define OV7610_REG_RED 0x02 /* red channel balance */
550#define OV7610_REG_SAT 0x03 /* saturation */
551#define OV8610_REG_HUE 0x04 /* 04 reserved */
552#define OV7610_REG_CNT 0x05 /* Y contrast */
553#define OV7610_REG_BRT 0x06 /* Y brightness */
554#define OV7610_REG_COM_C 0x14 /* misc common regs */
555#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
556#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
557#define OV7610_REG_COM_I 0x29 /* misc settings */
558
559/* OV7660 and OV7670 registers */
560#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
561#define OV7670_R01_BLUE 0x01 /* blue gain */
562#define OV7670_R02_RED 0x02 /* red gain */
563#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */
564#define OV7670_R04_COM1 0x04 /* Control 1 */
565/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */
566#define OV7670_R0C_COM3 0x0c /* Control 3 */
567#define OV7670_R0D_COM4 0x0d /* Control 4 */
568#define OV7670_R0E_COM5 0x0e /* All "reserved" */
569#define OV7670_R0F_COM6 0x0f /* Control 6 */
570#define OV7670_R10_AECH 0x10 /* More bits of AEC value */
571#define OV7670_R11_CLKRC 0x11 /* Clock control */
572#define OV7670_R12_COM7 0x12 /* Control 7 */
573#define OV7670_COM7_FMT_VGA 0x00
574/*#define OV7670_COM7_YUV 0x00 * YUV */
575#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */
576#define OV7670_COM7_FMT_MASK 0x38
577#define OV7670_COM7_RESET 0x80 /* Register reset */
578#define OV7670_R13_COM8 0x13 /* Control 8 */
579#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */
580#define OV7670_COM8_AWB 0x02 /* White balance enable */
581#define OV7670_COM8_AGC 0x04 /* Auto gain enable */
582#define OV7670_COM8_BFILT 0x20 /* Band filter enable */
583#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */
584#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
585#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */
586#define OV7670_R15_COM10 0x15 /* Control 10 */
587#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */
588#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */
589#define OV7670_R19_VSTART 0x19 /* Vert start high bits */
590#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */
591#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */
592#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */
593#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
594#define OV7670_R24_AEW 0x24 /* AGC upper limit */
595#define OV7670_R25_AEB 0x25 /* AGC lower limit */
596#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */
597#define OV7670_R32_HREF 0x32 /* HREF pieces */
598#define OV7670_R3A_TSLB 0x3a /* lots of stuff */
599#define OV7670_R3B_COM11 0x3b /* Control 11 */
600#define OV7670_COM11_EXP 0x02
601#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
602#define OV7670_R3C_COM12 0x3c /* Control 12 */
603#define OV7670_R3D_COM13 0x3d /* Control 13 */
604#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */
605#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */
606#define OV7670_R3E_COM14 0x3e /* Control 14 */
607#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */
608#define OV7670_R40_COM15 0x40 /* Control 15 */
609/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */
610#define OV7670_R41_COM16 0x41 /* Control 16 */
611#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */
612/* end of ov7660 common registers */
613#define OV7670_R55_BRIGHT 0x55 /* Brightness */
614#define OV7670_R56_CONTRAS 0x56 /* Contrast control */
615#define OV7670_R69_GFIX 0x69 /* Fix gain control */
616/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */
617#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */
618#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */
619#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */
620#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */
621#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */
622#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */
623#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */
624#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */
625#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */
626
627struct ov_regvals {
628 u8 reg;
629 u8 val;
630};
631struct ov_i2c_regvals {
632 u8 reg;
633 u8 val;
634};
635
636/* Settings for OV2610 camera chip */
637static const struct ov_i2c_regvals norm_2610[] = {
638 { 0x12, 0x80 }, /* reset */
639};
640
641static const struct ov_i2c_regvals norm_2610ae[] = {
642 {0x12, 0x80}, /* reset */
643 {0x13, 0xcd},
644 {0x09, 0x01},
645 {0x0d, 0x00},
646 {0x11, 0x80},
647 {0x12, 0x20}, /* 1600x1200 */
648 {0x33, 0x0c},
649 {0x35, 0x90},
650 {0x36, 0x37},
651/* ms-win traces */
652 {0x11, 0x83}, /* clock / 3 ? */
653 {0x2d, 0x00}, /* 60 Hz filter */
654 {0x24, 0xb0}, /* normal colors */
655 {0x25, 0x90},
656 {0x10, 0x43},
657};
658
659static const struct ov_i2c_regvals norm_3620b[] = {
660 /*
661 * From the datasheet: "Note that after writing to register COMH
662 * (0x12) to change the sensor mode, registers related to the
663 * sensor’s cropping window will be reset back to their default
664 * values."
665 *
666 * "wait 4096 external clock ... to make sure the sensor is
667 * stable and ready to access registers" i.e. 160us at 24MHz
668 */
669 { 0x12, 0x80 }, /* COMH reset */
670 { 0x12, 0x00 }, /* QXGA, master */
671
672 /*
673 * 11 CLKRC "Clock Rate Control"
674 * [7] internal frequency doublers: on
675 * [6] video port mode: master
676 * [5:0] clock divider: 1
677 */
678 { 0x11, 0x80 },
679
680 /*
681 * 13 COMI "Common Control I"
682 * = 192 (0xC0) 11000000
683 * COMI[7] "AEC speed selection"
684 * = 1 (0x01) 1....... "Faster AEC correction"
685 * COMI[6] "AEC speed step selection"
686 * = 1 (0x01) .1...... "Big steps, fast"
687 * COMI[5] "Banding filter on off"
688 * = 0 (0x00) ..0..... "Off"
689 * COMI[4] "Banding filter option"
690 * = 0 (0x00) ...0.... "Main clock is 48 MHz and
691 * the PLL is ON"
692 * COMI[3] "Reserved"
693 * = 0 (0x00) ....0...
694 * COMI[2] "AGC auto manual control selection"
695 * = 0 (0x00) .....0.. "Manual"
696 * COMI[1] "AWB auto manual control selection"
697 * = 0 (0x00) ......0. "Manual"
698 * COMI[0] "Exposure control"
699 * = 0 (0x00) .......0 "Manual"
700 */
701 { 0x13, 0xc0 },
702
703 /*
704 * 09 COMC "Common Control C"
705 * = 8 (0x08) 00001000
706 * COMC[7:5] "Reserved"
707 * = 0 (0x00) 000.....
708 * COMC[4] "Sleep Mode Enable"
709 * = 0 (0x00) ...0.... "Normal mode"
710 * COMC[3:2] "Sensor sampling reset timing selection"
711 * = 2 (0x02) ....10.. "Longer reset time"
712 * COMC[1:0] "Output drive current select"
713 * = 0 (0x00) ......00 "Weakest"
714 */
715 { 0x09, 0x08 },
716
717 /*
718 * 0C COMD "Common Control D"
719 * = 8 (0x08) 00001000
720 * COMD[7] "Reserved"
721 * = 0 (0x00) 0.......
722 * COMD[6] "Swap MSB and LSB at the output port"
723 * = 0 (0x00) .0...... "False"
724 * COMD[5:3] "Reserved"
725 * = 1 (0x01) ..001...
726 * COMD[2] "Output Average On Off"
727 * = 0 (0x00) .....0.. "Output Normal"
728 * COMD[1] "Sensor precharge voltage selection"
729 * = 0 (0x00) ......0. "Selects internal
730 * reference precharge
731 * voltage"
732 * COMD[0] "Snapshot option"
733 * = 0 (0x00) .......0 "Enable live video output
734 * after snapshot sequence"
735 */
736 { 0x0c, 0x08 },
737
738 /*
739 * 0D COME "Common Control E"
740 * = 161 (0xA1) 10100001
741 * COME[7] "Output average option"
742 * = 1 (0x01) 1....... "Output average of 4 pixels"
743 * COME[6] "Anti-blooming control"
744 * = 0 (0x00) .0...... "Off"
745 * COME[5:3] "Reserved"
746 * = 4 (0x04) ..100...
747 * COME[2] "Clock output power down pin status"
748 * = 0 (0x00) .....0.. "Tri-state data output pin
749 * on power down"
750 * COME[1] "Data output pin status selection at power down"
751 * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK,
752 * HREF, and CHSYNC pins on
753 * power down"
754 * COME[0] "Auto zero circuit select"
755 * = 1 (0x01) .......1 "On"
756 */
757 { 0x0d, 0xa1 },
758
759 /*
760 * 0E COMF "Common Control F"
761 * = 112 (0x70) 01110000
762 * COMF[7] "System clock selection"
763 * = 0 (0x00) 0....... "Use 24 MHz system clock"
764 * COMF[6:4] "Reserved"
765 * = 7 (0x07) .111....
766 * COMF[3] "Manual auto negative offset canceling selection"
767 * = 0 (0x00) ....0... "Auto detect negative
768 * offset and cancel it"
769 * COMF[2:0] "Reserved"
770 * = 0 (0x00) .....000
771 */
772 { 0x0e, 0x70 },
773
774 /*
775 * 0F COMG "Common Control G"
776 * = 66 (0x42) 01000010
777 * COMG[7] "Optical black output selection"
778 * = 0 (0x00) 0....... "Disable"
779 * COMG[6] "Black level calibrate selection"
780 * = 1 (0x01) .1...... "Use optical black pixels
781 * to calibrate"
782 * COMG[5:4] "Reserved"
783 * = 0 (0x00) ..00....
784 * COMG[3] "Channel offset adjustment"
785 * = 0 (0x00) ....0... "Disable offset adjustment"
786 * COMG[2] "ADC black level calibration option"
787 * = 0 (0x00) .....0.. "Use B/G line and G/R
788 * line to calibrate each
789 * channel's black level"
790 * COMG[1] "Reserved"
791 * = 1 (0x01) ......1.
792 * COMG[0] "ADC black level calibration enable"
793 * = 0 (0x00) .......0 "Disable"
794 */
795 { 0x0f, 0x42 },
796
797 /*
798 * 14 COMJ "Common Control J"
799 * = 198 (0xC6) 11000110
800 * COMJ[7:6] "AGC gain ceiling"
801 * = 3 (0x03) 11...... "8x"
802 * COMJ[5:4] "Reserved"
803 * = 0 (0x00) ..00....
804 * COMJ[3] "Auto banding filter"
805 * = 0 (0x00) ....0... "Banding filter is always
806 * on off depending on
807 * COMI[5] setting"
808 * COMJ[2] "VSYNC drop option"
809 * = 1 (0x01) .....1.. "SYNC is dropped if frame
810 * data is dropped"
811 * COMJ[1] "Frame data drop"
812 * = 1 (0x01) ......1. "Drop frame data if
813 * exposure is not within
814 * tolerance. In AEC mode,
815 * data is normally dropped
816 * when data is out of
817 * range."
818 * COMJ[0] "Reserved"
819 * = 0 (0x00) .......0
820 */
821 { 0x14, 0xc6 },
822
823 /*
824 * 15 COMK "Common Control K"
825 * = 2 (0x02) 00000010
826 * COMK[7] "CHSYNC pin output swap"
827 * = 0 (0x00) 0....... "CHSYNC"
828 * COMK[6] "HREF pin output swap"
829 * = 0 (0x00) .0...... "HREF"
830 * COMK[5] "PCLK output selection"
831 * = 0 (0x00) ..0..... "PCLK always output"
832 * COMK[4] "PCLK edge selection"
833 * = 0 (0x00) ...0.... "Data valid on falling edge"
834 * COMK[3] "HREF output polarity"
835 * = 0 (0x00) ....0... "positive"
836 * COMK[2] "Reserved"
837 * = 0 (0x00) .....0..
838 * COMK[1] "VSYNC polarity"
839 * = 1 (0x01) ......1. "negative"
840 * COMK[0] "HSYNC polarity"
841 * = 0 (0x00) .......0 "positive"
842 */
843 { 0x15, 0x02 },
844
845 /*
846 * 33 CHLF "Current Control"
847 * = 9 (0x09) 00001001
848 * CHLF[7:6] "Sensor current control"
849 * = 0 (0x00) 00......
850 * CHLF[5] "Sensor current range control"
851 * = 0 (0x00) ..0..... "normal range"
852 * CHLF[4] "Sensor current"
853 * = 0 (0x00) ...0.... "normal current"
854 * CHLF[3] "Sensor buffer current control"
855 * = 1 (0x01) ....1... "half current"
856 * CHLF[2] "Column buffer current control"
857 * = 0 (0x00) .....0.. "normal current"
858 * CHLF[1] "Analog DSP current control"
859 * = 0 (0x00) ......0. "normal current"
860 * CHLF[1] "ADC current control"
861 * = 0 (0x00) ......0. "normal current"
862 */
863 { 0x33, 0x09 },
864
865 /*
866 * 34 VBLM "Blooming Control"
867 * = 80 (0x50) 01010000
868 * VBLM[7] "Hard soft reset switch"
869 * = 0 (0x00) 0....... "Hard reset"
870 * VBLM[6:4] "Blooming voltage selection"
871 * = 5 (0x05) .101....
872 * VBLM[3:0] "Sensor current control"
873 * = 0 (0x00) ....0000
874 */
875 { 0x34, 0x50 },
876
877 /*
878 * 36 VCHG "Sensor Precharge Voltage Control"
879 * = 0 (0x00) 00000000
880 * VCHG[7] "Reserved"
881 * = 0 (0x00) 0.......
882 * VCHG[6:4] "Sensor precharge voltage control"
883 * = 0 (0x00) .000....
884 * VCHG[3:0] "Sensor array common reference"
885 * = 0 (0x00) ....0000
886 */
887 { 0x36, 0x00 },
888
889 /*
890 * 37 ADC "ADC Reference Control"
891 * = 4 (0x04) 00000100
892 * ADC[7:4] "Reserved"
893 * = 0 (0x00) 0000....
894 * ADC[3] "ADC input signal range"
895 * = 0 (0x00) ....0... "Input signal 1.0x"
896 * ADC[2:0] "ADC range control"
897 * = 4 (0x04) .....100
898 */
899 { 0x37, 0x04 },
900
901 /*
902 * 38 ACOM "Analog Common Ground"
903 * = 82 (0x52) 01010010
904 * ACOM[7] "Analog gain control"
905 * = 0 (0x00) 0....... "Gain 1x"
906 * ACOM[6] "Analog black level calibration"
907 * = 1 (0x01) .1...... "On"
908 * ACOM[5:0] "Reserved"
909 * = 18 (0x12) ..010010
910 */
911 { 0x38, 0x52 },
912
913 /*
914 * 3A FREFA "Internal Reference Adjustment"
915 * = 0 (0x00) 00000000
916 * FREFA[7:0] "Range"
917 * = 0 (0x00) 00000000
918 */
919 { 0x3a, 0x00 },
920
921 /*
922 * 3C FVOPT "Internal Reference Adjustment"
923 * = 31 (0x1F) 00011111
924 * FVOPT[7:0] "Range"
925 * = 31 (0x1F) 00011111
926 */
927 { 0x3c, 0x1f },
928
929 /*
930 * 44 Undocumented = 0 (0x00) 00000000
931 * 44[7:0] "It's a secret"
932 * = 0 (0x00) 00000000
933 */
934 { 0x44, 0x00 },
935
936 /*
937 * 40 Undocumented = 0 (0x00) 00000000
938 * 40[7:0] "It's a secret"
939 * = 0 (0x00) 00000000
940 */
941 { 0x40, 0x00 },
942
943 /*
944 * 41 Undocumented = 0 (0x00) 00000000
945 * 41[7:0] "It's a secret"
946 * = 0 (0x00) 00000000
947 */
948 { 0x41, 0x00 },
949
950 /*
951 * 42 Undocumented = 0 (0x00) 00000000
952 * 42[7:0] "It's a secret"
953 * = 0 (0x00) 00000000
954 */
955 { 0x42, 0x00 },
956
957 /*
958 * 43 Undocumented = 0 (0x00) 00000000
959 * 43[7:0] "It's a secret"
960 * = 0 (0x00) 00000000
961 */
962 { 0x43, 0x00 },
963
964 /*
965 * 45 Undocumented = 128 (0x80) 10000000
966 * 45[7:0] "It's a secret"
967 * = 128 (0x80) 10000000
968 */
969 { 0x45, 0x80 },
970
971 /*
972 * 48 Undocumented = 192 (0xC0) 11000000
973 * 48[7:0] "It's a secret"
974 * = 192 (0xC0) 11000000
975 */
976 { 0x48, 0xc0 },
977
978 /*
979 * 49 Undocumented = 25 (0x19) 00011001
980 * 49[7:0] "It's a secret"
981 * = 25 (0x19) 00011001
982 */
983 { 0x49, 0x19 },
984
985 /*
986 * 4B Undocumented = 128 (0x80) 10000000
987 * 4B[7:0] "It's a secret"
988 * = 128 (0x80) 10000000
989 */
990 { 0x4b, 0x80 },
991
992 /*
993 * 4D Undocumented = 196 (0xC4) 11000100
994 * 4D[7:0] "It's a secret"
995 * = 196 (0xC4) 11000100
996 */
997 { 0x4d, 0xc4 },
998
999 /*
1000 * 35 VREF "Reference Voltage Control"
1001 * = 76 (0x4c) 01001100
1002 * VREF[7:5] "Column high reference control"
1003 * = 2 (0x02) 010..... "higher voltage"
1004 * VREF[4:2] "Column low reference control"
1005 * = 3 (0x03) ...011.. "Highest voltage"
1006 * VREF[1:0] "Reserved"
1007 * = 0 (0x00) ......00
1008 */
1009 { 0x35, 0x4c },
1010
1011 /*
1012 * 3D Undocumented = 0 (0x00) 00000000
1013 * 3D[7:0] "It's a secret"
1014 * = 0 (0x00) 00000000
1015 */
1016 { 0x3d, 0x00 },
1017
1018 /*
1019 * 3E Undocumented = 0 (0x00) 00000000
1020 * 3E[7:0] "It's a secret"
1021 * = 0 (0x00) 00000000
1022 */
1023 { 0x3e, 0x00 },
1024
1025 /*
1026 * 3B FREFB "Internal Reference Adjustment"
1027 * = 24 (0x18) 00011000
1028 * FREFB[7:0] "Range"
1029 * = 24 (0x18) 00011000
1030 */
1031 { 0x3b, 0x18 },
1032
1033 /*
1034 * 33 CHLF "Current Control"
1035 * = 25 (0x19) 00011001
1036 * CHLF[7:6] "Sensor current control"
1037 * = 0 (0x00) 00......
1038 * CHLF[5] "Sensor current range control"
1039 * = 0 (0x00) ..0..... "normal range"
1040 * CHLF[4] "Sensor current"
1041 * = 1 (0x01) ...1.... "double current"
1042 * CHLF[3] "Sensor buffer current control"
1043 * = 1 (0x01) ....1... "half current"
1044 * CHLF[2] "Column buffer current control"
1045 * = 0 (0x00) .....0.. "normal current"
1046 * CHLF[1] "Analog DSP current control"
1047 * = 0 (0x00) ......0. "normal current"
1048 * CHLF[1] "ADC current control"
1049 * = 0 (0x00) ......0. "normal current"
1050 */
1051 { 0x33, 0x19 },
1052
1053 /*
1054 * 34 VBLM "Blooming Control"
1055 * = 90 (0x5A) 01011010
1056 * VBLM[7] "Hard soft reset switch"
1057 * = 0 (0x00) 0....... "Hard reset"
1058 * VBLM[6:4] "Blooming voltage selection"
1059 * = 5 (0x05) .101....
1060 * VBLM[3:0] "Sensor current control"
1061 * = 10 (0x0A) ....1010
1062 */
1063 { 0x34, 0x5a },
1064
1065 /*
1066 * 3B FREFB "Internal Reference Adjustment"
1067 * = 0 (0x00) 00000000
1068 * FREFB[7:0] "Range"
1069 * = 0 (0x00) 00000000
1070 */
1071 { 0x3b, 0x00 },
1072
1073 /*
1074 * 33 CHLF "Current Control"
1075 * = 9 (0x09) 00001001
1076 * CHLF[7:6] "Sensor current control"
1077 * = 0 (0x00) 00......
1078 * CHLF[5] "Sensor current range control"
1079 * = 0 (0x00) ..0..... "normal range"
1080 * CHLF[4] "Sensor current"
1081 * = 0 (0x00) ...0.... "normal current"
1082 * CHLF[3] "Sensor buffer current control"
1083 * = 1 (0x01) ....1... "half current"
1084 * CHLF[2] "Column buffer current control"
1085 * = 0 (0x00) .....0.. "normal current"
1086 * CHLF[1] "Analog DSP current control"
1087 * = 0 (0x00) ......0. "normal current"
1088 * CHLF[1] "ADC current control"
1089 * = 0 (0x00) ......0. "normal current"
1090 */
1091 { 0x33, 0x09 },
1092
1093 /*
1094 * 34 VBLM "Blooming Control"
1095 * = 80 (0x50) 01010000
1096 * VBLM[7] "Hard soft reset switch"
1097 * = 0 (0x00) 0....... "Hard reset"
1098 * VBLM[6:4] "Blooming voltage selection"
1099 * = 5 (0x05) .101....
1100 * VBLM[3:0] "Sensor current control"
1101 * = 0 (0x00) ....0000
1102 */
1103 { 0x34, 0x50 },
1104
1105 /*
1106 * 12 COMH "Common Control H"
1107 * = 64 (0x40) 01000000
1108 * COMH[7] "SRST"
1109 * = 0 (0x00) 0....... "No-op"
1110 * COMH[6:4] "Resolution selection"
1111 * = 4 (0x04) .100.... "XGA"
1112 * COMH[3] "Master slave selection"
1113 * = 0 (0x00) ....0... "Master mode"
1114 * COMH[2] "Internal B/R channel option"
1115 * = 0 (0x00) .....0.. "B/R use same channel"
1116 * COMH[1] "Color bar test pattern"
1117 * = 0 (0x00) ......0. "Off"
1118 * COMH[0] "Reserved"
1119 * = 0 (0x00) .......0
1120 */
1121 { 0x12, 0x40 },
1122
1123 /*
1124 * 17 HREFST "Horizontal window start"
1125 * = 31 (0x1F) 00011111
1126 * HREFST[7:0] "Horizontal window start, 8 MSBs"
1127 * = 31 (0x1F) 00011111
1128 */
1129 { 0x17, 0x1f },
1130
1131 /*
1132 * 18 HREFEND "Horizontal window end"
1133 * = 95 (0x5F) 01011111
1134 * HREFEND[7:0] "Horizontal Window End, 8 MSBs"
1135 * = 95 (0x5F) 01011111
1136 */
1137 { 0x18, 0x5f },
1138
1139 /*
1140 * 19 VSTRT "Vertical window start"
1141 * = 0 (0x00) 00000000
1142 * VSTRT[7:0] "Vertical Window Start, 8 MSBs"
1143 * = 0 (0x00) 00000000
1144 */
1145 { 0x19, 0x00 },
1146
1147 /*
1148 * 1A VEND "Vertical window end"
1149 * = 96 (0x60) 01100000
1150 * VEND[7:0] "Vertical Window End, 8 MSBs"
1151 * = 96 (0x60) 01100000
1152 */
1153 { 0x1a, 0x60 },
1154
1155 /*
1156 * 32 COMM "Common Control M"
1157 * = 18 (0x12) 00010010
1158 * COMM[7:6] "Pixel clock divide option"
1159 * = 0 (0x00) 00...... "/1"
1160 * COMM[5:3] "Horizontal window end position, 3 LSBs"
1161 * = 2 (0x02) ..010...
1162 * COMM[2:0] "Horizontal window start position, 3 LSBs"
1163 * = 2 (0x02) .....010
1164 */
1165 { 0x32, 0x12 },
1166
1167 /*
1168 * 03 COMA "Common Control A"
1169 * = 74 (0x4A) 01001010
1170 * COMA[7:4] "AWB Update Threshold"
1171 * = 4 (0x04) 0100....
1172 * COMA[3:2] "Vertical window end line control 2 LSBs"
1173 * = 2 (0x02) ....10..
1174 * COMA[1:0] "Vertical window start line control 2 LSBs"
1175 * = 2 (0x02) ......10
1176 */
1177 { 0x03, 0x4a },
1178
1179 /*
1180 * 11 CLKRC "Clock Rate Control"
1181 * = 128 (0x80) 10000000
1182 * CLKRC[7] "Internal frequency doublers on off seclection"
1183 * = 1 (0x01) 1....... "On"
1184 * CLKRC[6] "Digital video master slave selection"
1185 * = 0 (0x00) .0...... "Master mode, sensor
1186 * provides PCLK"
1187 * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }"
1188 * = 0 (0x00) ..000000
1189 */
1190 { 0x11, 0x80 },
1191
1192 /*
1193 * 12 COMH "Common Control H"
1194 * = 0 (0x00) 00000000
1195 * COMH[7] "SRST"
1196 * = 0 (0x00) 0....... "No-op"
1197 * COMH[6:4] "Resolution selection"
1198 * = 0 (0x00) .000.... "QXGA"
1199 * COMH[3] "Master slave selection"
1200 * = 0 (0x00) ....0... "Master mode"
1201 * COMH[2] "Internal B/R channel option"
1202 * = 0 (0x00) .....0.. "B/R use same channel"
1203 * COMH[1] "Color bar test pattern"
1204 * = 0 (0x00) ......0. "Off"
1205 * COMH[0] "Reserved"
1206 * = 0 (0x00) .......0
1207 */
1208 { 0x12, 0x00 },
1209
1210 /*
1211 * 12 COMH "Common Control H"
1212 * = 64 (0x40) 01000000
1213 * COMH[7] "SRST"
1214 * = 0 (0x00) 0....... "No-op"
1215 * COMH[6:4] "Resolution selection"
1216 * = 4 (0x04) .100.... "XGA"
1217 * COMH[3] "Master slave selection"
1218 * = 0 (0x00) ....0... "Master mode"
1219 * COMH[2] "Internal B/R channel option"
1220 * = 0 (0x00) .....0.. "B/R use same channel"
1221 * COMH[1] "Color bar test pattern"
1222 * = 0 (0x00) ......0. "Off"
1223 * COMH[0] "Reserved"
1224 * = 0 (0x00) .......0
1225 */
1226 { 0x12, 0x40 },
1227
1228 /*
1229 * 17 HREFST "Horizontal window start"
1230 * = 31 (0x1F) 00011111
1231 * HREFST[7:0] "Horizontal window start, 8 MSBs"
1232 * = 31 (0x1F) 00011111
1233 */
1234 { 0x17, 0x1f },
1235
1236 /*
1237 * 18 HREFEND "Horizontal window end"
1238 * = 95 (0x5F) 01011111
1239 * HREFEND[7:0] "Horizontal Window End, 8 MSBs"
1240 * = 95 (0x5F) 01011111
1241 */
1242 { 0x18, 0x5f },
1243
1244 /*
1245 * 19 VSTRT "Vertical window start"
1246 * = 0 (0x00) 00000000
1247 * VSTRT[7:0] "Vertical Window Start, 8 MSBs"
1248 * = 0 (0x00) 00000000
1249 */
1250 { 0x19, 0x00 },
1251
1252 /*
1253 * 1A VEND "Vertical window end"
1254 * = 96 (0x60) 01100000
1255 * VEND[7:0] "Vertical Window End, 8 MSBs"
1256 * = 96 (0x60) 01100000
1257 */
1258 { 0x1a, 0x60 },
1259
1260 /*
1261 * 32 COMM "Common Control M"
1262 * = 18 (0x12) 00010010
1263 * COMM[7:6] "Pixel clock divide option"
1264 * = 0 (0x00) 00...... "/1"
1265 * COMM[5:3] "Horizontal window end position, 3 LSBs"
1266 * = 2 (0x02) ..010...
1267 * COMM[2:0] "Horizontal window start position, 3 LSBs"
1268 * = 2 (0x02) .....010
1269 */
1270 { 0x32, 0x12 },
1271
1272 /*
1273 * 03 COMA "Common Control A"
1274 * = 74 (0x4A) 01001010
1275 * COMA[7:4] "AWB Update Threshold"
1276 * = 4 (0x04) 0100....
1277 * COMA[3:2] "Vertical window end line control 2 LSBs"
1278 * = 2 (0x02) ....10..
1279 * COMA[1:0] "Vertical window start line control 2 LSBs"
1280 * = 2 (0x02) ......10
1281 */
1282 { 0x03, 0x4a },
1283
1284 /*
1285 * 02 RED "Red Gain Control"
1286 * = 175 (0xAF) 10101111
1287 * RED[7] "Action"
1288 * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
1289 * RED[6:0] "Value"
1290 * = 47 (0x2F) .0101111
1291 */
1292 { 0x02, 0xaf },
1293
1294 /*
1295 * 2D ADDVSL "VSYNC Pulse Width"
1296 * = 210 (0xD2) 11010010
1297 * ADDVSL[7:0] "VSYNC pulse width, LSB"
1298 * = 210 (0xD2) 11010010
1299 */
1300 { 0x2d, 0xd2 },
1301
1302 /*
1303 * 00 GAIN = 24 (0x18) 00011000
1304 * GAIN[7:6] "Reserved"
1305 * = 0 (0x00) 00......
1306 * GAIN[5] "Double"
1307 * = 0 (0x00) ..0..... "False"
1308 * GAIN[4] "Double"
1309 * = 1 (0x01) ...1.... "True"
1310 * GAIN[3:0] "Range"
1311 * = 8 (0x08) ....1000
1312 */
1313 { 0x00, 0x18 },
1314
1315 /*
1316 * 01 BLUE "Blue Gain Control"
1317 * = 240 (0xF0) 11110000
1318 * BLUE[7] "Action"
1319 * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
1320 * BLUE[6:0] "Value"
1321 * = 112 (0x70) .1110000
1322 */
1323 { 0x01, 0xf0 },
1324
1325 /*
1326 * 10 AEC "Automatic Exposure Control"
1327 * = 10 (0x0A) 00001010
1328 * AEC[7:0] "Automatic Exposure Control, 8 MSBs"
1329 * = 10 (0x0A) 00001010
1330 */
1331 { 0x10, 0x0a },
1332
1333 { 0xe1, 0x67 },
1334 { 0xe3, 0x03 },
1335 { 0xe4, 0x26 },
1336 { 0xe5, 0x3e },
1337 { 0xf8, 0x01 },
1338 { 0xff, 0x01 },
1339};
1340
1341static const struct ov_i2c_regvals norm_6x20[] = {
1342 { 0x12, 0x80 }, /* reset */
1343 { 0x11, 0x01 },
1344 { 0x03, 0x60 },
1345 { 0x05, 0x7f }, /* For when autoadjust is off */
1346 { 0x07, 0xa8 },
1347 /* The ratio of 0x0c and 0x0d controls the white point */
1348 { 0x0c, 0x24 },
1349 { 0x0d, 0x24 },
1350 { 0x0f, 0x15 }, /* COMS */
1351 { 0x10, 0x75 }, /* AEC Exposure time */
1352 { 0x12, 0x24 }, /* Enable AGC */
1353 { 0x14, 0x04 },
1354 /* 0x16: 0x06 helps frame stability with moving objects */
1355 { 0x16, 0x06 },
1356/* { 0x20, 0x30 }, * Aperture correction enable */
1357 { 0x26, 0xb2 }, /* BLC enable */
1358 /* 0x28: 0x05 Selects RGB format if RGB on */
1359 { 0x28, 0x05 },
1360 { 0x2a, 0x04 }, /* Disable framerate adjust */
1361/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
1362 { 0x2d, 0x85 },
1363 { 0x33, 0xa0 }, /* Color Processing Parameter */
1364 { 0x34, 0xd2 }, /* Max A/D range */
1365 { 0x38, 0x8b },
1366 { 0x39, 0x40 },
1367
1368 { 0x3c, 0x39 }, /* Enable AEC mode changing */
1369 { 0x3c, 0x3c }, /* Change AEC mode */
1370 { 0x3c, 0x24 }, /* Disable AEC mode changing */
1371
1372 { 0x3d, 0x80 },
1373 /* These next two registers (0x4a, 0x4b) are undocumented.
1374 * They control the color balance */
1375 { 0x4a, 0x80 },
1376 { 0x4b, 0x80 },
1377 { 0x4d, 0xd2 }, /* This reduces noise a bit */
1378 { 0x4e, 0xc1 },
1379 { 0x4f, 0x04 },
1380/* Do 50-53 have any effect? */
1381/* Toggle 0x12[2] off and on here? */
1382};
1383
1384static const struct ov_i2c_regvals norm_6x30[] = {
1385 { 0x12, 0x80 }, /* Reset */
1386 { 0x00, 0x1f }, /* Gain */
1387 { 0x01, 0x99 }, /* Blue gain */
1388 { 0x02, 0x7c }, /* Red gain */
1389 { 0x03, 0xc0 }, /* Saturation */
1390 { 0x05, 0x0a }, /* Contrast */
1391 { 0x06, 0x95 }, /* Brightness */
1392 { 0x07, 0x2d }, /* Sharpness */
1393 { 0x0c, 0x20 },
1394 { 0x0d, 0x20 },
1395 { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
1396 { 0x0f, 0x05 },
1397 { 0x10, 0x9a },
1398 { 0x11, 0x00 }, /* Pixel clock = fastest */
1399 { 0x12, 0x24 }, /* Enable AGC and AWB */
1400 { 0x13, 0x21 },
1401 { 0x14, 0x80 },
1402 { 0x15, 0x01 },
1403 { 0x16, 0x03 },
1404 { 0x17, 0x38 },
1405 { 0x18, 0xea },
1406 { 0x19, 0x04 },
1407 { 0x1a, 0x93 },
1408 { 0x1b, 0x00 },
1409 { 0x1e, 0xc4 },
1410 { 0x1f, 0x04 },
1411 { 0x20, 0x20 },
1412 { 0x21, 0x10 },
1413 { 0x22, 0x88 },
1414 { 0x23, 0xc0 }, /* Crystal circuit power level */
1415 { 0x25, 0x9a }, /* Increase AEC black ratio */
1416 { 0x26, 0xb2 }, /* BLC enable */
1417 { 0x27, 0xa2 },
1418 { 0x28, 0x00 },
1419 { 0x29, 0x00 },
1420 { 0x2a, 0x84 }, /* 60 Hz power */
1421 { 0x2b, 0xa8 }, /* 60 Hz power */
1422 { 0x2c, 0xa0 },
1423 { 0x2d, 0x95 }, /* Enable auto-brightness */
1424 { 0x2e, 0x88 },
1425 { 0x33, 0x26 },
1426 { 0x34, 0x03 },
1427 { 0x36, 0x8f },
1428 { 0x37, 0x80 },
1429 { 0x38, 0x83 },
1430 { 0x39, 0x80 },
1431 { 0x3a, 0x0f },
1432 { 0x3b, 0x3c },
1433 { 0x3c, 0x1a },
1434 { 0x3d, 0x80 },
1435 { 0x3e, 0x80 },
1436 { 0x3f, 0x0e },
1437 { 0x40, 0x00 }, /* White bal */
1438 { 0x41, 0x00 }, /* White bal */
1439 { 0x42, 0x80 },
1440 { 0x43, 0x3f }, /* White bal */
1441 { 0x44, 0x80 },
1442 { 0x45, 0x20 },
1443 { 0x46, 0x20 },
1444 { 0x47, 0x80 },
1445 { 0x48, 0x7f },
1446 { 0x49, 0x00 },
1447 { 0x4a, 0x00 },
1448 { 0x4b, 0x80 },
1449 { 0x4c, 0xd0 },
1450 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
1451 { 0x4e, 0x40 },
1452 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
1453 { 0x50, 0xff },
1454 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
1455 { 0x55, 0xff },
1456 { 0x56, 0x12 },
1457 { 0x57, 0x81 },
1458 { 0x58, 0x75 },
1459 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
1460 { 0x5a, 0x2c },
1461 { 0x5b, 0x0f }, /* AWB chrominance levels */
1462 { 0x5c, 0x10 },
1463 { 0x3d, 0x80 },
1464 { 0x27, 0xa6 },
1465 { 0x12, 0x20 }, /* Toggle AWB */
1466 { 0x12, 0x24 },
1467};
1468
1469/* Lawrence Glaister <lg@jfm.bc.ca> reports:
1470 *
1471 * Register 0x0f in the 7610 has the following effects:
1472 *
1473 * 0x85 (AEC method 1): Best overall, good contrast range
1474 * 0x45 (AEC method 2): Very overexposed
1475 * 0xa5 (spec sheet default): Ok, but the black level is
1476 * shifted resulting in loss of contrast
1477 * 0x05 (old driver setting): very overexposed, too much
1478 * contrast
1479 */
1480static const struct ov_i2c_regvals norm_7610[] = {
1481 { 0x10, 0xff },
1482 { 0x16, 0x06 },
1483 { 0x28, 0x24 },
1484 { 0x2b, 0xac },
1485 { 0x12, 0x00 },
1486 { 0x38, 0x81 },
1487 { 0x28, 0x24 }, /* 0c */
1488 { 0x0f, 0x85 }, /* lg's setting */
1489 { 0x15, 0x01 },
1490 { 0x20, 0x1c },
1491 { 0x23, 0x2a },
1492 { 0x24, 0x10 },
1493 { 0x25, 0x8a },
1494 { 0x26, 0xa2 },
1495 { 0x27, 0xc2 },
1496 { 0x2a, 0x04 },
1497 { 0x2c, 0xfe },
1498 { 0x2d, 0x93 },
1499 { 0x30, 0x71 },
1500 { 0x31, 0x60 },
1501 { 0x32, 0x26 },
1502 { 0x33, 0x20 },
1503 { 0x34, 0x48 },
1504 { 0x12, 0x24 },
1505 { 0x11, 0x01 },
1506 { 0x0c, 0x24 },
1507 { 0x0d, 0x24 },
1508};
1509
1510static const struct ov_i2c_regvals norm_7620[] = {
1511 { 0x12, 0x80 }, /* reset */
1512 { 0x00, 0x00 }, /* gain */
1513 { 0x01, 0x80 }, /* blue gain */
1514 { 0x02, 0x80 }, /* red gain */
1515 { 0x03, 0xc0 }, /* OV7670_R03_VREF */
1516 { 0x06, 0x60 },
1517 { 0x07, 0x00 },
1518 { 0x0c, 0x24 },
1519 { 0x0c, 0x24 },
1520 { 0x0d, 0x24 },
1521 { 0x11, 0x01 },
1522 { 0x12, 0x24 },
1523 { 0x13, 0x01 },
1524 { 0x14, 0x84 },
1525 { 0x15, 0x01 },
1526 { 0x16, 0x03 },
1527 { 0x17, 0x2f },
1528 { 0x18, 0xcf },
1529 { 0x19, 0x06 },
1530 { 0x1a, 0xf5 },
1531 { 0x1b, 0x00 },
1532 { 0x20, 0x18 },
1533 { 0x21, 0x80 },
1534 { 0x22, 0x80 },
1535 { 0x23, 0x00 },
1536 { 0x26, 0xa2 },
1537 { 0x27, 0xea },
1538 { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
1539 { 0x29, 0x00 },
1540 { 0x2a, 0x10 },
1541 { 0x2b, 0x00 },
1542 { 0x2c, 0x88 },
1543 { 0x2d, 0x91 },
1544 { 0x2e, 0x80 },
1545 { 0x2f, 0x44 },
1546 { 0x60, 0x27 },
1547 { 0x61, 0x02 },
1548 { 0x62, 0x5f },
1549 { 0x63, 0xd5 },
1550 { 0x64, 0x57 },
1551 { 0x65, 0x83 },
1552 { 0x66, 0x55 },
1553 { 0x67, 0x92 },
1554 { 0x68, 0xcf },
1555 { 0x69, 0x76 },
1556 { 0x6a, 0x22 },
1557 { 0x6b, 0x00 },
1558 { 0x6c, 0x02 },
1559 { 0x6d, 0x44 },
1560 { 0x6e, 0x80 },
1561 { 0x6f, 0x1d },
1562 { 0x70, 0x8b },
1563 { 0x71, 0x00 },
1564 { 0x72, 0x14 },
1565 { 0x73, 0x54 },
1566 { 0x74, 0x00 },
1567 { 0x75, 0x8e },
1568 { 0x76, 0x00 },
1569 { 0x77, 0xff },
1570 { 0x78, 0x80 },
1571 { 0x79, 0x80 },
1572 { 0x7a, 0x80 },
1573 { 0x7b, 0xe2 },
1574 { 0x7c, 0x00 },
1575};
1576
1577/* 7640 and 7648. The defaults should be OK for most registers. */
1578static const struct ov_i2c_regvals norm_7640[] = {
1579 { 0x12, 0x80 },
1580 { 0x12, 0x14 },
1581};
1582
1583static const struct ov_regvals init_519_ov7660[] = {
1584 { 0x5d, 0x03 }, /* Turn off suspend mode */
1585 { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */
1586 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
1587 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
1588 { 0xa3, 0x18 },
1589 { 0xa4, 0x04 },
1590 { 0xa5, 0x28 },
1591 { 0x37, 0x00 }, /* SetUsbInit */
1592 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
1593 /* Enable both fields, YUV Input, disable defect comp (why?) */
1594 { 0x20, 0x0c }, /* 0x0d does U <-> V swap */
1595 { 0x21, 0x38 },
1596 { 0x22, 0x1d },
1597 { 0x17, 0x50 }, /* undocumented */
1598 { 0x37, 0x00 }, /* undocumented */
1599 { 0x40, 0xff }, /* I2C timeout counter */
1600 { 0x46, 0x00 }, /* I2C clock prescaler */
1601};
1602static const struct ov_i2c_regvals norm_7660[] = {
1603 {OV7670_R12_COM7, OV7670_COM7_RESET},
1604 {OV7670_R11_CLKRC, 0x81},
1605 {0x92, 0x00}, /* DM_LNL */
1606 {0x93, 0x00}, /* DM_LNH */
1607 {0x9d, 0x4c}, /* BD50ST */
1608 {0x9e, 0x3f}, /* BD60ST */
1609 {OV7670_R3B_COM11, 0x02},
1610 {OV7670_R13_COM8, 0xf5},
1611 {OV7670_R10_AECH, 0x00},
1612 {OV7670_R00_GAIN, 0x00},
1613 {OV7670_R01_BLUE, 0x7c},
1614 {OV7670_R02_RED, 0x9d},
1615 {OV7670_R12_COM7, 0x00},
1616 {OV7670_R04_COM1, 00},
1617 {OV7670_R18_HSTOP, 0x01},
1618 {OV7670_R17_HSTART, 0x13},
1619 {OV7670_R32_HREF, 0x92},
1620 {OV7670_R19_VSTART, 0x02},
1621 {OV7670_R1A_VSTOP, 0x7a},
1622 {OV7670_R03_VREF, 0x00},
1623 {OV7670_R0E_COM5, 0x04},
1624 {OV7670_R0F_COM6, 0x62},
1625 {OV7670_R15_COM10, 0x00},
1626 {0x16, 0x02}, /* RSVD */
1627 {0x1b, 0x00}, /* PSHFT */
1628 {OV7670_R1E_MVFP, 0x01},
1629 {0x29, 0x3c}, /* RSVD */
1630 {0x33, 0x00}, /* CHLF */
1631 {0x34, 0x07}, /* ARBLM */
1632 {0x35, 0x84}, /* RSVD */
1633 {0x36, 0x00}, /* RSVD */
1634 {0x37, 0x04}, /* ADC */
1635 {0x39, 0x43}, /* OFON */
1636 {OV7670_R3A_TSLB, 0x00},
1637 {OV7670_R3C_COM12, 0x6c},
1638 {OV7670_R3D_COM13, 0x98},
1639 {OV7670_R3F_EDGE, 0x23},
1640 {OV7670_R40_COM15, 0xc1},
1641 {OV7670_R41_COM16, 0x22},
1642 {0x6b, 0x0a}, /* DBLV */
1643 {0xa1, 0x08}, /* RSVD */
1644 {0x69, 0x80}, /* HV */
1645 {0x43, 0xf0}, /* RSVD.. */
1646 {0x44, 0x10},
1647 {0x45, 0x78},
1648 {0x46, 0xa8},
1649 {0x47, 0x60},
1650 {0x48, 0x80},
1651 {0x59, 0xba},
1652 {0x5a, 0x9a},
1653 {0x5b, 0x22},
1654 {0x5c, 0xb9},
1655 {0x5d, 0x9b},
1656 {0x5e, 0x10},
1657 {0x5f, 0xe0},
1658 {0x60, 0x85},
1659 {0x61, 0x60},
1660 {0x9f, 0x9d}, /* RSVD */
1661 {0xa0, 0xa0}, /* DSPC2 */
1662 {0x4f, 0x60}, /* matrix */
1663 {0x50, 0x64},
1664 {0x51, 0x04},
1665 {0x52, 0x18},
1666 {0x53, 0x3c},
1667 {0x54, 0x54},
1668 {0x55, 0x40},
1669 {0x56, 0x40},
1670 {0x57, 0x40},
1671 {0x58, 0x0d}, /* matrix sign */
1672 {0x8b, 0xcc}, /* RSVD */
1673 {0x8c, 0xcc},
1674 {0x8d, 0xcf},
1675 {0x6c, 0x40}, /* gamma curve */
1676 {0x6d, 0xe0},
1677 {0x6e, 0xa0},
1678 {0x6f, 0x80},
1679 {0x70, 0x70},
1680 {0x71, 0x80},
1681 {0x72, 0x60},
1682 {0x73, 0x60},
1683 {0x74, 0x50},
1684 {0x75, 0x40},
1685 {0x76, 0x38},
1686 {0x77, 0x3c},
1687 {0x78, 0x32},
1688 {0x79, 0x1a},
1689 {0x7a, 0x28},
1690 {0x7b, 0x24},
1691 {0x7c, 0x04}, /* gamma curve */
1692 {0x7d, 0x12},
1693 {0x7e, 0x26},
1694 {0x7f, 0x46},
1695 {0x80, 0x54},
1696 {0x81, 0x64},
1697 {0x82, 0x70},
1698 {0x83, 0x7c},
1699 {0x84, 0x86},
1700 {0x85, 0x8e},
1701 {0x86, 0x9c},
1702 {0x87, 0xab},
1703 {0x88, 0xc4},
1704 {0x89, 0xd1},
1705 {0x8a, 0xe5},
1706 {OV7670_R14_COM9, 0x1e},
1707 {OV7670_R24_AEW, 0x80},
1708 {OV7670_R25_AEB, 0x72},
1709 {OV7670_R26_VPT, 0xb3},
1710 {0x62, 0x80}, /* LCC1 */
1711 {0x63, 0x80}, /* LCC2 */
1712 {0x64, 0x06}, /* LCC3 */
1713 {0x65, 0x00}, /* LCC4 */
1714 {0x66, 0x01}, /* LCC5 */
1715 {0x94, 0x0e}, /* RSVD.. */
1716 {0x95, 0x14},
1717 {OV7670_R13_COM8, OV7670_COM8_FASTAEC
1718 | OV7670_COM8_AECSTEP
1719 | OV7670_COM8_BFILT
1720 | 0x10
1721 | OV7670_COM8_AGC
1722 | OV7670_COM8_AWB
1723 | OV7670_COM8_AEC},
1724 {0xa1, 0xc8}
1725};
1726static const struct ov_i2c_regvals norm_9600[] = {
1727 {0x12, 0x80},
1728 {0x0c, 0x28},
1729 {0x11, 0x80},
1730 {0x13, 0xb5},
1731 {0x14, 0x3e},
1732 {0x1b, 0x04},
1733 {0x24, 0xb0},
1734 {0x25, 0x90},
1735 {0x26, 0x94},
1736 {0x35, 0x90},
1737 {0x37, 0x07},
1738 {0x38, 0x08},
1739 {0x01, 0x8e},
1740 {0x02, 0x85}
1741};
1742
1743/* 7670. Defaults taken from OmniVision provided data,
1744* as provided by Jonathan Corbet of OLPC */
1745static const struct ov_i2c_regvals norm_7670[] = {
1746 { OV7670_R12_COM7, OV7670_COM7_RESET },
1747 { OV7670_R3A_TSLB, 0x04 }, /* OV */
1748 { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
1749 { OV7670_R11_CLKRC, 0x01 },
1750/*
1751 * Set the hardware window. These values from OV don't entirely
1752 * make sense - hstop is less than hstart. But they work...
1753 */
1754 { OV7670_R17_HSTART, 0x13 },
1755 { OV7670_R18_HSTOP, 0x01 },
1756 { OV7670_R32_HREF, 0xb6 },
1757 { OV7670_R19_VSTART, 0x02 },
1758 { OV7670_R1A_VSTOP, 0x7a },
1759 { OV7670_R03_VREF, 0x0a },
1760
1761 { OV7670_R0C_COM3, 0x00 },
1762 { OV7670_R3E_COM14, 0x00 },
1763/* Mystery scaling numbers */
1764 { 0x70, 0x3a },
1765 { 0x71, 0x35 },
1766 { 0x72, 0x11 },
1767 { 0x73, 0xf0 },
1768 { 0xa2, 0x02 },
1769/* { OV7670_R15_COM10, 0x0 }, */
1770
1771/* Gamma curve values */
1772 { 0x7a, 0x20 },
1773 { 0x7b, 0x10 },
1774 { 0x7c, 0x1e },
1775 { 0x7d, 0x35 },
1776 { 0x7e, 0x5a },
1777 { 0x7f, 0x69 },
1778 { 0x80, 0x76 },
1779 { 0x81, 0x80 },
1780 { 0x82, 0x88 },
1781 { 0x83, 0x8f },
1782 { 0x84, 0x96 },
1783 { 0x85, 0xa3 },
1784 { 0x86, 0xaf },
1785 { 0x87, 0xc4 },
1786 { 0x88, 0xd7 },
1787 { 0x89, 0xe8 },
1788
1789/* AGC and AEC parameters. Note we start by disabling those features,
1790 then turn them only after tweaking the values. */
1791 { OV7670_R13_COM8, OV7670_COM8_FASTAEC
1792 | OV7670_COM8_AECSTEP
1793 | OV7670_COM8_BFILT },
1794 { OV7670_R00_GAIN, 0x00 },
1795 { OV7670_R10_AECH, 0x00 },
1796 { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
1797 { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
1798 { OV7670_RA5_BD50MAX, 0x05 },
1799 { OV7670_RAB_BD60MAX, 0x07 },
1800 { OV7670_R24_AEW, 0x95 },
1801 { OV7670_R25_AEB, 0x33 },
1802 { OV7670_R26_VPT, 0xe3 },
1803 { OV7670_R9F_HAECC1, 0x78 },
1804 { OV7670_RA0_HAECC2, 0x68 },
1805 { 0xa1, 0x03 }, /* magic */
1806 { OV7670_RA6_HAECC3, 0xd8 },
1807 { OV7670_RA7_HAECC4, 0xd8 },
1808 { OV7670_RA8_HAECC5, 0xf0 },
1809 { OV7670_RA9_HAECC6, 0x90 },
1810 { OV7670_RAA_HAECC7, 0x94 },
1811 { OV7670_R13_COM8, OV7670_COM8_FASTAEC
1812 | OV7670_COM8_AECSTEP
1813 | OV7670_COM8_BFILT
1814 | OV7670_COM8_AGC
1815 | OV7670_COM8_AEC },
1816
1817/* Almost all of these are magic "reserved" values. */
1818 { OV7670_R0E_COM5, 0x61 },
1819 { OV7670_R0F_COM6, 0x4b },
1820 { 0x16, 0x02 },
1821 { OV7670_R1E_MVFP, 0x07 },
1822 { 0x21, 0x02 },
1823 { 0x22, 0x91 },
1824 { 0x29, 0x07 },
1825 { 0x33, 0x0b },
1826 { 0x35, 0x0b },
1827 { 0x37, 0x1d },
1828 { 0x38, 0x71 },
1829 { 0x39, 0x2a },
1830 { OV7670_R3C_COM12, 0x78 },
1831 { 0x4d, 0x40 },
1832 { 0x4e, 0x20 },
1833 { OV7670_R69_GFIX, 0x00 },
1834 { 0x6b, 0x4a },
1835 { 0x74, 0x10 },
1836 { 0x8d, 0x4f },
1837 { 0x8e, 0x00 },
1838 { 0x8f, 0x00 },
1839 { 0x90, 0x00 },
1840 { 0x91, 0x00 },
1841 { 0x96, 0x00 },
1842 { 0x9a, 0x00 },
1843 { 0xb0, 0x84 },
1844 { 0xb1, 0x0c },
1845 { 0xb2, 0x0e },
1846 { 0xb3, 0x82 },
1847 { 0xb8, 0x0a },
1848
1849/* More reserved magic, some of which tweaks white balance */
1850 { 0x43, 0x0a },
1851 { 0x44, 0xf0 },
1852 { 0x45, 0x34 },
1853 { 0x46, 0x58 },
1854 { 0x47, 0x28 },
1855 { 0x48, 0x3a },
1856 { 0x59, 0x88 },
1857 { 0x5a, 0x88 },
1858 { 0x5b, 0x44 },
1859 { 0x5c, 0x67 },
1860 { 0x5d, 0x49 },
1861 { 0x5e, 0x0e },
1862 { 0x6c, 0x0a },
1863 { 0x6d, 0x55 },
1864 { 0x6e, 0x11 },
1865 { 0x6f, 0x9f }, /* "9e for advance AWB" */
1866 { 0x6a, 0x40 },
1867 { OV7670_R01_BLUE, 0x40 },
1868 { OV7670_R02_RED, 0x60 },
1869 { OV7670_R13_COM8, OV7670_COM8_FASTAEC
1870 | OV7670_COM8_AECSTEP
1871 | OV7670_COM8_BFILT
1872 | OV7670_COM8_AGC
1873 | OV7670_COM8_AEC
1874 | OV7670_COM8_AWB },
1875
1876/* Matrix coefficients */
1877 { 0x4f, 0x80 },
1878 { 0x50, 0x80 },
1879 { 0x51, 0x00 },
1880 { 0x52, 0x22 },
1881 { 0x53, 0x5e },
1882 { 0x54, 0x80 },
1883 { 0x58, 0x9e },
1884
1885 { OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
1886 { OV7670_R3F_EDGE, 0x00 },
1887 { 0x75, 0x05 },
1888 { 0x76, 0xe1 },
1889 { 0x4c, 0x00 },
1890 { 0x77, 0x01 },
1891 { OV7670_R3D_COM13, OV7670_COM13_GAMMA
1892 | OV7670_COM13_UVSAT
1893 | 2}, /* was 3 */
1894 { 0x4b, 0x09 },
1895 { 0xc9, 0x60 },
1896 { OV7670_R41_COM16, 0x38 },
1897 { 0x56, 0x40 },
1898
1899 { 0x34, 0x11 },
1900 { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
1901 { 0xa4, 0x88 },
1902 { 0x96, 0x00 },
1903 { 0x97, 0x30 },
1904 { 0x98, 0x20 },
1905 { 0x99, 0x30 },
1906 { 0x9a, 0x84 },
1907 { 0x9b, 0x29 },
1908 { 0x9c, 0x03 },
1909 { 0x9d, 0x4c },
1910 { 0x9e, 0x3f },
1911 { 0x78, 0x04 },
1912
1913/* Extra-weird stuff. Some sort of multiplexor register */
1914 { 0x79, 0x01 },
1915 { 0xc8, 0xf0 },
1916 { 0x79, 0x0f },
1917 { 0xc8, 0x00 },
1918 { 0x79, 0x10 },
1919 { 0xc8, 0x7e },
1920 { 0x79, 0x0a },
1921 { 0xc8, 0x80 },
1922 { 0x79, 0x0b },
1923 { 0xc8, 0x01 },
1924 { 0x79, 0x0c },
1925 { 0xc8, 0x0f },
1926 { 0x79, 0x0d },
1927 { 0xc8, 0x20 },
1928 { 0x79, 0x09 },
1929 { 0xc8, 0x80 },
1930 { 0x79, 0x02 },
1931 { 0xc8, 0xc0 },
1932 { 0x79, 0x03 },
1933 { 0xc8, 0x40 },
1934 { 0x79, 0x05 },
1935 { 0xc8, 0x30 },
1936 { 0x79, 0x26 },
1937};
1938
1939static const struct ov_i2c_regvals norm_8610[] = {
1940 { 0x12, 0x80 },
1941 { 0x00, 0x00 },
1942 { 0x01, 0x80 },
1943 { 0x02, 0x80 },
1944 { 0x03, 0xc0 },
1945 { 0x04, 0x30 },
1946 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
1947 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
1948 { 0x0a, 0x86 },
1949 { 0x0b, 0xb0 },
1950 { 0x0c, 0x20 },
1951 { 0x0d, 0x20 },
1952 { 0x11, 0x01 },
1953 { 0x12, 0x25 },
1954 { 0x13, 0x01 },
1955 { 0x14, 0x04 },
1956 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
1957 { 0x16, 0x03 },
1958 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
1959 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
1960 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
1961 { 0x1a, 0xf5 },
1962 { 0x1b, 0x00 },
1963 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
1964 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
1965 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
1966 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
1967 { 0x26, 0xa2 },
1968 { 0x27, 0xea },
1969 { 0x28, 0x00 },
1970 { 0x29, 0x00 },
1971 { 0x2a, 0x80 },
1972 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
1973 { 0x2c, 0xac },
1974 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
1975 { 0x2e, 0x80 },
1976 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
1977 { 0x4c, 0x00 },
1978 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
1979 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
1980 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
1981 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
1982 { 0x63, 0xff },
1983 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
1984 * maybe thats wrong */
1985 { 0x65, 0x00 },
1986 { 0x66, 0x55 },
1987 { 0x67, 0xb0 },
1988 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
1989 { 0x69, 0x02 },
1990 { 0x6a, 0x22 },
1991 { 0x6b, 0x00 },
1992 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
1993 * deleting bit7 colors the first images red */
1994 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
1995 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
1996 { 0x6f, 0x01 },
1997 { 0x70, 0x8b },
1998 { 0x71, 0x00 },
1999 { 0x72, 0x14 },
2000 { 0x73, 0x54 },
2001 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
2002 { 0x75, 0x0e },
2003 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
2004 { 0x77, 0xff },
2005 { 0x78, 0x80 },
2006 { 0x79, 0x80 },
2007 { 0x7a, 0x80 },
2008 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
2009 { 0x7c, 0x00 },
2010 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
2011 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
2012 { 0x7f, 0xfb },
2013 { 0x80, 0x28 },
2014 { 0x81, 0x00 },
2015 { 0x82, 0x23 },
2016 { 0x83, 0x0b },
2017 { 0x84, 0x00 },
2018 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
2019 { 0x86, 0xc9 },
2020 { 0x87, 0x00 },
2021 { 0x88, 0x00 },
2022 { 0x89, 0x01 },
2023 { 0x12, 0x20 },
2024 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
2025};
2026
2027static unsigned char ov7670_abs_to_sm(unsigned char v)
2028{
2029 if (v > 127)
2030 return v & 0x7f;
2031 return (128 - v) | 0x80;
2032}
2033
2034/* Write a OV519 register */
2035static void reg_w(struct sd *sd, u16 index, u16 value)
2036{
2037 int ret, req = 0;
2038
2039 if (sd->gspca_dev.usb_err < 0)
2040 return;
2041
2042 switch (sd->bridge) {
2043 case BRIDGE_OV511:
2044 case BRIDGE_OV511PLUS:
2045 req = 2;
2046 break;
2047 case BRIDGE_OVFX2:
2048 req = 0x0a;
2049 /* fall through */
2050 case BRIDGE_W9968CF:
2051 PDEBUG(D_USBO, "SET %02x %04x %04x",
2052 req, value, index);
2053 ret = usb_control_msg(sd->gspca_dev.dev,
2054 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2055 req,
2056 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2057 value, index, NULL, 0, 500);
2058 goto leave;
2059 default:
2060 req = 1;
2061 }
2062
2063 PDEBUG(D_USBO, "SET %02x 0000 %04x %02x",
2064 req, index, value);
2065 sd->gspca_dev.usb_buf[0] = value;
2066 ret = usb_control_msg(sd->gspca_dev.dev,
2067 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2068 req,
2069 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2070 0, index,
2071 sd->gspca_dev.usb_buf, 1, 500);
2072leave:
2073 if (ret < 0) {
2074 pr_err("reg_w %02x failed %d\n", index, ret);
2075 sd->gspca_dev.usb_err = ret;
2076 return;
2077 }
2078}
2079
2080/* Read from a OV519 register, note not valid for the w9968cf!! */
2081/* returns: negative is error, pos or zero is data */
2082static int reg_r(struct sd *sd, u16 index)
2083{
2084 int ret;
2085 int req;
2086
2087 if (sd->gspca_dev.usb_err < 0)
2088 return -1;
2089
2090 switch (sd->bridge) {
2091 case BRIDGE_OV511:
2092 case BRIDGE_OV511PLUS:
2093 req = 3;
2094 break;
2095 case BRIDGE_OVFX2:
2096 req = 0x0b;
2097 break;
2098 default:
2099 req = 1;
2100 }
2101
2102 ret = usb_control_msg(sd->gspca_dev.dev,
2103 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
2104 req,
2105 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2106 0, index, sd->gspca_dev.usb_buf, 1, 500);
2107
2108 if (ret >= 0) {
2109 ret = sd->gspca_dev.usb_buf[0];
2110 PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
2111 req, index, ret);
2112 } else {
2113 pr_err("reg_r %02x failed %d\n", index, ret);
2114 sd->gspca_dev.usb_err = ret;
2115 }
2116
2117 return ret;
2118}
2119
2120/* Read 8 values from a OV519 register */
2121static int reg_r8(struct sd *sd,
2122 u16 index)
2123{
2124 int ret;
2125
2126 if (sd->gspca_dev.usb_err < 0)
2127 return -1;
2128
2129 ret = usb_control_msg(sd->gspca_dev.dev,
2130 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
2131 1, /* REQ_IO */
2132 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2133 0, index, sd->gspca_dev.usb_buf, 8, 500);
2134
2135 if (ret >= 0) {
2136 ret = sd->gspca_dev.usb_buf[0];
2137 } else {
2138 pr_err("reg_r8 %02x failed %d\n", index, ret);
2139 sd->gspca_dev.usb_err = ret;
2140 }
2141
2142 return ret;
2143}
2144
2145/*
2146 * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
2147 * the same position as 1's in "mask" are cleared and set to "value". Bits
2148 * that are in the same position as 0's in "mask" are preserved, regardless
2149 * of their respective state in "value".
2150 */
2151static void reg_w_mask(struct sd *sd,
2152 u16 index,
2153 u8 value,
2154 u8 mask)
2155{
2156 int ret;
2157 u8 oldval;
2158
2159 if (mask != 0xff) {
2160 value &= mask; /* Enforce mask on value */
2161 ret = reg_r(sd, index);
2162 if (ret < 0)
2163 return;
2164
2165 oldval = ret & ~mask; /* Clear the masked bits */
2166 value |= oldval; /* Set the desired bits */
2167 }
2168 reg_w(sd, index, value);
2169}
2170
2171/*
2172 * Writes multiple (n) byte value to a single register. Only valid with certain
2173 * registers (0x30 and 0xc4 - 0xce).
2174 */
2175static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
2176{
2177 int ret;
2178
2179 if (sd->gspca_dev.usb_err < 0)
2180 return;
2181
2182 *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
2183
2184 ret = usb_control_msg(sd->gspca_dev.dev,
2185 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2186 1 /* REG_IO */,
2187 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2188 0, index,
2189 sd->gspca_dev.usb_buf, n, 500);
2190 if (ret < 0) {
2191 pr_err("reg_w32 %02x failed %d\n", index, ret);
2192 sd->gspca_dev.usb_err = ret;
2193 }
2194}
2195
2196static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
2197{
2198 int rc, retries;
2199
2200 PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
2201
2202 /* Three byte write cycle */
2203 for (retries = 6; ; ) {
2204 /* Select camera register */
2205 reg_w(sd, R51x_I2C_SADDR_3, reg);
2206
2207 /* Write "value" to I2C data port of OV511 */
2208 reg_w(sd, R51x_I2C_DATA, value);
2209
2210 /* Initiate 3-byte write cycle */
2211 reg_w(sd, R511_I2C_CTL, 0x01);
2212
2213 do {
2214 rc = reg_r(sd, R511_I2C_CTL);
2215 } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
2216
2217 if (rc < 0)
2218 return;
2219
2220 if ((rc & 2) == 0) /* Ack? */
2221 break;
2222 if (--retries < 0) {
2223 PDEBUG(D_USBO, "i2c write retries exhausted");
2224 return;
2225 }
2226 }
2227}
2228
2229static int ov511_i2c_r(struct sd *sd, u8 reg)
2230{
2231 int rc, value, retries;
2232
2233 /* Two byte write cycle */
2234 for (retries = 6; ; ) {
2235 /* Select camera register */
2236 reg_w(sd, R51x_I2C_SADDR_2, reg);
2237
2238 /* Initiate 2-byte write cycle */
2239 reg_w(sd, R511_I2C_CTL, 0x03);
2240
2241 do {
2242 rc = reg_r(sd, R511_I2C_CTL);
2243 } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
2244
2245 if (rc < 0)
2246 return rc;
2247
2248 if ((rc & 2) == 0) /* Ack? */
2249 break;
2250
2251 /* I2C abort */
2252 reg_w(sd, R511_I2C_CTL, 0x10);
2253
2254 if (--retries < 0) {
2255 PDEBUG(D_USBI, "i2c write retries exhausted");
2256 return -1;
2257 }
2258 }
2259
2260 /* Two byte read cycle */
2261 for (retries = 6; ; ) {
2262 /* Initiate 2-byte read cycle */
2263 reg_w(sd, R511_I2C_CTL, 0x05);
2264
2265 do {
2266 rc = reg_r(sd, R511_I2C_CTL);
2267 } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
2268
2269 if (rc < 0)
2270 return rc;
2271
2272 if ((rc & 2) == 0) /* Ack? */
2273 break;
2274
2275 /* I2C abort */
2276 reg_w(sd, R511_I2C_CTL, 0x10);
2277
2278 if (--retries < 0) {
2279 PDEBUG(D_USBI, "i2c read retries exhausted");
2280 return -1;
2281 }
2282 }
2283
2284 value = reg_r(sd, R51x_I2C_DATA);
2285
2286 PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value);
2287
2288 /* This is needed to make i2c_w() work */
2289 reg_w(sd, R511_I2C_CTL, 0x05);
2290
2291 return value;
2292}
2293
2294/*
2295 * The OV518 I2C I/O procedure is different, hence, this function.
2296 * This is normally only called from i2c_w(). Note that this function
2297 * always succeeds regardless of whether the sensor is present and working.
2298 */
2299static void ov518_i2c_w(struct sd *sd,
2300 u8 reg,
2301 u8 value)
2302{
2303 PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
2304
2305 /* Select camera register */
2306 reg_w(sd, R51x_I2C_SADDR_3, reg);
2307
2308 /* Write "value" to I2C data port of OV511 */
2309 reg_w(sd, R51x_I2C_DATA, value);
2310
2311 /* Initiate 3-byte write cycle */
2312 reg_w(sd, R518_I2C_CTL, 0x01);
2313
2314 /* wait for write complete */
2315 msleep(4);
2316 reg_r8(sd, R518_I2C_CTL);
2317}
2318
2319/*
2320 * returns: negative is error, pos or zero is data
2321 *
2322 * The OV518 I2C I/O procedure is different, hence, this function.
2323 * This is normally only called from i2c_r(). Note that this function
2324 * always succeeds regardless of whether the sensor is present and working.
2325 */
2326static int ov518_i2c_r(struct sd *sd, u8 reg)
2327{
2328 int value;
2329
2330 /* Select camera register */
2331 reg_w(sd, R51x_I2C_SADDR_2, reg);
2332
2333 /* Initiate 2-byte write cycle */
2334 reg_w(sd, R518_I2C_CTL, 0x03);
2335 reg_r8(sd, R518_I2C_CTL);
2336
2337 /* Initiate 2-byte read cycle */
2338 reg_w(sd, R518_I2C_CTL, 0x05);
2339 reg_r8(sd, R518_I2C_CTL);
2340
2341 value = reg_r(sd, R51x_I2C_DATA);
2342 PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
2343 return value;
2344}
2345
2346static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
2347{
2348 int ret;
2349
2350 if (sd->gspca_dev.usb_err < 0)
2351 return;
2352
2353 ret = usb_control_msg(sd->gspca_dev.dev,
2354 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2355 0x02,
2356 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2357 (u16) value, (u16) reg, NULL, 0, 500);
2358
2359 if (ret < 0) {
2360 pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
2361 sd->gspca_dev.usb_err = ret;
2362 }
2363
2364 PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value);
2365}
2366
2367static int ovfx2_i2c_r(struct sd *sd, u8 reg)
2368{
2369 int ret;
2370
2371 if (sd->gspca_dev.usb_err < 0)
2372 return -1;
2373
2374 ret = usb_control_msg(sd->gspca_dev.dev,
2375 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
2376 0x03,
2377 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2378 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
2379
2380 if (ret >= 0) {
2381 ret = sd->gspca_dev.usb_buf[0];
2382 PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
2383 } else {
2384 pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
2385 sd->gspca_dev.usb_err = ret;
2386 }
2387
2388 return ret;
2389}
2390
2391static void i2c_w(struct sd *sd, u8 reg, u8 value)
2392{
2393 if (sd->sensor_reg_cache[reg] == value)
2394 return;
2395
2396 switch (sd->bridge) {
2397 case BRIDGE_OV511:
2398 case BRIDGE_OV511PLUS:
2399 ov511_i2c_w(sd, reg, value);
2400 break;
2401 case BRIDGE_OV518:
2402 case BRIDGE_OV518PLUS:
2403 case BRIDGE_OV519:
2404 ov518_i2c_w(sd, reg, value);
2405 break;
2406 case BRIDGE_OVFX2:
2407 ovfx2_i2c_w(sd, reg, value);
2408 break;
2409 case BRIDGE_W9968CF:
2410 w9968cf_i2c_w(sd, reg, value);
2411 break;
2412 }
2413
2414 if (sd->gspca_dev.usb_err >= 0) {
2415 /* Up on sensor reset empty the register cache */
2416 if (reg == 0x12 && (value & 0x80))
2417 memset(sd->sensor_reg_cache, -1,
2418 sizeof(sd->sensor_reg_cache));
2419 else
2420 sd->sensor_reg_cache[reg] = value;
2421 }
2422}
2423
2424static int i2c_r(struct sd *sd, u8 reg)
2425{
2426 int ret = -1;
2427
2428 if (sd->sensor_reg_cache[reg] != -1)
2429 return sd->sensor_reg_cache[reg];
2430
2431 switch (sd->bridge) {
2432 case BRIDGE_OV511:
2433 case BRIDGE_OV511PLUS:
2434 ret = ov511_i2c_r(sd, reg);
2435 break;
2436 case BRIDGE_OV518:
2437 case BRIDGE_OV518PLUS:
2438 case BRIDGE_OV519:
2439 ret = ov518_i2c_r(sd, reg);
2440 break;
2441 case BRIDGE_OVFX2:
2442 ret = ovfx2_i2c_r(sd, reg);
2443 break;
2444 case BRIDGE_W9968CF:
2445 ret = w9968cf_i2c_r(sd, reg);
2446 break;
2447 }
2448
2449 if (ret >= 0)
2450 sd->sensor_reg_cache[reg] = ret;
2451
2452 return ret;
2453}
2454
2455/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
2456 * the same position as 1's in "mask" are cleared and set to "value". Bits
2457 * that are in the same position as 0's in "mask" are preserved, regardless
2458 * of their respective state in "value".
2459 */
2460static void i2c_w_mask(struct sd *sd,
2461 u8 reg,
2462 u8 value,
2463 u8 mask)
2464{
2465 int rc;
2466 u8 oldval;
2467
2468 value &= mask; /* Enforce mask on value */
2469 rc = i2c_r(sd, reg);
2470 if (rc < 0)
2471 return;
2472 oldval = rc & ~mask; /* Clear the masked bits */
2473 value |= oldval; /* Set the desired bits */
2474 i2c_w(sd, reg, value);
2475}
2476
2477/* Temporarily stops OV511 from functioning. Must do this before changing
2478 * registers while the camera is streaming */
2479static inline void ov51x_stop(struct sd *sd)
2480{
2481 PDEBUG(D_STREAM, "stopping");
2482 sd->stopped = 1;
2483 switch (sd->bridge) {
2484 case BRIDGE_OV511:
2485 case BRIDGE_OV511PLUS:
2486 reg_w(sd, R51x_SYS_RESET, 0x3d);
2487 break;
2488 case BRIDGE_OV518:
2489 case BRIDGE_OV518PLUS:
2490 reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
2491 break;
2492 case BRIDGE_OV519:
2493 reg_w(sd, OV519_R51_RESET1, 0x0f);
2494 reg_w(sd, OV519_R51_RESET1, 0x00);
2495 reg_w(sd, 0x22, 0x00); /* FRAR */
2496 break;
2497 case BRIDGE_OVFX2:
2498 reg_w_mask(sd, 0x0f, 0x00, 0x02);
2499 break;
2500 case BRIDGE_W9968CF:
2501 reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
2502 break;
2503 }
2504}
2505
2506/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
2507 * actually stopped (for performance). */
2508static inline void ov51x_restart(struct sd *sd)
2509{
2510 PDEBUG(D_STREAM, "restarting");
2511 if (!sd->stopped)
2512 return;
2513 sd->stopped = 0;
2514
2515 /* Reinitialize the stream */
2516 switch (sd->bridge) {
2517 case BRIDGE_OV511:
2518 case BRIDGE_OV511PLUS:
2519 reg_w(sd, R51x_SYS_RESET, 0x00);
2520 break;
2521 case BRIDGE_OV518:
2522 case BRIDGE_OV518PLUS:
2523 reg_w(sd, 0x2f, 0x80);
2524 reg_w(sd, R51x_SYS_RESET, 0x00);
2525 break;
2526 case BRIDGE_OV519:
2527 reg_w(sd, OV519_R51_RESET1, 0x0f);
2528 reg_w(sd, OV519_R51_RESET1, 0x00);
2529 reg_w(sd, 0x22, 0x1d); /* FRAR */
2530 break;
2531 case BRIDGE_OVFX2:
2532 reg_w_mask(sd, 0x0f, 0x02, 0x02);
2533 break;
2534 case BRIDGE_W9968CF:
2535 reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
2536 break;
2537 }
2538}
2539
2540static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
2541
2542/* This does an initial reset of an OmniVision sensor and ensures that I2C
2543 * is synchronized. Returns <0 on failure.
2544 */
2545static int init_ov_sensor(struct sd *sd, u8 slave)
2546{
2547 int i;
2548
2549 ov51x_set_slave_ids(sd, slave);
2550
2551 /* Reset the sensor */
2552 i2c_w(sd, 0x12, 0x80);
2553
2554 /* Wait for it to initialize */
2555 msleep(150);
2556
2557 for (i = 0; i < i2c_detect_tries; i++) {
2558 if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
2559 i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
2560 PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
2561 return 0;
2562 }
2563
2564 /* Reset the sensor */
2565 i2c_w(sd, 0x12, 0x80);
2566
2567 /* Wait for it to initialize */
2568 msleep(150);
2569
2570 /* Dummy read to sync I2C */
2571 if (i2c_r(sd, 0x00) < 0)
2572 return -1;
2573 }
2574 return -1;
2575}
2576
2577/* Set the read and write slave IDs. The "slave" argument is the write slave,
2578 * and the read slave will be set to (slave + 1).
2579 * This should not be called from outside the i2c I/O functions.
2580 * Sets I2C read and write slave IDs. Returns <0 for error
2581 */
2582static void ov51x_set_slave_ids(struct sd *sd,
2583 u8 slave)
2584{
2585 switch (sd->bridge) {
2586 case BRIDGE_OVFX2:
2587 reg_w(sd, OVFX2_I2C_ADDR, slave);
2588 return;
2589 case BRIDGE_W9968CF:
2590 sd->sensor_addr = slave;
2591 return;
2592 }
2593
2594 reg_w(sd, R51x_I2C_W_SID, slave);
2595 reg_w(sd, R51x_I2C_R_SID, slave + 1);
2596}
2597
2598static void write_regvals(struct sd *sd,
2599 const struct ov_regvals *regvals,
2600 int n)
2601{
2602 while (--n >= 0) {
2603 reg_w(sd, regvals->reg, regvals->val);
2604 regvals++;
2605 }
2606}
2607
2608static void write_i2c_regvals(struct sd *sd,
2609 const struct ov_i2c_regvals *regvals,
2610 int n)
2611{
2612 while (--n >= 0) {
2613 i2c_w(sd, regvals->reg, regvals->val);
2614 regvals++;
2615 }
2616}
2617
2618/****************************************************************************
2619 *
2620 * OV511 and sensor configuration
2621 *
2622 ***************************************************************************/
2623
2624/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
2625static void ov_hires_configure(struct sd *sd)
2626{
2627 int high, low;
2628
2629 if (sd->bridge != BRIDGE_OVFX2) {
2630 pr_err("error hires sensors only supported with ovfx2\n");
2631 return;
2632 }
2633
2634 PDEBUG(D_PROBE, "starting ov hires configuration");
2635
2636 /* Detect sensor (sub)type */
2637 high = i2c_r(sd, 0x0a);
2638 low = i2c_r(sd, 0x0b);
2639 /* info("%x, %x", high, low); */
2640 switch (high) {
2641 case 0x96:
2642 switch (low) {
2643 case 0x40:
2644 PDEBUG(D_PROBE, "Sensor is a OV2610");
2645 sd->sensor = SEN_OV2610;
2646 return;
2647 case 0x41:
2648 PDEBUG(D_PROBE, "Sensor is a OV2610AE");
2649 sd->sensor = SEN_OV2610AE;
2650 return;
2651 case 0xb1:
2652 PDEBUG(D_PROBE, "Sensor is a OV9600");
2653 sd->sensor = SEN_OV9600;
2654 return;
2655 }
2656 break;
2657 case 0x36:
2658 if ((low & 0x0f) == 0x00) {
2659 PDEBUG(D_PROBE, "Sensor is a OV3610");
2660 sd->sensor = SEN_OV3610;
2661 return;
2662 }
2663 break;
2664 }
2665 pr_err("Error unknown sensor type: %02x%02x\n", high, low);
2666}
2667
2668/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
2669 * the same register settings as the OV8610, since they are very similar.
2670 */
2671static void ov8xx0_configure(struct sd *sd)
2672{
2673 int rc;
2674
2675 PDEBUG(D_PROBE, "starting ov8xx0 configuration");
2676
2677 /* Detect sensor (sub)type */
2678 rc = i2c_r(sd, OV7610_REG_COM_I);
2679 if (rc < 0) {
2680 PDEBUG(D_ERR, "Error detecting sensor type");
2681 return;
2682 }
2683 if ((rc & 3) == 1)
2684 sd->sensor = SEN_OV8610;
2685 else
2686 pr_err("Unknown image sensor version: %d\n", rc & 3);
2687}
2688
2689/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
2690 * the same register settings as the OV7610, since they are very similar.
2691 */
2692static void ov7xx0_configure(struct sd *sd)
2693{
2694 int rc, high, low;
2695
2696 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
2697
2698 /* Detect sensor (sub)type */
2699 rc = i2c_r(sd, OV7610_REG_COM_I);
2700
2701 /* add OV7670 here
2702 * it appears to be wrongly detected as a 7610 by default */
2703 if (rc < 0) {
2704 pr_err("Error detecting sensor type\n");
2705 return;
2706 }
2707 if ((rc & 3) == 3) {
2708 /* quick hack to make OV7670s work */
2709 high = i2c_r(sd, 0x0a);
2710 low = i2c_r(sd, 0x0b);
2711 /* info("%x, %x", high, low); */
2712 if (high == 0x76 && (low & 0xf0) == 0x70) {
2713 PDEBUG(D_PROBE, "Sensor is an OV76%02x", low);
2714 sd->sensor = SEN_OV7670;
2715 } else {
2716 PDEBUG(D_PROBE, "Sensor is an OV7610");
2717 sd->sensor = SEN_OV7610;
2718 }
2719 } else if ((rc & 3) == 1) {
2720 /* I don't know what's different about the 76BE yet. */
2721 if (i2c_r(sd, 0x15) & 1) {
2722 PDEBUG(D_PROBE, "Sensor is an OV7620AE");
2723 sd->sensor = SEN_OV7620AE;
2724 } else {
2725 PDEBUG(D_PROBE, "Sensor is an OV76BE");
2726 sd->sensor = SEN_OV76BE;
2727 }
2728 } else if ((rc & 3) == 0) {
2729 /* try to read product id registers */
2730 high = i2c_r(sd, 0x0a);
2731 if (high < 0) {
2732 pr_err("Error detecting camera chip PID\n");
2733 return;
2734 }
2735 low = i2c_r(sd, 0x0b);
2736 if (low < 0) {
2737 pr_err("Error detecting camera chip VER\n");
2738 return;
2739 }
2740 if (high == 0x76) {
2741 switch (low) {
2742 case 0x30:
2743 pr_err("Sensor is an OV7630/OV7635\n");
2744 pr_err("7630 is not supported by this driver\n");
2745 return;
2746 case 0x40:
2747 PDEBUG(D_PROBE, "Sensor is an OV7645");
2748 sd->sensor = SEN_OV7640; /* FIXME */
2749 break;
2750 case 0x45:
2751 PDEBUG(D_PROBE, "Sensor is an OV7645B");
2752 sd->sensor = SEN_OV7640; /* FIXME */
2753 break;
2754 case 0x48:
2755 PDEBUG(D_PROBE, "Sensor is an OV7648");
2756 sd->sensor = SEN_OV7648;
2757 break;
2758 case 0x60:
2759 PDEBUG(D_PROBE, "Sensor is a OV7660");
2760 sd->sensor = SEN_OV7660;
2761 break;
2762 default:
2763 pr_err("Unknown sensor: 0x76%02x\n", low);
2764 return;
2765 }
2766 } else {
2767 PDEBUG(D_PROBE, "Sensor is an OV7620");
2768 sd->sensor = SEN_OV7620;
2769 }
2770 } else {
2771 pr_err("Unknown image sensor version: %d\n", rc & 3);
2772 }
2773}
2774
2775/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
2776static void ov6xx0_configure(struct sd *sd)
2777{
2778 int rc;
2779 PDEBUG(D_PROBE, "starting OV6xx0 configuration");
2780
2781 /* Detect sensor (sub)type */
2782 rc = i2c_r(sd, OV7610_REG_COM_I);
2783 if (rc < 0) {
2784 pr_err("Error detecting sensor type\n");
2785 return;
2786 }
2787
2788 /* Ugh. The first two bits are the version bits, but
2789 * the entire register value must be used. I guess OVT
2790 * underestimated how many variants they would make. */
2791 switch (rc) {
2792 case 0x00:
2793 sd->sensor = SEN_OV6630;
2794 pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
2795 break;
2796 case 0x01:
2797 sd->sensor = SEN_OV6620;
2798 PDEBUG(D_PROBE, "Sensor is an OV6620");
2799 break;
2800 case 0x02:
2801 sd->sensor = SEN_OV6630;
2802 PDEBUG(D_PROBE, "Sensor is an OV66308AE");
2803 break;
2804 case 0x03:
2805 sd->sensor = SEN_OV66308AF;
2806 PDEBUG(D_PROBE, "Sensor is an OV66308AF");
2807 break;
2808 case 0x90:
2809 sd->sensor = SEN_OV6630;
2810 pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
2811 break;
2812 default:
2813 pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
2814 return;
2815 }
2816
2817 /* Set sensor-specific vars */
2818 sd->sif = 1;
2819}
2820
2821/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
2822static void ov51x_led_control(struct sd *sd, int on)
2823{
2824 if (sd->invert_led)
2825 on = !on;
2826
2827 switch (sd->bridge) {
2828 /* OV511 has no LED control */
2829 case BRIDGE_OV511PLUS:
2830 reg_w(sd, R511_SYS_LED_CTL, on);
2831 break;
2832 case BRIDGE_OV518:
2833 case BRIDGE_OV518PLUS:
2834 reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
2835 break;
2836 case BRIDGE_OV519:
2837 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
2838 break;
2839 }
2840}
2841
2842static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
2843{
2844 struct sd *sd = (struct sd *) gspca_dev;
2845
2846 if (!sd->snapshot_needs_reset)
2847 return;
2848
2849 /* Note it is important that we clear sd->snapshot_needs_reset,
2850 before actually clearing the snapshot state in the bridge
2851 otherwise we might race with the pkt_scan interrupt handler */
2852 sd->snapshot_needs_reset = 0;
2853
2854 switch (sd->bridge) {
2855 case BRIDGE_OV511:
2856 case BRIDGE_OV511PLUS:
2857 reg_w(sd, R51x_SYS_SNAP, 0x02);
2858 reg_w(sd, R51x_SYS_SNAP, 0x00);
2859 break;
2860 case BRIDGE_OV518:
2861 case BRIDGE_OV518PLUS:
2862 reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */
2863 reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */
2864 break;
2865 case BRIDGE_OV519:
2866 reg_w(sd, R51x_SYS_RESET, 0x40);
2867 reg_w(sd, R51x_SYS_RESET, 0x00);
2868 break;
2869 }
2870}
2871
2872static void ov51x_upload_quan_tables(struct sd *sd)
2873{
2874 const unsigned char yQuanTable511[] = {
2875 0, 1, 1, 2, 2, 3, 3, 4,
2876 1, 1, 1, 2, 2, 3, 4, 4,
2877 1, 1, 2, 2, 3, 4, 4, 4,
2878 2, 2, 2, 3, 4, 4, 4, 4,
2879 2, 2, 3, 4, 4, 5, 5, 5,
2880 3, 3, 4, 4, 5, 5, 5, 5,
2881 3, 4, 4, 4, 5, 5, 5, 5,
2882 4, 4, 4, 4, 5, 5, 5, 5
2883 };
2884
2885 const unsigned char uvQuanTable511[] = {
2886 0, 2, 2, 3, 4, 4, 4, 4,
2887 2, 2, 2, 4, 4, 4, 4, 4,
2888 2, 2, 3, 4, 4, 4, 4, 4,
2889 3, 4, 4, 4, 4, 4, 4, 4,
2890 4, 4, 4, 4, 4, 4, 4, 4,
2891 4, 4, 4, 4, 4, 4, 4, 4,
2892 4, 4, 4, 4, 4, 4, 4, 4,
2893 4, 4, 4, 4, 4, 4, 4, 4
2894 };
2895
2896 /* OV518 quantization tables are 8x4 (instead of 8x8) */
2897 const unsigned char yQuanTable518[] = {
2898 5, 4, 5, 6, 6, 7, 7, 7,
2899 5, 5, 5, 5, 6, 7, 7, 7,
2900 6, 6, 6, 6, 7, 7, 7, 8,
2901 7, 7, 6, 7, 7, 7, 8, 8
2902 };
2903 const unsigned char uvQuanTable518[] = {
2904 6, 6, 6, 7, 7, 7, 7, 7,
2905 6, 6, 6, 7, 7, 7, 7, 7,
2906 6, 6, 6, 7, 7, 7, 7, 8,
2907 7, 7, 7, 7, 7, 7, 8, 8
2908 };
2909
2910 const unsigned char *pYTable, *pUVTable;
2911 unsigned char val0, val1;
2912 int i, size, reg = R51x_COMP_LUT_BEGIN;
2913
2914 PDEBUG(D_PROBE, "Uploading quantization tables");
2915
2916 if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
2917 pYTable = yQuanTable511;
2918 pUVTable = uvQuanTable511;
2919 size = 32;
2920 } else {
2921 pYTable = yQuanTable518;
2922 pUVTable = uvQuanTable518;
2923 size = 16;
2924 }
2925
2926 for (i = 0; i < size; i++) {
2927 val0 = *pYTable++;
2928 val1 = *pYTable++;
2929 val0 &= 0x0f;
2930 val1 &= 0x0f;
2931 val0 |= val1 << 4;
2932 reg_w(sd, reg, val0);
2933
2934 val0 = *pUVTable++;
2935 val1 = *pUVTable++;
2936 val0 &= 0x0f;
2937 val1 &= 0x0f;
2938 val0 |= val1 << 4;
2939 reg_w(sd, reg + size, val0);
2940
2941 reg++;
2942 }
2943}
2944
2945/* This initializes the OV511/OV511+ and the sensor */
2946static void ov511_configure(struct gspca_dev *gspca_dev)
2947{
2948 struct sd *sd = (struct sd *) gspca_dev;
2949
2950 /* For 511 and 511+ */
2951 const struct ov_regvals init_511[] = {
2952 { R51x_SYS_RESET, 0x7f },
2953 { R51x_SYS_INIT, 0x01 },
2954 { R51x_SYS_RESET, 0x7f },
2955 { R51x_SYS_INIT, 0x01 },
2956 { R51x_SYS_RESET, 0x3f },
2957 { R51x_SYS_INIT, 0x01 },
2958 { R51x_SYS_RESET, 0x3d },
2959 };
2960
2961 const struct ov_regvals norm_511[] = {
2962 { R511_DRAM_FLOW_CTL, 0x01 },
2963 { R51x_SYS_SNAP, 0x00 },
2964 { R51x_SYS_SNAP, 0x02 },
2965 { R51x_SYS_SNAP, 0x00 },
2966 { R511_FIFO_OPTS, 0x1f },
2967 { R511_COMP_EN, 0x00 },
2968 { R511_COMP_LUT_EN, 0x03 },
2969 };
2970
2971 const struct ov_regvals norm_511_p[] = {
2972 { R511_DRAM_FLOW_CTL, 0xff },
2973 { R51x_SYS_SNAP, 0x00 },
2974 { R51x_SYS_SNAP, 0x02 },
2975 { R51x_SYS_SNAP, 0x00 },
2976 { R511_FIFO_OPTS, 0xff },
2977 { R511_COMP_EN, 0x00 },
2978 { R511_COMP_LUT_EN, 0x03 },
2979 };
2980
2981 const struct ov_regvals compress_511[] = {
2982 { 0x70, 0x1f },
2983 { 0x71, 0x05 },
2984 { 0x72, 0x06 },
2985 { 0x73, 0x06 },
2986 { 0x74, 0x14 },
2987 { 0x75, 0x03 },
2988 { 0x76, 0x04 },
2989 { 0x77, 0x04 },
2990 };
2991
2992 PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
2993
2994 write_regvals(sd, init_511, ARRAY_SIZE(init_511));
2995
2996 switch (sd->bridge) {
2997 case BRIDGE_OV511:
2998 write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
2999 break;
3000 case BRIDGE_OV511PLUS:
3001 write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
3002 break;
3003 }
3004
3005 /* Init compression */
3006 write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
3007
3008 ov51x_upload_quan_tables(sd);
3009}
3010
3011/* This initializes the OV518/OV518+ and the sensor */
3012static void ov518_configure(struct gspca_dev *gspca_dev)
3013{
3014 struct sd *sd = (struct sd *) gspca_dev;
3015
3016 /* For 518 and 518+ */
3017 const struct ov_regvals init_518[] = {
3018 { R51x_SYS_RESET, 0x40 },
3019 { R51x_SYS_INIT, 0xe1 },
3020 { R51x_SYS_RESET, 0x3e },
3021 { R51x_SYS_INIT, 0xe1 },
3022 { R51x_SYS_RESET, 0x00 },
3023 { R51x_SYS_INIT, 0xe1 },
3024 { 0x46, 0x00 },
3025 { 0x5d, 0x03 },
3026 };
3027
3028 const struct ov_regvals norm_518[] = {
3029 { R51x_SYS_SNAP, 0x02 }, /* Reset */
3030 { R51x_SYS_SNAP, 0x01 }, /* Enable */
3031 { 0x31, 0x0f },
3032 { 0x5d, 0x03 },
3033 { 0x24, 0x9f },
3034 { 0x25, 0x90 },
3035 { 0x20, 0x00 },
3036 { 0x51, 0x04 },
3037 { 0x71, 0x19 },
3038 { 0x2f, 0x80 },
3039 };
3040
3041 const struct ov_regvals norm_518_p[] = {
3042 { R51x_SYS_SNAP, 0x02 }, /* Reset */
3043 { R51x_SYS_SNAP, 0x01 }, /* Enable */
3044 { 0x31, 0x0f },
3045 { 0x5d, 0x03 },
3046 { 0x24, 0x9f },
3047 { 0x25, 0x90 },
3048 { 0x20, 0x60 },
3049 { 0x51, 0x02 },
3050 { 0x71, 0x19 },
3051 { 0x40, 0xff },
3052 { 0x41, 0x42 },
3053 { 0x46, 0x00 },
3054 { 0x33, 0x04 },
3055 { 0x21, 0x19 },
3056 { 0x3f, 0x10 },
3057 { 0x2f, 0x80 },
3058 };
3059
3060 /* First 5 bits of custom ID reg are a revision ID on OV518 */
3061 PDEBUG(D_PROBE, "Device revision %d",
3062 0x1f & reg_r(sd, R51x_SYS_CUST_ID));
3063
3064 write_regvals(sd, init_518, ARRAY_SIZE(init_518));
3065
3066 /* Set LED GPIO pin to output mode */
3067 reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
3068
3069 switch (sd->bridge) {
3070 case BRIDGE_OV518:
3071 write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
3072 break;
3073 case BRIDGE_OV518PLUS:
3074 write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
3075 break;
3076 }
3077
3078 ov51x_upload_quan_tables(sd);
3079
3080 reg_w(sd, 0x2f, 0x80);
3081}
3082
3083static void ov519_configure(struct sd *sd)
3084{
3085 static const struct ov_regvals init_519[] = {
3086 { 0x5a, 0x6d }, /* EnableSystem */
3087 { 0x53, 0x9b }, /* don't enable the microcontroller */
3088 { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
3089 { 0x5d, 0x03 },
3090 { 0x49, 0x01 },
3091 { 0x48, 0x00 },
3092 /* Set LED pin to output mode. Bit 4 must be cleared or sensor
3093 * detection will fail. This deserves further investigation. */
3094 { OV519_GPIO_IO_CTRL0, 0xee },
3095 { OV519_R51_RESET1, 0x0f },
3096 { OV519_R51_RESET1, 0x00 },
3097 { 0x22, 0x00 },
3098 /* windows reads 0x55 at this point*/
3099 };
3100
3101 write_regvals(sd, init_519, ARRAY_SIZE(init_519));
3102}
3103
3104static void ovfx2_configure(struct sd *sd)
3105{
3106 static const struct ov_regvals init_fx2[] = {
3107 { 0x00, 0x60 },
3108 { 0x02, 0x01 },
3109 { 0x0f, 0x1d },
3110 { 0xe9, 0x82 },
3111 { 0xea, 0xc7 },
3112 { 0xeb, 0x10 },
3113 { 0xec, 0xf6 },
3114 };
3115
3116 sd->stopped = 1;
3117
3118 write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
3119}
3120
3121/* set the mode */
3122/* This function works for ov7660 only */
3123static void ov519_set_mode(struct sd *sd)
3124{
3125 static const struct ov_regvals bridge_ov7660[2][10] = {
3126 {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
3127 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
3128 {0x25, 0x01}, {0x26, 0x00}},
3129 {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
3130 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
3131 {0x25, 0x03}, {0x26, 0x00}}
3132 };
3133 static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
3134 {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
3135 {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
3136 };
3137 static const struct ov_i2c_regvals sensor_ov7660_2[] = {
3138 {OV7670_R17_HSTART, 0x13},
3139 {OV7670_R18_HSTOP, 0x01},
3140 {OV7670_R32_HREF, 0x92},
3141 {OV7670_R19_VSTART, 0x02},
3142 {OV7670_R1A_VSTOP, 0x7a},
3143 {OV7670_R03_VREF, 0x00},
3144/* {0x33, 0x00}, */
3145/* {0x34, 0x07}, */
3146/* {0x36, 0x00}, */
3147/* {0x6b, 0x0a}, */
3148 };
3149
3150 write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
3151 ARRAY_SIZE(bridge_ov7660[0]));
3152 write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
3153 ARRAY_SIZE(sensor_ov7660[0]));
3154 write_i2c_regvals(sd, sensor_ov7660_2,
3155 ARRAY_SIZE(sensor_ov7660_2));
3156}
3157
3158/* set the frame rate */
3159/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
3160static void ov519_set_fr(struct sd *sd)
3161{
3162 int fr;
3163 u8 clock;
3164 /* frame rate table with indices:
3165 * - mode = 0: 320x240, 1: 640x480
3166 * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
3167 * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
3168 */
3169 static const u8 fr_tb[2][6][3] = {
3170 {{0x04, 0xff, 0x00},
3171 {0x04, 0x1f, 0x00},
3172 {0x04, 0x1b, 0x00},
3173 {0x04, 0x15, 0x00},
3174 {0x04, 0x09, 0x00},
3175 {0x04, 0x01, 0x00}},
3176 {{0x0c, 0xff, 0x00},
3177 {0x0c, 0x1f, 0x00},
3178 {0x0c, 0x1b, 0x00},
3179 {0x04, 0xff, 0x01},
3180 {0x04, 0x1f, 0x01},
3181 {0x04, 0x1b, 0x01}},
3182 };
3183
3184 if (frame_rate > 0)
3185 sd->frame_rate = frame_rate;
3186 if (sd->frame_rate >= 30)
3187 fr = 0;
3188 else if (sd->frame_rate >= 25)
3189 fr = 1;
3190 else if (sd->frame_rate >= 20)
3191 fr = 2;
3192 else if (sd->frame_rate >= 15)
3193 fr = 3;
3194 else if (sd->frame_rate >= 10)
3195 fr = 4;
3196 else
3197 fr = 5;
3198 reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
3199 reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
3200 clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
3201 if (sd->sensor == SEN_OV7660)
3202 clock |= 0x80; /* enable double clock */
3203 ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
3204}
3205
3206static void setautogain(struct gspca_dev *gspca_dev, s32 val)
3207{
3208 struct sd *sd = (struct sd *) gspca_dev;
3209
3210 i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05);
3211}
3212
3213/* this function is called at probe time */
3214static int sd_config(struct gspca_dev *gspca_dev,
3215 const struct usb_device_id *id)
3216{
3217 struct sd *sd = (struct sd *) gspca_dev;
3218 struct cam *cam = &gspca_dev->cam;
3219
3220 sd->bridge = id->driver_info & BRIDGE_MASK;
3221 sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
3222
3223 switch (sd->bridge) {
3224 case BRIDGE_OV511:
3225 case BRIDGE_OV511PLUS:
3226 cam->cam_mode = ov511_vga_mode;
3227 cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
3228 break;
3229 case BRIDGE_OV518:
3230 case BRIDGE_OV518PLUS:
3231 cam->cam_mode = ov518_vga_mode;
3232 cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
3233 break;
3234 case BRIDGE_OV519:
3235 cam->cam_mode = ov519_vga_mode;
3236 cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
3237 break;
3238 case BRIDGE_OVFX2:
3239 cam->cam_mode = ov519_vga_mode;
3240 cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
3241 cam->bulk_size = OVFX2_BULK_SIZE;
3242 cam->bulk_nurbs = MAX_NURBS;
3243 cam->bulk = 1;
3244 break;
3245 case BRIDGE_W9968CF:
3246 cam->cam_mode = w9968cf_vga_mode;
3247 cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
3248 break;
3249 }
3250
3251 sd->frame_rate = 15;
3252
3253 return 0;
3254}
3255
3256/* this function is called at probe and resume time */
3257static int sd_init(struct gspca_dev *gspca_dev)
3258{
3259 struct sd *sd = (struct sd *) gspca_dev;
3260 struct cam *cam = &gspca_dev->cam;
3261
3262 switch (sd->bridge) {
3263 case BRIDGE_OV511:
3264 case BRIDGE_OV511PLUS:
3265 ov511_configure(gspca_dev);
3266 break;
3267 case BRIDGE_OV518:
3268 case BRIDGE_OV518PLUS:
3269 ov518_configure(gspca_dev);
3270 break;
3271 case BRIDGE_OV519:
3272 ov519_configure(sd);
3273 break;
3274 case BRIDGE_OVFX2:
3275 ovfx2_configure(sd);
3276 break;
3277 case BRIDGE_W9968CF:
3278 w9968cf_configure(sd);
3279 break;
3280 }
3281
3282 /* The OV519 must be more aggressive about sensor detection since
3283 * I2C write will never fail if the sensor is not present. We have
3284 * to try to initialize the sensor to detect its presence */
3285 sd->sensor = -1;
3286
3287 /* Test for 76xx */
3288 if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
3289 ov7xx0_configure(sd);
3290
3291 /* Test for 6xx0 */
3292 } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
3293 ov6xx0_configure(sd);
3294
3295 /* Test for 8xx0 */
3296 } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
3297 ov8xx0_configure(sd);
3298
3299 /* Test for 3xxx / 2xxx */
3300 } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
3301 ov_hires_configure(sd);
3302 } else {
3303 pr_err("Can't determine sensor slave IDs\n");
3304 goto error;
3305 }
3306
3307 if (sd->sensor < 0)
3308 goto error;
3309
3310 ov51x_led_control(sd, 0); /* turn LED off */
3311
3312 switch (sd->bridge) {
3313 case BRIDGE_OV511:
3314 case BRIDGE_OV511PLUS:
3315 if (sd->sif) {
3316 cam->cam_mode = ov511_sif_mode;
3317 cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
3318 }
3319 break;
3320 case BRIDGE_OV518:
3321 case BRIDGE_OV518PLUS:
3322 if (sd->sif) {
3323 cam->cam_mode = ov518_sif_mode;
3324 cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
3325 }
3326 break;
3327 case BRIDGE_OV519:
3328 if (sd->sif) {
3329 cam->cam_mode = ov519_sif_mode;
3330 cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
3331 }
3332 break;
3333 case BRIDGE_OVFX2:
3334 switch (sd->sensor) {
3335 case SEN_OV2610:
3336 case SEN_OV2610AE:
3337 cam->cam_mode = ovfx2_ov2610_mode;
3338 cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode);
3339 break;
3340 case SEN_OV3610:
3341 cam->cam_mode = ovfx2_ov3610_mode;
3342 cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
3343 break;
3344 case SEN_OV9600:
3345 cam->cam_mode = ovfx2_ov9600_mode;
3346 cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
3347 break;
3348 default:
3349 if (sd->sif) {
3350 cam->cam_mode = ov519_sif_mode;
3351 cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
3352 }
3353 break;
3354 }
3355 break;
3356 case BRIDGE_W9968CF:
3357 if (sd->sif)
3358 cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
3359
3360 /* w9968cf needs initialisation once the sensor is known */
3361 w9968cf_init(sd);
3362 break;
3363 }
3364
3365 /* initialize the sensor */
3366 switch (sd->sensor) {
3367 case SEN_OV2610:
3368 write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
3369
3370 /* Enable autogain, autoexpo, awb, bandfilter */
3371 i2c_w_mask(sd, 0x13, 0x27, 0x27);
3372 break;
3373 case SEN_OV2610AE:
3374 write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae));
3375
3376 /* enable autoexpo */
3377 i2c_w_mask(sd, 0x13, 0x05, 0x05);
3378 break;
3379 case SEN_OV3610:
3380 write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
3381
3382 /* Enable autogain, autoexpo, awb, bandfilter */
3383 i2c_w_mask(sd, 0x13, 0x27, 0x27);
3384 break;
3385 case SEN_OV6620:
3386 write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
3387 break;
3388 case SEN_OV6630:
3389 case SEN_OV66308AF:
3390 write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
3391 break;
3392 default:
3393/* case SEN_OV7610: */
3394/* case SEN_OV76BE: */
3395 write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
3396 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
3397 break;
3398 case SEN_OV7620:
3399 case SEN_OV7620AE:
3400 write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
3401 break;
3402 case SEN_OV7640:
3403 case SEN_OV7648:
3404 write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
3405 break;
3406 case SEN_OV7660:
3407 i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
3408 msleep(14);
3409 reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
3410 write_regvals(sd, init_519_ov7660,
3411 ARRAY_SIZE(init_519_ov7660));
3412 write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
3413 sd->gspca_dev.curr_mode = 1; /* 640x480 */
3414 ov519_set_mode(sd);
3415 ov519_set_fr(sd);
3416 sd_reset_snapshot(gspca_dev);
3417 ov51x_restart(sd);
3418 ov51x_stop(sd); /* not in win traces */
3419 ov51x_led_control(sd, 0);
3420 break;
3421 case SEN_OV7670:
3422 write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
3423 break;
3424 case SEN_OV8610:
3425 write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
3426 break;
3427 case SEN_OV9600:
3428 write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
3429
3430 /* enable autoexpo */
3431/* i2c_w_mask(sd, 0x13, 0x05, 0x05); */
3432 break;
3433 }
3434 return gspca_dev->usb_err;
3435error:
3436 PDEBUG(D_ERR, "OV519 Config failed");
3437 return -EINVAL;
3438}
3439
3440/* function called at start time before URB creation */
3441static int sd_isoc_init(struct gspca_dev *gspca_dev)
3442{
3443 struct sd *sd = (struct sd *) gspca_dev;
3444
3445 switch (sd->bridge) {
3446 case BRIDGE_OVFX2:
3447 if (gspca_dev->width != 800)
3448 gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
3449 else
3450 gspca_dev->cam.bulk_size = 7 * 4096;
3451 break;
3452 }
3453 return 0;
3454}
3455
3456/* Set up the OV511/OV511+ with the given image parameters.
3457 *
3458 * Do not put any sensor-specific code in here (including I2C I/O functions)
3459 */
3460static void ov511_mode_init_regs(struct sd *sd)
3461{
3462 int hsegs, vsegs, packet_size, fps, needed;
3463 int interlaced = 0;
3464 struct usb_host_interface *alt;
3465 struct usb_interface *intf;
3466
3467 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
3468 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
3469 if (!alt) {
3470 pr_err("Couldn't get altsetting\n");
3471 sd->gspca_dev.usb_err = -EIO;
3472 return;
3473 }
3474
3475 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
3476 reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
3477
3478 reg_w(sd, R511_CAM_UV_EN, 0x01);
3479 reg_w(sd, R511_SNAP_UV_EN, 0x01);
3480 reg_w(sd, R511_SNAP_OPTS, 0x03);
3481
3482 /* Here I'm assuming that snapshot size == image size.
3483 * I hope that's always true. --claudio
3484 */
3485 hsegs = (sd->gspca_dev.width >> 3) - 1;
3486 vsegs = (sd->gspca_dev.height >> 3) - 1;
3487
3488 reg_w(sd, R511_CAM_PXCNT, hsegs);
3489 reg_w(sd, R511_CAM_LNCNT, vsegs);
3490 reg_w(sd, R511_CAM_PXDIV, 0x00);
3491 reg_w(sd, R511_CAM_LNDIV, 0x00);
3492
3493 /* YUV420, low pass filter on */
3494 reg_w(sd, R511_CAM_OPTS, 0x03);
3495
3496 /* Snapshot additions */
3497 reg_w(sd, R511_SNAP_PXCNT, hsegs);
3498 reg_w(sd, R511_SNAP_LNCNT, vsegs);
3499 reg_w(sd, R511_SNAP_PXDIV, 0x00);
3500 reg_w(sd, R511_SNAP_LNDIV, 0x00);
3501
3502 /******** Set the framerate ********/
3503 if (frame_rate > 0)
3504 sd->frame_rate = frame_rate;
3505
3506 switch (sd->sensor) {
3507 case SEN_OV6620:
3508 /* No framerate control, doesn't like higher rates yet */
3509 sd->clockdiv = 3;
3510 break;
3511
3512 /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
3513 for more sensors we need to do this for them too */
3514 case SEN_OV7620:
3515 case SEN_OV7620AE:
3516 case SEN_OV7640:
3517 case SEN_OV7648:
3518 case SEN_OV76BE:
3519 if (sd->gspca_dev.width == 320)
3520 interlaced = 1;
3521 /* Fall through */
3522 case SEN_OV6630:
3523 case SEN_OV7610:
3524 case SEN_OV7670:
3525 switch (sd->frame_rate) {
3526 case 30:
3527 case 25:
3528 /* Not enough bandwidth to do 640x480 @ 30 fps */
3529 if (sd->gspca_dev.width != 640) {
3530 sd->clockdiv = 0;
3531 break;
3532 }
3533 /* Fall through for 640x480 case */
3534 default:
3535/* case 20: */
3536/* case 15: */
3537 sd->clockdiv = 1;
3538 break;
3539 case 10:
3540 sd->clockdiv = 2;
3541 break;
3542 case 5:
3543 sd->clockdiv = 5;
3544 break;
3545 }
3546 if (interlaced) {
3547 sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
3548 /* Higher then 10 does not work */
3549 if (sd->clockdiv > 10)
3550 sd->clockdiv = 10;
3551 }
3552 break;
3553
3554 case SEN_OV8610:
3555 /* No framerate control ?? */
3556 sd->clockdiv = 0;
3557 break;
3558 }
3559
3560 /* Check if we have enough bandwidth to disable compression */
3561 fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
3562 needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
3563 /* 1000 isoc packets/sec */
3564 if (needed > 1000 * packet_size) {
3565 /* Enable Y and UV quantization and compression */
3566 reg_w(sd, R511_COMP_EN, 0x07);
3567 reg_w(sd, R511_COMP_LUT_EN, 0x03);
3568 } else {
3569 reg_w(sd, R511_COMP_EN, 0x06);
3570 reg_w(sd, R511_COMP_LUT_EN, 0x00);
3571 }
3572
3573 reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
3574 reg_w(sd, R51x_SYS_RESET, 0);
3575}
3576
3577/* Sets up the OV518/OV518+ with the given image parameters
3578 *
3579 * OV518 needs a completely different approach, until we can figure out what
3580 * the individual registers do. Also, only 15 FPS is supported now.
3581 *
3582 * Do not put any sensor-specific code in here (including I2C I/O functions)
3583 */
3584static void ov518_mode_init_regs(struct sd *sd)
3585{
3586 int hsegs, vsegs, packet_size;
3587 struct usb_host_interface *alt;
3588 struct usb_interface *intf;
3589
3590 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
3591 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
3592 if (!alt) {
3593 pr_err("Couldn't get altsetting\n");
3594 sd->gspca_dev.usb_err = -EIO;
3595 return;
3596 }
3597
3598 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
3599 ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
3600
3601 /******** Set the mode ********/
3602 reg_w(sd, 0x2b, 0);
3603 reg_w(sd, 0x2c, 0);
3604 reg_w(sd, 0x2d, 0);
3605 reg_w(sd, 0x2e, 0);
3606 reg_w(sd, 0x3b, 0);
3607 reg_w(sd, 0x3c, 0);
3608 reg_w(sd, 0x3d, 0);
3609 reg_w(sd, 0x3e, 0);
3610
3611 if (sd->bridge == BRIDGE_OV518) {
3612 /* Set 8-bit (YVYU) input format */
3613 reg_w_mask(sd, 0x20, 0x08, 0x08);
3614
3615 /* Set 12-bit (4:2:0) output format */
3616 reg_w_mask(sd, 0x28, 0x80, 0xf0);
3617 reg_w_mask(sd, 0x38, 0x80, 0xf0);
3618 } else {
3619 reg_w(sd, 0x28, 0x80);
3620 reg_w(sd, 0x38, 0x80);
3621 }
3622
3623 hsegs = sd->gspca_dev.width / 16;
3624 vsegs = sd->gspca_dev.height / 4;
3625
3626 reg_w(sd, 0x29, hsegs);
3627 reg_w(sd, 0x2a, vsegs);
3628
3629 reg_w(sd, 0x39, hsegs);
3630 reg_w(sd, 0x3a, vsegs);
3631
3632 /* Windows driver does this here; who knows why */
3633 reg_w(sd, 0x2f, 0x80);
3634
3635 /******** Set the framerate ********/
3636 sd->clockdiv = 1;
3637
3638 /* Mode independent, but framerate dependent, regs */
3639 /* 0x51: Clock divider; Only works on some cams which use 2 crystals */
3640 reg_w(sd, 0x51, 0x04);
3641 reg_w(sd, 0x22, 0x18);
3642 reg_w(sd, 0x23, 0xff);
3643
3644 if (sd->bridge == BRIDGE_OV518PLUS) {
3645 switch (sd->sensor) {
3646 case SEN_OV7620AE:
3647 if (sd->gspca_dev.width == 320) {
3648 reg_w(sd, 0x20, 0x00);
3649 reg_w(sd, 0x21, 0x19);
3650 } else {
3651 reg_w(sd, 0x20, 0x60);
3652 reg_w(sd, 0x21, 0x1f);
3653 }
3654 break;
3655 case SEN_OV7620:
3656 reg_w(sd, 0x20, 0x00);
3657 reg_w(sd, 0x21, 0x19);
3658 break;
3659 default:
3660 reg_w(sd, 0x21, 0x19);
3661 }
3662 } else
3663 reg_w(sd, 0x71, 0x17); /* Compression-related? */
3664
3665 /* FIXME: Sensor-specific */
3666 /* Bit 5 is what matters here. Of course, it is "reserved" */
3667 i2c_w(sd, 0x54, 0x23);
3668
3669 reg_w(sd, 0x2f, 0x80);
3670
3671 if (sd->bridge == BRIDGE_OV518PLUS) {
3672 reg_w(sd, 0x24, 0x94);
3673 reg_w(sd, 0x25, 0x90);
3674 ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
3675 ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */
3676 ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */
3677 ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */
3678 ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */
3679 ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */
3680 ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */
3681 ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */
3682 ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */
3683 } else {
3684 reg_w(sd, 0x24, 0x9f);
3685 reg_w(sd, 0x25, 0x90);
3686 ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
3687 ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */
3688 ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */
3689 ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */
3690 ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */
3691 ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */
3692 ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */
3693 ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */
3694 ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */
3695 }
3696
3697 reg_w(sd, 0x2f, 0x80);
3698}
3699
3700/* Sets up the OV519 with the given image parameters
3701 *
3702 * OV519 needs a completely different approach, until we can figure out what
3703 * the individual registers do.
3704 *
3705 * Do not put any sensor-specific code in here (including I2C I/O functions)
3706 */
3707static void ov519_mode_init_regs(struct sd *sd)
3708{
3709 static const struct ov_regvals mode_init_519_ov7670[] = {
3710 { 0x5d, 0x03 }, /* Turn off suspend mode */
3711 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
3712 { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
3713 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
3714 { 0xa3, 0x18 },
3715 { 0xa4, 0x04 },
3716 { 0xa5, 0x28 },
3717 { 0x37, 0x00 }, /* SetUsbInit */
3718 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
3719 /* Enable both fields, YUV Input, disable defect comp (why?) */
3720 { 0x20, 0x0c },
3721 { 0x21, 0x38 },
3722 { 0x22, 0x1d },
3723 { 0x17, 0x50 }, /* undocumented */
3724 { 0x37, 0x00 }, /* undocumented */
3725 { 0x40, 0xff }, /* I2C timeout counter */
3726 { 0x46, 0x00 }, /* I2C clock prescaler */
3727 { 0x59, 0x04 }, /* new from windrv 090403 */
3728 { 0xff, 0x00 }, /* undocumented */
3729 /* windows reads 0x55 at this point, why? */
3730 };
3731
3732 static const struct ov_regvals mode_init_519[] = {
3733 { 0x5d, 0x03 }, /* Turn off suspend mode */
3734 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
3735 { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
3736 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
3737 { 0xa3, 0x18 },
3738 { 0xa4, 0x04 },
3739 { 0xa5, 0x28 },
3740 { 0x37, 0x00 }, /* SetUsbInit */
3741 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
3742 /* Enable both fields, YUV Input, disable defect comp (why?) */
3743 { 0x22, 0x1d },
3744 { 0x17, 0x50 }, /* undocumented */
3745 { 0x37, 0x00 }, /* undocumented */
3746 { 0x40, 0xff }, /* I2C timeout counter */
3747 { 0x46, 0x00 }, /* I2C clock prescaler */
3748 { 0x59, 0x04 }, /* new from windrv 090403 */
3749 { 0xff, 0x00 }, /* undocumented */
3750 /* windows reads 0x55 at this point, why? */
3751 };
3752
3753 /******** Set the mode ********/
3754 switch (sd->sensor) {
3755 default:
3756 write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
3757 if (sd->sensor == SEN_OV7640 ||
3758 sd->sensor == SEN_OV7648) {
3759 /* Select 8-bit input mode */
3760 reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
3761 }
3762 break;
3763 case SEN_OV7660:
3764 return; /* done by ov519_set_mode/fr() */
3765 case SEN_OV7670:
3766 write_regvals(sd, mode_init_519_ov7670,
3767 ARRAY_SIZE(mode_init_519_ov7670));
3768 break;
3769 }
3770
3771 reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
3772 reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3);
3773 if (sd->sensor == SEN_OV7670 &&
3774 sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
3775 reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
3776 else if (sd->sensor == SEN_OV7648 &&
3777 sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
3778 reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
3779 else
3780 reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
3781 reg_w(sd, OV519_R13_X_OFFSETH, 0x00);
3782 reg_w(sd, OV519_R14_Y_OFFSETL, 0x00);
3783 reg_w(sd, OV519_R15_Y_OFFSETH, 0x00);
3784 reg_w(sd, OV519_R16_DIVIDER, 0x00);
3785 reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */
3786 reg_w(sd, 0x26, 0x00); /* Undocumented */
3787
3788 /******** Set the framerate ********/
3789 if (frame_rate > 0)
3790 sd->frame_rate = frame_rate;
3791
3792/* FIXME: These are only valid at the max resolution. */
3793 sd->clockdiv = 0;
3794 switch (sd->sensor) {
3795 case SEN_OV7640:
3796 case SEN_OV7648:
3797 switch (sd->frame_rate) {
3798 default:
3799/* case 30: */
3800 reg_w(sd, 0xa4, 0x0c);
3801 reg_w(sd, 0x23, 0xff);
3802 break;
3803 case 25:
3804 reg_w(sd, 0xa4, 0x0c);
3805 reg_w(sd, 0x23, 0x1f);
3806 break;
3807 case 20:
3808 reg_w(sd, 0xa4, 0x0c);
3809 reg_w(sd, 0x23, 0x1b);
3810 break;
3811 case 15:
3812 reg_w(sd, 0xa4, 0x04);
3813 reg_w(sd, 0x23, 0xff);
3814 sd->clockdiv = 1;
3815 break;
3816 case 10:
3817 reg_w(sd, 0xa4, 0x04);
3818 reg_w(sd, 0x23, 0x1f);
3819 sd->clockdiv = 1;
3820 break;
3821 case 5:
3822 reg_w(sd, 0xa4, 0x04);
3823 reg_w(sd, 0x23, 0x1b);
3824 sd->clockdiv = 1;
3825 break;
3826 }
3827 break;
3828 case SEN_OV8610:
3829 switch (sd->frame_rate) {
3830 default: /* 15 fps */
3831/* case 15: */
3832 reg_w(sd, 0xa4, 0x06);
3833 reg_w(sd, 0x23, 0xff);
3834 break;
3835 case 10:
3836 reg_w(sd, 0xa4, 0x06);
3837 reg_w(sd, 0x23, 0x1f);
3838 break;
3839 case 5:
3840 reg_w(sd, 0xa4, 0x06);
3841 reg_w(sd, 0x23, 0x1b);
3842 break;
3843 }
3844 break;
3845 case SEN_OV7670: /* guesses, based on 7640 */
3846 PDEBUG(D_STREAM, "Setting framerate to %d fps",
3847 (sd->frame_rate == 0) ? 15 : sd->frame_rate);
3848 reg_w(sd, 0xa4, 0x10);
3849 switch (sd->frame_rate) {
3850 case 30:
3851 reg_w(sd, 0x23, 0xff);
3852 break;
3853 case 20:
3854 reg_w(sd, 0x23, 0x1b);
3855 break;
3856 default:
3857/* case 15: */
3858 reg_w(sd, 0x23, 0xff);
3859 sd->clockdiv = 1;
3860 break;
3861 }
3862 break;
3863 }
3864}
3865
3866static void mode_init_ov_sensor_regs(struct sd *sd)
3867{
3868 struct gspca_dev *gspca_dev;
3869 int qvga, xstart, xend, ystart, yend;
3870 u8 v;
3871
3872 gspca_dev = &sd->gspca_dev;
3873 qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
3874
3875 /******** Mode (VGA/QVGA) and sensor specific regs ********/
3876 switch (sd->sensor) {
3877 case SEN_OV2610:
3878 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
3879 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
3880 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
3881 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
3882 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
3883 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
3884 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
3885 return;
3886 case SEN_OV2610AE: {
3887 u8 v;
3888
3889 /* frame rates:
3890 * 10fps / 5 fps for 1600x1200
3891 * 40fps / 20fps for 800x600
3892 */
3893 v = 80;
3894 if (qvga) {
3895 if (sd->frame_rate < 25)
3896 v = 0x81;
3897 } else {
3898 if (sd->frame_rate < 10)
3899 v = 0x81;
3900 }
3901 i2c_w(sd, 0x11, v);
3902 i2c_w(sd, 0x12, qvga ? 0x60 : 0x20);
3903 return;
3904 }
3905 case SEN_OV3610:
3906 if (qvga) {
3907 xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
3908 ystart = (776 - gspca_dev->height) / 2;
3909 } else {
3910 xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4);
3911 ystart = (1544 - gspca_dev->height) / 2;
3912 }
3913 xend = xstart + gspca_dev->width;
3914 yend = ystart + gspca_dev->height;
3915 /* Writing to the COMH register resets the other windowing regs
3916 to their default values, so we must do this first. */
3917 i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0);
3918 i2c_w_mask(sd, 0x32,
3919 (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7),
3920 0x3f);
3921 i2c_w_mask(sd, 0x03,
3922 (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3),
3923 0x0f);
3924 i2c_w(sd, 0x17, xstart >> 4);
3925 i2c_w(sd, 0x18, xend >> 4);
3926 i2c_w(sd, 0x19, ystart >> 3);
3927 i2c_w(sd, 0x1a, yend >> 3);
3928 return;
3929 case SEN_OV8610:
3930 /* For OV8610 qvga means qsvga */
3931 i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
3932 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
3933 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
3934 i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */
3935 i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */
3936 break;
3937 case SEN_OV7610:
3938 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
3939 i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
3940 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
3941 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
3942 break;
3943 case SEN_OV7620:
3944 case SEN_OV7620AE:
3945 case SEN_OV76BE:
3946 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
3947 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
3948 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
3949 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
3950 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
3951 i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
3952 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
3953 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
3954 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
3955 if (sd->sensor == SEN_OV76BE)
3956 i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
3957 break;
3958 case SEN_OV7640:
3959 case SEN_OV7648:
3960 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
3961 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
3962 /* Setting this undocumented bit in qvga mode removes a very
3963 annoying vertical shaking of the image */
3964 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
3965 /* Unknown */
3966 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
3967 /* Allow higher automatic gain (to allow higher framerates) */
3968 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
3969 i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
3970 break;
3971 case SEN_OV7670:
3972 /* set COM7_FMT_VGA or COM7_FMT_QVGA
3973 * do we need to set anything else?
3974 * HSTART etc are set in set_ov_sensor_window itself */
3975 i2c_w_mask(sd, OV7670_R12_COM7,
3976 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
3977 OV7670_COM7_FMT_MASK);
3978 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
3979 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
3980 OV7670_COM8_AWB);
3981 if (qvga) { /* QVGA from ov7670.c by
3982 * Jonathan Corbet */
3983 xstart = 164;
3984 xend = 28;
3985 ystart = 14;
3986 yend = 494;
3987 } else { /* VGA */
3988 xstart = 158;
3989 xend = 14;
3990 ystart = 10;
3991 yend = 490;
3992 }
3993 /* OV7670 hardware window registers are split across
3994 * multiple locations */
3995 i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
3996 i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
3997 v = i2c_r(sd, OV7670_R32_HREF);
3998 v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
3999 msleep(10); /* need to sleep between read and write to
4000 * same reg! */
4001 i2c_w(sd, OV7670_R32_HREF, v);
4002
4003 i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
4004 i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
4005 v = i2c_r(sd, OV7670_R03_VREF);
4006 v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
4007 msleep(10); /* need to sleep between read and write to
4008 * same reg! */
4009 i2c_w(sd, OV7670_R03_VREF, v);
4010 break;
4011 case SEN_OV6620:
4012 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4013 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
4014 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4015 break;
4016 case SEN_OV6630:
4017 case SEN_OV66308AF:
4018 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4019 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4020 break;
4021 case SEN_OV9600: {
4022 const struct ov_i2c_regvals *vals;
4023 static const struct ov_i2c_regvals sxga_15[] = {
4024 {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
4025 };
4026 static const struct ov_i2c_regvals sxga_7_5[] = {
4027 {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
4028 };
4029 static const struct ov_i2c_regvals vga_30[] = {
4030 {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
4031 };
4032 static const struct ov_i2c_regvals vga_15[] = {
4033 {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
4034 };
4035
4036 /* frame rates:
4037 * 15fps / 7.5 fps for 1280x1024
4038 * 30fps / 15fps for 640x480
4039 */
4040 i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
4041 if (qvga)
4042 vals = sd->frame_rate < 30 ? vga_15 : vga_30;
4043 else
4044 vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
4045 write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
4046 return;
4047 }
4048 default:
4049 return;
4050 }
4051
4052 /******** Clock programming ********/
4053 i2c_w(sd, 0x11, sd->clockdiv);
4054}
4055
4056/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
4057static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
4058{
4059 struct sd *sd = (struct sd *) gspca_dev;
4060
4061 if (sd->gspca_dev.streaming)
4062 reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */
4063 i2c_w_mask(sd, OV7670_R1E_MVFP,
4064 OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip,
4065 OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
4066 if (sd->gspca_dev.streaming)
4067 reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */
4068}
4069
4070static void set_ov_sensor_window(struct sd *sd)
4071{
4072 struct gspca_dev *gspca_dev;
4073 int qvga, crop;
4074 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
4075
4076 /* mode setup is fully handled in mode_init_ov_sensor_regs for these */
4077 switch (sd->sensor) {
4078 case SEN_OV2610:
4079 case SEN_OV2610AE:
4080 case SEN_OV3610:
4081 case SEN_OV7670:
4082 case SEN_OV9600:
4083 mode_init_ov_sensor_regs(sd);
4084 return;
4085 case SEN_OV7660:
4086 ov519_set_mode(sd);
4087 ov519_set_fr(sd);
4088 return;
4089 }
4090
4091 gspca_dev = &sd->gspca_dev;
4092 qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
4093 crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
4094
4095 /* The different sensor ICs handle setting up of window differently.
4096 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
4097 switch (sd->sensor) {
4098 case SEN_OV8610:
4099 hwsbase = 0x1e;
4100 hwebase = 0x1e;
4101 vwsbase = 0x02;
4102 vwebase = 0x02;
4103 break;
4104 case SEN_OV7610:
4105 case SEN_OV76BE:
4106 hwsbase = 0x38;
4107 hwebase = 0x3a;
4108 vwsbase = vwebase = 0x05;
4109 break;
4110 case SEN_OV6620:
4111 case SEN_OV6630:
4112 case SEN_OV66308AF:
4113 hwsbase = 0x38;
4114 hwebase = 0x3a;
4115 vwsbase = 0x05;
4116 vwebase = 0x06;
4117 if (sd->sensor == SEN_OV66308AF && qvga)
4118 /* HDG: this fixes U and V getting swapped */
4119 hwsbase++;
4120 if (crop) {
4121 hwsbase += 8;
4122 hwebase += 8;
4123 vwsbase += 11;
4124 vwebase += 11;
4125 }
4126 break;
4127 case SEN_OV7620:
4128 case SEN_OV7620AE:
4129 hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
4130 hwebase = 0x2f;
4131 vwsbase = vwebase = 0x05;
4132 break;
4133 case SEN_OV7640:
4134 case SEN_OV7648:
4135 hwsbase = 0x1a;
4136 hwebase = 0x1a;
4137 vwsbase = vwebase = 0x03;
4138 break;
4139 default:
4140 return;
4141 }
4142
4143 switch (sd->sensor) {
4144 case SEN_OV6620:
4145 case SEN_OV6630:
4146 case SEN_OV66308AF:
4147 if (qvga) { /* QCIF */
4148 hwscale = 0;
4149 vwscale = 0;
4150 } else { /* CIF */
4151 hwscale = 1;
4152 vwscale = 1; /* The datasheet says 0;
4153 * it's wrong */
4154 }
4155 break;
4156 case SEN_OV8610:
4157 if (qvga) { /* QSVGA */
4158 hwscale = 1;
4159 vwscale = 1;
4160 } else { /* SVGA */
4161 hwscale = 2;
4162 vwscale = 2;
4163 }
4164 break;
4165 default: /* SEN_OV7xx0 */
4166 if (qvga) { /* QVGA */
4167 hwscale = 1;
4168 vwscale = 0;
4169 } else { /* VGA */
4170 hwscale = 2;
4171 vwscale = 1;
4172 }
4173 }
4174
4175 mode_init_ov_sensor_regs(sd);
4176
4177 i2c_w(sd, 0x17, hwsbase);
4178 i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
4179 i2c_w(sd, 0x19, vwsbase);
4180 i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
4181}
4182
4183/* -- start the camera -- */
4184static int sd_start(struct gspca_dev *gspca_dev)
4185{
4186 struct sd *sd = (struct sd *) gspca_dev;
4187
4188 /* Default for most bridges, allow bridge_mode_init_regs to override */
4189 sd->sensor_width = sd->gspca_dev.width;
4190 sd->sensor_height = sd->gspca_dev.height;
4191
4192 switch (sd->bridge) {
4193 case BRIDGE_OV511:
4194 case BRIDGE_OV511PLUS:
4195 ov511_mode_init_regs(sd);
4196 break;
4197 case BRIDGE_OV518:
4198 case BRIDGE_OV518PLUS:
4199 ov518_mode_init_regs(sd);
4200 break;
4201 case BRIDGE_OV519:
4202 ov519_mode_init_regs(sd);
4203 break;
4204 /* case BRIDGE_OVFX2: nothing to do */
4205 case BRIDGE_W9968CF:
4206 w9968cf_mode_init_regs(sd);
4207 break;
4208 }
4209
4210 set_ov_sensor_window(sd);
4211
4212 /* Force clear snapshot state in case the snapshot button was
4213 pressed while we weren't streaming */
4214 sd->snapshot_needs_reset = 1;
4215 sd_reset_snapshot(gspca_dev);
4216
4217 sd->first_frame = 3;
4218
4219 ov51x_restart(sd);
4220 ov51x_led_control(sd, 1);
4221 return gspca_dev->usb_err;
4222}
4223
4224static void sd_stopN(struct gspca_dev *gspca_dev)
4225{
4226 struct sd *sd = (struct sd *) gspca_dev;
4227
4228 ov51x_stop(sd);
4229 ov51x_led_control(sd, 0);
4230}
4231
4232static void sd_stop0(struct gspca_dev *gspca_dev)
4233{
4234 struct sd *sd = (struct sd *) gspca_dev;
4235
4236 if (!sd->gspca_dev.present)
4237 return;
4238 if (sd->bridge == BRIDGE_W9968CF)
4239 w9968cf_stop0(sd);
4240
4241#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
4242 /* If the last button state is pressed, release it now! */
4243 if (sd->snapshot_pressed) {
4244 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
4245 input_sync(gspca_dev->input_dev);
4246 sd->snapshot_pressed = 0;
4247 }
4248#endif
4249 if (sd->bridge == BRIDGE_OV519)
4250 reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
4251}
4252
4253static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
4254{
4255 struct sd *sd = (struct sd *) gspca_dev;
4256
4257 if (sd->snapshot_pressed != state) {
4258#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
4259 input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
4260 input_sync(gspca_dev->input_dev);
4261#endif
4262 if (state)
4263 sd->snapshot_needs_reset = 1;
4264
4265 sd->snapshot_pressed = state;
4266 } else {
4267 /* On the ov511 / ov519 we need to reset the button state
4268 multiple times, as resetting does not work as long as the
4269 button stays pressed */
4270 switch (sd->bridge) {
4271 case BRIDGE_OV511:
4272 case BRIDGE_OV511PLUS:
4273 case BRIDGE_OV519:
4274 if (state)
4275 sd->snapshot_needs_reset = 1;
4276 break;
4277 }
4278 }
4279}
4280
4281static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
4282 u8 *in, /* isoc packet */
4283 int len) /* iso packet length */
4284{
4285 struct sd *sd = (struct sd *) gspca_dev;
4286
4287 /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
4288 * byte non-zero. The EOF packet has image width/height in the
4289 * 10th and 11th bytes. The 9th byte is given as follows:
4290 *
4291 * bit 7: EOF
4292 * 6: compression enabled
4293 * 5: 422/420/400 modes
4294 * 4: 422/420/400 modes
4295 * 3: 1
4296 * 2: snapshot button on
4297 * 1: snapshot frame
4298 * 0: even/odd field
4299 */
4300 if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
4301 (in[8] & 0x08)) {
4302 ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
4303 if (in[8] & 0x80) {
4304 /* Frame end */
4305 if ((in[9] + 1) * 8 != gspca_dev->width ||
4306 (in[10] + 1) * 8 != gspca_dev->height) {
4307 PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
4308 " requested: %dx%d\n",
4309 (in[9] + 1) * 8, (in[10] + 1) * 8,
4310 gspca_dev->width, gspca_dev->height);
4311 gspca_dev->last_packet_type = DISCARD_PACKET;
4312 return;
4313 }
4314 /* Add 11 byte footer to frame, might be useful */
4315 gspca_frame_add(gspca_dev, LAST_PACKET, in, 11);
4316 return;
4317 } else {
4318 /* Frame start */
4319 gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0);
4320 sd->packet_nr = 0;
4321 }
4322 }
4323
4324 /* Ignore the packet number */
4325 len--;
4326
4327 /* intermediate packet */
4328 gspca_frame_add(gspca_dev, INTER_PACKET, in, len);
4329}
4330
4331static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
4332 u8 *data, /* isoc packet */
4333 int len) /* iso packet length */
4334{
4335 struct sd *sd = (struct sd *) gspca_dev;
4336
4337 /* A false positive here is likely, until OVT gives me
4338 * the definitive SOF/EOF format */
4339 if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
4340 ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1);
4341 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
4342 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
4343 sd->packet_nr = 0;
4344 }
4345
4346 if (gspca_dev->last_packet_type == DISCARD_PACKET)
4347 return;
4348
4349 /* Does this device use packet numbers ? */
4350 if (len & 7) {
4351 len--;
4352 if (sd->packet_nr == data[len])
4353 sd->packet_nr++;
4354 /* The last few packets of the frame (which are all 0's
4355 except that they may contain part of the footer), are
4356 numbered 0 */
4357 else if (sd->packet_nr == 0 || data[len]) {
4358 PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
4359 (int)data[len], (int)sd->packet_nr);
4360 gspca_dev->last_packet_type = DISCARD_PACKET;
4361 return;
4362 }
4363 }
4364
4365 /* intermediate packet */
4366 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4367}
4368
4369static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
4370 u8 *data, /* isoc packet */
4371 int len) /* iso packet length */
4372{
4373 /* Header of ov519 is 16 bytes:
4374 * Byte Value Description
4375 * 0 0xff magic
4376 * 1 0xff magic
4377 * 2 0xff magic
4378 * 3 0xXX 0x50 = SOF, 0x51 = EOF
4379 * 9 0xXX 0x01 initial frame without data,
4380 * 0x00 standard frame with image
4381 * 14 Lo in EOF: length of image data / 8
4382 * 15 Hi
4383 */
4384
4385 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
4386 switch (data[3]) {
4387 case 0x50: /* start of frame */
4388 /* Don't check the button state here, as the state
4389 usually (always ?) changes at EOF and checking it
4390 here leads to unnecessary snapshot state resets. */
4391#define HDRSZ 16
4392 data += HDRSZ;
4393 len -= HDRSZ;
4394#undef HDRSZ
4395 if (data[0] == 0xff || data[1] == 0xd8)
4396 gspca_frame_add(gspca_dev, FIRST_PACKET,
4397 data, len);
4398 else
4399 gspca_dev->last_packet_type = DISCARD_PACKET;
4400 return;
4401 case 0x51: /* end of frame */
4402 ov51x_handle_button(gspca_dev, data[11] & 1);
4403 if (data[9] != 0)
4404 gspca_dev->last_packet_type = DISCARD_PACKET;
4405 gspca_frame_add(gspca_dev, LAST_PACKET,
4406 NULL, 0);
4407 return;
4408 }
4409 }
4410
4411 /* intermediate packet */
4412 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4413}
4414
4415static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
4416 u8 *data, /* isoc packet */
4417 int len) /* iso packet length */
4418{
4419 struct sd *sd = (struct sd *) gspca_dev;
4420
4421 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4422
4423 /* A short read signals EOF */
4424 if (len < gspca_dev->cam.bulk_size) {
4425 /* If the frame is short, and it is one of the first ones
4426 the sensor and bridge are still syncing, so drop it. */
4427 if (sd->first_frame) {
4428 sd->first_frame--;
4429 if (gspca_dev->image_len <
4430 sd->gspca_dev.width * sd->gspca_dev.height)
4431 gspca_dev->last_packet_type = DISCARD_PACKET;
4432 }
4433 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
4434 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
4435 }
4436}
4437
4438static void sd_pkt_scan(struct gspca_dev *gspca_dev,
4439 u8 *data, /* isoc packet */
4440 int len) /* iso packet length */
4441{
4442 struct sd *sd = (struct sd *) gspca_dev;
4443
4444 switch (sd->bridge) {
4445 case BRIDGE_OV511:
4446 case BRIDGE_OV511PLUS:
4447 ov511_pkt_scan(gspca_dev, data, len);
4448 break;
4449 case BRIDGE_OV518:
4450 case BRIDGE_OV518PLUS:
4451 ov518_pkt_scan(gspca_dev, data, len);
4452 break;
4453 case BRIDGE_OV519:
4454 ov519_pkt_scan(gspca_dev, data, len);
4455 break;
4456 case BRIDGE_OVFX2:
4457 ovfx2_pkt_scan(gspca_dev, data, len);
4458 break;
4459 case BRIDGE_W9968CF:
4460 w9968cf_pkt_scan(gspca_dev, data, len);
4461 break;
4462 }
4463}
4464
4465/* -- management routines -- */
4466
4467static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
4468{
4469 struct sd *sd = (struct sd *) gspca_dev;
4470 static const struct ov_i2c_regvals brit_7660[][7] = {
4471 {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
4472 {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
4473 {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
4474 {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
4475 {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
4476 {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
4477 {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
4478 {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
4479 {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
4480 {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
4481 {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
4482 {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
4483 {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
4484 {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
4485 };
4486
4487 switch (sd->sensor) {
4488 case SEN_OV8610:
4489 case SEN_OV7610:
4490 case SEN_OV76BE:
4491 case SEN_OV6620:
4492 case SEN_OV6630:
4493 case SEN_OV66308AF:
4494 case SEN_OV7640:
4495 case SEN_OV7648:
4496 i2c_w(sd, OV7610_REG_BRT, val);
4497 break;
4498 case SEN_OV7620:
4499 case SEN_OV7620AE:
4500 i2c_w(sd, OV7610_REG_BRT, val);
4501 break;
4502 case SEN_OV7660:
4503 write_i2c_regvals(sd, brit_7660[val],
4504 ARRAY_SIZE(brit_7660[0]));
4505 break;
4506 case SEN_OV7670:
4507/*win trace
4508 * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
4509 i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
4510 break;
4511 }
4512}
4513
4514static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
4515{
4516 struct sd *sd = (struct sd *) gspca_dev;
4517 static const struct ov_i2c_regvals contrast_7660[][31] = {
4518 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
4519 {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
4520 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
4521 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
4522 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
4523 {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
4524 {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
4525 {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
4526 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
4527 {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
4528 {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
4529 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
4530 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
4531 {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
4532 {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
4533 {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
4534 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
4535 {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
4536 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
4537 {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
4538 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
4539 {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
4540 {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
4541 {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
4542 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
4543 {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
4544 {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
4545 {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
4546 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
4547 {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
4548 {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
4549 {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
4550 {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
4551 {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
4552 {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
4553 {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
4554 {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
4555 {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
4556 {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
4557 {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
4558 {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
4559 {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
4560 {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
4561 {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
4562 {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
4563 {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
4564 {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
4565 {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
4566 {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
4567 {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
4568 {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
4569 {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
4570 {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
4571 {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
4572 {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
4573 {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
4574 };
4575
4576 switch (sd->sensor) {
4577 case SEN_OV7610:
4578 case SEN_OV6620:
4579 i2c_w(sd, OV7610_REG_CNT, val);
4580 break;
4581 case SEN_OV6630:
4582 case SEN_OV66308AF:
4583 i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
4584 break;
4585 case SEN_OV8610: {
4586 static const u8 ctab[] = {
4587 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
4588 };
4589
4590 /* Use Y gamma control instead. Bit 0 enables it. */
4591 i2c_w(sd, 0x64, ctab[val >> 5]);
4592 break;
4593 }
4594 case SEN_OV7620:
4595 case SEN_OV7620AE: {
4596 static const u8 ctab[] = {
4597 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
4598 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
4599 };
4600
4601 /* Use Y gamma control instead. Bit 0 enables it. */
4602 i2c_w(sd, 0x64, ctab[val >> 4]);
4603 break;
4604 }
4605 case SEN_OV7660:
4606 write_i2c_regvals(sd, contrast_7660[val],
4607 ARRAY_SIZE(contrast_7660[0]));
4608 break;
4609 case SEN_OV7670:
4610 /* check that this isn't just the same as ov7610 */
4611 i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
4612 break;
4613 }
4614}
4615
4616static void setexposure(struct gspca_dev *gspca_dev, s32 val)
4617{
4618 struct sd *sd = (struct sd *) gspca_dev;
4619
4620 i2c_w(sd, 0x10, val);
4621}
4622
4623static void setcolors(struct gspca_dev *gspca_dev, s32 val)
4624{
4625 struct sd *sd = (struct sd *) gspca_dev;
4626 static const struct ov_i2c_regvals colors_7660[][6] = {
4627 {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
4628 {0x53, 0x19}, {0x54, 0x23}},
4629 {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
4630 {0x53, 0x2c}, {0x54, 0x3e}},
4631 {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
4632 {0x53, 0x40}, {0x54, 0x59}},
4633 {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
4634 {0x53, 0x53}, {0x54, 0x73}},
4635 {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
4636 {0x53, 0x66}, {0x54, 0x8e}},
4637 };
4638
4639 switch (sd->sensor) {
4640 case SEN_OV8610:
4641 case SEN_OV7610:
4642 case SEN_OV76BE:
4643 case SEN_OV6620:
4644 case SEN_OV6630:
4645 case SEN_OV66308AF:
4646 i2c_w(sd, OV7610_REG_SAT, val);
4647 break;
4648 case SEN_OV7620:
4649 case SEN_OV7620AE:
4650 /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
4651/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
4652 if (rc < 0)
4653 goto out; */
4654 i2c_w(sd, OV7610_REG_SAT, val);
4655 break;
4656 case SEN_OV7640:
4657 case SEN_OV7648:
4658 i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
4659 break;
4660 case SEN_OV7660:
4661 write_i2c_regvals(sd, colors_7660[val],
4662 ARRAY_SIZE(colors_7660[0]));
4663 break;
4664 case SEN_OV7670:
4665 /* supported later once I work out how to do it
4666 * transparently fail now! */
4667 /* set REG_COM13 values for UV sat auto mode */
4668 break;
4669 }
4670}
4671
4672static void setautobright(struct gspca_dev *gspca_dev, s32 val)
4673{
4674 struct sd *sd = (struct sd *) gspca_dev;
4675
4676 i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10);
4677}
4678
4679static void setfreq_i(struct sd *sd, s32 val)
4680{
4681 if (sd->sensor == SEN_OV7660
4682 || sd->sensor == SEN_OV7670) {
4683 switch (val) {
4684 case 0: /* Banding filter disabled */
4685 i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
4686 break;
4687 case 1: /* 50 hz */
4688 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
4689 OV7670_COM8_BFILT);
4690 i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
4691 break;
4692 case 2: /* 60 hz */
4693 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
4694 OV7670_COM8_BFILT);
4695 i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
4696 break;
4697 case 3: /* Auto hz - ov7670 only */
4698 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
4699 OV7670_COM8_BFILT);
4700 i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
4701 0x18);
4702 break;
4703 }
4704 } else {
4705 switch (val) {
4706 case 0: /* Banding filter disabled */
4707 i2c_w_mask(sd, 0x2d, 0x00, 0x04);
4708 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
4709 break;
4710 case 1: /* 50 hz (filter on and framerate adj) */
4711 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
4712 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
4713 /* 20 fps -> 16.667 fps */
4714 if (sd->sensor == SEN_OV6620 ||
4715 sd->sensor == SEN_OV6630 ||
4716 sd->sensor == SEN_OV66308AF)
4717 i2c_w(sd, 0x2b, 0x5e);
4718 else
4719 i2c_w(sd, 0x2b, 0xac);
4720 break;
4721 case 2: /* 60 hz (filter on, ...) */
4722 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
4723 if (sd->sensor == SEN_OV6620 ||
4724 sd->sensor == SEN_OV6630 ||
4725 sd->sensor == SEN_OV66308AF) {
4726 /* 20 fps -> 15 fps */
4727 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
4728 i2c_w(sd, 0x2b, 0xa8);
4729 } else {
4730 /* no framerate adj. */
4731 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
4732 }
4733 break;
4734 }
4735 }
4736}
4737
4738static void setfreq(struct gspca_dev *gspca_dev, s32 val)
4739{
4740 struct sd *sd = (struct sd *) gspca_dev;
4741
4742 setfreq_i(sd, val);
4743
4744 /* Ugly but necessary */
4745 if (sd->bridge == BRIDGE_W9968CF)
4746 w9968cf_set_crop_window(sd);
4747}
4748
4749static int sd_get_jcomp(struct gspca_dev *gspca_dev,
4750 struct v4l2_jpegcompression *jcomp)
4751{
4752 struct sd *sd = (struct sd *) gspca_dev;
4753
4754 if (sd->bridge != BRIDGE_W9968CF)
4755 return -ENOTTY;
4756
4757 memset(jcomp, 0, sizeof *jcomp);
4758 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
4759 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
4760 V4L2_JPEG_MARKER_DRI;
4761 return 0;
4762}
4763
4764static int sd_set_jcomp(struct gspca_dev *gspca_dev,
4765 struct v4l2_jpegcompression *jcomp)
4766{
4767 struct sd *sd = (struct sd *) gspca_dev;
4768
4769 if (sd->bridge != BRIDGE_W9968CF)
4770 return -ENOTTY;
4771
4772 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
4773 return 0;
4774}
4775
4776static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
4777{
4778 struct gspca_dev *gspca_dev =
4779 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
4780 struct sd *sd = (struct sd *)gspca_dev;
4781
4782 gspca_dev->usb_err = 0;
4783
4784 switch (ctrl->id) {
4785 case V4L2_CID_AUTOGAIN:
4786 gspca_dev->exposure->val = i2c_r(sd, 0x10);
4787 break;
4788 }
4789 return 0;
4790}
4791
4792static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
4793{
4794 struct gspca_dev *gspca_dev =
4795 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
4796 struct sd *sd = (struct sd *)gspca_dev;
4797
4798 gspca_dev->usb_err = 0;
4799
4800 if (!gspca_dev->streaming)
4801 return 0;
4802
4803 switch (ctrl->id) {
4804 case V4L2_CID_BRIGHTNESS:
4805 setbrightness(gspca_dev, ctrl->val);
4806 break;
4807 case V4L2_CID_CONTRAST:
4808 setcontrast(gspca_dev, ctrl->val);
4809 break;
4810 case V4L2_CID_POWER_LINE_FREQUENCY:
4811 setfreq(gspca_dev, ctrl->val);
4812 break;
4813 case V4L2_CID_AUTOBRIGHTNESS:
4814 if (ctrl->is_new)
4815 setautobright(gspca_dev, ctrl->val);
4816 if (!ctrl->val && sd->brightness->is_new)
4817 setbrightness(gspca_dev, sd->brightness->val);
4818 break;
4819 case V4L2_CID_SATURATION:
4820 setcolors(gspca_dev, ctrl->val);
4821 break;
4822 case V4L2_CID_HFLIP:
4823 sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
4824 break;
4825 case V4L2_CID_AUTOGAIN:
4826 if (ctrl->is_new)
4827 setautogain(gspca_dev, ctrl->val);
4828 if (!ctrl->val && gspca_dev->exposure->is_new)
4829 setexposure(gspca_dev, gspca_dev->exposure->val);
4830 break;
4831 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
4832 return -EBUSY; /* Should never happen, as we grab the ctrl */
4833 }
4834 return gspca_dev->usb_err;
4835}
4836
4837static const struct v4l2_ctrl_ops sd_ctrl_ops = {
4838 .g_volatile_ctrl = sd_g_volatile_ctrl,
4839 .s_ctrl = sd_s_ctrl,
4840};
4841
4842static int sd_init_controls(struct gspca_dev *gspca_dev)
4843{
4844 struct sd *sd = (struct sd *)gspca_dev;
4845 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
4846
4847 gspca_dev->vdev.ctrl_handler = hdl;
4848 v4l2_ctrl_handler_init(hdl, 10);
4849 if (valid_controls[sd->sensor].has_brightness)
4850 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4851 V4L2_CID_BRIGHTNESS, 0,
4852 sd->sensor == SEN_OV7660 ? 6 : 255, 1,
4853 sd->sensor == SEN_OV7660 ? 3 : 127);
4854 if (valid_controls[sd->sensor].has_contrast) {
4855 if (sd->sensor == SEN_OV7660)
4856 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4857 V4L2_CID_CONTRAST, 0, 6, 1, 3);
4858 else
4859 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4860 V4L2_CID_CONTRAST, 0, 255, 1,
4861 (sd->sensor == SEN_OV6630 ||
4862 sd->sensor == SEN_OV66308AF) ? 200 : 127);
4863 }
4864 if (valid_controls[sd->sensor].has_sat)
4865 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4866 V4L2_CID_SATURATION, 0,
4867 sd->sensor == SEN_OV7660 ? 4 : 255, 1,
4868 sd->sensor == SEN_OV7660 ? 2 : 127);
4869 if (valid_controls[sd->sensor].has_exposure)
4870 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4871 V4L2_CID_EXPOSURE, 0, 255, 1, 127);
4872 if (valid_controls[sd->sensor].has_hvflip) {
4873 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4874 V4L2_CID_HFLIP, 0, 1, 1, 0);
4875 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4876 V4L2_CID_VFLIP, 0, 1, 1, 0);
4877 }
4878 if (valid_controls[sd->sensor].has_autobright)
4879 sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4880 V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1);
4881 if (valid_controls[sd->sensor].has_autogain)
4882 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4883 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
4884 if (valid_controls[sd->sensor].has_freq) {
4885 if (sd->sensor == SEN_OV7670)
4886 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
4887 V4L2_CID_POWER_LINE_FREQUENCY,
4888 V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
4889 V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
4890 else
4891 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
4892 V4L2_CID_POWER_LINE_FREQUENCY,
4893 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
4894 }
4895 if (sd->bridge == BRIDGE_W9968CF)
4896 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4897 V4L2_CID_JPEG_COMPRESSION_QUALITY,
4898 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
4899
4900 if (hdl->error) {
4901 pr_err("Could not initialize controls\n");
4902 return hdl->error;
4903 }
4904 if (gspca_dev->autogain)
4905 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true);
4906 if (sd->autobright)
4907 v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false);
4908 if (sd->hflip)
4909 v4l2_ctrl_cluster(2, &sd->hflip);
4910 return 0;
4911}
4912
4913/* sub-driver description */
4914static const struct sd_desc sd_desc = {
4915 .name = MODULE_NAME,
4916 .config = sd_config,
4917 .init = sd_init,
4918 .init_controls = sd_init_controls,
4919 .isoc_init = sd_isoc_init,
4920 .start = sd_start,
4921 .stopN = sd_stopN,
4922 .stop0 = sd_stop0,
4923 .pkt_scan = sd_pkt_scan,
4924 .dq_callback = sd_reset_snapshot,
4925 .get_jcomp = sd_get_jcomp,
4926 .set_jcomp = sd_set_jcomp,
4927#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
4928 .other_input = 1,
4929#endif
4930};
4931
4932/* -- module initialisation -- */
4933static const struct usb_device_id device_table[] = {
4934 {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
4935 {USB_DEVICE(0x041e, 0x4052),
4936 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
4937 {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
4938 {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
4939 {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
4940 {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
4941 {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
4942 {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
4943 {USB_DEVICE(0x045e, 0x028c),
4944 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
4945 {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
4946 {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
4947 {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
4948 {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
4949 {USB_DEVICE(0x05a9, 0x0519),
4950 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
4951 {USB_DEVICE(0x05a9, 0x0530),
4952 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
4953 {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
4954 {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
4955 {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
4956 {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
4957 {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
4958 {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
4959 {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
4960 {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
4961 {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
4962 {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
4963 {}
4964};
4965
4966MODULE_DEVICE_TABLE(usb, device_table);
4967
4968/* -- device connect -- */
4969static int sd_probe(struct usb_interface *intf,
4970 const struct usb_device_id *id)
4971{
4972 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
4973 THIS_MODULE);
4974}
4975
4976static struct usb_driver sd_driver = {
4977 .name = MODULE_NAME,
4978 .id_table = device_table,
4979 .probe = sd_probe,
4980 .disconnect = gspca_disconnect,
4981#ifdef CONFIG_PM
4982 .suspend = gspca_suspend,
4983 .resume = gspca_resume,
4984 .reset_resume = gspca_resume,
4985#endif
4986};
4987
4988module_usb_driver(sd_driver);
4989
4990module_param(frame_rate, int, 0644);
4991MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
new file mode 100644
index 00000000000..bb09d7884b8
--- /dev/null
+++ b/drivers/media/usb/gspca/ov534.c
@@ -0,0 +1,1544 @@
1/*
2 * ov534-ov7xxx gspca driver
3 *
4 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
5 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
6 * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
7 *
8 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
9 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
10 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
11 *
12 * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr
13 * PS3 Eye camera - brightness, contrast, awb, agc, aec controls
14 * added by Max Thrun <bear24rw@gmail.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 */
30
31#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32
33#define MODULE_NAME "ov534"
34
35#include "gspca.h"
36
37#include <linux/fixp-arith.h>
38#include <media/v4l2-ctrls.h>
39
40#define OV534_REG_ADDRESS 0xf1 /* sensor address */
41#define OV534_REG_SUBADDR 0xf2
42#define OV534_REG_WRITE 0xf3
43#define OV534_REG_READ 0xf4
44#define OV534_REG_OPERATION 0xf5
45#define OV534_REG_STATUS 0xf6
46
47#define OV534_OP_WRITE_3 0x37
48#define OV534_OP_WRITE_2 0x33
49#define OV534_OP_READ_2 0xf9
50
51#define CTRL_TIMEOUT 500
52
53MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
54MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
55MODULE_LICENSE("GPL");
56
57/* specific webcam descriptor */
58struct sd {
59 struct gspca_dev gspca_dev; /* !! must be the first item */
60
61 struct v4l2_ctrl_handler ctrl_handler;
62 struct v4l2_ctrl *hue;
63 struct v4l2_ctrl *saturation;
64 struct v4l2_ctrl *brightness;
65 struct v4l2_ctrl *contrast;
66 struct { /* gain control cluster */
67 struct v4l2_ctrl *autogain;
68 struct v4l2_ctrl *gain;
69 };
70 struct v4l2_ctrl *autowhitebalance;
71 struct { /* exposure control cluster */
72 struct v4l2_ctrl *autoexposure;
73 struct v4l2_ctrl *exposure;
74 };
75 struct v4l2_ctrl *sharpness;
76 struct v4l2_ctrl *hflip;
77 struct v4l2_ctrl *vflip;
78 struct v4l2_ctrl *plfreq;
79
80 __u32 last_pts;
81 u16 last_fid;
82 u8 frame_rate;
83
84 u8 sensor;
85};
86enum sensors {
87 SENSOR_OV767x,
88 SENSOR_OV772x,
89 NSENSORS
90};
91
92static int sd_start(struct gspca_dev *gspca_dev);
93static void sd_stopN(struct gspca_dev *gspca_dev);
94
95
96static const struct v4l2_pix_format ov772x_mode[] = {
97 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
98 .bytesperline = 320 * 2,
99 .sizeimage = 320 * 240 * 2,
100 .colorspace = V4L2_COLORSPACE_SRGB,
101 .priv = 1},
102 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
103 .bytesperline = 640 * 2,
104 .sizeimage = 640 * 480 * 2,
105 .colorspace = V4L2_COLORSPACE_SRGB,
106 .priv = 0},
107};
108static const struct v4l2_pix_format ov767x_mode[] = {
109 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
110 .bytesperline = 320,
111 .sizeimage = 320 * 240 * 3 / 8 + 590,
112 .colorspace = V4L2_COLORSPACE_JPEG},
113 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
114 .bytesperline = 640,
115 .sizeimage = 640 * 480 * 3 / 8 + 590,
116 .colorspace = V4L2_COLORSPACE_JPEG},
117};
118
119static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
120static const u8 vga_rates[] = {60, 50, 40, 30, 15};
121
122static const struct framerates ov772x_framerates[] = {
123 { /* 320x240 */
124 .rates = qvga_rates,
125 .nrates = ARRAY_SIZE(qvga_rates),
126 },
127 { /* 640x480 */
128 .rates = vga_rates,
129 .nrates = ARRAY_SIZE(vga_rates),
130 },
131};
132
133struct reg_array {
134 const u8 (*val)[2];
135 int len;
136};
137
138static const u8 bridge_init_767x[][2] = {
139/* comments from the ms-win file apollo7670.set */
140/* str1 */
141 {0xf1, 0x42},
142 {0x88, 0xf8},
143 {0x89, 0xff},
144 {0x76, 0x03},
145 {0x92, 0x03},
146 {0x95, 0x10},
147 {0xe2, 0x00},
148 {0xe7, 0x3e},
149 {0x8d, 0x1c},
150 {0x8e, 0x00},
151 {0x8f, 0x00},
152 {0x1f, 0x00},
153 {0xc3, 0xf9},
154 {0x89, 0xff},
155 {0x88, 0xf8},
156 {0x76, 0x03},
157 {0x92, 0x01},
158 {0x93, 0x18},
159 {0x1c, 0x00},
160 {0x1d, 0x48},
161 {0x1d, 0x00},
162 {0x1d, 0xff},
163 {0x1d, 0x02},
164 {0x1d, 0x58},
165 {0x1d, 0x00},
166 {0x1c, 0x0a},
167 {0x1d, 0x0a},
168 {0x1d, 0x0e},
169 {0xc0, 0x50}, /* HSize 640 */
170 {0xc1, 0x3c}, /* VSize 480 */
171 {0x34, 0x05}, /* enable Audio Suspend mode */
172 {0xc2, 0x0c}, /* Input YUV */
173 {0xc3, 0xf9}, /* enable PRE */
174 {0x34, 0x05}, /* enable Audio Suspend mode */
175 {0xe7, 0x2e}, /* this solves failure of "SuspendResumeTest" */
176 {0x31, 0xf9}, /* enable 1.8V Suspend */
177 {0x35, 0x02}, /* turn on JPEG */
178 {0xd9, 0x10},
179 {0x25, 0x42}, /* GPIO[8]:Input */
180 {0x94, 0x11}, /* If the default setting is loaded when
181 * system boots up, this flag is closed here */
182};
183static const u8 sensor_init_767x[][2] = {
184 {0x12, 0x80},
185 {0x11, 0x03},
186 {0x3a, 0x04},
187 {0x12, 0x00},
188 {0x17, 0x13},
189 {0x18, 0x01},
190 {0x32, 0xb6},
191 {0x19, 0x02},
192 {0x1a, 0x7a},
193 {0x03, 0x0a},
194 {0x0c, 0x00},
195 {0x3e, 0x00},
196 {0x70, 0x3a},
197 {0x71, 0x35},
198 {0x72, 0x11},
199 {0x73, 0xf0},
200 {0xa2, 0x02},
201 {0x7a, 0x2a}, /* set Gamma=1.6 below */
202 {0x7b, 0x12},
203 {0x7c, 0x1d},
204 {0x7d, 0x2d},
205 {0x7e, 0x45},
206 {0x7f, 0x50},
207 {0x80, 0x59},
208 {0x81, 0x62},
209 {0x82, 0x6b},
210 {0x83, 0x73},
211 {0x84, 0x7b},
212 {0x85, 0x8a},
213 {0x86, 0x98},
214 {0x87, 0xb2},
215 {0x88, 0xca},
216 {0x89, 0xe0},
217 {0x13, 0xe0},
218 {0x00, 0x00},
219 {0x10, 0x00},
220 {0x0d, 0x40},
221 {0x14, 0x38}, /* gain max 16x */
222 {0xa5, 0x05},
223 {0xab, 0x07},
224 {0x24, 0x95},
225 {0x25, 0x33},
226 {0x26, 0xe3},
227 {0x9f, 0x78},
228 {0xa0, 0x68},
229 {0xa1, 0x03},
230 {0xa6, 0xd8},
231 {0xa7, 0xd8},
232 {0xa8, 0xf0},
233 {0xa9, 0x90},
234 {0xaa, 0x94},
235 {0x13, 0xe5},
236 {0x0e, 0x61},
237 {0x0f, 0x4b},
238 {0x16, 0x02},
239 {0x21, 0x02},
240 {0x22, 0x91},
241 {0x29, 0x07},
242 {0x33, 0x0b},
243 {0x35, 0x0b},
244 {0x37, 0x1d},
245 {0x38, 0x71},
246 {0x39, 0x2a},
247 {0x3c, 0x78},
248 {0x4d, 0x40},
249 {0x4e, 0x20},
250 {0x69, 0x00},
251 {0x6b, 0x4a},
252 {0x74, 0x10},
253 {0x8d, 0x4f},
254 {0x8e, 0x00},
255 {0x8f, 0x00},
256 {0x90, 0x00},
257 {0x91, 0x00},
258 {0x96, 0x00},
259 {0x9a, 0x80},
260 {0xb0, 0x84},
261 {0xb1, 0x0c},
262 {0xb2, 0x0e},
263 {0xb3, 0x82},
264 {0xb8, 0x0a},
265 {0x43, 0x0a},
266 {0x44, 0xf0},
267 {0x45, 0x34},
268 {0x46, 0x58},
269 {0x47, 0x28},
270 {0x48, 0x3a},
271 {0x59, 0x88},
272 {0x5a, 0x88},
273 {0x5b, 0x44},
274 {0x5c, 0x67},
275 {0x5d, 0x49},
276 {0x5e, 0x0e},
277 {0x6c, 0x0a},
278 {0x6d, 0x55},
279 {0x6e, 0x11},
280 {0x6f, 0x9f},
281 {0x6a, 0x40},
282 {0x01, 0x40},
283 {0x02, 0x40},
284 {0x13, 0xe7},
285 {0x4f, 0x80},
286 {0x50, 0x80},
287 {0x51, 0x00},
288 {0x52, 0x22},
289 {0x53, 0x5e},
290 {0x54, 0x80},
291 {0x58, 0x9e},
292 {0x41, 0x08},
293 {0x3f, 0x00},
294 {0x75, 0x04},
295 {0x76, 0xe1},
296 {0x4c, 0x00},
297 {0x77, 0x01},
298 {0x3d, 0xc2},
299 {0x4b, 0x09},
300 {0xc9, 0x60},
301 {0x41, 0x38}, /* jfm: auto sharpness + auto de-noise */
302 {0x56, 0x40},
303 {0x34, 0x11},
304 {0x3b, 0xc2},
305 {0xa4, 0x8a}, /* Night mode trigger point */
306 {0x96, 0x00},
307 {0x97, 0x30},
308 {0x98, 0x20},
309 {0x99, 0x20},
310 {0x9a, 0x84},
311 {0x9b, 0x29},
312 {0x9c, 0x03},
313 {0x9d, 0x4c},
314 {0x9e, 0x3f},
315 {0x78, 0x04},
316 {0x79, 0x01},
317 {0xc8, 0xf0},
318 {0x79, 0x0f},
319 {0xc8, 0x00},
320 {0x79, 0x10},
321 {0xc8, 0x7e},
322 {0x79, 0x0a},
323 {0xc8, 0x80},
324 {0x79, 0x0b},
325 {0xc8, 0x01},
326 {0x79, 0x0c},
327 {0xc8, 0x0f},
328 {0x79, 0x0d},
329 {0xc8, 0x20},
330 {0x79, 0x09},
331 {0xc8, 0x80},
332 {0x79, 0x02},
333 {0xc8, 0xc0},
334 {0x79, 0x03},
335 {0xc8, 0x20},
336 {0x79, 0x26},
337};
338static const u8 bridge_start_vga_767x[][2] = {
339/* str59 JPG */
340 {0x94, 0xaa},
341 {0xf1, 0x42},
342 {0xe5, 0x04},
343 {0xc0, 0x50},
344 {0xc1, 0x3c},
345 {0xc2, 0x0c},
346 {0x35, 0x02}, /* turn on JPEG */
347 {0xd9, 0x10},
348 {0xda, 0x00}, /* for higher clock rate(30fps) */
349 {0x34, 0x05}, /* enable Audio Suspend mode */
350 {0xc3, 0xf9}, /* enable PRE */
351 {0x8c, 0x00}, /* CIF VSize LSB[2:0] */
352 {0x8d, 0x1c}, /* output YUV */
353/* {0x34, 0x05}, * enable Audio Suspend mode (?) */
354 {0x50, 0x00}, /* H/V divider=0 */
355 {0x51, 0xa0}, /* input H=640/4 */
356 {0x52, 0x3c}, /* input V=480/4 */
357 {0x53, 0x00}, /* offset X=0 */
358 {0x54, 0x00}, /* offset Y=0 */
359 {0x55, 0x00}, /* H/V size[8]=0 */
360 {0x57, 0x00}, /* H-size[9]=0 */
361 {0x5c, 0x00}, /* output size[9:8]=0 */
362 {0x5a, 0xa0}, /* output H=640/4 */
363 {0x5b, 0x78}, /* output V=480/4 */
364 {0x1c, 0x0a},
365 {0x1d, 0x0a},
366 {0x94, 0x11},
367};
368static const u8 sensor_start_vga_767x[][2] = {
369 {0x11, 0x01},
370 {0x1e, 0x04},
371 {0x19, 0x02},
372 {0x1a, 0x7a},
373};
374static const u8 bridge_start_qvga_767x[][2] = {
375/* str86 JPG */
376 {0x94, 0xaa},
377 {0xf1, 0x42},
378 {0xe5, 0x04},
379 {0xc0, 0x80},
380 {0xc1, 0x60},
381 {0xc2, 0x0c},
382 {0x35, 0x02}, /* turn on JPEG */
383 {0xd9, 0x10},
384 {0xc0, 0x50}, /* CIF HSize 640 */
385 {0xc1, 0x3c}, /* CIF VSize 480 */
386 {0x8c, 0x00}, /* CIF VSize LSB[2:0] */
387 {0x8d, 0x1c}, /* output YUV */
388 {0x34, 0x05}, /* enable Audio Suspend mode */
389 {0xc2, 0x4c}, /* output YUV and Enable DCW */
390 {0xc3, 0xf9}, /* enable PRE */
391 {0x1c, 0x00}, /* indirect addressing */
392 {0x1d, 0x48}, /* output YUV422 */
393 {0x50, 0x89}, /* H/V divider=/2; plus DCW AVG */
394 {0x51, 0xa0}, /* DCW input H=640/4 */
395 {0x52, 0x78}, /* DCW input V=480/4 */
396 {0x53, 0x00}, /* offset X=0 */
397 {0x54, 0x00}, /* offset Y=0 */
398 {0x55, 0x00}, /* H/V size[8]=0 */
399 {0x57, 0x00}, /* H-size[9]=0 */
400 {0x5c, 0x00}, /* DCW output size[9:8]=0 */
401 {0x5a, 0x50}, /* DCW output H=320/4 */
402 {0x5b, 0x3c}, /* DCW output V=240/4 */
403 {0x1c, 0x0a},
404 {0x1d, 0x0a},
405 {0x94, 0x11},
406};
407static const u8 sensor_start_qvga_767x[][2] = {
408 {0x11, 0x01},
409 {0x1e, 0x04},
410 {0x19, 0x02},
411 {0x1a, 0x7a},
412};
413
414static const u8 bridge_init_772x[][2] = {
415 { 0xc2, 0x0c },
416 { 0x88, 0xf8 },
417 { 0xc3, 0x69 },
418 { 0x89, 0xff },
419 { 0x76, 0x03 },
420 { 0x92, 0x01 },
421 { 0x93, 0x18 },
422 { 0x94, 0x10 },
423 { 0x95, 0x10 },
424 { 0xe2, 0x00 },
425 { 0xe7, 0x3e },
426
427 { 0x96, 0x00 },
428
429 { 0x97, 0x20 },
430 { 0x97, 0x20 },
431 { 0x97, 0x20 },
432 { 0x97, 0x0a },
433 { 0x97, 0x3f },
434 { 0x97, 0x4a },
435 { 0x97, 0x20 },
436 { 0x97, 0x15 },
437 { 0x97, 0x0b },
438
439 { 0x8e, 0x40 },
440 { 0x1f, 0x81 },
441 { 0x34, 0x05 },
442 { 0xe3, 0x04 },
443 { 0x88, 0x00 },
444 { 0x89, 0x00 },
445 { 0x76, 0x00 },
446 { 0xe7, 0x2e },
447 { 0x31, 0xf9 },
448 { 0x25, 0x42 },
449 { 0x21, 0xf0 },
450
451 { 0x1c, 0x00 },
452 { 0x1d, 0x40 },
453 { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
454 { 0x1d, 0x00 }, /* payload size */
455
456 { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
457 { 0x1d, 0x58 }, /* frame size */
458 { 0x1d, 0x00 }, /* frame size */
459
460 { 0x1c, 0x0a },
461 { 0x1d, 0x08 }, /* turn on UVC header */
462 { 0x1d, 0x0e }, /* .. */
463
464 { 0x8d, 0x1c },
465 { 0x8e, 0x80 },
466 { 0xe5, 0x04 },
467
468 { 0xc0, 0x50 },
469 { 0xc1, 0x3c },
470 { 0xc2, 0x0c },
471};
472static const u8 sensor_init_772x[][2] = {
473 { 0x12, 0x80 },
474 { 0x11, 0x01 },
475/*fixme: better have a delay?*/
476 { 0x11, 0x01 },
477 { 0x11, 0x01 },
478 { 0x11, 0x01 },
479 { 0x11, 0x01 },
480 { 0x11, 0x01 },
481 { 0x11, 0x01 },
482 { 0x11, 0x01 },
483 { 0x11, 0x01 },
484 { 0x11, 0x01 },
485 { 0x11, 0x01 },
486
487 { 0x3d, 0x03 },
488 { 0x17, 0x26 },
489 { 0x18, 0xa0 },
490 { 0x19, 0x07 },
491 { 0x1a, 0xf0 },
492 { 0x32, 0x00 },
493 { 0x29, 0xa0 },
494 { 0x2c, 0xf0 },
495 { 0x65, 0x20 },
496 { 0x11, 0x01 },
497 { 0x42, 0x7f },
498 { 0x63, 0xaa }, /* AWB - was e0 */
499 { 0x64, 0xff },
500 { 0x66, 0x00 },
501 { 0x13, 0xf0 }, /* com8 */
502 { 0x0d, 0x41 },
503 { 0x0f, 0xc5 },
504 { 0x14, 0x11 },
505
506 { 0x22, 0x7f },
507 { 0x23, 0x03 },
508 { 0x24, 0x40 },
509 { 0x25, 0x30 },
510 { 0x26, 0xa1 },
511 { 0x2a, 0x00 },
512 { 0x2b, 0x00 },
513 { 0x6b, 0xaa },
514 { 0x13, 0xff }, /* AWB */
515
516 { 0x90, 0x05 },
517 { 0x91, 0x01 },
518 { 0x92, 0x03 },
519 { 0x93, 0x00 },
520 { 0x94, 0x60 },
521 { 0x95, 0x3c },
522 { 0x96, 0x24 },
523 { 0x97, 0x1e },
524 { 0x98, 0x62 },
525 { 0x99, 0x80 },
526 { 0x9a, 0x1e },
527 { 0x9b, 0x08 },
528 { 0x9c, 0x20 },
529 { 0x9e, 0x81 },
530
531 { 0xa6, 0x07 },
532 { 0x7e, 0x0c },
533 { 0x7f, 0x16 },
534 { 0x80, 0x2a },
535 { 0x81, 0x4e },
536 { 0x82, 0x61 },
537 { 0x83, 0x6f },
538 { 0x84, 0x7b },
539 { 0x85, 0x86 },
540 { 0x86, 0x8e },
541 { 0x87, 0x97 },
542 { 0x88, 0xa4 },
543 { 0x89, 0xaf },
544 { 0x8a, 0xc5 },
545 { 0x8b, 0xd7 },
546 { 0x8c, 0xe8 },
547 { 0x8d, 0x20 },
548
549 { 0x0c, 0x90 },
550
551 { 0x2b, 0x00 },
552 { 0x22, 0x7f },
553 { 0x23, 0x03 },
554 { 0x11, 0x01 },
555 { 0x0c, 0xd0 },
556 { 0x64, 0xff },
557 { 0x0d, 0x41 },
558
559 { 0x14, 0x41 },
560 { 0x0e, 0xcd },
561 { 0xac, 0xbf },
562 { 0x8e, 0x00 }, /* De-noise threshold */
563 { 0x0c, 0xd0 }
564};
565static const u8 bridge_start_vga_772x[][2] = {
566 {0x1c, 0x00},
567 {0x1d, 0x40},
568 {0x1d, 0x02},
569 {0x1d, 0x00},
570 {0x1d, 0x02},
571 {0x1d, 0x58},
572 {0x1d, 0x00},
573 {0xc0, 0x50},
574 {0xc1, 0x3c},
575};
576static const u8 sensor_start_vga_772x[][2] = {
577 {0x12, 0x00},
578 {0x17, 0x26},
579 {0x18, 0xa0},
580 {0x19, 0x07},
581 {0x1a, 0xf0},
582 {0x29, 0xa0},
583 {0x2c, 0xf0},
584 {0x65, 0x20},
585};
586static const u8 bridge_start_qvga_772x[][2] = {
587 {0x1c, 0x00},
588 {0x1d, 0x40},
589 {0x1d, 0x02},
590 {0x1d, 0x00},
591 {0x1d, 0x01},
592 {0x1d, 0x4b},
593 {0x1d, 0x00},
594 {0xc0, 0x28},
595 {0xc1, 0x1e},
596};
597static const u8 sensor_start_qvga_772x[][2] = {
598 {0x12, 0x40},
599 {0x17, 0x3f},
600 {0x18, 0x50},
601 {0x19, 0x03},
602 {0x1a, 0x78},
603 {0x29, 0x50},
604 {0x2c, 0x78},
605 {0x65, 0x2f},
606};
607
608static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
609{
610 struct usb_device *udev = gspca_dev->dev;
611 int ret;
612
613 if (gspca_dev->usb_err < 0)
614 return;
615
616 PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
617 gspca_dev->usb_buf[0] = val;
618 ret = usb_control_msg(udev,
619 usb_sndctrlpipe(udev, 0),
620 0x01,
621 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
622 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
623 if (ret < 0) {
624 pr_err("write failed %d\n", ret);
625 gspca_dev->usb_err = ret;
626 }
627}
628
629static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
630{
631 struct usb_device *udev = gspca_dev->dev;
632 int ret;
633
634 if (gspca_dev->usb_err < 0)
635 return 0;
636 ret = usb_control_msg(udev,
637 usb_rcvctrlpipe(udev, 0),
638 0x01,
639 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
640 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
641 PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
642 if (ret < 0) {
643 pr_err("read failed %d\n", ret);
644 gspca_dev->usb_err = ret;
645 }
646 return gspca_dev->usb_buf[0];
647}
648
649/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
650 * (direction and output)? */
651static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
652{
653 u8 data;
654
655 PDEBUG(D_CONF, "led status: %d", status);
656
657 data = ov534_reg_read(gspca_dev, 0x21);
658 data |= 0x80;
659 ov534_reg_write(gspca_dev, 0x21, data);
660
661 data = ov534_reg_read(gspca_dev, 0x23);
662 if (status)
663 data |= 0x80;
664 else
665 data &= ~0x80;
666
667 ov534_reg_write(gspca_dev, 0x23, data);
668
669 if (!status) {
670 data = ov534_reg_read(gspca_dev, 0x21);
671 data &= ~0x80;
672 ov534_reg_write(gspca_dev, 0x21, data);
673 }
674}
675
676static int sccb_check_status(struct gspca_dev *gspca_dev)
677{
678 u8 data;
679 int i;
680
681 for (i = 0; i < 5; i++) {
682 msleep(10);
683 data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
684
685 switch (data) {
686 case 0x00:
687 return 1;
688 case 0x04:
689 return 0;
690 case 0x03:
691 break;
692 default:
693 PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
694 data, i + 1);
695 }
696 }
697 return 0;
698}
699
700static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
701{
702 PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
703 ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
704 ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
705 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
706
707 if (!sccb_check_status(gspca_dev)) {
708 pr_err("sccb_reg_write failed\n");
709 gspca_dev->usb_err = -EIO;
710 }
711}
712
713static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
714{
715 ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
716 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
717 if (!sccb_check_status(gspca_dev))
718 pr_err("sccb_reg_read failed 1\n");
719
720 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
721 if (!sccb_check_status(gspca_dev))
722 pr_err("sccb_reg_read failed 2\n");
723
724 return ov534_reg_read(gspca_dev, OV534_REG_READ);
725}
726
727/* output a bridge sequence (reg - val) */
728static void reg_w_array(struct gspca_dev *gspca_dev,
729 const u8 (*data)[2], int len)
730{
731 while (--len >= 0) {
732 ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
733 data++;
734 }
735}
736
737/* output a sensor sequence (reg - val) */
738static void sccb_w_array(struct gspca_dev *gspca_dev,
739 const u8 (*data)[2], int len)
740{
741 while (--len >= 0) {
742 if ((*data)[0] != 0xff) {
743 sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
744 } else {
745 sccb_reg_read(gspca_dev, (*data)[1]);
746 sccb_reg_write(gspca_dev, 0xff, 0x00);
747 }
748 data++;
749 }
750}
751
752/* ov772x specific controls */
753static void set_frame_rate(struct gspca_dev *gspca_dev)
754{
755 struct sd *sd = (struct sd *) gspca_dev;
756 int i;
757 struct rate_s {
758 u8 fps;
759 u8 r11;
760 u8 r0d;
761 u8 re5;
762 };
763 const struct rate_s *r;
764 static const struct rate_s rate_0[] = { /* 640x480 */
765 {60, 0x01, 0xc1, 0x04},
766 {50, 0x01, 0x41, 0x02},
767 {40, 0x02, 0xc1, 0x04},
768 {30, 0x04, 0x81, 0x02},
769 {15, 0x03, 0x41, 0x04},
770 };
771 static const struct rate_s rate_1[] = { /* 320x240 */
772 {125, 0x02, 0x81, 0x02},
773 {100, 0x02, 0xc1, 0x04},
774 {75, 0x03, 0xc1, 0x04},
775 {60, 0x04, 0xc1, 0x04},
776 {50, 0x02, 0x41, 0x04},
777 {40, 0x03, 0x41, 0x04},
778 {30, 0x04, 0x41, 0x04},
779 };
780
781 if (sd->sensor != SENSOR_OV772x)
782 return;
783 if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
784 r = rate_0;
785 i = ARRAY_SIZE(rate_0);
786 } else {
787 r = rate_1;
788 i = ARRAY_SIZE(rate_1);
789 }
790 while (--i > 0) {
791 if (sd->frame_rate >= r->fps)
792 break;
793 r++;
794 }
795
796 sccb_reg_write(gspca_dev, 0x11, r->r11);
797 sccb_reg_write(gspca_dev, 0x0d, r->r0d);
798 ov534_reg_write(gspca_dev, 0xe5, r->re5);
799
800 PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
801}
802
803static void sethue(struct gspca_dev *gspca_dev, s32 val)
804{
805 struct sd *sd = (struct sd *) gspca_dev;
806
807 if (sd->sensor == SENSOR_OV767x) {
808 /* TBD */
809 } else {
810 s16 huesin;
811 s16 huecos;
812
813 /* fixp_sin and fixp_cos accept only positive values, while
814 * our val is between -90 and 90
815 */
816 val += 360;
817
818 /* According to the datasheet the registers expect HUESIN and
819 * HUECOS to be the result of the trigonometric functions,
820 * scaled by 0x80.
821 *
822 * The 0x100 here represents the maximun absolute value
823 * returned byt fixp_sin and fixp_cos, so the scaling will
824 * consider the result like in the interval [-1.0, 1.0].
825 */
826 huesin = fixp_sin(val) * 0x80 / 0x100;
827 huecos = fixp_cos(val) * 0x80 / 0x100;
828
829 if (huesin < 0) {
830 sccb_reg_write(gspca_dev, 0xab,
831 sccb_reg_read(gspca_dev, 0xab) | 0x2);
832 huesin = -huesin;
833 } else {
834 sccb_reg_write(gspca_dev, 0xab,
835 sccb_reg_read(gspca_dev, 0xab) & ~0x2);
836
837 }
838 sccb_reg_write(gspca_dev, 0xa9, (u8)huecos);
839 sccb_reg_write(gspca_dev, 0xaa, (u8)huesin);
840 }
841}
842
843static void setsaturation(struct gspca_dev *gspca_dev, s32 val)
844{
845 struct sd *sd = (struct sd *) gspca_dev;
846
847 if (sd->sensor == SENSOR_OV767x) {
848 int i;
849 static u8 color_tb[][6] = {
850 {0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
851 {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
852 {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
853 {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
854 {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
855 {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
856 {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
857 };
858
859 for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
860 sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
861 } else {
862 sccb_reg_write(gspca_dev, 0xa7, val); /* U saturation */
863 sccb_reg_write(gspca_dev, 0xa8, val); /* V saturation */
864 }
865}
866
867static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
868{
869 struct sd *sd = (struct sd *) gspca_dev;
870
871 if (sd->sensor == SENSOR_OV767x) {
872 if (val < 0)
873 val = 0x80 - val;
874 sccb_reg_write(gspca_dev, 0x55, val); /* bright */
875 } else {
876 sccb_reg_write(gspca_dev, 0x9b, val);
877 }
878}
879
880static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
881{
882 struct sd *sd = (struct sd *) gspca_dev;
883
884 if (sd->sensor == SENSOR_OV767x)
885 sccb_reg_write(gspca_dev, 0x56, val); /* contras */
886 else
887 sccb_reg_write(gspca_dev, 0x9c, val);
888}
889
890static void setgain(struct gspca_dev *gspca_dev, s32 val)
891{
892 switch (val & 0x30) {
893 case 0x00:
894 val &= 0x0f;
895 break;
896 case 0x10:
897 val &= 0x0f;
898 val |= 0x30;
899 break;
900 case 0x20:
901 val &= 0x0f;
902 val |= 0x70;
903 break;
904 default:
905/* case 0x30: */
906 val &= 0x0f;
907 val |= 0xf0;
908 break;
909 }
910 sccb_reg_write(gspca_dev, 0x00, val);
911}
912
913static s32 getgain(struct gspca_dev *gspca_dev)
914{
915 return sccb_reg_read(gspca_dev, 0x00);
916}
917
918static void setexposure(struct gspca_dev *gspca_dev, s32 val)
919{
920 struct sd *sd = (struct sd *) gspca_dev;
921
922 if (sd->sensor == SENSOR_OV767x) {
923
924 /* set only aec[9:2] */
925 sccb_reg_write(gspca_dev, 0x10, val); /* aech */
926 } else {
927
928 /* 'val' is one byte and represents half of the exposure value
929 * we are going to set into registers, a two bytes value:
930 *
931 * MSB: ((u16) val << 1) >> 8 == val >> 7
932 * LSB: ((u16) val << 1) & 0xff == val << 1
933 */
934 sccb_reg_write(gspca_dev, 0x08, val >> 7);
935 sccb_reg_write(gspca_dev, 0x10, val << 1);
936 }
937}
938
939static s32 getexposure(struct gspca_dev *gspca_dev)
940{
941 struct sd *sd = (struct sd *) gspca_dev;
942
943 if (sd->sensor == SENSOR_OV767x) {
944 /* get only aec[9:2] */
945 return sccb_reg_read(gspca_dev, 0x10); /* aech */
946 } else {
947 u8 hi = sccb_reg_read(gspca_dev, 0x08);
948 u8 lo = sccb_reg_read(gspca_dev, 0x10);
949 return (hi << 8 | lo) >> 1;
950 }
951}
952
953static void setagc(struct gspca_dev *gspca_dev, s32 val)
954{
955 if (val) {
956 sccb_reg_write(gspca_dev, 0x13,
957 sccb_reg_read(gspca_dev, 0x13) | 0x04);
958 sccb_reg_write(gspca_dev, 0x64,
959 sccb_reg_read(gspca_dev, 0x64) | 0x03);
960 } else {
961 sccb_reg_write(gspca_dev, 0x13,
962 sccb_reg_read(gspca_dev, 0x13) & ~0x04);
963 sccb_reg_write(gspca_dev, 0x64,
964 sccb_reg_read(gspca_dev, 0x64) & ~0x03);
965 }
966}
967
968static void setawb(struct gspca_dev *gspca_dev, s32 val)
969{
970 struct sd *sd = (struct sd *) gspca_dev;
971
972 if (val) {
973 sccb_reg_write(gspca_dev, 0x13,
974 sccb_reg_read(gspca_dev, 0x13) | 0x02);
975 if (sd->sensor == SENSOR_OV772x)
976 sccb_reg_write(gspca_dev, 0x63,
977 sccb_reg_read(gspca_dev, 0x63) | 0xc0);
978 } else {
979 sccb_reg_write(gspca_dev, 0x13,
980 sccb_reg_read(gspca_dev, 0x13) & ~0x02);
981 if (sd->sensor == SENSOR_OV772x)
982 sccb_reg_write(gspca_dev, 0x63,
983 sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
984 }
985}
986
987static void setaec(struct gspca_dev *gspca_dev, s32 val)
988{
989 struct sd *sd = (struct sd *) gspca_dev;
990 u8 data;
991
992 data = sd->sensor == SENSOR_OV767x ?
993 0x05 : /* agc + aec */
994 0x01; /* agc */
995 switch (val) {
996 case V4L2_EXPOSURE_AUTO:
997 sccb_reg_write(gspca_dev, 0x13,
998 sccb_reg_read(gspca_dev, 0x13) | data);
999 break;
1000 case V4L2_EXPOSURE_MANUAL:
1001 sccb_reg_write(gspca_dev, 0x13,
1002 sccb_reg_read(gspca_dev, 0x13) & ~data);
1003 break;
1004 }
1005}
1006
1007static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
1008{
1009 sccb_reg_write(gspca_dev, 0x91, val); /* Auto de-noise threshold */
1010 sccb_reg_write(gspca_dev, 0x8e, val); /* De-noise threshold */
1011}
1012
1013static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
1014{
1015 struct sd *sd = (struct sd *) gspca_dev;
1016 u8 val;
1017
1018 if (sd->sensor == SENSOR_OV767x) {
1019 val = sccb_reg_read(gspca_dev, 0x1e); /* mvfp */
1020 val &= ~0x30;
1021 if (hflip)
1022 val |= 0x20;
1023 if (vflip)
1024 val |= 0x10;
1025 sccb_reg_write(gspca_dev, 0x1e, val);
1026 } else {
1027 val = sccb_reg_read(gspca_dev, 0x0c);
1028 val &= ~0xc0;
1029 if (hflip == 0)
1030 val |= 0x40;
1031 if (vflip == 0)
1032 val |= 0x80;
1033 sccb_reg_write(gspca_dev, 0x0c, val);
1034 }
1035}
1036
1037static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
1038{
1039 struct sd *sd = (struct sd *) gspca_dev;
1040
1041 val = val ? 0x9e : 0x00;
1042 if (sd->sensor == SENSOR_OV767x) {
1043 sccb_reg_write(gspca_dev, 0x2a, 0x00);
1044 if (val)
1045 val = 0x9d; /* insert dummy to 25fps for 50Hz */
1046 }
1047 sccb_reg_write(gspca_dev, 0x2b, val);
1048}
1049
1050
1051/* this function is called at probe time */
1052static int sd_config(struct gspca_dev *gspca_dev,
1053 const struct usb_device_id *id)
1054{
1055 struct sd *sd = (struct sd *) gspca_dev;
1056 struct cam *cam;
1057
1058 cam = &gspca_dev->cam;
1059
1060 cam->cam_mode = ov772x_mode;
1061 cam->nmodes = ARRAY_SIZE(ov772x_mode);
1062
1063 sd->frame_rate = 30;
1064
1065 return 0;
1066}
1067
1068static int ov534_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1069{
1070 struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
1071 struct gspca_dev *gspca_dev = &sd->gspca_dev;
1072
1073 switch (ctrl->id) {
1074 case V4L2_CID_AUTOGAIN:
1075 gspca_dev->usb_err = 0;
1076 if (ctrl->val && sd->gain && gspca_dev->streaming)
1077 sd->gain->val = getgain(gspca_dev);
1078 return gspca_dev->usb_err;
1079
1080 case V4L2_CID_EXPOSURE_AUTO:
1081 gspca_dev->usb_err = 0;
1082 if (ctrl->val == V4L2_EXPOSURE_AUTO && sd->exposure &&
1083 gspca_dev->streaming)
1084 sd->exposure->val = getexposure(gspca_dev);
1085 return gspca_dev->usb_err;
1086 }
1087 return -EINVAL;
1088}
1089
1090static int ov534_s_ctrl(struct v4l2_ctrl *ctrl)
1091{
1092 struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
1093 struct gspca_dev *gspca_dev = &sd->gspca_dev;
1094
1095 gspca_dev->usb_err = 0;
1096 if (!gspca_dev->streaming)
1097 return 0;
1098
1099 switch (ctrl->id) {
1100 case V4L2_CID_HUE:
1101 sethue(gspca_dev, ctrl->val);
1102 break;
1103 case V4L2_CID_SATURATION:
1104 setsaturation(gspca_dev, ctrl->val);
1105 break;
1106 case V4L2_CID_BRIGHTNESS:
1107 setbrightness(gspca_dev, ctrl->val);
1108 break;
1109 case V4L2_CID_CONTRAST:
1110 setcontrast(gspca_dev, ctrl->val);
1111 break;
1112 case V4L2_CID_AUTOGAIN:
1113 /* case V4L2_CID_GAIN: */
1114 setagc(gspca_dev, ctrl->val);
1115 if (!gspca_dev->usb_err && !ctrl->val && sd->gain)
1116 setgain(gspca_dev, sd->gain->val);
1117 break;
1118 case V4L2_CID_AUTO_WHITE_BALANCE:
1119 setawb(gspca_dev, ctrl->val);
1120 break;
1121 case V4L2_CID_EXPOSURE_AUTO:
1122 /* case V4L2_CID_EXPOSURE: */
1123 setaec(gspca_dev, ctrl->val);
1124 if (!gspca_dev->usb_err && ctrl->val == V4L2_EXPOSURE_MANUAL &&
1125 sd->exposure)
1126 setexposure(gspca_dev, sd->exposure->val);
1127 break;
1128 case V4L2_CID_SHARPNESS:
1129 setsharpness(gspca_dev, ctrl->val);
1130 break;
1131 case V4L2_CID_HFLIP:
1132 sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
1133 break;
1134 case V4L2_CID_VFLIP:
1135 sethvflip(gspca_dev, sd->hflip->val, ctrl->val);
1136 break;
1137 case V4L2_CID_POWER_LINE_FREQUENCY:
1138 setlightfreq(gspca_dev, ctrl->val);
1139 break;
1140 }
1141 return gspca_dev->usb_err;
1142}
1143
1144static const struct v4l2_ctrl_ops ov534_ctrl_ops = {
1145 .g_volatile_ctrl = ov534_g_volatile_ctrl,
1146 .s_ctrl = ov534_s_ctrl,
1147};
1148
1149static int sd_init_controls(struct gspca_dev *gspca_dev)
1150{
1151 struct sd *sd = (struct sd *) gspca_dev;
1152 struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler;
1153 /* parameters with different values between the supported sensors */
1154 int saturation_min;
1155 int saturation_max;
1156 int saturation_def;
1157 int brightness_min;
1158 int brightness_max;
1159 int brightness_def;
1160 int contrast_max;
1161 int contrast_def;
1162 int exposure_min;
1163 int exposure_max;
1164 int exposure_def;
1165 int hflip_def;
1166
1167 if (sd->sensor == SENSOR_OV767x) {
1168 saturation_min = 0,
1169 saturation_max = 6,
1170 saturation_def = 3,
1171 brightness_min = -127;
1172 brightness_max = 127;
1173 brightness_def = 0;
1174 contrast_max = 0x80;
1175 contrast_def = 0x40;
1176 exposure_min = 0x08;
1177 exposure_max = 0x60;
1178 exposure_def = 0x13;
1179 hflip_def = 1;
1180 } else {
1181 saturation_min = 0,
1182 saturation_max = 255,
1183 saturation_def = 64,
1184 brightness_min = 0;
1185 brightness_max = 255;
1186 brightness_def = 0;
1187 contrast_max = 255;
1188 contrast_def = 32;
1189 exposure_min = 0;
1190 exposure_max = 255;
1191 exposure_def = 120;
1192 hflip_def = 0;
1193 }
1194
1195 gspca_dev->vdev.ctrl_handler = hdl;
1196
1197 v4l2_ctrl_handler_init(hdl, 13);
1198
1199 if (sd->sensor == SENSOR_OV772x)
1200 sd->hue = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1201 V4L2_CID_HUE, -90, 90, 1, 0);
1202
1203 sd->saturation = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1204 V4L2_CID_SATURATION, saturation_min, saturation_max, 1,
1205 saturation_def);
1206 sd->brightness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1207 V4L2_CID_BRIGHTNESS, brightness_min, brightness_max, 1,
1208 brightness_def);
1209 sd->contrast = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1210 V4L2_CID_CONTRAST, 0, contrast_max, 1, contrast_def);
1211
1212 if (sd->sensor == SENSOR_OV772x) {
1213 sd->autogain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1214 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1215 sd->gain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1216 V4L2_CID_GAIN, 0, 63, 1, 20);
1217 }
1218
1219 sd->autoexposure = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
1220 V4L2_CID_EXPOSURE_AUTO,
1221 V4L2_EXPOSURE_MANUAL, 0,
1222 V4L2_EXPOSURE_AUTO);
1223 sd->exposure = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1224 V4L2_CID_EXPOSURE, exposure_min, exposure_max, 1,
1225 exposure_def);
1226
1227 sd->autowhitebalance = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1228 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
1229
1230 if (sd->sensor == SENSOR_OV772x)
1231 sd->sharpness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1232 V4L2_CID_SHARPNESS, 0, 63, 1, 0);
1233
1234 sd->hflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1235 V4L2_CID_HFLIP, 0, 1, 1, hflip_def);
1236 sd->vflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
1237 V4L2_CID_VFLIP, 0, 1, 1, 0);
1238 sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
1239 V4L2_CID_POWER_LINE_FREQUENCY,
1240 V4L2_CID_POWER_LINE_FREQUENCY_50HZ, 0,
1241 V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
1242
1243 if (hdl->error) {
1244 pr_err("Could not initialize controls\n");
1245 return hdl->error;
1246 }
1247
1248 if (sd->sensor == SENSOR_OV772x)
1249 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
1250
1251 v4l2_ctrl_auto_cluster(2, &sd->autoexposure, V4L2_EXPOSURE_MANUAL,
1252 true);
1253
1254 return 0;
1255}
1256
1257/* this function is called at probe and resume time */
1258static int sd_init(struct gspca_dev *gspca_dev)
1259{
1260 struct sd *sd = (struct sd *) gspca_dev;
1261 u16 sensor_id;
1262 static const struct reg_array bridge_init[NSENSORS] = {
1263 [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
1264 [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
1265 };
1266 static const struct reg_array sensor_init[NSENSORS] = {
1267 [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
1268 [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
1269 };
1270
1271 /* reset bridge */
1272 ov534_reg_write(gspca_dev, 0xe7, 0x3a);
1273 ov534_reg_write(gspca_dev, 0xe0, 0x08);
1274 msleep(100);
1275
1276 /* initialize the sensor address */
1277 ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
1278
1279 /* reset sensor */
1280 sccb_reg_write(gspca_dev, 0x12, 0x80);
1281 msleep(10);
1282
1283 /* probe the sensor */
1284 sccb_reg_read(gspca_dev, 0x0a);
1285 sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
1286 sccb_reg_read(gspca_dev, 0x0b);
1287 sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
1288 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1289
1290 if ((sensor_id & 0xfff0) == 0x7670) {
1291 sd->sensor = SENSOR_OV767x;
1292 gspca_dev->cam.cam_mode = ov767x_mode;
1293 gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
1294 } else {
1295 sd->sensor = SENSOR_OV772x;
1296 gspca_dev->cam.bulk = 1;
1297 gspca_dev->cam.bulk_size = 16384;
1298 gspca_dev->cam.bulk_nurbs = 2;
1299 gspca_dev->cam.mode_framerates = ov772x_framerates;
1300 }
1301
1302 /* initialize */
1303 reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
1304 bridge_init[sd->sensor].len);
1305 ov534_set_led(gspca_dev, 1);
1306 sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
1307 sensor_init[sd->sensor].len);
1308 if (sd->sensor == SENSOR_OV767x)
1309 sd_start(gspca_dev);
1310 sd_stopN(gspca_dev);
1311/* set_frame_rate(gspca_dev); */
1312
1313 return gspca_dev->usb_err;
1314}
1315
1316static int sd_start(struct gspca_dev *gspca_dev)
1317{
1318 struct sd *sd = (struct sd *) gspca_dev;
1319 int mode;
1320 static const struct reg_array bridge_start[NSENSORS][2] = {
1321 [SENSOR_OV767x] = {{bridge_start_qvga_767x,
1322 ARRAY_SIZE(bridge_start_qvga_767x)},
1323 {bridge_start_vga_767x,
1324 ARRAY_SIZE(bridge_start_vga_767x)}},
1325 [SENSOR_OV772x] = {{bridge_start_qvga_772x,
1326 ARRAY_SIZE(bridge_start_qvga_772x)},
1327 {bridge_start_vga_772x,
1328 ARRAY_SIZE(bridge_start_vga_772x)}},
1329 };
1330 static const struct reg_array sensor_start[NSENSORS][2] = {
1331 [SENSOR_OV767x] = {{sensor_start_qvga_767x,
1332 ARRAY_SIZE(sensor_start_qvga_767x)},
1333 {sensor_start_vga_767x,
1334 ARRAY_SIZE(sensor_start_vga_767x)}},
1335 [SENSOR_OV772x] = {{sensor_start_qvga_772x,
1336 ARRAY_SIZE(sensor_start_qvga_772x)},
1337 {sensor_start_vga_772x,
1338 ARRAY_SIZE(sensor_start_vga_772x)}},
1339 };
1340
1341 /* (from ms-win trace) */
1342 if (sd->sensor == SENSOR_OV767x)
1343 sccb_reg_write(gspca_dev, 0x1e, 0x04);
1344 /* black sun enable ? */
1345
1346 mode = gspca_dev->curr_mode; /* 0: 320x240, 1: 640x480 */
1347 reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
1348 bridge_start[sd->sensor][mode].len);
1349 sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
1350 sensor_start[sd->sensor][mode].len);
1351
1352 set_frame_rate(gspca_dev);
1353
1354 if (sd->hue)
1355 sethue(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue));
1356 setsaturation(gspca_dev, v4l2_ctrl_g_ctrl(sd->saturation));
1357 if (sd->autogain)
1358 setagc(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
1359 setawb(gspca_dev, v4l2_ctrl_g_ctrl(sd->autowhitebalance));
1360 setaec(gspca_dev, v4l2_ctrl_g_ctrl(sd->autoexposure));
1361 if (sd->gain)
1362 setgain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
1363 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
1364 setbrightness(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness));
1365 setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
1366 if (sd->sharpness)
1367 setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
1368 sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
1369 v4l2_ctrl_g_ctrl(sd->vflip));
1370 setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
1371
1372 ov534_set_led(gspca_dev, 1);
1373 ov534_reg_write(gspca_dev, 0xe0, 0x00);
1374 return gspca_dev->usb_err;
1375}
1376
1377static void sd_stopN(struct gspca_dev *gspca_dev)
1378{
1379 ov534_reg_write(gspca_dev, 0xe0, 0x09);
1380 ov534_set_led(gspca_dev, 0);
1381}
1382
1383/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1384#define UVC_STREAM_EOH (1 << 7)
1385#define UVC_STREAM_ERR (1 << 6)
1386#define UVC_STREAM_STI (1 << 5)
1387#define UVC_STREAM_RES (1 << 4)
1388#define UVC_STREAM_SCR (1 << 3)
1389#define UVC_STREAM_PTS (1 << 2)
1390#define UVC_STREAM_EOF (1 << 1)
1391#define UVC_STREAM_FID (1 << 0)
1392
1393static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1394 u8 *data, int len)
1395{
1396 struct sd *sd = (struct sd *) gspca_dev;
1397 __u32 this_pts;
1398 u16 this_fid;
1399 int remaining_len = len;
1400 int payload_len;
1401
1402 payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
1403 do {
1404 len = min(remaining_len, payload_len);
1405
1406 /* Payloads are prefixed with a UVC-style header. We
1407 consider a frame to start when the FID toggles, or the PTS
1408 changes. A frame ends when EOF is set, and we've received
1409 the correct number of bytes. */
1410
1411 /* Verify UVC header. Header length is always 12 */
1412 if (data[0] != 12 || len < 12) {
1413 PDEBUG(D_PACK, "bad header");
1414 goto discard;
1415 }
1416
1417 /* Check errors */
1418 if (data[1] & UVC_STREAM_ERR) {
1419 PDEBUG(D_PACK, "payload error");
1420 goto discard;
1421 }
1422
1423 /* Extract PTS and FID */
1424 if (!(data[1] & UVC_STREAM_PTS)) {
1425 PDEBUG(D_PACK, "PTS not present");
1426 goto discard;
1427 }
1428 this_pts = (data[5] << 24) | (data[4] << 16)
1429 | (data[3] << 8) | data[2];
1430 this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
1431
1432 /* If PTS or FID has changed, start a new frame. */
1433 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1434 if (gspca_dev->last_packet_type == INTER_PACKET)
1435 gspca_frame_add(gspca_dev, LAST_PACKET,
1436 NULL, 0);
1437 sd->last_pts = this_pts;
1438 sd->last_fid = this_fid;
1439 gspca_frame_add(gspca_dev, FIRST_PACKET,
1440 data + 12, len - 12);
1441 /* If this packet is marked as EOF, end the frame */
1442 } else if (data[1] & UVC_STREAM_EOF) {
1443 sd->last_pts = 0;
1444 if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
1445 && gspca_dev->image_len + len - 12 !=
1446 gspca_dev->width * gspca_dev->height * 2) {
1447 PDEBUG(D_PACK, "wrong sized frame");
1448 goto discard;
1449 }
1450 gspca_frame_add(gspca_dev, LAST_PACKET,
1451 data + 12, len - 12);
1452 } else {
1453
1454 /* Add the data from this payload */
1455 gspca_frame_add(gspca_dev, INTER_PACKET,
1456 data + 12, len - 12);
1457 }
1458
1459 /* Done this payload */
1460 goto scan_next;
1461
1462discard:
1463 /* Discard data until a new frame starts. */
1464 gspca_dev->last_packet_type = DISCARD_PACKET;
1465
1466scan_next:
1467 remaining_len -= len;
1468 data += len;
1469 } while (remaining_len > 0);
1470}
1471
1472/* get stream parameters (framerate) */
1473static void sd_get_streamparm(struct gspca_dev *gspca_dev,
1474 struct v4l2_streamparm *parm)
1475{
1476 struct v4l2_captureparm *cp = &parm->parm.capture;
1477 struct v4l2_fract *tpf = &cp->timeperframe;
1478 struct sd *sd = (struct sd *) gspca_dev;
1479
1480 cp->capability |= V4L2_CAP_TIMEPERFRAME;
1481 tpf->numerator = 1;
1482 tpf->denominator = sd->frame_rate;
1483}
1484
1485/* set stream parameters (framerate) */
1486static void sd_set_streamparm(struct gspca_dev *gspca_dev,
1487 struct v4l2_streamparm *parm)
1488{
1489 struct v4l2_captureparm *cp = &parm->parm.capture;
1490 struct v4l2_fract *tpf = &cp->timeperframe;
1491 struct sd *sd = (struct sd *) gspca_dev;
1492
1493 /* Set requested framerate */
1494 sd->frame_rate = tpf->denominator / tpf->numerator;
1495 if (gspca_dev->streaming)
1496 set_frame_rate(gspca_dev);
1497
1498 /* Return the actual framerate */
1499 tpf->numerator = 1;
1500 tpf->denominator = sd->frame_rate;
1501}
1502
1503/* sub-driver description */
1504static const struct sd_desc sd_desc = {
1505 .name = MODULE_NAME,
1506 .config = sd_config,
1507 .init = sd_init,
1508 .init_controls = sd_init_controls,
1509 .start = sd_start,
1510 .stopN = sd_stopN,
1511 .pkt_scan = sd_pkt_scan,
1512 .get_streamparm = sd_get_streamparm,
1513 .set_streamparm = sd_set_streamparm,
1514};
1515
1516/* -- module initialisation -- */
1517static const struct usb_device_id device_table[] = {
1518 {USB_DEVICE(0x1415, 0x2000)},
1519 {USB_DEVICE(0x06f8, 0x3002)},
1520 {}
1521};
1522
1523MODULE_DEVICE_TABLE(usb, device_table);
1524
1525/* -- device connect -- */
1526static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1527{
1528 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1529 THIS_MODULE);
1530}
1531
1532static struct usb_driver sd_driver = {
1533 .name = MODULE_NAME,
1534 .id_table = device_table,
1535 .probe = sd_probe,
1536 .disconnect = gspca_disconnect,
1537#ifdef CONFIG_PM
1538 .suspend = gspca_suspend,
1539 .resume = gspca_resume,
1540 .reset_resume = gspca_resume,
1541#endif
1542};
1543
1544module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/ov534_9.c b/drivers/media/usb/gspca/ov534_9.c
new file mode 100644
index 00000000000..c4cd028fe0b
--- /dev/null
+++ b/drivers/media/usb/gspca/ov534_9.c
@@ -0,0 +1,1500 @@
1/*
2 * ov534-ov9xxx gspca driver
3 *
4 * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
5 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
6 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
7 *
8 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
9 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
10 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29#define MODULE_NAME "ov534_9"
30
31#include "gspca.h"
32
33#define OV534_REG_ADDRESS 0xf1 /* sensor address */
34#define OV534_REG_SUBADDR 0xf2
35#define OV534_REG_WRITE 0xf3
36#define OV534_REG_READ 0xf4
37#define OV534_REG_OPERATION 0xf5
38#define OV534_REG_STATUS 0xf6
39
40#define OV534_OP_WRITE_3 0x37
41#define OV534_OP_WRITE_2 0x33
42#define OV534_OP_READ_2 0xf9
43
44#define CTRL_TIMEOUT 500
45
46MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
47MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
48MODULE_LICENSE("GPL");
49
50/* specific webcam descriptor */
51struct sd {
52 struct gspca_dev gspca_dev; /* !! must be the first item */
53 __u32 last_pts;
54 u8 last_fid;
55
56 u8 sensor;
57};
58enum sensors {
59 SENSOR_OV965x, /* ov9657 */
60 SENSOR_OV971x, /* ov9712 */
61 SENSOR_OV562x, /* ov5621 */
62 NSENSORS
63};
64
65static const struct v4l2_pix_format ov965x_mode[] = {
66#define QVGA_MODE 0
67 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
68 .bytesperline = 320,
69 .sizeimage = 320 * 240 * 3 / 8 + 590,
70 .colorspace = V4L2_COLORSPACE_JPEG},
71#define VGA_MODE 1
72 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
73 .bytesperline = 640,
74 .sizeimage = 640 * 480 * 3 / 8 + 590,
75 .colorspace = V4L2_COLORSPACE_JPEG},
76#define SVGA_MODE 2
77 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
78 .bytesperline = 800,
79 .sizeimage = 800 * 600 * 3 / 8 + 590,
80 .colorspace = V4L2_COLORSPACE_JPEG},
81#define XGA_MODE 3
82 {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
83 .bytesperline = 1024,
84 .sizeimage = 1024 * 768 * 3 / 8 + 590,
85 .colorspace = V4L2_COLORSPACE_JPEG},
86#define SXGA_MODE 4
87 {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
88 .bytesperline = 1280,
89 .sizeimage = 1280 * 1024 * 3 / 8 + 590,
90 .colorspace = V4L2_COLORSPACE_JPEG},
91};
92
93static const struct v4l2_pix_format ov971x_mode[] = {
94 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
95 .bytesperline = 640,
96 .sizeimage = 640 * 480,
97 .colorspace = V4L2_COLORSPACE_SRGB
98 }
99};
100
101static const struct v4l2_pix_format ov562x_mode[] = {
102 {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
103 .bytesperline = 2592,
104 .sizeimage = 2592 * 1680,
105 .colorspace = V4L2_COLORSPACE_SRGB
106 }
107};
108
109static const u8 bridge_init[][2] = {
110 {0x88, 0xf8},
111 {0x89, 0xff},
112 {0x76, 0x03},
113 {0x92, 0x03},
114 {0x95, 0x10},
115 {0xe2, 0x00},
116 {0xe7, 0x3e},
117 {0x8d, 0x1c},
118 {0x8e, 0x00},
119 {0x8f, 0x00},
120 {0x1f, 0x00},
121 {0xc3, 0xf9},
122 {0x89, 0xff},
123 {0x88, 0xf8},
124 {0x76, 0x03},
125 {0x92, 0x01},
126 {0x93, 0x18},
127 {0x1c, 0x0a},
128 {0x1d, 0x48},
129 {0xc0, 0x50},
130 {0xc1, 0x3c},
131 {0x34, 0x05},
132 {0xc2, 0x0c},
133 {0xc3, 0xf9},
134 {0x34, 0x05},
135 {0xe7, 0x2e},
136 {0x31, 0xf9},
137 {0x35, 0x02},
138 {0xd9, 0x10},
139 {0x25, 0x42},
140 {0x94, 0x11},
141};
142
143static const u8 ov965x_init[][2] = {
144 {0x12, 0x80}, /* com7 - SSCB reset */
145 {0x00, 0x00}, /* gain */
146 {0x01, 0x80}, /* blue */
147 {0x02, 0x80}, /* red */
148 {0x03, 0x1b}, /* vref */
149 {0x04, 0x03}, /* com1 - exposure low bits */
150 {0x0b, 0x57}, /* ver */
151 {0x0e, 0x61}, /* com5 */
152 {0x0f, 0x42}, /* com6 */
153 {0x11, 0x00}, /* clkrc */
154 {0x12, 0x02}, /* com7 - 15fps VGA YUYV */
155 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
156 {0x14, 0x28}, /* com9 */
157 {0x16, 0x24}, /* reg16 */
158 {0x17, 0x1d}, /* hstart*/
159 {0x18, 0xbd}, /* hstop */
160 {0x19, 0x01}, /* vstrt */
161 {0x1a, 0x81}, /* vstop*/
162 {0x1e, 0x04}, /* mvfp */
163 {0x24, 0x3c}, /* aew */
164 {0x25, 0x36}, /* aeb */
165 {0x26, 0x71}, /* vpt */
166 {0x27, 0x08}, /* bbias */
167 {0x28, 0x08}, /* gbbias */
168 {0x29, 0x15}, /* gr com */
169 {0x2a, 0x00}, /* exhch */
170 {0x2b, 0x00}, /* exhcl */
171 {0x2c, 0x08}, /* rbias */
172 {0x32, 0xff}, /* href */
173 {0x33, 0x00}, /* chlf */
174 {0x34, 0x3f}, /* aref1 */
175 {0x35, 0x00}, /* aref2 */
176 {0x36, 0xf8}, /* aref3 */
177 {0x38, 0x72}, /* adc2 */
178 {0x39, 0x57}, /* aref4 */
179 {0x3a, 0x80}, /* tslb - yuyv */
180 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
181 {0x3d, 0x99}, /* com13 */
182 {0x3f, 0xc1}, /* edge */
183 {0x40, 0xc0}, /* com15 */
184 {0x41, 0x40}, /* com16 */
185 {0x42, 0xc0}, /* com17 */
186 {0x43, 0x0a}, /* rsvd */
187 {0x44, 0xf0},
188 {0x45, 0x46},
189 {0x46, 0x62},
190 {0x47, 0x2a},
191 {0x48, 0x3c},
192 {0x4a, 0xfc},
193 {0x4b, 0xfc},
194 {0x4c, 0x7f},
195 {0x4d, 0x7f},
196 {0x4e, 0x7f},
197 {0x4f, 0x98}, /* matrix */
198 {0x50, 0x98},
199 {0x51, 0x00},
200 {0x52, 0x28},
201 {0x53, 0x70},
202 {0x54, 0x98},
203 {0x58, 0x1a}, /* matrix coef sign */
204 {0x59, 0x85}, /* AWB control */
205 {0x5a, 0xa9},
206 {0x5b, 0x64},
207 {0x5c, 0x84},
208 {0x5d, 0x53},
209 {0x5e, 0x0e},
210 {0x5f, 0xf0}, /* AWB blue limit */
211 {0x60, 0xf0}, /* AWB red limit */
212 {0x61, 0xf0}, /* AWB green limit */
213 {0x62, 0x00}, /* lcc1 */
214 {0x63, 0x00}, /* lcc2 */
215 {0x64, 0x02}, /* lcc3 */
216 {0x65, 0x16}, /* lcc4 */
217 {0x66, 0x01}, /* lcc5 */
218 {0x69, 0x02}, /* hv */
219 {0x6b, 0x5a}, /* dbvl */
220 {0x6c, 0x04},
221 {0x6d, 0x55},
222 {0x6e, 0x00},
223 {0x6f, 0x9d},
224 {0x70, 0x21}, /* dnsth */
225 {0x71, 0x78},
226 {0x72, 0x00}, /* poidx */
227 {0x73, 0x01}, /* pckdv */
228 {0x74, 0x3a}, /* xindx */
229 {0x75, 0x35}, /* yindx */
230 {0x76, 0x01},
231 {0x77, 0x02},
232 {0x7a, 0x12}, /* gamma curve */
233 {0x7b, 0x08},
234 {0x7c, 0x16},
235 {0x7d, 0x30},
236 {0x7e, 0x5e},
237 {0x7f, 0x72},
238 {0x80, 0x82},
239 {0x81, 0x8e},
240 {0x82, 0x9a},
241 {0x83, 0xa4},
242 {0x84, 0xac},
243 {0x85, 0xb8},
244 {0x86, 0xc3},
245 {0x87, 0xd6},
246 {0x88, 0xe6},
247 {0x89, 0xf2},
248 {0x8a, 0x03},
249 {0x8c, 0x89}, /* com19 */
250 {0x14, 0x28}, /* com9 */
251 {0x90, 0x7d},
252 {0x91, 0x7b},
253 {0x9d, 0x03}, /* lcc6 */
254 {0x9e, 0x04}, /* lcc7 */
255 {0x9f, 0x7a},
256 {0xa0, 0x79},
257 {0xa1, 0x40}, /* aechm */
258 {0xa4, 0x50}, /* com21 */
259 {0xa5, 0x68}, /* com26 */
260 {0xa6, 0x4a}, /* AWB green */
261 {0xa8, 0xc1}, /* refa8 */
262 {0xa9, 0xef}, /* refa9 */
263 {0xaa, 0x92},
264 {0xab, 0x04},
265 {0xac, 0x80}, /* black level control */
266 {0xad, 0x80},
267 {0xae, 0x80},
268 {0xaf, 0x80},
269 {0xb2, 0xf2},
270 {0xb3, 0x20},
271 {0xb4, 0x20}, /* ctrlb4 */
272 {0xb5, 0x00},
273 {0xb6, 0xaf},
274 {0xbb, 0xae},
275 {0xbc, 0x7f}, /* ADC channel offsets */
276 {0xdb, 0x7f},
277 {0xbe, 0x7f},
278 {0xbf, 0x7f},
279 {0xc0, 0xe2},
280 {0xc1, 0xc0},
281 {0xc2, 0x01},
282 {0xc3, 0x4e},
283 {0xc6, 0x85},
284 {0xc7, 0x80}, /* com24 */
285 {0xc9, 0xe0},
286 {0xca, 0xe8},
287 {0xcb, 0xf0},
288 {0xcc, 0xd8},
289 {0xcd, 0xf1},
290 {0x4f, 0x98}, /* matrix */
291 {0x50, 0x98},
292 {0x51, 0x00},
293 {0x52, 0x28},
294 {0x53, 0x70},
295 {0x54, 0x98},
296 {0x58, 0x1a},
297 {0xff, 0x41}, /* read 41, write ff 00 */
298 {0x41, 0x40}, /* com16 */
299
300 {0xc5, 0x03}, /* 60 Hz banding filter */
301 {0x6a, 0x02}, /* 50 Hz banding filter */
302
303 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
304 {0x36, 0xfa}, /* aref3 */
305 {0x69, 0x0a}, /* hv */
306 {0x8c, 0x89}, /* com22 */
307 {0x14, 0x28}, /* com9 */
308 {0x3e, 0x0c},
309 {0x41, 0x40}, /* com16 */
310 {0x72, 0x00},
311 {0x73, 0x00},
312 {0x74, 0x3a},
313 {0x75, 0x35},
314 {0x76, 0x01},
315 {0xc7, 0x80},
316 {0x03, 0x12}, /* vref */
317 {0x17, 0x16}, /* hstart */
318 {0x18, 0x02}, /* hstop */
319 {0x19, 0x01}, /* vstrt */
320 {0x1a, 0x3d}, /* vstop */
321 {0x32, 0xff}, /* href */
322 {0xc0, 0xaa},
323};
324
325static const u8 bridge_init_2[][2] = {
326 {0x94, 0xaa},
327 {0xf1, 0x60},
328 {0xe5, 0x04},
329 {0xc0, 0x50},
330 {0xc1, 0x3c},
331 {0x8c, 0x00},
332 {0x8d, 0x1c},
333 {0x34, 0x05},
334
335 {0xc2, 0x0c},
336 {0xc3, 0xf9},
337 {0xda, 0x01},
338 {0x50, 0x00},
339 {0x51, 0xa0},
340 {0x52, 0x3c},
341 {0x53, 0x00},
342 {0x54, 0x00},
343 {0x55, 0x00},
344 {0x57, 0x00},
345 {0x5c, 0x00},
346 {0x5a, 0xa0},
347 {0x5b, 0x78},
348 {0x35, 0x02},
349 {0xd9, 0x10},
350 {0x94, 0x11},
351};
352
353static const u8 ov965x_init_2[][2] = {
354 {0x3b, 0xc4},
355 {0x1e, 0x04}, /* mvfp */
356 {0x13, 0xe0}, /* com8 */
357 {0x00, 0x00}, /* gain */
358 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
359 {0x11, 0x03}, /* clkrc */
360 {0x6b, 0x5a}, /* dblv */
361 {0x6a, 0x05},
362 {0xc5, 0x07},
363 {0xa2, 0x4b},
364 {0xa3, 0x3e},
365 {0x2d, 0x00},
366 {0xff, 0x42}, /* read 42, write ff 00 */
367 {0x42, 0xc0}, /* com17 */
368 {0x2d, 0x00},
369 {0xff, 0x42}, /* read 42, write ff 00 */
370 {0x42, 0xc1}, /* com17 */
371/* sharpness */
372 {0x3f, 0x01},
373 {0xff, 0x42}, /* read 42, write ff 00 */
374 {0x42, 0xc1}, /* com17 */
375/* saturation */
376 {0x4f, 0x98}, /* matrix */
377 {0x50, 0x98},
378 {0x51, 0x00},
379 {0x52, 0x28},
380 {0x53, 0x70},
381 {0x54, 0x98},
382 {0x58, 0x1a},
383 {0xff, 0x41}, /* read 41, write ff 00 */
384 {0x41, 0x40}, /* com16 */
385/* contrast */
386 {0x56, 0x40},
387/* brightness */
388 {0x55, 0x8f},
389/* expo */
390 {0x10, 0x25}, /* aech - exposure high bits */
391 {0xff, 0x13}, /* read 13, write ff 00 */
392 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
393};
394
395static const u8 ov971x_init[][2] = {
396 {0x12, 0x80},
397 {0x09, 0x10},
398 {0x1e, 0x07},
399 {0x5f, 0x18},
400 {0x69, 0x04},
401 {0x65, 0x2a},
402 {0x68, 0x0a},
403 {0x39, 0x28},
404 {0x4d, 0x90},
405 {0xc1, 0x80},
406 {0x0c, 0x30},
407 {0x6d, 0x02},
408 {0x96, 0xf1},
409 {0xbc, 0x68},
410 {0x12, 0x00},
411 {0x3b, 0x00},
412 {0x97, 0x80},
413 {0x17, 0x25},
414 {0x18, 0xa2},
415 {0x19, 0x01},
416 {0x1a, 0xca},
417 {0x03, 0x0a},
418 {0x32, 0x07},
419 {0x98, 0x40}, /*{0x98, 0x00},*/
420 {0x99, 0xA0}, /*{0x99, 0x00},*/
421 {0x9a, 0x01}, /*{0x9a, 0x00},*/
422 {0x57, 0x00},
423 {0x58, 0x78}, /*{0x58, 0xc8},*/
424 {0x59, 0x50}, /*{0x59, 0xa0},*/
425 {0x4c, 0x13},
426 {0x4b, 0x36},
427 {0x3d, 0x3c},
428 {0x3e, 0x03},
429 {0xbd, 0x50}, /*{0xbd, 0xa0},*/
430 {0xbe, 0x78}, /*{0xbe, 0xc8},*/
431 {0x4e, 0x55},
432 {0x4f, 0x55},
433 {0x50, 0x55},
434 {0x51, 0x55},
435 {0x24, 0x55},
436 {0x25, 0x40},
437 {0x26, 0xa1},
438 {0x5c, 0x59},
439 {0x5d, 0x00},
440 {0x11, 0x00},
441 {0x2a, 0x98},
442 {0x2b, 0x06},
443 {0x2d, 0x00},
444 {0x2e, 0x00},
445 {0x13, 0xa5},
446 {0x14, 0x40},
447 {0x4a, 0x00},
448 {0x49, 0xce},
449 {0x22, 0x03},
450 {0x09, 0x00}
451};
452
453static const u8 ov965x_start_1_vga[][2] = { /* same for qvga */
454 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
455 {0x36, 0xfa}, /* aref3 */
456 {0x69, 0x0a}, /* hv */
457 {0x8c, 0x89}, /* com22 */
458 {0x14, 0x28}, /* com9 */
459 {0x3e, 0x0c}, /* com14 */
460 {0x41, 0x40}, /* com16 */
461 {0x72, 0x00},
462 {0x73, 0x00},
463 {0x74, 0x3a},
464 {0x75, 0x35},
465 {0x76, 0x01},
466 {0xc7, 0x80}, /* com24 */
467 {0x03, 0x12}, /* vref */
468 {0x17, 0x16}, /* hstart */
469 {0x18, 0x02}, /* hstop */
470 {0x19, 0x01}, /* vstrt */
471 {0x1a, 0x3d}, /* vstop */
472 {0x32, 0xff}, /* href */
473 {0xc0, 0xaa},
474};
475
476static const u8 ov965x_start_1_svga[][2] = {
477 {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
478 {0x36, 0xf8}, /* aref3 */
479 {0x69, 0x02}, /* hv */
480 {0x8c, 0x0d}, /* com22 */
481 {0x3e, 0x0c}, /* com14 */
482 {0x41, 0x40}, /* com16 */
483 {0x72, 0x00},
484 {0x73, 0x01},
485 {0x74, 0x3a},
486 {0x75, 0x35},
487 {0x76, 0x01},
488 {0xc7, 0x80}, /* com24 */
489 {0x03, 0x1b}, /* vref */
490 {0x17, 0x1d}, /* hstart */
491 {0x18, 0xbd}, /* hstop */
492 {0x19, 0x01}, /* vstrt */
493 {0x1a, 0x81}, /* vstop */
494 {0x32, 0xff}, /* href */
495 {0xc0, 0xe2},
496};
497
498static const u8 ov965x_start_1_xga[][2] = {
499 {0x12, 0x02}, /* com7 */
500 {0x36, 0xf8}, /* aref3 */
501 {0x69, 0x02}, /* hv */
502 {0x8c, 0x89}, /* com22 */
503 {0x14, 0x28}, /* com9 */
504 {0x3e, 0x0c}, /* com14 */
505 {0x41, 0x40}, /* com16 */
506 {0x72, 0x00},
507 {0x73, 0x01},
508 {0x74, 0x3a},
509 {0x75, 0x35},
510 {0x76, 0x01},
511 {0xc7, 0x80}, /* com24 */
512 {0x03, 0x1b}, /* vref */
513 {0x17, 0x1d}, /* hstart */
514 {0x18, 0xbd}, /* hstop */
515 {0x19, 0x01}, /* vstrt */
516 {0x1a, 0x81}, /* vstop */
517 {0x32, 0xff}, /* href */
518 {0xc0, 0xe2},
519};
520
521static const u8 ov965x_start_1_sxga[][2] = {
522 {0x12, 0x02}, /* com7 */
523 {0x36, 0xf8}, /* aref3 */
524 {0x69, 0x02}, /* hv */
525 {0x8c, 0x89}, /* com22 */
526 {0x14, 0x28}, /* com9 */
527 {0x3e, 0x0c}, /* com14 */
528 {0x41, 0x40}, /* com16 */
529 {0x72, 0x00},
530 {0x73, 0x01},
531 {0x74, 0x3a},
532 {0x75, 0x35},
533 {0x76, 0x01},
534 {0xc7, 0x80}, /* com24 */
535 {0x03, 0x1b}, /* vref */
536 {0x17, 0x1d}, /* hstart */
537 {0x18, 0x02}, /* hstop */
538 {0x19, 0x01}, /* vstrt */
539 {0x1a, 0x81}, /* vstop */
540 {0x32, 0xff}, /* href */
541 {0xc0, 0xe2},
542};
543
544static const u8 bridge_start_qvga[][2] = {
545 {0x94, 0xaa},
546 {0xf1, 0x60},
547 {0xe5, 0x04},
548 {0xc0, 0x50},
549 {0xc1, 0x3c},
550 {0x8c, 0x00},
551 {0x8d, 0x1c},
552 {0x34, 0x05},
553
554 {0xc2, 0x4c},
555 {0xc3, 0xf9},
556 {0xda, 0x00},
557 {0x50, 0x00},
558 {0x51, 0xa0},
559 {0x52, 0x78},
560 {0x53, 0x00},
561 {0x54, 0x00},
562 {0x55, 0x00},
563 {0x57, 0x00},
564 {0x5c, 0x00},
565 {0x5a, 0x50},
566 {0x5b, 0x3c},
567 {0x35, 0x02},
568 {0xd9, 0x10},
569 {0x94, 0x11},
570};
571
572static const u8 bridge_start_vga[][2] = {
573 {0x94, 0xaa},
574 {0xf1, 0x60},
575 {0xe5, 0x04},
576 {0xc0, 0x50},
577 {0xc1, 0x3c},
578 {0x8c, 0x00},
579 {0x8d, 0x1c},
580 {0x34, 0x05},
581 {0xc2, 0x0c},
582 {0xc3, 0xf9},
583 {0xda, 0x01},
584 {0x50, 0x00},
585 {0x51, 0xa0},
586 {0x52, 0x3c},
587 {0x53, 0x00},
588 {0x54, 0x00},
589 {0x55, 0x00},
590 {0x57, 0x00},
591 {0x5c, 0x00},
592 {0x5a, 0xa0},
593 {0x5b, 0x78},
594 {0x35, 0x02},
595 {0xd9, 0x10},
596 {0x94, 0x11},
597};
598
599static const u8 bridge_start_svga[][2] = {
600 {0x94, 0xaa},
601 {0xf1, 0x60},
602 {0xe5, 0x04},
603 {0xc0, 0xa0},
604 {0xc1, 0x80},
605 {0x8c, 0x00},
606 {0x8d, 0x1c},
607 {0x34, 0x05},
608 {0xc2, 0x4c},
609 {0xc3, 0xf9},
610 {0x50, 0x00},
611 {0x51, 0x40},
612 {0x52, 0x00},
613 {0x53, 0x00},
614 {0x54, 0x00},
615 {0x55, 0x88},
616 {0x57, 0x00},
617 {0x5c, 0x00},
618 {0x5a, 0xc8},
619 {0x5b, 0x96},
620 {0x35, 0x02},
621 {0xd9, 0x10},
622 {0xda, 0x00},
623 {0x94, 0x11},
624};
625
626static const u8 bridge_start_xga[][2] = {
627 {0x94, 0xaa},
628 {0xf1, 0x60},
629 {0xe5, 0x04},
630 {0xc0, 0xa0},
631 {0xc1, 0x80},
632 {0x8c, 0x00},
633 {0x8d, 0x1c},
634 {0x34, 0x05},
635 {0xc2, 0x4c},
636 {0xc3, 0xf9},
637 {0x50, 0x00},
638 {0x51, 0x40},
639 {0x52, 0x00},
640 {0x53, 0x00},
641 {0x54, 0x00},
642 {0x55, 0x88},
643 {0x57, 0x00},
644 {0x5c, 0x01},
645 {0x5a, 0x00},
646 {0x5b, 0xc0},
647 {0x35, 0x02},
648 {0xd9, 0x10},
649 {0xda, 0x01},
650 {0x94, 0x11},
651};
652
653static const u8 bridge_start_sxga[][2] = {
654 {0x94, 0xaa},
655 {0xf1, 0x60},
656 {0xe5, 0x04},
657 {0xc0, 0xa0},
658 {0xc1, 0x80},
659 {0x8c, 0x00},
660 {0x8d, 0x1c},
661 {0x34, 0x05},
662 {0xc2, 0x0c},
663 {0xc3, 0xf9},
664 {0xda, 0x00},
665 {0x35, 0x02},
666 {0xd9, 0x10},
667 {0x94, 0x11},
668};
669
670static const u8 ov965x_start_2_qvga[][2] = {
671 {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
672 {0x1e, 0x04}, /* mvfp */
673 {0x13, 0xe0}, /* com8 */
674 {0x00, 0x00},
675 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
676 {0x11, 0x01}, /* clkrc */
677 {0x6b, 0x5a}, /* dblv */
678 {0x6a, 0x02}, /* 50 Hz banding filter */
679 {0xc5, 0x03}, /* 60 Hz banding filter */
680 {0xa2, 0x96}, /* bd50 */
681 {0xa3, 0x7d}, /* bd60 */
682
683 {0xff, 0x13}, /* read 13, write ff 00 */
684 {0x13, 0xe7},
685 {0x3a, 0x80}, /* tslb - yuyv */
686};
687
688static const u8 ov965x_start_2_vga[][2] = {
689 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
690 {0x1e, 0x04}, /* mvfp */
691 {0x13, 0xe0}, /* com8 */
692 {0x00, 0x00},
693 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
694 {0x11, 0x03}, /* clkrc */
695 {0x6b, 0x5a}, /* dblv */
696 {0x6a, 0x05}, /* 50 Hz banding filter */
697 {0xc5, 0x07}, /* 60 Hz banding filter */
698 {0xa2, 0x4b}, /* bd50 */
699 {0xa3, 0x3e}, /* bd60 */
700
701 {0x2d, 0x00}, /* advfl */
702};
703
704static const u8 ov965x_start_2_svga[][2] = { /* same for xga */
705 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
706 {0x1e, 0x04}, /* mvfp */
707 {0x13, 0xe0}, /* com8 */
708 {0x00, 0x00},
709 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
710 {0x11, 0x01}, /* clkrc */
711 {0x6b, 0x5a}, /* dblv */
712 {0x6a, 0x0c}, /* 50 Hz banding filter */
713 {0xc5, 0x0f}, /* 60 Hz banding filter */
714 {0xa2, 0x4e}, /* bd50 */
715 {0xa3, 0x41}, /* bd60 */
716};
717
718static const u8 ov965x_start_2_sxga[][2] = {
719 {0x13, 0xe0}, /* com8 */
720 {0x00, 0x00},
721 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
722 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
723 {0x1e, 0x04}, /* mvfp */
724 {0x11, 0x01}, /* clkrc */
725 {0x6b, 0x5a}, /* dblv */
726 {0x6a, 0x0c}, /* 50 Hz banding filter */
727 {0xc5, 0x0f}, /* 60 Hz banding filter */
728 {0xa2, 0x4e}, /* bd50 */
729 {0xa3, 0x41}, /* bd60 */
730};
731
732static const u8 ov562x_init[][2] = {
733 {0x88, 0x20},
734 {0x89, 0x0a},
735 {0x8a, 0x90},
736 {0x8b, 0x06},
737 {0x8c, 0x01},
738 {0x8d, 0x10},
739 {0x1c, 0x00},
740 {0x1d, 0x48},
741 {0x1d, 0x00},
742 {0x1d, 0xff},
743 {0x1c, 0x0a},
744 {0x1d, 0x2e},
745 {0x1d, 0x1e},
746};
747
748static const u8 ov562x_init_2[][2] = {
749 {0x12, 0x80},
750 {0x11, 0x41},
751 {0x13, 0x00},
752 {0x10, 0x1e},
753 {0x3b, 0x07},
754 {0x5b, 0x40},
755 {0x39, 0x07},
756 {0x53, 0x02},
757 {0x54, 0x60},
758 {0x04, 0x20},
759 {0x27, 0x04},
760 {0x3d, 0x40},
761 {0x36, 0x00},
762 {0xc5, 0x04},
763 {0x4e, 0x00},
764 {0x4f, 0x93},
765 {0x50, 0x7b},
766 {0xca, 0x0c},
767 {0xcb, 0x0f},
768 {0x39, 0x07},
769 {0x4a, 0x10},
770 {0x3e, 0x0a},
771 {0x3d, 0x00},
772 {0x0c, 0x38},
773 {0x38, 0x90},
774 {0x46, 0x30},
775 {0x4f, 0x93},
776 {0x50, 0x7b},
777 {0xab, 0x00},
778 {0xca, 0x0c},
779 {0xcb, 0x0f},
780 {0x37, 0x02},
781 {0x44, 0x48},
782 {0x8d, 0x44},
783 {0x2a, 0x00},
784 {0x2b, 0x00},
785 {0x32, 0x00},
786 {0x38, 0x90},
787 {0x53, 0x02},
788 {0x54, 0x60},
789 {0x12, 0x00},
790 {0x17, 0x12},
791 {0x18, 0xb4},
792 {0x19, 0x0c},
793 {0x1a, 0xf4},
794 {0x03, 0x4a},
795 {0x89, 0x20},
796 {0x83, 0x80},
797 {0xb7, 0x9d},
798 {0xb6, 0x11},
799 {0xb5, 0x55},
800 {0xb4, 0x00},
801 {0xa9, 0xf0},
802 {0xa8, 0x0a},
803 {0xb8, 0xf0},
804 {0xb9, 0xf0},
805 {0xba, 0xf0},
806 {0x81, 0x07},
807 {0x63, 0x44},
808 {0x13, 0xc7},
809 {0x14, 0x60},
810 {0x33, 0x75},
811 {0x2c, 0x00},
812 {0x09, 0x00},
813 {0x35, 0x30},
814 {0x27, 0x04},
815 {0x3c, 0x07},
816 {0x3a, 0x0a},
817 {0x3b, 0x07},
818 {0x01, 0x40},
819 {0x02, 0x40},
820 {0x16, 0x40},
821 {0x52, 0xb0},
822 {0x51, 0x83},
823 {0x21, 0xbb},
824 {0x22, 0x10},
825 {0x23, 0x03},
826 {0x35, 0x38},
827 {0x20, 0x90},
828 {0x28, 0x30},
829 {0x73, 0xe1},
830 {0x6c, 0x00},
831 {0x6d, 0x80},
832 {0x6e, 0x00},
833 {0x70, 0x04},
834 {0x71, 0x00},
835 {0x8d, 0x04},
836 {0x64, 0x00},
837 {0x65, 0x00},
838 {0x66, 0x00},
839 {0x67, 0x00},
840 {0x68, 0x00},
841 {0x69, 0x00},
842 {0x6a, 0x00},
843 {0x6b, 0x00},
844 {0x71, 0x94},
845 {0x74, 0x20},
846 {0x80, 0x09},
847 {0x85, 0xc0},
848};
849
850static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
851{
852 struct usb_device *udev = gspca_dev->dev;
853 int ret;
854
855 if (gspca_dev->usb_err < 0)
856 return;
857 gspca_dev->usb_buf[0] = val;
858 ret = usb_control_msg(udev,
859 usb_sndctrlpipe(udev, 0),
860 0x01,
861 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
862 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
863 if (ret < 0) {
864 pr_err("reg_w failed %d\n", ret);
865 gspca_dev->usb_err = ret;
866 }
867}
868
869static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
870{
871 PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
872 reg_w_i(gspca_dev, reg, val);
873}
874
875static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
876{
877 struct usb_device *udev = gspca_dev->dev;
878 int ret;
879
880 if (gspca_dev->usb_err < 0)
881 return 0;
882 ret = usb_control_msg(udev,
883 usb_rcvctrlpipe(udev, 0),
884 0x01,
885 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
886 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
887 PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
888 if (ret < 0) {
889 pr_err("reg_r err %d\n", ret);
890 gspca_dev->usb_err = ret;
891 }
892 return gspca_dev->usb_buf[0];
893}
894
895static int sccb_check_status(struct gspca_dev *gspca_dev)
896{
897 u8 data;
898 int i;
899
900 for (i = 0; i < 5; i++) {
901 msleep(10);
902 data = reg_r(gspca_dev, OV534_REG_STATUS);
903
904 switch (data) {
905 case 0x00:
906 return 1;
907 case 0x04:
908 return 0;
909 case 0x03:
910 break;
911 default:
912 PDEBUG(D_USBI|D_USBO,
913 "sccb status 0x%02x, attempt %d/5",
914 data, i + 1);
915 }
916 }
917 return 0;
918}
919
920static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
921{
922 PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
923 reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
924 reg_w_i(gspca_dev, OV534_REG_WRITE, val);
925 reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
926
927 if (!sccb_check_status(gspca_dev))
928 pr_err("sccb_write failed\n");
929}
930
931static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
932{
933 reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
934 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
935 if (!sccb_check_status(gspca_dev))
936 pr_err("sccb_read failed 1\n");
937
938 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
939 if (!sccb_check_status(gspca_dev))
940 pr_err("sccb_read failed 2\n");
941
942 return reg_r(gspca_dev, OV534_REG_READ);
943}
944
945/* output a bridge sequence (reg - val) */
946static void reg_w_array(struct gspca_dev *gspca_dev,
947 const u8 (*data)[2], int len)
948{
949 while (--len >= 0) {
950 reg_w(gspca_dev, (*data)[0], (*data)[1]);
951 data++;
952 }
953}
954
955/* output a sensor sequence (reg - val) */
956static void sccb_w_array(struct gspca_dev *gspca_dev,
957 const u8 (*data)[2], int len)
958{
959 while (--len >= 0) {
960 if ((*data)[0] != 0xff) {
961 sccb_write(gspca_dev, (*data)[0], (*data)[1]);
962 } else {
963 sccb_read(gspca_dev, (*data)[1]);
964 sccb_write(gspca_dev, 0xff, 0x00);
965 }
966 data++;
967 }
968}
969
970/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
971 * (direction and output)? */
972static void set_led(struct gspca_dev *gspca_dev, int status)
973{
974 u8 data;
975
976 PDEBUG(D_CONF, "led status: %d", status);
977
978 data = reg_r(gspca_dev, 0x21);
979 data |= 0x80;
980 reg_w(gspca_dev, 0x21, data);
981
982 data = reg_r(gspca_dev, 0x23);
983 if (status)
984 data |= 0x80;
985 else
986 data &= ~0x80;
987
988 reg_w(gspca_dev, 0x23, data);
989
990 if (!status) {
991 data = reg_r(gspca_dev, 0x21);
992 data &= ~0x80;
993 reg_w(gspca_dev, 0x21, data);
994 }
995}
996
997static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
998{
999 struct sd *sd = (struct sd *) gspca_dev;
1000 u8 val;
1001 s8 sval;
1002
1003 if (sd->sensor == SENSOR_OV562x) {
1004 sval = brightness;
1005 val = 0x76;
1006 val += sval;
1007 sccb_write(gspca_dev, 0x24, val);
1008 val = 0x6a;
1009 val += sval;
1010 sccb_write(gspca_dev, 0x25, val);
1011 if (sval < -40)
1012 val = 0x71;
1013 else if (sval < 20)
1014 val = 0x94;
1015 else
1016 val = 0xe6;
1017 sccb_write(gspca_dev, 0x26, val);
1018 } else {
1019 val = brightness;
1020 if (val < 8)
1021 val = 15 - val; /* f .. 8 */
1022 else
1023 val = val - 8; /* 0 .. 7 */
1024 sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */
1025 0x0f | (val << 4));
1026 }
1027}
1028
1029static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
1030{
1031 sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
1032 val << 4);
1033}
1034
1035static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)
1036{
1037 u8 val;
1038
1039/*fixme: should adjust agc/awb/aec by different controls */
1040 val = sccb_read(gspca_dev, 0x13); /* com8 */
1041 sccb_write(gspca_dev, 0xff, 0x00);
1042 if (autogain)
1043 val |= 0x05; /* agc & aec */
1044 else
1045 val &= 0xfa;
1046 sccb_write(gspca_dev, 0x13, val);
1047}
1048
1049static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)
1050{
1051 static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
1052 u8 val;
1053
1054 sccb_write(gspca_dev, 0x10, expo[exposure]); /* aec[9:2] */
1055
1056 val = sccb_read(gspca_dev, 0x13); /* com8 */
1057 sccb_write(gspca_dev, 0xff, 0x00);
1058 sccb_write(gspca_dev, 0x13, val);
1059
1060 val = sccb_read(gspca_dev, 0xa1); /* aech */
1061 sccb_write(gspca_dev, 0xff, 0x00);
1062 sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */
1063}
1064
1065static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
1066{
1067 if (val < 0) { /* auto */
1068 val = sccb_read(gspca_dev, 0x42); /* com17 */
1069 sccb_write(gspca_dev, 0xff, 0x00);
1070 sccb_write(gspca_dev, 0x42, val | 0x40);
1071 /* Edge enhancement strength auto adjust */
1072 return;
1073 }
1074 if (val != 0)
1075 val = 1 << (val - 1);
1076 sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */
1077 val);
1078 val = sccb_read(gspca_dev, 0x42); /* com17 */
1079 sccb_write(gspca_dev, 0xff, 0x00);
1080 sccb_write(gspca_dev, 0x42, val & 0xbf);
1081}
1082
1083static void setsatur(struct gspca_dev *gspca_dev, s32 val)
1084{
1085 u8 val1, val2, val3;
1086 static const u8 matrix[5][2] = {
1087 {0x14, 0x38},
1088 {0x1e, 0x54},
1089 {0x28, 0x70},
1090 {0x32, 0x8c},
1091 {0x48, 0x90}
1092 };
1093
1094 val1 = matrix[val][0];
1095 val2 = matrix[val][1];
1096 val3 = val1 + val2;
1097 sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */
1098 sccb_write(gspca_dev, 0x50, val3);
1099 sccb_write(gspca_dev, 0x51, 0x00);
1100 sccb_write(gspca_dev, 0x52, val1);
1101 sccb_write(gspca_dev, 0x53, val2);
1102 sccb_write(gspca_dev, 0x54, val3);
1103 sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */
1104
1105 val1 = sccb_read(gspca_dev, 0x41); /* com16 */
1106 sccb_write(gspca_dev, 0xff, 0x00);
1107 sccb_write(gspca_dev, 0x41, val1);
1108}
1109
1110static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)
1111{
1112 u8 val;
1113
1114 val = sccb_read(gspca_dev, 0x13); /* com8 */
1115 sccb_write(gspca_dev, 0xff, 0x00);
1116 if (freq == 0) {
1117 sccb_write(gspca_dev, 0x13, val & 0xdf);
1118 return;
1119 }
1120 sccb_write(gspca_dev, 0x13, val | 0x20);
1121
1122 val = sccb_read(gspca_dev, 0x42); /* com17 */
1123 sccb_write(gspca_dev, 0xff, 0x00);
1124 if (freq == 1)
1125 val |= 0x01;
1126 else
1127 val &= 0xfe;
1128 sccb_write(gspca_dev, 0x42, val);
1129}
1130
1131/* this function is called at probe time */
1132static int sd_config(struct gspca_dev *gspca_dev,
1133 const struct usb_device_id *id)
1134{
1135 return 0;
1136}
1137
1138/* this function is called at probe and resume time */
1139static int sd_init(struct gspca_dev *gspca_dev)
1140{
1141 struct sd *sd = (struct sd *) gspca_dev;
1142 u16 sensor_id;
1143
1144 /* reset bridge */
1145 reg_w(gspca_dev, 0xe7, 0x3a);
1146 reg_w(gspca_dev, 0xe0, 0x08);
1147 msleep(100);
1148
1149 /* initialize the sensor address */
1150 reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
1151
1152 /* reset sensor */
1153 sccb_write(gspca_dev, 0x12, 0x80);
1154 msleep(10);
1155
1156 /* probe the sensor */
1157 sccb_read(gspca_dev, 0x0a);
1158 sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
1159 sccb_read(gspca_dev, 0x0b);
1160 sensor_id |= sccb_read(gspca_dev, 0x0b);
1161 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1162
1163 /* initialize */
1164 if ((sensor_id & 0xfff0) == 0x9650) {
1165 sd->sensor = SENSOR_OV965x;
1166
1167 gspca_dev->cam.cam_mode = ov965x_mode;
1168 gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
1169
1170 reg_w_array(gspca_dev, bridge_init,
1171 ARRAY_SIZE(bridge_init));
1172 sccb_w_array(gspca_dev, ov965x_init,
1173 ARRAY_SIZE(ov965x_init));
1174 reg_w_array(gspca_dev, bridge_init_2,
1175 ARRAY_SIZE(bridge_init_2));
1176 sccb_w_array(gspca_dev, ov965x_init_2,
1177 ARRAY_SIZE(ov965x_init_2));
1178 reg_w(gspca_dev, 0xe0, 0x00);
1179 reg_w(gspca_dev, 0xe0, 0x01);
1180 set_led(gspca_dev, 0);
1181 reg_w(gspca_dev, 0xe0, 0x00);
1182 } else if ((sensor_id & 0xfff0) == 0x9710) {
1183 const char *p;
1184 int l;
1185
1186 sd->sensor = SENSOR_OV971x;
1187
1188 gspca_dev->cam.cam_mode = ov971x_mode;
1189 gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
1190
1191 gspca_dev->cam.bulk = 1;
1192 gspca_dev->cam.bulk_size = 16384;
1193 gspca_dev->cam.bulk_nurbs = 2;
1194
1195 sccb_w_array(gspca_dev, ov971x_init,
1196 ARRAY_SIZE(ov971x_init));
1197
1198 /* set video format on bridge processor */
1199 /* access bridge processor's video format registers at: 0x00 */
1200 reg_w(gspca_dev, 0x1c, 0x00);
1201 /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
1202 reg_w(gspca_dev, 0x1d, 0x00);
1203
1204 /* Will W. specific stuff
1205 * set VSYNC to
1206 * output (0x1f) if first webcam
1207 * input (0x17) if 2nd or 3rd webcam */
1208 p = video_device_node_name(&gspca_dev->vdev);
1209 l = strlen(p) - 1;
1210 if (p[l] == '0')
1211 reg_w(gspca_dev, 0x56, 0x1f);
1212 else
1213 reg_w(gspca_dev, 0x56, 0x17);
1214 } else if ((sensor_id & 0xfff0) == 0x5620) {
1215 sd->sensor = SENSOR_OV562x;
1216 gspca_dev->cam.cam_mode = ov562x_mode;
1217 gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
1218
1219 reg_w_array(gspca_dev, ov562x_init,
1220 ARRAY_SIZE(ov562x_init));
1221 sccb_w_array(gspca_dev, ov562x_init_2,
1222 ARRAY_SIZE(ov562x_init_2));
1223 reg_w(gspca_dev, 0xe0, 0x00);
1224 } else {
1225 pr_err("Unknown sensor %04x", sensor_id);
1226 return -EINVAL;
1227 }
1228
1229 return gspca_dev->usb_err;
1230}
1231
1232static int sd_start(struct gspca_dev *gspca_dev)
1233{
1234 struct sd *sd = (struct sd *) gspca_dev;
1235
1236 if (sd->sensor == SENSOR_OV971x)
1237 return gspca_dev->usb_err;
1238 if (sd->sensor == SENSOR_OV562x)
1239 return gspca_dev->usb_err;
1240
1241 switch (gspca_dev->curr_mode) {
1242 case QVGA_MODE: /* 320x240 */
1243 sccb_w_array(gspca_dev, ov965x_start_1_vga,
1244 ARRAY_SIZE(ov965x_start_1_vga));
1245 reg_w_array(gspca_dev, bridge_start_qvga,
1246 ARRAY_SIZE(bridge_start_qvga));
1247 sccb_w_array(gspca_dev, ov965x_start_2_qvga,
1248 ARRAY_SIZE(ov965x_start_2_qvga));
1249 break;
1250 case VGA_MODE: /* 640x480 */
1251 sccb_w_array(gspca_dev, ov965x_start_1_vga,
1252 ARRAY_SIZE(ov965x_start_1_vga));
1253 reg_w_array(gspca_dev, bridge_start_vga,
1254 ARRAY_SIZE(bridge_start_vga));
1255 sccb_w_array(gspca_dev, ov965x_start_2_vga,
1256 ARRAY_SIZE(ov965x_start_2_vga));
1257 break;
1258 case SVGA_MODE: /* 800x600 */
1259 sccb_w_array(gspca_dev, ov965x_start_1_svga,
1260 ARRAY_SIZE(ov965x_start_1_svga));
1261 reg_w_array(gspca_dev, bridge_start_svga,
1262 ARRAY_SIZE(bridge_start_svga));
1263 sccb_w_array(gspca_dev, ov965x_start_2_svga,
1264 ARRAY_SIZE(ov965x_start_2_svga));
1265 break;
1266 case XGA_MODE: /* 1024x768 */
1267 sccb_w_array(gspca_dev, ov965x_start_1_xga,
1268 ARRAY_SIZE(ov965x_start_1_xga));
1269 reg_w_array(gspca_dev, bridge_start_xga,
1270 ARRAY_SIZE(bridge_start_xga));
1271 sccb_w_array(gspca_dev, ov965x_start_2_svga,
1272 ARRAY_SIZE(ov965x_start_2_svga));
1273 break;
1274 default:
1275/* case SXGA_MODE: * 1280x1024 */
1276 sccb_w_array(gspca_dev, ov965x_start_1_sxga,
1277 ARRAY_SIZE(ov965x_start_1_sxga));
1278 reg_w_array(gspca_dev, bridge_start_sxga,
1279 ARRAY_SIZE(bridge_start_sxga));
1280 sccb_w_array(gspca_dev, ov965x_start_2_sxga,
1281 ARRAY_SIZE(ov965x_start_2_sxga));
1282 break;
1283 }
1284
1285 reg_w(gspca_dev, 0xe0, 0x00);
1286 reg_w(gspca_dev, 0xe0, 0x00);
1287 set_led(gspca_dev, 1);
1288 return gspca_dev->usb_err;
1289}
1290
1291static void sd_stopN(struct gspca_dev *gspca_dev)
1292{
1293 reg_w(gspca_dev, 0xe0, 0x01);
1294 set_led(gspca_dev, 0);
1295 reg_w(gspca_dev, 0xe0, 0x00);
1296}
1297
1298/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1299#define UVC_STREAM_EOH (1 << 7)
1300#define UVC_STREAM_ERR (1 << 6)
1301#define UVC_STREAM_STI (1 << 5)
1302#define UVC_STREAM_RES (1 << 4)
1303#define UVC_STREAM_SCR (1 << 3)
1304#define UVC_STREAM_PTS (1 << 2)
1305#define UVC_STREAM_EOF (1 << 1)
1306#define UVC_STREAM_FID (1 << 0)
1307
1308static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1309 u8 *data, int len)
1310{
1311 struct sd *sd = (struct sd *) gspca_dev;
1312 __u32 this_pts;
1313 u8 this_fid;
1314 int remaining_len = len;
1315 int payload_len;
1316
1317 payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
1318 do {
1319 len = min(remaining_len, payload_len);
1320
1321 /* Payloads are prefixed with a UVC-style header. We
1322 consider a frame to start when the FID toggles, or the PTS
1323 changes. A frame ends when EOF is set, and we've received
1324 the correct number of bytes. */
1325
1326 /* Verify UVC header. Header length is always 12 */
1327 if (data[0] != 12 || len < 12) {
1328 PDEBUG(D_PACK, "bad header");
1329 goto discard;
1330 }
1331
1332 /* Check errors */
1333 if (data[1] & UVC_STREAM_ERR) {
1334 PDEBUG(D_PACK, "payload error");
1335 goto discard;
1336 }
1337
1338 /* Extract PTS and FID */
1339 if (!(data[1] & UVC_STREAM_PTS)) {
1340 PDEBUG(D_PACK, "PTS not present");
1341 goto discard;
1342 }
1343 this_pts = (data[5] << 24) | (data[4] << 16)
1344 | (data[3] << 8) | data[2];
1345 this_fid = data[1] & UVC_STREAM_FID;
1346
1347 /* If PTS or FID has changed, start a new frame. */
1348 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1349 if (gspca_dev->last_packet_type == INTER_PACKET)
1350 gspca_frame_add(gspca_dev, LAST_PACKET,
1351 NULL, 0);
1352 sd->last_pts = this_pts;
1353 sd->last_fid = this_fid;
1354 gspca_frame_add(gspca_dev, FIRST_PACKET,
1355 data + 12, len - 12);
1356 /* If this packet is marked as EOF, end the frame */
1357 } else if (data[1] & UVC_STREAM_EOF) {
1358 sd->last_pts = 0;
1359 gspca_frame_add(gspca_dev, LAST_PACKET,
1360 data + 12, len - 12);
1361 } else {
1362
1363 /* Add the data from this payload */
1364 gspca_frame_add(gspca_dev, INTER_PACKET,
1365 data + 12, len - 12);
1366 }
1367
1368 /* Done this payload */
1369 goto scan_next;
1370
1371discard:
1372 /* Discard data until a new frame starts. */
1373 gspca_dev->last_packet_type = DISCARD_PACKET;
1374
1375scan_next:
1376 remaining_len -= len;
1377 data += len;
1378 } while (remaining_len > 0);
1379}
1380
1381static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1382{
1383 struct gspca_dev *gspca_dev =
1384 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1385
1386 gspca_dev->usb_err = 0;
1387
1388 if (!gspca_dev->streaming)
1389 return 0;
1390
1391 switch (ctrl->id) {
1392 case V4L2_CID_BRIGHTNESS:
1393 setbrightness(gspca_dev, ctrl->val);
1394 break;
1395 case V4L2_CID_CONTRAST:
1396 setcontrast(gspca_dev, ctrl->val);
1397 break;
1398 case V4L2_CID_SATURATION:
1399 setsatur(gspca_dev, ctrl->val);
1400 break;
1401 case V4L2_CID_POWER_LINE_FREQUENCY:
1402 setlightfreq(gspca_dev, ctrl->val);
1403 break;
1404 case V4L2_CID_SHARPNESS:
1405 setsharpness(gspca_dev, ctrl->val);
1406 break;
1407 case V4L2_CID_AUTOGAIN:
1408 if (ctrl->is_new)
1409 setautogain(gspca_dev, ctrl->val);
1410 if (!ctrl->val && gspca_dev->exposure->is_new)
1411 setexposure(gspca_dev, gspca_dev->exposure->val);
1412 break;
1413 }
1414 return gspca_dev->usb_err;
1415}
1416
1417static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1418 .s_ctrl = sd_s_ctrl,
1419};
1420
1421static int sd_init_controls(struct gspca_dev *gspca_dev)
1422{
1423 struct sd *sd = (struct sd *)gspca_dev;
1424 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1425
1426 if (sd->sensor == SENSOR_OV971x)
1427 return 0;
1428 gspca_dev->vdev.ctrl_handler = hdl;
1429 v4l2_ctrl_handler_init(hdl, 7);
1430 if (sd->sensor == SENSOR_OV562x) {
1431 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1432 V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);
1433 } else {
1434 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1435 V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);
1436 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1437 V4L2_CID_CONTRAST, 0, 15, 1, 3);
1438 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1439 V4L2_CID_SATURATION, 0, 4, 1, 2);
1440 /* -1 = auto */
1441 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1442 V4L2_CID_SHARPNESS, -1, 4, 1, -1);
1443 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1444 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1445 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1446 V4L2_CID_EXPOSURE, 0, 3, 1, 0);
1447 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
1448 V4L2_CID_POWER_LINE_FREQUENCY,
1449 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
1450 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
1451 }
1452
1453 if (hdl->error) {
1454 pr_err("Could not initialize controls\n");
1455 return hdl->error;
1456 }
1457 return 0;
1458}
1459
1460/* sub-driver description */
1461static const struct sd_desc sd_desc = {
1462 .name = MODULE_NAME,
1463 .config = sd_config,
1464 .init = sd_init,
1465 .init_controls = sd_init_controls,
1466 .start = sd_start,
1467 .stopN = sd_stopN,
1468 .pkt_scan = sd_pkt_scan,
1469};
1470
1471/* -- module initialisation -- */
1472static const struct usb_device_id device_table[] = {
1473 {USB_DEVICE(0x05a9, 0x8065)},
1474 {USB_DEVICE(0x06f8, 0x3003)},
1475 {USB_DEVICE(0x05a9, 0x1550)},
1476 {}
1477};
1478
1479MODULE_DEVICE_TABLE(usb, device_table);
1480
1481/* -- device connect -- */
1482static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1483{
1484 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1485 THIS_MODULE);
1486}
1487
1488static struct usb_driver sd_driver = {
1489 .name = MODULE_NAME,
1490 .id_table = device_table,
1491 .probe = sd_probe,
1492 .disconnect = gspca_disconnect,
1493#ifdef CONFIG_PM
1494 .suspend = gspca_suspend,
1495 .resume = gspca_resume,
1496 .reset_resume = gspca_resume,
1497#endif
1498};
1499
1500module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c
new file mode 100644
index 00000000000..d236d1791f7
--- /dev/null
+++ b/drivers/media/usb/gspca/pac207.c
@@ -0,0 +1,469 @@
1/*
2 * Pixart PAC207BCA library
3 *
4 * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#define MODULE_NAME "pac207"
29
30#include <linux/input.h>
31#include "gspca.h"
32/* Include pac common sof detection functions */
33#include "pac_common.h"
34
35MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
36MODULE_DESCRIPTION("Pixart PAC207");
37MODULE_LICENSE("GPL");
38
39#define PAC207_CTRL_TIMEOUT 100 /* ms */
40
41#define PAC207_BRIGHTNESS_MIN 0
42#define PAC207_BRIGHTNESS_MAX 255
43#define PAC207_BRIGHTNESS_DEFAULT 46
44#define PAC207_BRIGHTNESS_REG 0x08
45
46#define PAC207_EXPOSURE_MIN 3
47#define PAC207_EXPOSURE_MAX 90 /* 1 sec expo time / 1 fps */
48#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */
49#define PAC207_EXPOSURE_REG 0x02
50
51#define PAC207_GAIN_MIN 0
52#define PAC207_GAIN_MAX 31
53#define PAC207_GAIN_DEFAULT 7 /* power on default: 9 */
54#define PAC207_GAIN_REG 0x0e
55
56#define PAC207_AUTOGAIN_DEADZONE 30
57
58/* specific webcam descriptor */
59struct sd {
60 struct gspca_dev gspca_dev; /* !! must be the first item */
61
62 struct v4l2_ctrl *brightness;
63
64 u8 mode;
65 u8 sof_read;
66 u8 header_read;
67 u8 autogain_ignore_frames;
68
69 atomic_t avg_lum;
70};
71
72static const struct v4l2_pix_format sif_mode[] = {
73 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
74 .bytesperline = 176,
75 .sizeimage = (176 + 2) * 144,
76 /* uncompressed, add 2 bytes / line for line header */
77 .colorspace = V4L2_COLORSPACE_SRGB,
78 .priv = 1},
79 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
80 .bytesperline = 352,
81 /* compressed, but only when needed (not compressed
82 when the framerate is low) */
83 .sizeimage = (352 + 2) * 288,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0},
86};
87
88static const __u8 pac207_sensor_init[][8] = {
89 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
90 {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
91 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
92 {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00},
93};
94
95static void pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
96 const u8 *buffer, u16 length)
97{
98 struct usb_device *udev = gspca_dev->dev;
99 int err;
100
101 if (gspca_dev->usb_err < 0)
102 return;
103
104 memcpy(gspca_dev->usb_buf, buffer, length);
105
106 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
107 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
108 0x00, index,
109 gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
110 if (err < 0) {
111 pr_err("Failed to write registers to index 0x%04X, error %d\n",
112 index, err);
113 gspca_dev->usb_err = err;
114 }
115}
116
117static void pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
118{
119 struct usb_device *udev = gspca_dev->dev;
120 int err;
121
122 if (gspca_dev->usb_err < 0)
123 return;
124
125 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
126 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
127 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
128 if (err) {
129 pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
130 index, value, err);
131 gspca_dev->usb_err = err;
132 }
133}
134
135static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
136{
137 struct usb_device *udev = gspca_dev->dev;
138 int res;
139
140 if (gspca_dev->usb_err < 0)
141 return 0;
142
143 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
144 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
145 0x00, index,
146 gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
147 if (res < 0) {
148 pr_err("Failed to read a register (index 0x%04X, error %d)\n",
149 index, res);
150 gspca_dev->usb_err = res;
151 return 0;
152 }
153
154 return gspca_dev->usb_buf[0];
155}
156
157/* this function is called at probe time */
158static int sd_config(struct gspca_dev *gspca_dev,
159 const struct usb_device_id *id)
160{
161 struct cam *cam;
162 u8 idreg[2];
163
164 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
165 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
166 idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4);
167 idreg[1] = idreg[1] & 0x0f;
168 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
169 idreg[0], idreg[1]);
170
171 if (idreg[0] != 0x27) {
172 PDEBUG(D_PROBE, "Error invalid sensor ID!");
173 return -ENODEV;
174 }
175
176 PDEBUG(D_PROBE,
177 "Pixart PAC207BCA Image Processor and Control Chip detected"
178 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
179
180 cam = &gspca_dev->cam;
181 cam->cam_mode = sif_mode;
182 cam->nmodes = ARRAY_SIZE(sif_mode);
183
184 return 0;
185}
186
187/* this function is called at probe and resume time */
188static int sd_init(struct gspca_dev *gspca_dev)
189{
190 pac207_write_reg(gspca_dev, 0x41, 0x00);
191 /* Bit_0=Image Format,
192 * Bit_1=LED,
193 * Bit_2=Compression test mode enable */
194 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
195
196 return gspca_dev->usb_err;
197}
198
199static void setcontrol(struct gspca_dev *gspca_dev, u16 reg, u16 val)
200{
201 pac207_write_reg(gspca_dev, reg, val);
202 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
203 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
204}
205
206static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
207{
208 struct gspca_dev *gspca_dev =
209 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
210 struct sd *sd = (struct sd *)gspca_dev;
211
212 gspca_dev->usb_err = 0;
213
214 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
215 /* when switching to autogain set defaults to make sure
216 we are on a valid point of the autogain gain /
217 exposure knee graph, and give this change time to
218 take effect before doing autogain. */
219 gspca_dev->exposure->val = PAC207_EXPOSURE_DEFAULT;
220 gspca_dev->gain->val = PAC207_GAIN_DEFAULT;
221 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
222 }
223
224 if (!gspca_dev->streaming)
225 return 0;
226
227 switch (ctrl->id) {
228 case V4L2_CID_BRIGHTNESS:
229 setcontrol(gspca_dev, PAC207_BRIGHTNESS_REG, ctrl->val);
230 break;
231 case V4L2_CID_AUTOGAIN:
232 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
233 setcontrol(gspca_dev, PAC207_EXPOSURE_REG,
234 gspca_dev->exposure->val);
235 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
236 setcontrol(gspca_dev, PAC207_GAIN_REG,
237 gspca_dev->gain->val);
238 break;
239 default:
240 return -EINVAL;
241 }
242 return gspca_dev->usb_err;
243}
244
245static const struct v4l2_ctrl_ops sd_ctrl_ops = {
246 .s_ctrl = sd_s_ctrl,
247};
248
249/* this function is called at probe time */
250static int sd_init_controls(struct gspca_dev *gspca_dev)
251{
252 struct sd *sd = (struct sd *) gspca_dev;
253 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
254
255 gspca_dev->vdev.ctrl_handler = hdl;
256 v4l2_ctrl_handler_init(hdl, 4);
257
258 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
259 V4L2_CID_BRIGHTNESS,
260 PAC207_BRIGHTNESS_MIN, PAC207_BRIGHTNESS_MAX,
261 1, PAC207_BRIGHTNESS_DEFAULT);
262 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
263 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
264 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
265 V4L2_CID_EXPOSURE,
266 PAC207_EXPOSURE_MIN, PAC207_EXPOSURE_MAX,
267 1, PAC207_EXPOSURE_DEFAULT);
268 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
269 V4L2_CID_GAIN,
270 PAC207_GAIN_MIN, PAC207_GAIN_MAX,
271 1, PAC207_GAIN_DEFAULT);
272 if (hdl->error) {
273 pr_err("Could not initialize controls\n");
274 return hdl->error;
275 }
276 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
277 return 0;
278}
279
280/* -- start the camera -- */
281static int sd_start(struct gspca_dev *gspca_dev)
282{
283 struct sd *sd = (struct sd *) gspca_dev;
284 __u8 mode;
285
286 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
287 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
288 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
289 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
290 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
291
292 /* Compression Balance */
293 if (gspca_dev->width == 176)
294 pac207_write_reg(gspca_dev, 0x4a, 0xff);
295 else
296 pac207_write_reg(gspca_dev, 0x4a, 0x30);
297 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
298 pac207_write_reg(gspca_dev, 0x08, v4l2_ctrl_g_ctrl(sd->brightness));
299
300 /* PGA global gain (Bit 4-0) */
301 pac207_write_reg(gspca_dev, 0x0e,
302 v4l2_ctrl_g_ctrl(gspca_dev->gain));
303 pac207_write_reg(gspca_dev, 0x02,
304 v4l2_ctrl_g_ctrl(gspca_dev->exposure)); /* PXCK = 12MHz /n */
305
306 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
307 if (gspca_dev->width == 176) { /* 176x144 */
308 mode |= 0x01;
309 PDEBUG(D_STREAM, "pac207_start mode 176x144");
310 } else { /* 352x288 */
311 PDEBUG(D_STREAM, "pac207_start mode 352x288");
312 }
313 pac207_write_reg(gspca_dev, 0x41, mode);
314
315 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
316 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
317 msleep(10);
318 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
319
320 sd->sof_read = 0;
321 sd->autogain_ignore_frames = 0;
322 atomic_set(&sd->avg_lum, -1);
323 return gspca_dev->usb_err;
324}
325
326static void sd_stopN(struct gspca_dev *gspca_dev)
327{
328 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
329 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
330 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
331}
332
333
334static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
335{
336 struct sd *sd = (struct sd *) gspca_dev;
337 int avg_lum = atomic_read(&sd->avg_lum);
338
339 if (avg_lum == -1)
340 return;
341
342 if (sd->autogain_ignore_frames > 0)
343 sd->autogain_ignore_frames--;
344 else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
345 90, PAC207_AUTOGAIN_DEADZONE))
346 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
347}
348
349static void sd_pkt_scan(struct gspca_dev *gspca_dev,
350 u8 *data,
351 int len)
352{
353 struct sd *sd = (struct sd *) gspca_dev;
354 unsigned char *sof;
355
356 sof = pac_find_sof(&sd->sof_read, data, len);
357 if (sof) {
358 int n;
359
360 /* finish decoding current frame */
361 n = sof - data;
362 if (n > sizeof pac_sof_marker)
363 n -= sizeof pac_sof_marker;
364 else
365 n = 0;
366 gspca_frame_add(gspca_dev, LAST_PACKET,
367 data, n);
368 sd->header_read = 0;
369 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
370 len -= sof - data;
371 data = sof;
372 }
373 if (sd->header_read < 11) {
374 int needed;
375
376 /* get average lumination from frame header (byte 5) */
377 if (sd->header_read < 5) {
378 needed = 5 - sd->header_read;
379 if (len >= needed)
380 atomic_set(&sd->avg_lum, data[needed - 1]);
381 }
382 /* skip the rest of the header */
383 needed = 11 - sd->header_read;
384 if (len <= needed) {
385 sd->header_read += len;
386 return;
387 }
388 data += needed;
389 len -= needed;
390 sd->header_read = 11;
391 }
392
393 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
394}
395
396#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
397static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
398 u8 *data, /* interrupt packet data */
399 int len) /* interrput packet length */
400{
401 int ret = -EINVAL;
402
403 if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) {
404 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
405 input_sync(gspca_dev->input_dev);
406 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
407 input_sync(gspca_dev->input_dev);
408 ret = 0;
409 }
410
411 return ret;
412}
413#endif
414
415/* sub-driver description */
416static const struct sd_desc sd_desc = {
417 .name = MODULE_NAME,
418 .config = sd_config,
419 .init = sd_init,
420 .init_controls = sd_init_controls,
421 .start = sd_start,
422 .stopN = sd_stopN,
423 .dq_callback = pac207_do_auto_gain,
424 .pkt_scan = sd_pkt_scan,
425#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
426 .int_pkt_scan = sd_int_pkt_scan,
427#endif
428};
429
430/* -- module initialisation -- */
431static const struct usb_device_id device_table[] = {
432 {USB_DEVICE(0x041e, 0x4028)},
433 {USB_DEVICE(0x093a, 0x2460)},
434 {USB_DEVICE(0x093a, 0x2461)},
435 {USB_DEVICE(0x093a, 0x2463)},
436 {USB_DEVICE(0x093a, 0x2464)},
437 {USB_DEVICE(0x093a, 0x2468)},
438 {USB_DEVICE(0x093a, 0x2470)},
439 {USB_DEVICE(0x093a, 0x2471)},
440 {USB_DEVICE(0x093a, 0x2472)},
441 {USB_DEVICE(0x093a, 0x2474)},
442 {USB_DEVICE(0x093a, 0x2476)},
443 {USB_DEVICE(0x145f, 0x013a)},
444 {USB_DEVICE(0x2001, 0xf115)},
445 {}
446};
447MODULE_DEVICE_TABLE(usb, device_table);
448
449/* -- device connect -- */
450static int sd_probe(struct usb_interface *intf,
451 const struct usb_device_id *id)
452{
453 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
454 THIS_MODULE);
455}
456
457static struct usb_driver sd_driver = {
458 .name = MODULE_NAME,
459 .id_table = device_table,
460 .probe = sd_probe,
461 .disconnect = gspca_disconnect,
462#ifdef CONFIG_PM
463 .suspend = gspca_suspend,
464 .resume = gspca_resume,
465 .reset_resume = gspca_resume,
466#endif
467};
468
469module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
new file mode 100644
index 00000000000..4877f7ab3d5
--- /dev/null
+++ b/drivers/media/usb/gspca/pac7302.c
@@ -0,0 +1,932 @@
1/*
2 * Pixart PAC7302 driver
3 *
4 * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
6 *
7 * Separated from Pixart PAC7311 library by Márton Németh
8 * Camera button input handling by Márton Németh <nm127@freemail.hu>
9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
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 * Some documentation about various registers as determined by trial and error.
28 *
29 * Register page 1:
30 *
31 * Address Description
32 * 0x78 Global control, bit 6 controls the LED (inverted)
33 * 0x80 Compression balance, 2 interesting settings:
34 * 0x0f Default
35 * 0x50 Values >= this switch the camera to a lower compression,
36 * using the same table for both luminance and chrominance.
37 * This gives a sharper picture. Only usable when running
38 * at < 15 fps! Note currently the driver does not use this
39 * as the quality gain is small and the generated JPG-s are
40 * only understood by v4l-utils >= 0.8.9
41 *
42 * Register page 3:
43 *
44 * Address Description
45 * 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
46 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
47 * 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
48 * 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
49 * 63 -> ~27 fps, the 2 msb's must always be 1 !!
50 * 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
51 * 1 -> ~30 fps, 2 -> ~20 fps
52 * 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
53 * 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
54 * 0x10 Gain 0-31
55 * 0x12 Another gain 0-31, unlike 0x10 this one seems to start with an
56 * amplification value of 1 rather then 0 at its lowest setting
57 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
58 * 0x80 Another framerate control, best left at 1, moving it from 1 to
59 * 2 causes the framerate to become 3/4th of what it was, and
60 * also seems to cause pixel averaging, resulting in an effective
61 * resolution of 320x240 and thus a much blockier image
62 *
63 * The registers are accessed in the following functions:
64 *
65 * Page | Register | Function
66 * -----+------------+---------------------------------------------------
67 * 0 | 0x0f..0x20 | setcolors()
68 * 0 | 0xa2..0xab | setbrightcont()
69 * 0 | 0xc5 | setredbalance()
70 * 0 | 0xc6 | setwhitebalance()
71 * 0 | 0xc7 | setbluebalance()
72 * 0 | 0xdc | setbrightcont(), setcolors()
73 * 3 | 0x02 | setexposure()
74 * 3 | 0x10, 0x12 | setgain()
75 * 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
76 * 3 | 0x21 | sethvflip()
77 */
78
79#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
80
81#include <linux/input.h>
82#include <media/v4l2-chip-ident.h>
83#include "gspca.h"
84/* Include pac common sof detection functions */
85#include "pac_common.h"
86
87#define PAC7302_GAIN_DEFAULT 15
88#define PAC7302_GAIN_KNEE 42
89#define PAC7302_EXPOSURE_DEFAULT 66 /* 33 ms / 30 fps */
90#define PAC7302_EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
91
92MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
93 "Thomas Kaiser thomas@kaiser-linux.li");
94MODULE_DESCRIPTION("Pixart PAC7302");
95MODULE_LICENSE("GPL");
96
97struct sd {
98 struct gspca_dev gspca_dev; /* !! must be the first item */
99
100 struct { /* brightness / contrast cluster */
101 struct v4l2_ctrl *brightness;
102 struct v4l2_ctrl *contrast;
103 };
104 struct v4l2_ctrl *saturation;
105 struct v4l2_ctrl *white_balance;
106 struct v4l2_ctrl *red_balance;
107 struct v4l2_ctrl *blue_balance;
108 struct { /* flip cluster */
109 struct v4l2_ctrl *hflip;
110 struct v4l2_ctrl *vflip;
111 };
112 u8 flags;
113#define FL_HFLIP 0x01 /* mirrored by default */
114#define FL_VFLIP 0x02 /* vertical flipped by default */
115
116 u8 sof_read;
117 s8 autogain_ignore_frames;
118
119 atomic_t avg_lum;
120};
121
122static const struct v4l2_pix_format vga_mode[] = {
123 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480 * 3 / 8 + 590,
126 .colorspace = V4L2_COLORSPACE_JPEG,
127 },
128};
129
130#define LOAD_PAGE3 255
131#define END_OF_SEQUENCE 0
132
133static const u8 init_7302[] = {
134/* index,value */
135 0xff, 0x01, /* page 1 */
136 0x78, 0x00, /* deactivate */
137 0xff, 0x01,
138 0x78, 0x40, /* led off */
139};
140static const u8 start_7302[] = {
141/* index, len, [value]* */
142 0xff, 1, 0x00, /* page 0 */
143 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
144 0x00, 0x00, 0x00, 0x00,
145 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
146 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
147 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
148 0x26, 2, 0xaa, 0xaa,
149 0x2e, 1, 0x31,
150 0x38, 1, 0x01,
151 0x3a, 3, 0x14, 0xff, 0x5a,
152 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
153 0x00, 0x54, 0x11,
154 0x55, 1, 0x00,
155 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
156 0x6b, 1, 0x00,
157 0x6e, 3, 0x08, 0x06, 0x00,
158 0x72, 3, 0x00, 0xff, 0x00,
159 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
160 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
161 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
162 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
163 0xd2, 0xeb,
164 0xaf, 1, 0x02,
165 0xb5, 2, 0x08, 0x08,
166 0xb8, 2, 0x08, 0x88,
167 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
168 0xcc, 1, 0x00,
169 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
170 0xc1, 0xd7, 0xec,
171 0xdc, 1, 0x01,
172 0xff, 1, 0x01, /* page 1 */
173 0x12, 3, 0x02, 0x00, 0x01,
174 0x3e, 2, 0x00, 0x00,
175 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
176 0x7c, 1, 0x00,
177 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
178 0x02, 0x00,
179 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
180 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
181 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
182 0xd8, 1, 0x01,
183 0xdb, 2, 0x00, 0x01,
184 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
185 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
186 0xeb, 1, 0x00,
187 0xff, 1, 0x02, /* page 2 */
188 0x22, 1, 0x00,
189 0xff, 1, 0x03, /* page 3 */
190 0, LOAD_PAGE3, /* load the page 3 */
191 0x11, 1, 0x01,
192 0xff, 1, 0x02, /* page 2 */
193 0x13, 1, 0x00,
194 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
195 0x27, 2, 0x14, 0x0c,
196 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
197 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
198 0x6e, 1, 0x08,
199 0xff, 1, 0x01, /* page 1 */
200 0x78, 1, 0x00,
201 0, END_OF_SEQUENCE /* end of sequence */
202};
203
204#define SKIP 0xaa
205/* page 3 - the value SKIP says skip the index - see reg_w_page() */
206static const u8 page3_7302[] = {
207 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
208 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
209 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
211 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
212 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
213 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
214 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
216 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
217 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
221 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
222 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
223 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
226 0x00
227};
228
229static void reg_w_buf(struct gspca_dev *gspca_dev,
230 u8 index,
231 const u8 *buffer, int len)
232{
233 int ret;
234
235 if (gspca_dev->usb_err < 0)
236 return;
237 memcpy(gspca_dev->usb_buf, buffer, len);
238 ret = usb_control_msg(gspca_dev->dev,
239 usb_sndctrlpipe(gspca_dev->dev, 0),
240 0, /* request */
241 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
242 0, /* value */
243 index, gspca_dev->usb_buf, len,
244 500);
245 if (ret < 0) {
246 pr_err("reg_w_buf failed i: %02x error %d\n",
247 index, ret);
248 gspca_dev->usb_err = ret;
249 }
250}
251
252
253static void reg_w(struct gspca_dev *gspca_dev,
254 u8 index,
255 u8 value)
256{
257 int ret;
258
259 if (gspca_dev->usb_err < 0)
260 return;
261 gspca_dev->usb_buf[0] = value;
262 ret = usb_control_msg(gspca_dev->dev,
263 usb_sndctrlpipe(gspca_dev->dev, 0),
264 0, /* request */
265 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
266 0, index, gspca_dev->usb_buf, 1,
267 500);
268 if (ret < 0) {
269 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
270 index, value, ret);
271 gspca_dev->usb_err = ret;
272 }
273}
274
275static void reg_w_seq(struct gspca_dev *gspca_dev,
276 const u8 *seq, int len)
277{
278 while (--len >= 0) {
279 reg_w(gspca_dev, seq[0], seq[1]);
280 seq += 2;
281 }
282}
283
284/* load the beginning of a page */
285static void reg_w_page(struct gspca_dev *gspca_dev,
286 const u8 *page, int len)
287{
288 int index;
289 int ret = 0;
290
291 if (gspca_dev->usb_err < 0)
292 return;
293 for (index = 0; index < len; index++) {
294 if (page[index] == SKIP) /* skip this index */
295 continue;
296 gspca_dev->usb_buf[0] = page[index];
297 ret = usb_control_msg(gspca_dev->dev,
298 usb_sndctrlpipe(gspca_dev->dev, 0),
299 0, /* request */
300 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
301 0, index, gspca_dev->usb_buf, 1,
302 500);
303 if (ret < 0) {
304 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
305 index, page[index], ret);
306 gspca_dev->usb_err = ret;
307 break;
308 }
309 }
310}
311
312/* output a variable sequence */
313static void reg_w_var(struct gspca_dev *gspca_dev,
314 const u8 *seq,
315 const u8 *page3, unsigned int page3_len)
316{
317 int index, len;
318
319 for (;;) {
320 index = *seq++;
321 len = *seq++;
322 switch (len) {
323 case END_OF_SEQUENCE:
324 return;
325 case LOAD_PAGE3:
326 reg_w_page(gspca_dev, page3, page3_len);
327 break;
328 default:
329#ifdef GSPCA_DEBUG
330 if (len > USB_BUF_SZ) {
331 PDEBUG(D_ERR|D_STREAM,
332 "Incorrect variable sequence");
333 return;
334 }
335#endif
336 while (len > 0) {
337 if (len < 8) {
338 reg_w_buf(gspca_dev,
339 index, seq, len);
340 seq += len;
341 break;
342 }
343 reg_w_buf(gspca_dev, index, seq, 8);
344 seq += 8;
345 index += 8;
346 len -= 8;
347 }
348 }
349 }
350 /* not reached */
351}
352
353/* this function is called at probe time for pac7302 */
354static int sd_config(struct gspca_dev *gspca_dev,
355 const struct usb_device_id *id)
356{
357 struct sd *sd = (struct sd *) gspca_dev;
358 struct cam *cam;
359
360 cam = &gspca_dev->cam;
361
362 cam->cam_mode = vga_mode; /* only 640x480 */
363 cam->nmodes = ARRAY_SIZE(vga_mode);
364
365 sd->flags = id->driver_info;
366 return 0;
367}
368
369static void setbrightcont(struct gspca_dev *gspca_dev)
370{
371 struct sd *sd = (struct sd *) gspca_dev;
372 int i, v;
373 static const u8 max[10] =
374 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
375 0xd4, 0xec};
376 static const u8 delta[10] =
377 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
378 0x11, 0x0b};
379
380 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
381 for (i = 0; i < 10; i++) {
382 v = max[i];
383 v += (sd->brightness->val - sd->brightness->maximum)
384 * 150 / sd->brightness->maximum; /* 200 ? */
385 v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
386 if (v < 0)
387 v = 0;
388 else if (v > 0xff)
389 v = 0xff;
390 reg_w(gspca_dev, 0xa2 + i, v);
391 }
392 reg_w(gspca_dev, 0xdc, 0x01);
393}
394
395static void setcolors(struct gspca_dev *gspca_dev)
396{
397 struct sd *sd = (struct sd *) gspca_dev;
398 int i, v;
399 static const int a[9] =
400 {217, -212, 0, -101, 170, -67, -38, -315, 355};
401 static const int b[9] =
402 {19, 106, 0, 19, 106, 1, 19, 106, 1};
403
404 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
405 reg_w(gspca_dev, 0x11, 0x01);
406 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
407 for (i = 0; i < 9; i++) {
408 v = a[i] * sd->saturation->val / sd->saturation->maximum;
409 v += b[i];
410 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
411 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
412 }
413 reg_w(gspca_dev, 0xdc, 0x01);
414}
415
416static void setwhitebalance(struct gspca_dev *gspca_dev)
417{
418 struct sd *sd = (struct sd *) gspca_dev;
419
420 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
421 reg_w(gspca_dev, 0xc6, sd->white_balance->val);
422
423 reg_w(gspca_dev, 0xdc, 0x01);
424}
425
426static void setredbalance(struct gspca_dev *gspca_dev)
427{
428 struct sd *sd = (struct sd *) gspca_dev;
429
430 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
431 reg_w(gspca_dev, 0xc5, sd->red_balance->val);
432
433 reg_w(gspca_dev, 0xdc, 0x01);
434}
435
436static void setbluebalance(struct gspca_dev *gspca_dev)
437{
438 struct sd *sd = (struct sd *) gspca_dev;
439
440 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
441 reg_w(gspca_dev, 0xc7, sd->blue_balance->val);
442
443 reg_w(gspca_dev, 0xdc, 0x01);
444}
445
446static void setgain(struct gspca_dev *gspca_dev)
447{
448 u8 reg10, reg12;
449
450 if (gspca_dev->gain->val < 32) {
451 reg10 = gspca_dev->gain->val;
452 reg12 = 0;
453 } else {
454 reg10 = 31;
455 reg12 = gspca_dev->gain->val - 31;
456 }
457
458 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
459 reg_w(gspca_dev, 0x10, reg10);
460 reg_w(gspca_dev, 0x12, reg12);
461
462 /* load registers to sensor (Bit 0, auto clear) */
463 reg_w(gspca_dev, 0x11, 0x01);
464}
465
466static void setexposure(struct gspca_dev *gspca_dev)
467{
468 u8 clockdiv;
469 u16 exposure;
470
471 /*
472 * Register 2 of frame 3 contains the clock divider configuring the
473 * no fps according to the formula: 90 / reg. sd->exposure is the
474 * desired exposure time in 0.5 ms.
475 */
476 clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000;
477
478 /*
479 * Note clockdiv = 3 also works, but when running at 30 fps, depending
480 * on the scene being recorded, the camera switches to another
481 * quantization table for certain JPEG blocks, and we don't know how
482 * to decompress these blocks. So we cap the framerate at 15 fps.
483 */
484 if (clockdiv < 6)
485 clockdiv = 6;
486 else if (clockdiv > 63)
487 clockdiv = 63;
488
489 /*
490 * Register 2 MUST be a multiple of 3, except when between 6 and 12?
491 * Always round up, otherwise we cannot get the desired frametime
492 * using the partial frame time exposure control.
493 */
494 if (clockdiv < 6 || clockdiv > 12)
495 clockdiv = ((clockdiv + 2) / 3) * 3;
496
497 /*
498 * frame exposure time in ms = 1000 * clockdiv / 90 ->
499 * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
500 */
501 exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv);
502 /* 0 = use full frametime, 448 = no exposure, reverse it */
503 exposure = 448 - exposure;
504
505 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
506 reg_w(gspca_dev, 0x02, clockdiv);
507 reg_w(gspca_dev, 0x0e, exposure & 0xff);
508 reg_w(gspca_dev, 0x0f, exposure >> 8);
509
510 /* load registers to sensor (Bit 0, auto clear) */
511 reg_w(gspca_dev, 0x11, 0x01);
512}
513
514static void sethvflip(struct gspca_dev *gspca_dev)
515{
516 struct sd *sd = (struct sd *) gspca_dev;
517 u8 data, hflip, vflip;
518
519 hflip = sd->hflip->val;
520 if (sd->flags & FL_HFLIP)
521 hflip = !hflip;
522 vflip = sd->vflip->val;
523 if (sd->flags & FL_VFLIP)
524 vflip = !vflip;
525
526 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
527 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
528 reg_w(gspca_dev, 0x21, data);
529
530 /* load registers to sensor (Bit 0, auto clear) */
531 reg_w(gspca_dev, 0x11, 0x01);
532}
533
534/* this function is called at probe and resume time for pac7302 */
535static int sd_init(struct gspca_dev *gspca_dev)
536{
537 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
538 return gspca_dev->usb_err;
539}
540
541static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
542{
543 struct gspca_dev *gspca_dev =
544 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
545 struct sd *sd = (struct sd *)gspca_dev;
546
547 gspca_dev->usb_err = 0;
548
549 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
550 /* when switching to autogain set defaults to make sure
551 we are on a valid point of the autogain gain /
552 exposure knee graph, and give this change time to
553 take effect before doing autogain. */
554 gspca_dev->exposure->val = PAC7302_EXPOSURE_DEFAULT;
555 gspca_dev->gain->val = PAC7302_GAIN_DEFAULT;
556 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
557 }
558
559 if (!gspca_dev->streaming)
560 return 0;
561
562 switch (ctrl->id) {
563 case V4L2_CID_BRIGHTNESS:
564 setbrightcont(gspca_dev);
565 break;
566 case V4L2_CID_SATURATION:
567 setcolors(gspca_dev);
568 break;
569 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
570 setwhitebalance(gspca_dev);
571 break;
572 case V4L2_CID_RED_BALANCE:
573 setredbalance(gspca_dev);
574 break;
575 case V4L2_CID_BLUE_BALANCE:
576 setbluebalance(gspca_dev);
577 break;
578 case V4L2_CID_AUTOGAIN:
579 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
580 setexposure(gspca_dev);
581 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
582 setgain(gspca_dev);
583 break;
584 case V4L2_CID_HFLIP:
585 sethvflip(gspca_dev);
586 break;
587 default:
588 return -EINVAL;
589 }
590 return gspca_dev->usb_err;
591}
592
593static const struct v4l2_ctrl_ops sd_ctrl_ops = {
594 .s_ctrl = sd_s_ctrl,
595};
596
597/* this function is called at probe time */
598static int sd_init_controls(struct gspca_dev *gspca_dev)
599{
600 struct sd *sd = (struct sd *) gspca_dev;
601 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
602
603 gspca_dev->vdev.ctrl_handler = hdl;
604 v4l2_ctrl_handler_init(hdl, 11);
605
606 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
607 V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
608 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
609 V4L2_CID_CONTRAST, 0, 255, 1, 127);
610
611 sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
612 V4L2_CID_SATURATION, 0, 255, 1, 127);
613 sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
614 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
615 0, 255, 1, 4);
616 sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
617 V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
618 sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
619 V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
620
621 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
622 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
623 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
624 V4L2_CID_EXPOSURE, 0, 1023, 1,
625 PAC7302_EXPOSURE_DEFAULT);
626 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
627 V4L2_CID_GAIN, 0, 62, 1,
628 PAC7302_GAIN_DEFAULT);
629
630 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
631 V4L2_CID_HFLIP, 0, 1, 1, 0);
632 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
633 V4L2_CID_VFLIP, 0, 1, 1, 0);
634
635 if (hdl->error) {
636 pr_err("Could not initialize controls\n");
637 return hdl->error;
638 }
639
640 v4l2_ctrl_cluster(2, &sd->brightness);
641 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
642 v4l2_ctrl_cluster(2, &sd->hflip);
643 return 0;
644}
645
646/* -- start the camera -- */
647static int sd_start(struct gspca_dev *gspca_dev)
648{
649 struct sd *sd = (struct sd *) gspca_dev;
650
651 reg_w_var(gspca_dev, start_7302,
652 page3_7302, sizeof(page3_7302));
653 setbrightcont(gspca_dev);
654 setcolors(gspca_dev);
655 setwhitebalance(gspca_dev);
656 setredbalance(gspca_dev);
657 setbluebalance(gspca_dev);
658 setexposure(gspca_dev);
659 setgain(gspca_dev);
660 sethvflip(gspca_dev);
661
662 sd->sof_read = 0;
663 sd->autogain_ignore_frames = 0;
664 atomic_set(&sd->avg_lum, 270 + sd->brightness->val);
665
666 /* start stream */
667 reg_w(gspca_dev, 0xff, 0x01);
668 reg_w(gspca_dev, 0x78, 0x01);
669
670 return gspca_dev->usb_err;
671}
672
673static void sd_stopN(struct gspca_dev *gspca_dev)
674{
675
676 /* stop stream */
677 reg_w(gspca_dev, 0xff, 0x01);
678 reg_w(gspca_dev, 0x78, 0x00);
679}
680
681/* called on streamoff with alt 0 and on disconnect for pac7302 */
682static void sd_stop0(struct gspca_dev *gspca_dev)
683{
684 if (!gspca_dev->present)
685 return;
686 reg_w(gspca_dev, 0xff, 0x01);
687 reg_w(gspca_dev, 0x78, 0x40);
688}
689
690static void do_autogain(struct gspca_dev *gspca_dev)
691{
692 struct sd *sd = (struct sd *) gspca_dev;
693 int avg_lum = atomic_read(&sd->avg_lum);
694 int desired_lum;
695 const int deadzone = 30;
696
697 if (sd->autogain_ignore_frames < 0)
698 return;
699
700 if (sd->autogain_ignore_frames > 0) {
701 sd->autogain_ignore_frames--;
702 } else {
703 desired_lum = 270 + sd->brightness->val;
704
705 if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum,
706 deadzone, PAC7302_GAIN_KNEE,
707 PAC7302_EXPOSURE_KNEE))
708 sd->autogain_ignore_frames =
709 PAC_AUTOGAIN_IGNORE_FRAMES;
710 }
711}
712
713/* JPEG header */
714static const u8 jpeg_header[] = {
715 0xff, 0xd8, /* SOI: Start of Image */
716
717 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
718 0x00, 0x11, /* length = 17 bytes (including this length field) */
719 0x08, /* Precision: 8 */
720 0x02, 0x80, /* height = 640 (image rotated) */
721 0x01, 0xe0, /* width = 480 */
722 0x03, /* Number of image components: 3 */
723 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
724 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
725 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
726
727 0xff, 0xda, /* SOS: Start Of Scan */
728 0x00, 0x0c, /* length = 12 bytes (including this length field) */
729 0x03, /* number of components: 3 */
730 0x01, 0x00, /* selector 1, table 0x00 */
731 0x02, 0x11, /* selector 2, table 0x11 */
732 0x03, 0x11, /* selector 3, table 0x11 */
733 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
734 0x00 /* Successive approximation: 0 */
735};
736
737/* this function is run at interrupt level */
738static void sd_pkt_scan(struct gspca_dev *gspca_dev,
739 u8 *data, /* isoc packet */
740 int len) /* iso packet length */
741{
742 struct sd *sd = (struct sd *) gspca_dev;
743 u8 *image;
744 u8 *sof;
745
746 sof = pac_find_sof(&sd->sof_read, data, len);
747 if (sof) {
748 int n, lum_offset, footer_length;
749
750 /*
751 * 6 bytes after the FF D9 EOF marker a number of lumination
752 * bytes are send corresponding to different parts of the
753 * image, the 14th and 15th byte after the EOF seem to
754 * correspond to the center of the image.
755 */
756 lum_offset = 61 + sizeof pac_sof_marker;
757 footer_length = 74;
758
759 /* Finish decoding current frame */
760 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
761 if (n < 0) {
762 gspca_dev->image_len += n;
763 n = 0;
764 } else {
765 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
766 }
767
768 image = gspca_dev->image;
769 if (image != NULL
770 && image[gspca_dev->image_len - 2] == 0xff
771 && image[gspca_dev->image_len - 1] == 0xd9)
772 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
773
774 n = sof - data;
775 len -= n;
776 data = sof;
777
778 /* Get average lumination */
779 if (gspca_dev->last_packet_type == LAST_PACKET &&
780 n >= lum_offset)
781 atomic_set(&sd->avg_lum, data[-lum_offset] +
782 data[-lum_offset + 1]);
783
784 /* Start the new frame with the jpeg header */
785 /* The PAC7302 has the image rotated 90 degrees */
786 gspca_frame_add(gspca_dev, FIRST_PACKET,
787 jpeg_header, sizeof jpeg_header);
788 }
789 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
790}
791
792#ifdef CONFIG_VIDEO_ADV_DEBUG
793static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
794 struct v4l2_dbg_register *reg)
795{
796 u8 index;
797 u8 value;
798
799 /*
800 * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
801 * long on the USB bus)
802 */
803 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
804 reg->match.addr == 0 &&
805 (reg->reg < 0x000000ff) &&
806 (reg->val <= 0x000000ff)
807 ) {
808 /* Currently writing to page 0 is only supported. */
809 /* reg_w() only supports 8bit index */
810 index = reg->reg;
811 value = reg->val;
812
813 /*
814 * Note that there shall be no access to other page
815 * by any other function between the page switch and
816 * the actual register write.
817 */
818 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
819 reg_w(gspca_dev, index, value);
820
821 reg_w(gspca_dev, 0xdc, 0x01);
822 }
823 return gspca_dev->usb_err;
824}
825
826static int sd_chip_ident(struct gspca_dev *gspca_dev,
827 struct v4l2_dbg_chip_ident *chip)
828{
829 int ret = -EINVAL;
830
831 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
832 chip->match.addr == 0) {
833 chip->revision = 0;
834 chip->ident = V4L2_IDENT_UNKNOWN;
835 ret = 0;
836 }
837 return ret;
838}
839#endif
840
841#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
842static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
843 u8 *data, /* interrupt packet data */
844 int len) /* interrput packet length */
845{
846 int ret = -EINVAL;
847 u8 data0, data1;
848
849 if (len == 2) {
850 data0 = data[0];
851 data1 = data[1];
852 if ((data0 == 0x00 && data1 == 0x11) ||
853 (data0 == 0x22 && data1 == 0x33) ||
854 (data0 == 0x44 && data1 == 0x55) ||
855 (data0 == 0x66 && data1 == 0x77) ||
856 (data0 == 0x88 && data1 == 0x99) ||
857 (data0 == 0xaa && data1 == 0xbb) ||
858 (data0 == 0xcc && data1 == 0xdd) ||
859 (data0 == 0xee && data1 == 0xff)) {
860 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
861 input_sync(gspca_dev->input_dev);
862 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
863 input_sync(gspca_dev->input_dev);
864 ret = 0;
865 }
866 }
867
868 return ret;
869}
870#endif
871
872/* sub-driver description for pac7302 */
873static const struct sd_desc sd_desc = {
874 .name = KBUILD_MODNAME,
875 .config = sd_config,
876 .init = sd_init,
877 .init_controls = sd_init_controls,
878 .start = sd_start,
879 .stopN = sd_stopN,
880 .stop0 = sd_stop0,
881 .pkt_scan = sd_pkt_scan,
882 .dq_callback = do_autogain,
883#ifdef CONFIG_VIDEO_ADV_DEBUG
884 .set_register = sd_dbg_s_register,
885 .get_chip_ident = sd_chip_ident,
886#endif
887#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
888 .int_pkt_scan = sd_int_pkt_scan,
889#endif
890};
891
892/* -- module initialisation -- */
893static const struct usb_device_id device_table[] = {
894 {USB_DEVICE(0x06f8, 0x3009)},
895 {USB_DEVICE(0x06f8, 0x301b)},
896 {USB_DEVICE(0x093a, 0x2620)},
897 {USB_DEVICE(0x093a, 0x2621)},
898 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
899 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
900 {USB_DEVICE(0x093a, 0x2625)},
901 {USB_DEVICE(0x093a, 0x2626)},
902 {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP},
903 {USB_DEVICE(0x093a, 0x2628)},
904 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
905 {USB_DEVICE(0x093a, 0x262a)},
906 {USB_DEVICE(0x093a, 0x262c)},
907 {USB_DEVICE(0x145f, 0x013c)},
908 {}
909};
910MODULE_DEVICE_TABLE(usb, device_table);
911
912/* -- device connect -- */
913static int sd_probe(struct usb_interface *intf,
914 const struct usb_device_id *id)
915{
916 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
917 THIS_MODULE);
918}
919
920static struct usb_driver sd_driver = {
921 .name = KBUILD_MODNAME,
922 .id_table = device_table,
923 .probe = sd_probe,
924 .disconnect = gspca_disconnect,
925#ifdef CONFIG_PM
926 .suspend = gspca_suspend,
927 .resume = gspca_resume,
928 .reset_resume = gspca_resume,
929#endif
930};
931
932module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac7311.c b/drivers/media/usb/gspca/pac7311.c
new file mode 100644
index 00000000000..ba3558d3f01
--- /dev/null
+++ b/drivers/media/usb/gspca/pac7311.c
@@ -0,0 +1,701 @@
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/* Some documentation about various registers as determined by trial and error.
23 *
24 * Register page 1:
25 *
26 * Address Description
27 * 0x08 Unknown compressor related, must always be 8 except when not
28 * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
29 * 0x1b Auto white balance related, bit 0 is AWB enable (inverted)
30 * bits 345 seem to toggle per color gains on/off (inverted)
31 * 0x78 Global control, bit 6 controls the LED (inverted)
32 * 0x80 Compression balance, interesting settings:
33 * 0x01 Use this to allow the camera to switch to higher compr.
34 * on the fly. Needed to stay within bandwidth @ 640x480@30
35 * 0x1c From usb captures under Windows for 640x480
36 * 0x2a Values >= this switch the camera to a lower compression,
37 * using the same table for both luminance and chrominance.
38 * This gives a sharper picture. Usable only at 640x480@ <
39 * 15 fps or 320x240 / 160x120. Note currently the driver
40 * does not use this as the quality gain is small and the
41 * generated JPG-s are only understood by v4l-utils >= 0.8.9
42 * 0x3f From usb captures under Windows for 320x240
43 * 0x69 From usb captures under Windows for 160x120
44 *
45 * Register page 4:
46 *
47 * Address Description
48 * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
49 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
50 * 0x0f Master gain 1-245, low value = high gain
51 * 0x10 Another gain 0-15, limited influence (1-2x gain I guess)
52 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
53 * Note setting vflip disabled leads to a much lower image quality,
54 * so we always vflip, and tell userspace to flip it back
55 * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
56 * completely disable the analog amplification block. Set to 0x68
57 * for max gain, 0x14 for minimal gain.
58 */
59
60#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
61
62#define MODULE_NAME "pac7311"
63
64#include <linux/input.h>
65#include "gspca.h"
66/* Include pac common sof detection functions */
67#include "pac_common.h"
68
69#define PAC7311_GAIN_DEFAULT 122
70#define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */
71
72MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
73MODULE_DESCRIPTION("Pixart PAC7311");
74MODULE_LICENSE("GPL");
75
76struct sd {
77 struct gspca_dev gspca_dev; /* !! must be the first item */
78
79 struct v4l2_ctrl *contrast;
80 struct v4l2_ctrl *hflip;
81
82 u8 sof_read;
83 u8 autogain_ignore_frames;
84
85 atomic_t avg_lum;
86};
87
88static const struct v4l2_pix_format vga_mode[] = {
89 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
90 .bytesperline = 160,
91 .sizeimage = 160 * 120 * 3 / 8 + 590,
92 .colorspace = V4L2_COLORSPACE_JPEG,
93 .priv = 2},
94 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
95 .bytesperline = 320,
96 .sizeimage = 320 * 240 * 3 / 8 + 590,
97 .colorspace = V4L2_COLORSPACE_JPEG,
98 .priv = 1},
99 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
100 .bytesperline = 640,
101 .sizeimage = 640 * 480 * 3 / 8 + 590,
102 .colorspace = V4L2_COLORSPACE_JPEG,
103 .priv = 0},
104};
105
106#define LOAD_PAGE4 254
107#define END_OF_SEQUENCE 0
108
109static const __u8 init_7311[] = {
110 0xff, 0x01,
111 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
112 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
113 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
114 0xff, 0x04,
115 0x27, 0x80,
116 0x28, 0xca,
117 0x29, 0x53,
118 0x2a, 0x0e,
119 0xff, 0x01,
120 0x3e, 0x20,
121};
122
123static const __u8 start_7311[] = {
124/* index, len, [value]* */
125 0xff, 1, 0x01, /* page 1 */
126 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
127 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
128 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
129 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00,
132 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
133 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
134 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
135 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
136 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
137 0xd0, 0xff,
138 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
139 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
140 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
141 0x18, 0x20,
142 0x96, 3, 0x01, 0x08, 0x04,
143 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
144 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
145 0x3f, 0x00, 0x0a, 0x01, 0x00,
146 0xff, 1, 0x04, /* page 4 */
147 0, LOAD_PAGE4, /* load the page 4 */
148 0x11, 1, 0x01,
149 0, END_OF_SEQUENCE /* end of sequence */
150};
151
152#define SKIP 0xaa
153/* page 4 - the value SKIP says skip the index - see reg_w_page() */
154static const __u8 page4_7311[] = {
155 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
156 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
157 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
159 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
160 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
161 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
162};
163
164static void reg_w_buf(struct gspca_dev *gspca_dev,
165 __u8 index,
166 const u8 *buffer, int len)
167{
168 int ret;
169
170 if (gspca_dev->usb_err < 0)
171 return;
172 memcpy(gspca_dev->usb_buf, buffer, len);
173 ret = usb_control_msg(gspca_dev->dev,
174 usb_sndctrlpipe(gspca_dev->dev, 0),
175 0, /* request */
176 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
177 0, /* value */
178 index, gspca_dev->usb_buf, len,
179 500);
180 if (ret < 0) {
181 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
182 index, ret);
183 gspca_dev->usb_err = ret;
184 }
185}
186
187
188static void reg_w(struct gspca_dev *gspca_dev,
189 __u8 index,
190 __u8 value)
191{
192 int ret;
193
194 if (gspca_dev->usb_err < 0)
195 return;
196 gspca_dev->usb_buf[0] = value;
197 ret = usb_control_msg(gspca_dev->dev,
198 usb_sndctrlpipe(gspca_dev->dev, 0),
199 0, /* request */
200 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
201 0, index, gspca_dev->usb_buf, 1,
202 500);
203 if (ret < 0) {
204 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
205 index, value, ret);
206 gspca_dev->usb_err = ret;
207 }
208}
209
210static void reg_w_seq(struct gspca_dev *gspca_dev,
211 const __u8 *seq, int len)
212{
213 while (--len >= 0) {
214 reg_w(gspca_dev, seq[0], seq[1]);
215 seq += 2;
216 }
217}
218
219/* load the beginning of a page */
220static void reg_w_page(struct gspca_dev *gspca_dev,
221 const __u8 *page, int len)
222{
223 int index;
224 int ret = 0;
225
226 if (gspca_dev->usb_err < 0)
227 return;
228 for (index = 0; index < len; index++) {
229 if (page[index] == SKIP) /* skip this index */
230 continue;
231 gspca_dev->usb_buf[0] = page[index];
232 ret = usb_control_msg(gspca_dev->dev,
233 usb_sndctrlpipe(gspca_dev->dev, 0),
234 0, /* request */
235 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236 0, index, gspca_dev->usb_buf, 1,
237 500);
238 if (ret < 0) {
239 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
240 index, page[index], ret);
241 gspca_dev->usb_err = ret;
242 break;
243 }
244 }
245}
246
247/* output a variable sequence */
248static void reg_w_var(struct gspca_dev *gspca_dev,
249 const __u8 *seq,
250 const __u8 *page4, unsigned int page4_len)
251{
252 int index, len;
253
254 for (;;) {
255 index = *seq++;
256 len = *seq++;
257 switch (len) {
258 case END_OF_SEQUENCE:
259 return;
260 case LOAD_PAGE4:
261 reg_w_page(gspca_dev, page4, page4_len);
262 break;
263 default:
264 if (len > USB_BUF_SZ) {
265 PDEBUG(D_ERR|D_STREAM,
266 "Incorrect variable sequence");
267 return;
268 }
269 while (len > 0) {
270 if (len < 8) {
271 reg_w_buf(gspca_dev,
272 index, seq, len);
273 seq += len;
274 break;
275 }
276 reg_w_buf(gspca_dev, index, seq, 8);
277 seq += 8;
278 index += 8;
279 len -= 8;
280 }
281 }
282 }
283 /* not reached */
284}
285
286/* this function is called at probe time for pac7311 */
287static int sd_config(struct gspca_dev *gspca_dev,
288 const struct usb_device_id *id)
289{
290 struct cam *cam = &gspca_dev->cam;
291
292 cam->cam_mode = vga_mode;
293 cam->nmodes = ARRAY_SIZE(vga_mode);
294 cam->input_flags = V4L2_IN_ST_VFLIP;
295
296 return 0;
297}
298
299static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
300{
301 reg_w(gspca_dev, 0xff, 0x04);
302 reg_w(gspca_dev, 0x10, val);
303 /* load registers to sensor (Bit 0, auto clear) */
304 reg_w(gspca_dev, 0x11, 0x01);
305}
306
307static void setgain(struct gspca_dev *gspca_dev, s32 val)
308{
309 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
310 reg_w(gspca_dev, 0x0e, 0x00);
311 reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
312
313 /* load registers to sensor (Bit 0, auto clear) */
314 reg_w(gspca_dev, 0x11, 0x01);
315}
316
317static void setexposure(struct gspca_dev *gspca_dev, s32 val)
318{
319 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
320 reg_w(gspca_dev, 0x02, val);
321
322 /* load registers to sensor (Bit 0, auto clear) */
323 reg_w(gspca_dev, 0x11, 0x01);
324
325 /*
326 * Page 1 register 8 must always be 0x08 except when not in
327 * 640x480 mode and page 4 reg 2 <= 3 then it must be 9
328 */
329 reg_w(gspca_dev, 0xff, 0x01);
330 if (gspca_dev->width != 640 && val <= 3)
331 reg_w(gspca_dev, 0x08, 0x09);
332 else
333 reg_w(gspca_dev, 0x08, 0x08);
334
335 /*
336 * Page1 register 80 sets the compression balance, normally we
337 * want / use 0x1c, but for 640x480@30fps we must allow the
338 * camera to use higher compression or we may run out of
339 * bandwidth.
340 */
341 if (gspca_dev->width == 640 && val == 2)
342 reg_w(gspca_dev, 0x80, 0x01);
343 else
344 reg_w(gspca_dev, 0x80, 0x1c);
345
346 /* load registers to sensor (Bit 0, auto clear) */
347 reg_w(gspca_dev, 0x11, 0x01);
348}
349
350static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
351{
352 __u8 data;
353
354 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
355 data = (hflip ? 0x04 : 0x00) |
356 (vflip ? 0x08 : 0x00);
357 reg_w(gspca_dev, 0x21, data);
358
359 /* load registers to sensor (Bit 0, auto clear) */
360 reg_w(gspca_dev, 0x11, 0x01);
361}
362
363/* this function is called at probe and resume time for pac7311 */
364static int sd_init(struct gspca_dev *gspca_dev)
365{
366 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
367 return gspca_dev->usb_err;
368}
369
370static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
371{
372 struct gspca_dev *gspca_dev =
373 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
374 struct sd *sd = (struct sd *)gspca_dev;
375
376 gspca_dev->usb_err = 0;
377
378 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
379 /* when switching to autogain set defaults to make sure
380 we are on a valid point of the autogain gain /
381 exposure knee graph, and give this change time to
382 take effect before doing autogain. */
383 gspca_dev->exposure->val = PAC7311_EXPOSURE_DEFAULT;
384 gspca_dev->gain->val = PAC7311_GAIN_DEFAULT;
385 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
386 }
387
388 if (!gspca_dev->streaming)
389 return 0;
390
391 switch (ctrl->id) {
392 case V4L2_CID_CONTRAST:
393 setcontrast(gspca_dev, ctrl->val);
394 break;
395 case V4L2_CID_AUTOGAIN:
396 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
397 setexposure(gspca_dev, gspca_dev->exposure->val);
398 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
399 setgain(gspca_dev, gspca_dev->gain->val);
400 break;
401 case V4L2_CID_HFLIP:
402 sethvflip(gspca_dev, sd->hflip->val, 1);
403 break;
404 default:
405 return -EINVAL;
406 }
407 return gspca_dev->usb_err;
408}
409
410static const struct v4l2_ctrl_ops sd_ctrl_ops = {
411 .s_ctrl = sd_s_ctrl,
412};
413
414/* this function is called at probe time */
415static int sd_init_controls(struct gspca_dev *gspca_dev)
416{
417 struct sd *sd = (struct sd *) gspca_dev;
418 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
419
420 gspca_dev->vdev.ctrl_handler = hdl;
421 v4l2_ctrl_handler_init(hdl, 5);
422
423 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
424 V4L2_CID_CONTRAST, 0, 15, 1, 7);
425 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
426 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
427 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
428 V4L2_CID_EXPOSURE, 2, 63, 1,
429 PAC7311_EXPOSURE_DEFAULT);
430 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
431 V4L2_CID_GAIN, 0, 244, 1,
432 PAC7311_GAIN_DEFAULT);
433 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
434 V4L2_CID_HFLIP, 0, 1, 1, 0);
435
436 if (hdl->error) {
437 pr_err("Could not initialize controls\n");
438 return hdl->error;
439 }
440
441 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
442 return 0;
443}
444
445/* -- start the camera -- */
446static int sd_start(struct gspca_dev *gspca_dev)
447{
448 struct sd *sd = (struct sd *) gspca_dev;
449
450 sd->sof_read = 0;
451
452 reg_w_var(gspca_dev, start_7311,
453 page4_7311, sizeof(page4_7311));
454 setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
455 setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
456 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
457 sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
458
459 /* set correct resolution */
460 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
461 case 2: /* 160x120 */
462 reg_w(gspca_dev, 0xff, 0x01);
463 reg_w(gspca_dev, 0x17, 0x20);
464 reg_w(gspca_dev, 0x87, 0x10);
465 break;
466 case 1: /* 320x240 */
467 reg_w(gspca_dev, 0xff, 0x01);
468 reg_w(gspca_dev, 0x17, 0x30);
469 reg_w(gspca_dev, 0x87, 0x11);
470 break;
471 case 0: /* 640x480 */
472 reg_w(gspca_dev, 0xff, 0x01);
473 reg_w(gspca_dev, 0x17, 0x00);
474 reg_w(gspca_dev, 0x87, 0x12);
475 break;
476 }
477
478 sd->sof_read = 0;
479 sd->autogain_ignore_frames = 0;
480 atomic_set(&sd->avg_lum, -1);
481
482 /* start stream */
483 reg_w(gspca_dev, 0xff, 0x01);
484 reg_w(gspca_dev, 0x78, 0x05);
485
486 return gspca_dev->usb_err;
487}
488
489static void sd_stopN(struct gspca_dev *gspca_dev)
490{
491 reg_w(gspca_dev, 0xff, 0x04);
492 reg_w(gspca_dev, 0x27, 0x80);
493 reg_w(gspca_dev, 0x28, 0xca);
494 reg_w(gspca_dev, 0x29, 0x53);
495 reg_w(gspca_dev, 0x2a, 0x0e);
496 reg_w(gspca_dev, 0xff, 0x01);
497 reg_w(gspca_dev, 0x3e, 0x20);
498 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
499 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
500 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
501}
502
503static void do_autogain(struct gspca_dev *gspca_dev)
504{
505 struct sd *sd = (struct sd *) gspca_dev;
506 int avg_lum = atomic_read(&sd->avg_lum);
507 int desired_lum, deadzone;
508
509 if (avg_lum == -1)
510 return;
511
512 desired_lum = 170;
513 deadzone = 20;
514
515 if (sd->autogain_ignore_frames > 0)
516 sd->autogain_ignore_frames--;
517 else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
518 desired_lum, deadzone))
519 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
520}
521
522/* JPEG header, part 1 */
523static const unsigned char pac_jpeg_header1[] = {
524 0xff, 0xd8, /* SOI: Start of Image */
525
526 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
527 0x00, 0x11, /* length = 17 bytes (including this length field) */
528 0x08 /* Precision: 8 */
529 /* 2 bytes is placed here: number of image lines */
530 /* 2 bytes is placed here: samples per line */
531};
532
533/* JPEG header, continued */
534static const unsigned char pac_jpeg_header2[] = {
535 0x03, /* Number of image components: 3 */
536 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
537 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
538 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
539
540 0xff, 0xda, /* SOS: Start Of Scan */
541 0x00, 0x0c, /* length = 12 bytes (including this length field) */
542 0x03, /* number of components: 3 */
543 0x01, 0x00, /* selector 1, table 0x00 */
544 0x02, 0x11, /* selector 2, table 0x11 */
545 0x03, 0x11, /* selector 3, table 0x11 */
546 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
547 0x00 /* Successive approximation: 0 */
548};
549
550static void pac_start_frame(struct gspca_dev *gspca_dev,
551 __u16 lines, __u16 samples_per_line)
552{
553 unsigned char tmpbuf[4];
554
555 gspca_frame_add(gspca_dev, FIRST_PACKET,
556 pac_jpeg_header1, sizeof(pac_jpeg_header1));
557
558 tmpbuf[0] = lines >> 8;
559 tmpbuf[1] = lines & 0xff;
560 tmpbuf[2] = samples_per_line >> 8;
561 tmpbuf[3] = samples_per_line & 0xff;
562
563 gspca_frame_add(gspca_dev, INTER_PACKET,
564 tmpbuf, sizeof(tmpbuf));
565 gspca_frame_add(gspca_dev, INTER_PACKET,
566 pac_jpeg_header2, sizeof(pac_jpeg_header2));
567}
568
569/* this function is run at interrupt level */
570static void sd_pkt_scan(struct gspca_dev *gspca_dev,
571 u8 *data, /* isoc packet */
572 int len) /* iso packet length */
573{
574 struct sd *sd = (struct sd *) gspca_dev;
575 u8 *image;
576 unsigned char *sof;
577
578 sof = pac_find_sof(&sd->sof_read, data, len);
579 if (sof) {
580 int n, lum_offset, footer_length;
581
582 /*
583 * 6 bytes after the FF D9 EOF marker a number of lumination
584 * bytes are send corresponding to different parts of the
585 * image, the 14th and 15th byte after the EOF seem to
586 * correspond to the center of the image.
587 */
588 lum_offset = 24 + sizeof pac_sof_marker;
589 footer_length = 26;
590
591 /* Finish decoding current frame */
592 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
593 if (n < 0) {
594 gspca_dev->image_len += n;
595 n = 0;
596 } else {
597 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
598 }
599 image = gspca_dev->image;
600 if (image != NULL
601 && image[gspca_dev->image_len - 2] == 0xff
602 && image[gspca_dev->image_len - 1] == 0xd9)
603 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
604
605 n = sof - data;
606 len -= n;
607 data = sof;
608
609 /* Get average lumination */
610 if (gspca_dev->last_packet_type == LAST_PACKET &&
611 n >= lum_offset)
612 atomic_set(&sd->avg_lum, data[-lum_offset] +
613 data[-lum_offset + 1]);
614 else
615 atomic_set(&sd->avg_lum, -1);
616
617 /* Start the new frame with the jpeg header */
618 pac_start_frame(gspca_dev,
619 gspca_dev->height, gspca_dev->width);
620 }
621 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
622}
623
624#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
625static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
626 u8 *data, /* interrupt packet data */
627 int len) /* interrupt packet length */
628{
629 int ret = -EINVAL;
630 u8 data0, data1;
631
632 if (len == 2) {
633 data0 = data[0];
634 data1 = data[1];
635 if ((data0 == 0x00 && data1 == 0x11) ||
636 (data0 == 0x22 && data1 == 0x33) ||
637 (data0 == 0x44 && data1 == 0x55) ||
638 (data0 == 0x66 && data1 == 0x77) ||
639 (data0 == 0x88 && data1 == 0x99) ||
640 (data0 == 0xaa && data1 == 0xbb) ||
641 (data0 == 0xcc && data1 == 0xdd) ||
642 (data0 == 0xee && data1 == 0xff)) {
643 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
644 input_sync(gspca_dev->input_dev);
645 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
646 input_sync(gspca_dev->input_dev);
647 ret = 0;
648 }
649 }
650
651 return ret;
652}
653#endif
654
655static const struct sd_desc sd_desc = {
656 .name = MODULE_NAME,
657 .config = sd_config,
658 .init = sd_init,
659 .init_controls = sd_init_controls,
660 .start = sd_start,
661 .stopN = sd_stopN,
662 .pkt_scan = sd_pkt_scan,
663 .dq_callback = do_autogain,
664#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
665 .int_pkt_scan = sd_int_pkt_scan,
666#endif
667};
668
669/* -- module initialisation -- */
670static const struct usb_device_id device_table[] = {
671 {USB_DEVICE(0x093a, 0x2600)},
672 {USB_DEVICE(0x093a, 0x2601)},
673 {USB_DEVICE(0x093a, 0x2603)},
674 {USB_DEVICE(0x093a, 0x2608)},
675 {USB_DEVICE(0x093a, 0x260e)},
676 {USB_DEVICE(0x093a, 0x260f)},
677 {}
678};
679MODULE_DEVICE_TABLE(usb, device_table);
680
681/* -- device connect -- */
682static int sd_probe(struct usb_interface *intf,
683 const struct usb_device_id *id)
684{
685 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
686 THIS_MODULE);
687}
688
689static struct usb_driver sd_driver = {
690 .name = MODULE_NAME,
691 .id_table = device_table,
692 .probe = sd_probe,
693 .disconnect = gspca_disconnect,
694#ifdef CONFIG_PM
695 .suspend = gspca_suspend,
696 .resume = gspca_resume,
697 .reset_resume = gspca_resume,
698#endif
699};
700
701module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac_common.h b/drivers/media/usb/gspca/pac_common.h
new file mode 100644
index 00000000000..8462a7c1a33
--- /dev/null
+++ b/drivers/media/usb/gspca/pac_common.h
@@ -0,0 +1,134 @@
1/*
2 * Pixart PAC207BCA / PAC73xx common functions
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/* We calculate the autogain at the end of the transfer of a frame, at this
27 moment a frame with the old settings is being captured and transmitted. So
28 if we adjust the gain or exposure we must ignore atleast the next frame for
29 the new settings to come into effect before doing any other adjustments. */
30#define PAC_AUTOGAIN_IGNORE_FRAMES 2
31
32static const unsigned char pac_sof_marker[5] =
33 { 0xff, 0xff, 0x00, 0xff, 0x96 };
34
35/*
36 The following state machine finds the SOF marker sequence
37 0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream.
38
39 +----------+
40 | 0: START |<---------------\
41 +----------+<-\ |
42 | \---/otherwise |
43 v 0xff |
44 +----------+ otherwise |
45 | 1 |--------------->*
46 | | ^
47 +----------+ |
48 | |
49 v 0xff |
50 +----------+<-\0xff |
51 /->| |--/ |
52 | | 2 |--------------->*
53 | | | otherwise ^
54 | +----------+ |
55 | | |
56 | v 0x00 |
57 | +----------+ |
58 | | 3 | |
59 | | |--------------->*
60 | +----------+ otherwise ^
61 | | |
62 0xff | v 0xff |
63 | +----------+ |
64 \--| 4 | |
65 | |----------------/
66 +----------+ otherwise
67 |
68 v 0x96
69 +----------+
70 | FOUND |
71 +----------+
72*/
73
74static unsigned char *pac_find_sof(u8 *sof_read,
75 unsigned char *m, int len)
76{
77 int i;
78
79 /* Search for the SOF marker (fixed part) in the header */
80 for (i = 0; i < len; i++) {
81 switch (*sof_read) {
82 case 0:
83 if (m[i] == 0xff)
84 *sof_read = 1;
85 break;
86 case 1:
87 if (m[i] == 0xff)
88 *sof_read = 2;
89 else
90 *sof_read = 0;
91 break;
92 case 2:
93 switch (m[i]) {
94 case 0x00:
95 *sof_read = 3;
96 break;
97 case 0xff:
98 /* stay in this state */
99 break;
100 default:
101 *sof_read = 0;
102 }
103 break;
104 case 3:
105 if (m[i] == 0xff)
106 *sof_read = 4;
107 else
108 *sof_read = 0;
109 break;
110 case 4:
111 switch (m[i]) {
112 case 0x96:
113 /* Pattern found */
114 PDEBUG(D_FRAM,
115 "SOF found, bytes to analyze: %u."
116 " Frame starts at byte #%u",
117 len, i + 1);
118 *sof_read = 0;
119 return m + i + 1;
120 break;
121 case 0xff:
122 *sof_read = 2;
123 break;
124 default:
125 *sof_read = 0;
126 }
127 break;
128 default:
129 *sof_read = 0;
130 }
131 }
132
133 return NULL;
134}
diff --git a/drivers/media/usb/gspca/se401.c b/drivers/media/usb/gspca/se401.c
new file mode 100644
index 00000000000..a33cb78a839
--- /dev/null
+++ b/drivers/media/usb/gspca/se401.c
@@ -0,0 +1,739 @@
1/*
2 * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
3 *
4 * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
5 *
6 * Based on the v4l1 se401 driver which is:
7 *
8 * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#define MODULE_NAME "se401"
29
30#define BULK_SIZE 4096
31#define PACKET_SIZE 1024
32#define READ_REQ_SIZE 64
33#define MAX_MODES ((READ_REQ_SIZE - 6) / 4)
34/* The se401 compression algorithm uses a fixed quant factor, which
35 can be configured by setting the high nibble of the SE401_OPERATINGMODE
36 feature. This needs to exactly match what is in libv4l! */
37#define SE401_QUANT_FACT 8
38
39#include <linux/input.h>
40#include <linux/slab.h>
41#include "gspca.h"
42#include "se401.h"
43
44MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
45MODULE_DESCRIPTION("Endpoints se401");
46MODULE_LICENSE("GPL");
47
48/* exposure change state machine states */
49enum {
50 EXPO_CHANGED,
51 EXPO_DROP_FRAME,
52 EXPO_NO_CHANGE,
53};
54
55/* specific webcam descriptor */
56struct sd {
57 struct gspca_dev gspca_dev; /* !! must be the first item */
58 struct { /* exposure/freq control cluster */
59 struct v4l2_ctrl *exposure;
60 struct v4l2_ctrl *freq;
61 };
62 bool has_brightness;
63 struct v4l2_pix_format fmts[MAX_MODES];
64 int pixels_read;
65 int packet_read;
66 u8 packet[PACKET_SIZE];
67 u8 restart_stream;
68 u8 button_state;
69 u8 resetlevel;
70 u8 resetlevel_frame_count;
71 int resetlevel_adjust_dir;
72 int expo_change_state;
73};
74
75
76static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
77 int silent)
78{
79 int err;
80
81 if (gspca_dev->usb_err < 0)
82 return;
83
84 err = usb_control_msg(gspca_dev->dev,
85 usb_sndctrlpipe(gspca_dev->dev, 0), req,
86 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
87 value, 0, NULL, 0, 1000);
88 if (err < 0) {
89 if (!silent)
90 pr_err("write req failed req %#04x val %#04x error %d\n",
91 req, value, err);
92 gspca_dev->usb_err = err;
93 }
94}
95
96static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
97{
98 int err;
99
100 if (gspca_dev->usb_err < 0)
101 return;
102
103 if (USB_BUF_SZ < READ_REQ_SIZE) {
104 pr_err("USB_BUF_SZ too small!!\n");
105 gspca_dev->usb_err = -ENOBUFS;
106 return;
107 }
108
109 err = usb_control_msg(gspca_dev->dev,
110 usb_rcvctrlpipe(gspca_dev->dev, 0), req,
111 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
112 0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
113 if (err < 0) {
114 if (!silent)
115 pr_err("read req failed req %#04x error %d\n",
116 req, err);
117 gspca_dev->usb_err = err;
118 }
119}
120
121static void se401_set_feature(struct gspca_dev *gspca_dev,
122 u16 selector, u16 param)
123{
124 int err;
125
126 if (gspca_dev->usb_err < 0)
127 return;
128
129 err = usb_control_msg(gspca_dev->dev,
130 usb_sndctrlpipe(gspca_dev->dev, 0),
131 SE401_REQ_SET_EXT_FEATURE,
132 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
133 param, selector, NULL, 0, 1000);
134 if (err < 0) {
135 pr_err("set feature failed sel %#04x param %#04x error %d\n",
136 selector, param, err);
137 gspca_dev->usb_err = err;
138 }
139}
140
141static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
142{
143 int err;
144
145 if (gspca_dev->usb_err < 0)
146 return gspca_dev->usb_err;
147
148 if (USB_BUF_SZ < 2) {
149 pr_err("USB_BUF_SZ too small!!\n");
150 gspca_dev->usb_err = -ENOBUFS;
151 return gspca_dev->usb_err;
152 }
153
154 err = usb_control_msg(gspca_dev->dev,
155 usb_rcvctrlpipe(gspca_dev->dev, 0),
156 SE401_REQ_GET_EXT_FEATURE,
157 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
158 0, selector, gspca_dev->usb_buf, 2, 1000);
159 if (err < 0) {
160 pr_err("get feature failed sel %#04x error %d\n",
161 selector, err);
162 gspca_dev->usb_err = err;
163 return err;
164 }
165 return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
166}
167
168static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
169{
170 /* HDG: this does not seem to do anything on my cam */
171 se401_write_req(gspca_dev, SE401_REQ_SET_BRT, val, 0);
172}
173
174static void setgain(struct gspca_dev *gspca_dev, s32 val)
175{
176 u16 gain = 63 - val;
177
178 /* red color gain */
179 se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
180 /* green color gain */
181 se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain);
182 /* blue color gain */
183 se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
184}
185
186static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq)
187{
188 struct sd *sd = (struct sd *) gspca_dev;
189 int integration = val << 6;
190 u8 expose_h, expose_m, expose_l;
191
192 /* Do this before the set_feature calls, for proper timing wrt
193 the interrupt driven pkt_scan. Note we may still race but that
194 is not a big issue, the expo change state machine is merely for
195 avoiding underexposed frames getting send out, if one sneaks
196 through so be it */
197 sd->expo_change_state = EXPO_CHANGED;
198
199 if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
200 integration = integration - integration % 106667;
201 if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
202 integration = integration - integration % 88889;
203
204 expose_h = (integration >> 16);
205 expose_m = (integration >> 8);
206 expose_l = integration;
207
208 /* integration time low */
209 se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l);
210 /* integration time mid */
211 se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m);
212 /* integration time high */
213 se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h);
214}
215
216static int sd_config(struct gspca_dev *gspca_dev,
217 const struct usb_device_id *id)
218{
219 struct sd *sd = (struct sd *)gspca_dev;
220 struct cam *cam = &gspca_dev->cam;
221 u8 *cd = gspca_dev->usb_buf;
222 int i, j, n;
223 int widths[MAX_MODES], heights[MAX_MODES];
224
225 /* Read the camera descriptor */
226 se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1);
227 if (gspca_dev->usb_err) {
228 /* Sometimes after being idle for a while the se401 won't
229 respond and needs a good kicking */
230 usb_reset_device(gspca_dev->dev);
231 gspca_dev->usb_err = 0;
232 se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0);
233 }
234
235 /* Some cameras start with their LED on */
236 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
237 if (gspca_dev->usb_err)
238 return gspca_dev->usb_err;
239
240 if (cd[1] != 0x41) {
241 pr_err("Wrong descriptor type\n");
242 return -ENODEV;
243 }
244
245 if (!(cd[2] & SE401_FORMAT_BAYER)) {
246 pr_err("Bayer format not supported!\n");
247 return -ENODEV;
248 }
249
250 if (cd[3])
251 pr_info("ExtraFeatures: %d\n", cd[3]);
252
253 n = cd[4] | (cd[5] << 8);
254 if (n > MAX_MODES) {
255 pr_err("Too many frame sizes\n");
256 return -ENODEV;
257 }
258
259 for (i = 0; i < n ; i++) {
260 widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8);
261 heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8);
262 }
263
264 for (i = 0; i < n ; i++) {
265 sd->fmts[i].width = widths[i];
266 sd->fmts[i].height = heights[i];
267 sd->fmts[i].field = V4L2_FIELD_NONE;
268 sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB;
269 sd->fmts[i].priv = 1;
270
271 /* janggu compression only works for 1/4th or 1/16th res */
272 for (j = 0; j < n; j++) {
273 if (widths[j] / 2 == widths[i] &&
274 heights[j] / 2 == heights[i]) {
275 sd->fmts[i].priv = 2;
276 break;
277 }
278 }
279 /* 1/16th if available too is better then 1/4th, because
280 we then use a larger area of the sensor */
281 for (j = 0; j < n; j++) {
282 if (widths[j] / 4 == widths[i] &&
283 heights[j] / 4 == heights[i]) {
284 sd->fmts[i].priv = 4;
285 break;
286 }
287 }
288
289 if (sd->fmts[i].priv == 1) {
290 /* Not a 1/4th or 1/16th res, use bayer */
291 sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
292 sd->fmts[i].bytesperline = widths[i];
293 sd->fmts[i].sizeimage = widths[i] * heights[i];
294 pr_info("Frame size: %dx%d bayer\n",
295 widths[i], heights[i]);
296 } else {
297 /* Found a match use janggu compression */
298 sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
299 sd->fmts[i].bytesperline = 0;
300 sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
301 pr_info("Frame size: %dx%d 1/%dth janggu\n",
302 widths[i], heights[i],
303 sd->fmts[i].priv * sd->fmts[i].priv);
304 }
305 }
306
307 cam->cam_mode = sd->fmts;
308 cam->nmodes = n;
309 cam->bulk = 1;
310 cam->bulk_size = BULK_SIZE;
311 cam->bulk_nurbs = 4;
312 sd->resetlevel = 0x2d; /* Set initial resetlevel */
313
314 /* See if the camera supports brightness */
315 se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
316 sd->has_brightness = !!gspca_dev->usb_err;
317 gspca_dev->usb_err = 0;
318
319 return 0;
320}
321
322/* this function is called at probe and resume time */
323static int sd_init(struct gspca_dev *gspca_dev)
324{
325 return 0;
326}
327
328/* function called at start time before URB creation */
329static int sd_isoc_init(struct gspca_dev *gspca_dev)
330{
331 gspca_dev->alt = 1; /* Ignore the bogus isoc alt settings */
332
333 return gspca_dev->usb_err;
334}
335
336/* -- start the camera -- */
337static int sd_start(struct gspca_dev *gspca_dev)
338{
339 struct sd *sd = (struct sd *)gspca_dev;
340 int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
341 int mode = 0;
342
343 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1);
344 if (gspca_dev->usb_err) {
345 /* Sometimes after being idle for a while the se401 won't
346 respond and needs a good kicking */
347 usb_reset_device(gspca_dev->dev);
348 gspca_dev->usb_err = 0;
349 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0);
350 }
351 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0);
352
353 se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05);
354
355 /* set size + mode */
356 se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
357 gspca_dev->width * mult, 0);
358 se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
359 gspca_dev->height * mult, 0);
360 /*
361 * HDG: disabled this as it does not seem to do anything
362 * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE,
363 * SE401_FORMAT_BAYER, 0);
364 */
365
366 switch (mult) {
367 case 1: /* Raw bayer */
368 mode = 0x03; break;
369 case 2: /* 1/4th janggu */
370 mode = SE401_QUANT_FACT << 4; break;
371 case 4: /* 1/16th janggu */
372 mode = (SE401_QUANT_FACT << 4) | 0x02; break;
373 }
374 se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
375
376 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
377
378 sd->packet_read = 0;
379 sd->pixels_read = 0;
380 sd->restart_stream = 0;
381 sd->resetlevel_frame_count = 0;
382 sd->resetlevel_adjust_dir = 0;
383 sd->expo_change_state = EXPO_NO_CHANGE;
384
385 se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0);
386
387 return gspca_dev->usb_err;
388}
389
390static void sd_stopN(struct gspca_dev *gspca_dev)
391{
392 se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0);
393 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
394 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0);
395}
396
397static void sd_dq_callback(struct gspca_dev *gspca_dev)
398{
399 struct sd *sd = (struct sd *)gspca_dev;
400 unsigned int ahrc, alrc;
401 int oldreset, adjust_dir;
402
403 /* Restart the stream if requested do so by pkt_scan */
404 if (sd->restart_stream) {
405 sd_stopN(gspca_dev);
406 sd_start(gspca_dev);
407 sd->restart_stream = 0;
408 }
409
410 /* Automatically adjust sensor reset level
411 Hyundai have some really nice docs about this and other sensor
412 related stuff on their homepage: www.hei.co.kr */
413 sd->resetlevel_frame_count++;
414 if (sd->resetlevel_frame_count < 20)
415 return;
416
417 /* For some reason this normally read-only register doesn't get reset
418 to zero after reading them just once... */
419 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH);
420 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
421 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH);
422 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
423 ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) +
424 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
425 alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) +
426 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
427
428 /* Not an exact science, but it seems to work pretty well... */
429 oldreset = sd->resetlevel;
430 if (alrc > 10) {
431 while (alrc >= 10 && sd->resetlevel < 63) {
432 sd->resetlevel++;
433 alrc /= 2;
434 }
435 } else if (ahrc > 20) {
436 while (ahrc >= 20 && sd->resetlevel > 0) {
437 sd->resetlevel--;
438 ahrc /= 2;
439 }
440 }
441 /* Detect ping-pong-ing and halve adjustment to avoid overshoot */
442 if (sd->resetlevel > oldreset)
443 adjust_dir = 1;
444 else
445 adjust_dir = -1;
446 if (sd->resetlevel_adjust_dir &&
447 sd->resetlevel_adjust_dir != adjust_dir)
448 sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2;
449
450 if (sd->resetlevel != oldreset) {
451 sd->resetlevel_adjust_dir = adjust_dir;
452 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
453 }
454
455 sd->resetlevel_frame_count = 0;
456}
457
458static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
459{
460 struct sd *sd = (struct sd *)gspca_dev;
461
462 switch (sd->expo_change_state) {
463 case EXPO_CHANGED:
464 /* The exposure was changed while this frame
465 was being send, so this frame is ok */
466 sd->expo_change_state = EXPO_DROP_FRAME;
467 break;
468 case EXPO_DROP_FRAME:
469 /* The exposure was changed while this frame
470 was being captured, drop it! */
471 gspca_dev->last_packet_type = DISCARD_PACKET;
472 sd->expo_change_state = EXPO_NO_CHANGE;
473 break;
474 case EXPO_NO_CHANGE:
475 break;
476 }
477 gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
478}
479
480static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
481{
482 struct sd *sd = (struct sd *)gspca_dev;
483 int imagesize = gspca_dev->width * gspca_dev->height;
484 int i, plen, bits, pixels, info, count;
485
486 if (sd->restart_stream)
487 return;
488
489 /* Sometimes a 1024 bytes garbage bulk packet is send between frames */
490 if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) {
491 gspca_dev->last_packet_type = DISCARD_PACKET;
492 return;
493 }
494
495 i = 0;
496 while (i < len) {
497 /* Read header if not already be present from prev bulk pkt */
498 if (sd->packet_read < 4) {
499 count = 4 - sd->packet_read;
500 if (count > len - i)
501 count = len - i;
502 memcpy(&sd->packet[sd->packet_read], &data[i], count);
503 sd->packet_read += count;
504 i += count;
505 if (sd->packet_read < 4)
506 break;
507 }
508 bits = sd->packet[3] + (sd->packet[2] << 8);
509 pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8);
510 info = (sd->packet[0] & 0xc0) >> 6;
511 plen = ((bits + 47) >> 4) << 1;
512 /* Sanity checks */
513 if (plen > 1024) {
514 pr_err("invalid packet len %d restarting stream\n",
515 plen);
516 goto error;
517 }
518 if (info == 3) {
519 pr_err("unknown frame info value restarting stream\n");
520 goto error;
521 }
522
523 /* Read (remainder of) packet contents */
524 count = plen - sd->packet_read;
525 if (count > len - i)
526 count = len - i;
527 memcpy(&sd->packet[sd->packet_read], &data[i], count);
528 sd->packet_read += count;
529 i += count;
530 if (sd->packet_read < plen)
531 break;
532
533 sd->pixels_read += pixels;
534 sd->packet_read = 0;
535
536 switch (info) {
537 case 0: /* Frame data */
538 gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet,
539 plen);
540 break;
541 case 1: /* EOF */
542 if (sd->pixels_read != imagesize) {
543 pr_err("frame size %d expected %d\n",
544 sd->pixels_read, imagesize);
545 goto error;
546 }
547 sd_complete_frame(gspca_dev, sd->packet, plen);
548 return; /* Discard the rest of the bulk packet !! */
549 case 2: /* SOF */
550 gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet,
551 plen);
552 sd->pixels_read = pixels;
553 break;
554 }
555 }
556 return;
557
558error:
559 sd->restart_stream = 1;
560 /* Give userspace a 0 bytes frame, so our dq callback gets
561 called and it can restart the stream */
562 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
563 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
564}
565
566static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len)
567{
568 struct cam *cam = &gspca_dev->cam;
569 int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
570
571 if (gspca_dev->image_len == 0) {
572 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
573 return;
574 }
575
576 if (gspca_dev->image_len + len >= imagesize) {
577 sd_complete_frame(gspca_dev, data, len);
578 return;
579 }
580
581 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
582}
583
584static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
585{
586 int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
587
588 if (len == 0)
589 return;
590
591 if (mult == 1) /* mult == 1 means raw bayer */
592 sd_pkt_scan_bayer(gspca_dev, data, len);
593 else
594 sd_pkt_scan_janggu(gspca_dev, data, len);
595}
596
597#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
598static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
599{
600 struct sd *sd = (struct sd *)gspca_dev;
601 u8 state;
602
603 if (len != 2)
604 return -EINVAL;
605
606 switch (data[0]) {
607 case 0:
608 case 1:
609 state = data[0];
610 break;
611 default:
612 return -EINVAL;
613 }
614 if (sd->button_state != state) {
615 input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
616 input_sync(gspca_dev->input_dev);
617 sd->button_state = state;
618 }
619
620 return 0;
621}
622#endif
623
624static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
625{
626 struct gspca_dev *gspca_dev =
627 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
628 struct sd *sd = (struct sd *)gspca_dev;
629
630 gspca_dev->usb_err = 0;
631
632 if (!gspca_dev->streaming)
633 return 0;
634
635 switch (ctrl->id) {
636 case V4L2_CID_BRIGHTNESS:
637 setbrightness(gspca_dev, ctrl->val);
638 break;
639 case V4L2_CID_GAIN:
640 setgain(gspca_dev, ctrl->val);
641 break;
642 case V4L2_CID_EXPOSURE:
643 setexposure(gspca_dev, ctrl->val, sd->freq->val);
644 break;
645 }
646 return gspca_dev->usb_err;
647}
648
649static const struct v4l2_ctrl_ops sd_ctrl_ops = {
650 .s_ctrl = sd_s_ctrl,
651};
652
653static int sd_init_controls(struct gspca_dev *gspca_dev)
654{
655 struct sd *sd = (struct sd *)gspca_dev;
656 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
657
658 gspca_dev->vdev.ctrl_handler = hdl;
659 v4l2_ctrl_handler_init(hdl, 4);
660 if (sd->has_brightness)
661 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
662 V4L2_CID_BRIGHTNESS, 0, 255, 1, 15);
663 /* max is really 63 but > 50 is not pretty */
664 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
665 V4L2_CID_GAIN, 0, 50, 1, 25);
666 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
667 V4L2_CID_EXPOSURE, 0, 32767, 1, 15000);
668 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
669 V4L2_CID_POWER_LINE_FREQUENCY,
670 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
671
672 if (hdl->error) {
673 pr_err("Could not initialize controls\n");
674 return hdl->error;
675 }
676 v4l2_ctrl_cluster(2, &sd->exposure);
677 return 0;
678}
679
680/* sub-driver description */
681static const struct sd_desc sd_desc = {
682 .name = MODULE_NAME,
683 .config = sd_config,
684 .init = sd_init,
685 .init_controls = sd_init_controls,
686 .isoc_init = sd_isoc_init,
687 .start = sd_start,
688 .stopN = sd_stopN,
689 .dq_callback = sd_dq_callback,
690 .pkt_scan = sd_pkt_scan,
691#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
692 .int_pkt_scan = sd_int_pkt_scan,
693#endif
694};
695
696/* -- module initialisation -- */
697static const struct usb_device_id device_table[] = {
698 {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */
699 {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */
700 {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */
701 {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */
702 {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */
703 {}
704};
705MODULE_DEVICE_TABLE(usb, device_table);
706
707/* -- device connect -- */
708static int sd_probe(struct usb_interface *intf,
709 const struct usb_device_id *id)
710{
711 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
712 THIS_MODULE);
713}
714
715static int sd_pre_reset(struct usb_interface *intf)
716{
717 return 0;
718}
719
720static int sd_post_reset(struct usb_interface *intf)
721{
722 return 0;
723}
724
725static struct usb_driver sd_driver = {
726 .name = MODULE_NAME,
727 .id_table = device_table,
728 .probe = sd_probe,
729 .disconnect = gspca_disconnect,
730#ifdef CONFIG_PM
731 .suspend = gspca_suspend,
732 .resume = gspca_resume,
733 .reset_resume = gspca_resume,
734#endif
735 .pre_reset = sd_pre_reset,
736 .post_reset = sd_post_reset,
737};
738
739module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/se401.h b/drivers/media/usb/gspca/se401.h
new file mode 100644
index 00000000000..96d8ebf3cf5
--- /dev/null
+++ b/drivers/media/usb/gspca/se401.h
@@ -0,0 +1,90 @@
1/*
2 * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
3 *
4 * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
5 *
6 * Based on the v4l1 se401 driver which is:
7 *
8 * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
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 SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06
27#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41
28#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42
29#define SE401_REQ_CAPTURE_FRAME 0x43
30#define SE401_REQ_GET_BRT 0x44
31#define SE401_REQ_SET_BRT 0x45
32#define SE401_REQ_GET_WIDTH 0x4c
33#define SE401_REQ_SET_WIDTH 0x4d
34#define SE401_REQ_GET_HEIGHT 0x4e
35#define SE401_REQ_SET_HEIGHT 0x4f
36#define SE401_REQ_GET_OUTPUT_MODE 0x50
37#define SE401_REQ_SET_OUTPUT_MODE 0x51
38#define SE401_REQ_GET_EXT_FEATURE 0x52
39#define SE401_REQ_SET_EXT_FEATURE 0x53
40#define SE401_REQ_CAMERA_POWER 0x56
41#define SE401_REQ_LED_CONTROL 0x57
42#define SE401_REQ_BIOS 0xff
43
44#define SE401_BIOS_READ 0x07
45
46#define SE401_FORMAT_BAYER 0x40
47
48/* Hyundai hv7131b registers
49 7121 and 7141 should be the same (haven't really checked...) */
50/* Mode registers: */
51#define HV7131_REG_MODE_A 0x00
52#define HV7131_REG_MODE_B 0x01
53#define HV7131_REG_MODE_C 0x02
54/* Frame registers: */
55#define HV7131_REG_FRSU 0x10
56#define HV7131_REG_FRSL 0x11
57#define HV7131_REG_FCSU 0x12
58#define HV7131_REG_FCSL 0x13
59#define HV7131_REG_FWHU 0x14
60#define HV7131_REG_FWHL 0x15
61#define HV7131_REG_FWWU 0x16
62#define HV7131_REG_FWWL 0x17
63/* Timing registers: */
64#define HV7131_REG_THBU 0x20
65#define HV7131_REG_THBL 0x21
66#define HV7131_REG_TVBU 0x22
67#define HV7131_REG_TVBL 0x23
68#define HV7131_REG_TITU 0x25
69#define HV7131_REG_TITM 0x26
70#define HV7131_REG_TITL 0x27
71#define HV7131_REG_TMCD 0x28
72/* Adjust Registers: */
73#define HV7131_REG_ARLV 0x30
74#define HV7131_REG_ARCG 0x31
75#define HV7131_REG_AGCG 0x32
76#define HV7131_REG_ABCG 0x33
77#define HV7131_REG_APBV 0x34
78#define HV7131_REG_ASLP 0x54
79/* Offset Registers: */
80#define HV7131_REG_OFSR 0x50
81#define HV7131_REG_OFSG 0x51
82#define HV7131_REG_OFSB 0x52
83/* REset level statistics registers: */
84#define HV7131_REG_LOREFNOH 0x57
85#define HV7131_REG_LOREFNOL 0x58
86#define HV7131_REG_HIREFNOH 0x59
87#define HV7131_REG_HIREFNOL 0x5a
88
89/* se401 registers */
90#define SE401_OPERATINGMODE 0x2000
diff --git a/drivers/media/usb/gspca/sn9c2028.c b/drivers/media/usb/gspca/sn9c2028.c
new file mode 100644
index 00000000000..03fa3fd940b
--- /dev/null
+++ b/drivers/media/usb/gspca/sn9c2028.c
@@ -0,0 +1,735 @@
1/*
2 * SN9C2028 library
3 *
4 * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "sn9c2028"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Theodore Kilgore");
28MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34 u8 sof_read;
35 u16 model;
36};
37
38struct init_command {
39 unsigned char instruction[6];
40 unsigned char to_read; /* length to read. 0 means no reply requested */
41};
42
43/* How to change the resolution of any of the VGA cams is unknown */
44static const struct v4l2_pix_format vga_mode[] = {
45 {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
46 .bytesperline = 640,
47 .sizeimage = 640 * 480 * 3 / 4,
48 .colorspace = V4L2_COLORSPACE_SRGB,
49 .priv = 0},
50};
51
52/* No way to change the resolution of the CIF cams is known */
53static const struct v4l2_pix_format cif_mode[] = {
54 {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
55 .bytesperline = 352,
56 .sizeimage = 352 * 288 * 3 / 4,
57 .colorspace = V4L2_COLORSPACE_SRGB,
58 .priv = 0},
59};
60
61/* the bytes to write are in gspca_dev->usb_buf */
62static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
63{
64 int rc;
65
66 PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
67 command[1], command[2], command[3], command[4], command[5]);
68
69 memcpy(gspca_dev->usb_buf, command, 6);
70 rc = usb_control_msg(gspca_dev->dev,
71 usb_sndctrlpipe(gspca_dev->dev, 0),
72 USB_REQ_GET_CONFIGURATION,
73 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
74 2, 0, gspca_dev->usb_buf, 6, 500);
75 if (rc < 0) {
76 pr_err("command write [%02x] error %d\n",
77 gspca_dev->usb_buf[0], rc);
78 return rc;
79 }
80
81 return 0;
82}
83
84static int sn9c2028_read1(struct gspca_dev *gspca_dev)
85{
86 int rc;
87
88 rc = usb_control_msg(gspca_dev->dev,
89 usb_rcvctrlpipe(gspca_dev->dev, 0),
90 USB_REQ_GET_STATUS,
91 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
92 1, 0, gspca_dev->usb_buf, 1, 500);
93 if (rc != 1) {
94 pr_err("read1 error %d\n", rc);
95 return (rc < 0) ? rc : -EIO;
96 }
97 PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
98 return gspca_dev->usb_buf[0];
99}
100
101static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
102{
103 int rc;
104 rc = usb_control_msg(gspca_dev->dev,
105 usb_rcvctrlpipe(gspca_dev->dev, 0),
106 USB_REQ_GET_STATUS,
107 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
108 4, 0, gspca_dev->usb_buf, 4, 500);
109 if (rc != 4) {
110 pr_err("read4 error %d\n", rc);
111 return (rc < 0) ? rc : -EIO;
112 }
113 memcpy(reading, gspca_dev->usb_buf, 4);
114 PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
115 reading[1], reading[2], reading[3]);
116 return rc;
117}
118
119static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
120{
121 int i, status;
122 __u8 reading[4];
123
124 status = sn9c2028_command(gspca_dev, command);
125 if (status < 0)
126 return status;
127
128 status = -1;
129 for (i = 0; i < 256 && status < 2; i++)
130 status = sn9c2028_read1(gspca_dev);
131 if (status != 2) {
132 pr_err("long command status read error %d\n", status);
133 return (status < 0) ? status : -EIO;
134 }
135
136 memset(reading, 0, 4);
137 status = sn9c2028_read4(gspca_dev, reading);
138 if (status < 0)
139 return status;
140
141 /* in general, the first byte of the response is the first byte of
142 * the command, or'ed with 8 */
143 status = sn9c2028_read1(gspca_dev);
144 if (status < 0)
145 return status;
146
147 return 0;
148}
149
150static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
151{
152 int err_code;
153
154 err_code = sn9c2028_command(gspca_dev, command);
155 if (err_code < 0)
156 return err_code;
157
158 err_code = sn9c2028_read1(gspca_dev);
159 if (err_code < 0)
160 return err_code;
161
162 return 0;
163}
164
165/* this function is called at probe time */
166static int sd_config(struct gspca_dev *gspca_dev,
167 const struct usb_device_id *id)
168{
169 struct sd *sd = (struct sd *) gspca_dev;
170 struct cam *cam = &gspca_dev->cam;
171
172 PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
173 id->idVendor, id->idProduct);
174
175 sd->model = id->idProduct;
176
177 switch (sd->model) {
178 case 0x7005:
179 PDEBUG(D_PROBE, "Genius Smart 300 camera");
180 break;
181 case 0x8000:
182 PDEBUG(D_PROBE, "DC31VC");
183 break;
184 case 0x8001:
185 PDEBUG(D_PROBE, "Spy camera");
186 break;
187 case 0x8003:
188 PDEBUG(D_PROBE, "CIF camera");
189 break;
190 case 0x8008:
191 PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
192 break;
193 case 0x800a:
194 PDEBUG(D_PROBE, "Vivitar 3350b type camera");
195 cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
196 break;
197 }
198
199 switch (sd->model) {
200 case 0x8000:
201 case 0x8001:
202 case 0x8003:
203 cam->cam_mode = cif_mode;
204 cam->nmodes = ARRAY_SIZE(cif_mode);
205 break;
206 default:
207 cam->cam_mode = vga_mode;
208 cam->nmodes = ARRAY_SIZE(vga_mode);
209 }
210 return 0;
211}
212
213/* this function is called at probe and resume time */
214static int sd_init(struct gspca_dev *gspca_dev)
215{
216 int status = -1;
217
218 sn9c2028_read1(gspca_dev);
219 sn9c2028_read1(gspca_dev);
220 status = sn9c2028_read1(gspca_dev);
221
222 return (status < 0) ? status : 0;
223}
224
225static int run_start_commands(struct gspca_dev *gspca_dev,
226 struct init_command *cam_commands, int n)
227{
228 int i, err_code = -1;
229
230 for (i = 0; i < n; i++) {
231 switch (cam_commands[i].to_read) {
232 case 4:
233 err_code = sn9c2028_long_command(gspca_dev,
234 cam_commands[i].instruction);
235 break;
236 case 1:
237 err_code = sn9c2028_short_command(gspca_dev,
238 cam_commands[i].instruction);
239 break;
240 case 0:
241 err_code = sn9c2028_command(gspca_dev,
242 cam_commands[i].instruction);
243 break;
244 }
245 if (err_code < 0)
246 return err_code;
247 }
248 return 0;
249}
250
251static int start_spy_cam(struct gspca_dev *gspca_dev)
252{
253 struct init_command spy_start_commands[] = {
254 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
255 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
256 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
257 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
258 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
259 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
260 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */
261 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
262 /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
263 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
264 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
265 /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
266 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
267 /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
268 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
269 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
270 /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
271 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
272 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
273 /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
274 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
275 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
276 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
277 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
278 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
279 {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
280 {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
281 /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
282 {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
283 /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
284 {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
285 {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
286 {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
287 /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
288 {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
289 {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
290 {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
291 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
292 {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
293 {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
294 {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
295 /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
296 /* brightness or gain. 0 is default. 4 is good
297 * indoors at night with incandescent lighting */
298 {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
299 {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
300 {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
301 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
302 {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
303 {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
304 /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
305 {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
306 /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
307 {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
308 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
309 /* Camera should start to capture now. */
310 };
311
312 return run_start_commands(gspca_dev, spy_start_commands,
313 ARRAY_SIZE(spy_start_commands));
314}
315
316static int start_cif_cam(struct gspca_dev *gspca_dev)
317{
318 struct init_command cif_start_commands[] = {
319 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
320 /* The entire sequence below seems redundant */
321 /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
322 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
323 {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
324 {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
325 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
326 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
327 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
328 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
329 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
330 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
331 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
332 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
333 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
334 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
335 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
336 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
337 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
338 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
339 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
340 {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
341 {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
342 {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
343 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
344 {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
345 {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
346 {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
347 {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
348 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
349 {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
350 {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
351 {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
352 {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
353 {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
354 {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
355 {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
356 {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
357 {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
358 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
359 {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
360 {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
361 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
362 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
363 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
364 /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
365 * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
366 * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
367 /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
368 * causes subsampling
369 * but not a change in the resolution setting! */
370 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
371 {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
372 {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
373 {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
374 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
375 {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
376 {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
377 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
378 {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
379 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
380 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
381 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
382 {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
383 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
384 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
385 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
386 /* Camera should start to capture now. */
387 };
388
389 return run_start_commands(gspca_dev, cif_start_commands,
390 ARRAY_SIZE(cif_start_commands));
391}
392
393static int start_ms350_cam(struct gspca_dev *gspca_dev)
394{
395 struct init_command ms350_start_commands[] = {
396 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
397 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
398 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
399 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
400 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
401 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
402 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
403 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
404 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
405 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
406 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
407 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
408 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
409 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
410 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
411 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
412 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
413 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
414 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
415 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
416 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
417 {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
418 {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
419 {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
420 {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
421 {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
422 {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
423 {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
424 {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
425 {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
426 {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
427 {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
428 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
429 {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
430 {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
431 {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
432 {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
433 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
434 {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
435 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
436 {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
437 {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
438 {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
439 {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
440 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */
441 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
442 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
443 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
444 {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
445 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
446 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
447 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
448 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
449 {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
450 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
451 {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
452 {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
453 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
454 /* Camera should start to capture now. */
455 };
456
457 return run_start_commands(gspca_dev, ms350_start_commands,
458 ARRAY_SIZE(ms350_start_commands));
459}
460
461static int start_genius_cam(struct gspca_dev *gspca_dev)
462{
463 struct init_command genius_start_commands[] = {
464 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
465 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
466 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
467 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
468 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
469 /* "preliminary" width and height settings */
470 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
471 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
472 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
473 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
474 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
475 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
476 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
477 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
478 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
479 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
480 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
481 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
482 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
483 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
484 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
485 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
486 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
487 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
488 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
489 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
490 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
491 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
492 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
493 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
494 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
495 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
496 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
497 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
498 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
499 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
500 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
501 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
502 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
503 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
504 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
505 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
506 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
507 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
508 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
509 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
510 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
511 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
512 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
513 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
514 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
515 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
516 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
517 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
518 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
519 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
520 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
521 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
522 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
523 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
524 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
525 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
526 /* Camera should start to capture now. */
527 };
528
529 return run_start_commands(gspca_dev, genius_start_commands,
530 ARRAY_SIZE(genius_start_commands));
531}
532
533static int start_vivitar_cam(struct gspca_dev *gspca_dev)
534{
535 struct init_command vivitar_start_commands[] = {
536 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
537 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
538 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
539 {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
540 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
541 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
542 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
543 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
544 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
545 {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
546 /*
547 * Above is changed from OEM 0x0b. Fixes Bayer tiling.
548 * Presumably gives a vertical shift of one row.
549 */
550 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
551 /* Above seems to do horizontal shift. */
552 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
553 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
554 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
555 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
556 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
557 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
558 /* Above three commands seem to relate to brightness. */
559 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
560 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
561 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
562 {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
563 {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
564 {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
565 {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
566 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
567 {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
568 {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
569 {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
570 {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
571 {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
572 {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
573 {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
574 {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
575 {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
576 {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
577 {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
578 {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
579 {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
580 {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
581 {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
582 {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
583 {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
584 {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
585 {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
586 {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
587 {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
588 {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
589 {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
590 {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
591 {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
592 {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
593 {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
594 {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
595 {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
596 /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
597 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
598 {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
599 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
600 {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
601 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
602 {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
603 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
604 {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
605 /* Above is brightness; OEM driver setting is 0x10 */
606 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
607 {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
608 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
609 };
610
611 return run_start_commands(gspca_dev, vivitar_start_commands,
612 ARRAY_SIZE(vivitar_start_commands));
613}
614
615static int sd_start(struct gspca_dev *gspca_dev)
616{
617 struct sd *sd = (struct sd *) gspca_dev;
618 int err_code;
619
620 sd->sof_read = 0;
621
622 switch (sd->model) {
623 case 0x7005:
624 err_code = start_genius_cam(gspca_dev);
625 break;
626 case 0x8001:
627 err_code = start_spy_cam(gspca_dev);
628 break;
629 case 0x8003:
630 err_code = start_cif_cam(gspca_dev);
631 break;
632 case 0x8008:
633 err_code = start_ms350_cam(gspca_dev);
634 break;
635 case 0x800a:
636 err_code = start_vivitar_cam(gspca_dev);
637 break;
638 default:
639 pr_err("Starting unknown camera, please report this\n");
640 return -ENXIO;
641 }
642
643 return err_code;
644}
645
646static void sd_stopN(struct gspca_dev *gspca_dev)
647{
648 int result;
649 __u8 data[6];
650
651 result = sn9c2028_read1(gspca_dev);
652 if (result < 0)
653 PDEBUG(D_ERR, "Camera Stop read failed");
654
655 memset(data, 0, 6);
656 data[0] = 0x14;
657 result = sn9c2028_command(gspca_dev, data);
658 if (result < 0)
659 PDEBUG(D_ERR, "Camera Stop command failed");
660}
661
662/* Include sn9c2028 sof detection functions */
663#include "sn9c2028.h"
664
665static void sd_pkt_scan(struct gspca_dev *gspca_dev,
666 __u8 *data, /* isoc packet */
667 int len) /* iso packet length */
668{
669 unsigned char *sof;
670
671 sof = sn9c2028_find_sof(gspca_dev, data, len);
672 if (sof) {
673 int n;
674
675 /* finish decoding current frame */
676 n = sof - data;
677 if (n > sizeof sn9c2028_sof_marker)
678 n -= sizeof sn9c2028_sof_marker;
679 else
680 n = 0;
681 gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
682 /* Start next frame. */
683 gspca_frame_add(gspca_dev, FIRST_PACKET,
684 sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
685 len -= sof - data;
686 data = sof;
687 }
688 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
689}
690
691/* sub-driver description */
692static const struct sd_desc sd_desc = {
693 .name = MODULE_NAME,
694 .config = sd_config,
695 .init = sd_init,
696 .start = sd_start,
697 .stopN = sd_stopN,
698 .pkt_scan = sd_pkt_scan,
699};
700
701/* -- module initialisation -- */
702static const struct usb_device_id device_table[] = {
703 {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
704 /* The Genius Smart is untested. I can't find an owner ! */
705 /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
706 {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
707 {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
708 /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
709 {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
710 {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
711 {}
712};
713MODULE_DEVICE_TABLE(usb, device_table);
714
715/* -- device connect -- */
716static int sd_probe(struct usb_interface *intf,
717 const struct usb_device_id *id)
718{
719 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
720 THIS_MODULE);
721}
722
723static struct usb_driver sd_driver = {
724 .name = MODULE_NAME,
725 .id_table = device_table,
726 .probe = sd_probe,
727 .disconnect = gspca_disconnect,
728#ifdef CONFIG_PM
729 .suspend = gspca_suspend,
730 .resume = gspca_resume,
731 .reset_resume = gspca_resume,
732#endif
733};
734
735module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sn9c2028.h b/drivers/media/usb/gspca/sn9c2028.h
new file mode 100644
index 00000000000..8fd1d3e0566
--- /dev/null
+++ b/drivers/media/usb/gspca/sn9c2028.h
@@ -0,0 +1,51 @@
1/*
2 * SN9C2028 common functions
3 *
4 * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu>
5 *
6 * Based closely upon the file gspca/pac_common.h
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24static const unsigned char sn9c2028_sof_marker[5] =
25 { 0xff, 0xff, 0x00, 0xc4, 0xc4 };
26
27static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev,
28 unsigned char *m, int len)
29{
30 struct sd *sd = (struct sd *) gspca_dev;
31 int i;
32
33 /* Search for the SOF marker (fixed part) in the header */
34 for (i = 0; i < len; i++) {
35 if (m[i] == sn9c2028_sof_marker[sd->sof_read]) {
36 sd->sof_read++;
37 if (sd->sof_read == sizeof(sn9c2028_sof_marker)) {
38 PDEBUG(D_FRAM,
39 "SOF found, bytes to analyze: %u."
40 " Frame starts at byte #%u",
41 len, i + 1);
42 sd->sof_read = 0;
43 return m + i + 1;
44 }
45 } else {
46 sd->sof_read = 0;
47 }
48 }
49
50 return NULL;
51}
diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
new file mode 100644
index 00000000000..b9c6f17eabb
--- /dev/null
+++ b/drivers/media/usb/gspca/sn9c20x.c
@@ -0,0 +1,2428 @@
1/*
2 * Sonix sn9c201 sn9c202 library
3 *
4 * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
6 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#include <linux/input.h>
26
27#include "gspca.h"
28#include "jpeg.h"
29
30#include <media/v4l2-chip-ident.h>
31#include <linux/dmi.h>
32
33MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
34 "microdia project <microdia@googlegroups.com>");
35MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
36MODULE_LICENSE("GPL");
37
38/*
39 * Pixel format private data
40 */
41#define SCALE_MASK 0x0f
42#define SCALE_160x120 0
43#define SCALE_320x240 1
44#define SCALE_640x480 2
45#define SCALE_1280x1024 3
46#define MODE_RAW 0x10
47#define MODE_JPEG 0x20
48#define MODE_SXGA 0x80
49
50#define SENSOR_OV9650 0
51#define SENSOR_OV9655 1
52#define SENSOR_SOI968 2
53#define SENSOR_OV7660 3
54#define SENSOR_OV7670 4
55#define SENSOR_MT9V011 5
56#define SENSOR_MT9V111 6
57#define SENSOR_MT9V112 7
58#define SENSOR_MT9M001 8
59#define SENSOR_MT9M111 9
60#define SENSOR_MT9M112 10
61#define SENSOR_HV7131R 11
62#define SENSOR_MT9VPRB 12
63
64/* camera flags */
65#define HAS_NO_BUTTON 0x1
66#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
67#define FLIP_DETECT 0x4
68
69/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev;
72
73 struct { /* color control cluster */
74 struct v4l2_ctrl *brightness;
75 struct v4l2_ctrl *contrast;
76 struct v4l2_ctrl *saturation;
77 struct v4l2_ctrl *hue;
78 };
79 struct { /* blue/red balance control cluster */
80 struct v4l2_ctrl *blue;
81 struct v4l2_ctrl *red;
82 };
83 struct { /* h/vflip control cluster */
84 struct v4l2_ctrl *hflip;
85 struct v4l2_ctrl *vflip;
86 };
87 struct v4l2_ctrl *gamma;
88 struct { /* autogain and exposure or gain control cluster */
89 struct v4l2_ctrl *autogain;
90 struct v4l2_ctrl *exposure;
91 struct v4l2_ctrl *gain;
92 };
93 struct v4l2_ctrl *jpegqual;
94
95 struct work_struct work;
96 struct workqueue_struct *work_thread;
97
98 u32 pktsz; /* (used by pkt_scan) */
99 u16 npkt;
100 s8 nchg;
101 u8 fmt; /* (used for JPEG QTAB update */
102
103#define MIN_AVG_LUM 80
104#define MAX_AVG_LUM 130
105 atomic_t avg_lum;
106 u8 old_step;
107 u8 older_step;
108 u8 exposure_step;
109
110 u8 i2c_addr;
111 u8 i2c_intf;
112 u8 sensor;
113 u8 hstart;
114 u8 vstart;
115
116 u8 jpeg_hdr[JPEG_HDR_SZ];
117
118 u8 flags;
119};
120
121static void qual_upd(struct work_struct *work);
122
123struct i2c_reg_u8 {
124 u8 reg;
125 u8 val;
126};
127
128struct i2c_reg_u16 {
129 u8 reg;
130 u16 val;
131};
132
133static const struct dmi_system_id flip_dmi_table[] = {
134 {
135 .ident = "MSI MS-1034",
136 .matches = {
137 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
138 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
139 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
140 }
141 },
142 {
143 .ident = "MSI MS-1632",
144 .matches = {
145 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
146 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
147 }
148 },
149 {
150 .ident = "MSI MS-1633X",
151 .matches = {
152 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
153 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
154 }
155 },
156 {
157 .ident = "MSI MS-1635X",
158 .matches = {
159 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
160 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
161 }
162 },
163 {
164 .ident = "ASUSTeK W7J",
165 .matches = {
166 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
167 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
168 }
169 },
170 {}
171};
172
173static const struct v4l2_pix_format vga_mode[] = {
174 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
175 .bytesperline = 160,
176 .sizeimage = 160 * 120 * 4 / 8 + 590,
177 .colorspace = V4L2_COLORSPACE_JPEG,
178 .priv = SCALE_160x120 | MODE_JPEG},
179 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
180 .bytesperline = 160,
181 .sizeimage = 160 * 120,
182 .colorspace = V4L2_COLORSPACE_SRGB,
183 .priv = SCALE_160x120 | MODE_RAW},
184 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
185 .bytesperline = 160,
186 .sizeimage = 240 * 120,
187 .colorspace = V4L2_COLORSPACE_SRGB,
188 .priv = SCALE_160x120},
189 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
190 .bytesperline = 320,
191 .sizeimage = 320 * 240 * 4 / 8 + 590,
192 .colorspace = V4L2_COLORSPACE_JPEG,
193 .priv = SCALE_320x240 | MODE_JPEG},
194 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
195 .bytesperline = 320,
196 .sizeimage = 320 * 240 ,
197 .colorspace = V4L2_COLORSPACE_SRGB,
198 .priv = SCALE_320x240 | MODE_RAW},
199 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
200 .bytesperline = 320,
201 .sizeimage = 480 * 240 ,
202 .colorspace = V4L2_COLORSPACE_SRGB,
203 .priv = SCALE_320x240},
204 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
205 .bytesperline = 640,
206 .sizeimage = 640 * 480 * 4 / 8 + 590,
207 .colorspace = V4L2_COLORSPACE_JPEG,
208 .priv = SCALE_640x480 | MODE_JPEG},
209 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
210 .bytesperline = 640,
211 .sizeimage = 640 * 480,
212 .colorspace = V4L2_COLORSPACE_SRGB,
213 .priv = SCALE_640x480 | MODE_RAW},
214 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
215 .bytesperline = 640,
216 .sizeimage = 960 * 480,
217 .colorspace = V4L2_COLORSPACE_SRGB,
218 .priv = SCALE_640x480},
219};
220
221static const struct v4l2_pix_format sxga_mode[] = {
222 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
223 .bytesperline = 160,
224 .sizeimage = 160 * 120 * 4 / 8 + 590,
225 .colorspace = V4L2_COLORSPACE_JPEG,
226 .priv = SCALE_160x120 | MODE_JPEG},
227 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
228 .bytesperline = 160,
229 .sizeimage = 160 * 120,
230 .colorspace = V4L2_COLORSPACE_SRGB,
231 .priv = SCALE_160x120 | MODE_RAW},
232 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
233 .bytesperline = 160,
234 .sizeimage = 240 * 120,
235 .colorspace = V4L2_COLORSPACE_SRGB,
236 .priv = SCALE_160x120},
237 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
238 .bytesperline = 320,
239 .sizeimage = 320 * 240 * 4 / 8 + 590,
240 .colorspace = V4L2_COLORSPACE_JPEG,
241 .priv = SCALE_320x240 | MODE_JPEG},
242 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
243 .bytesperline = 320,
244 .sizeimage = 320 * 240 ,
245 .colorspace = V4L2_COLORSPACE_SRGB,
246 .priv = SCALE_320x240 | MODE_RAW},
247 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
248 .bytesperline = 320,
249 .sizeimage = 480 * 240 ,
250 .colorspace = V4L2_COLORSPACE_SRGB,
251 .priv = SCALE_320x240},
252 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
253 .bytesperline = 640,
254 .sizeimage = 640 * 480 * 4 / 8 + 590,
255 .colorspace = V4L2_COLORSPACE_JPEG,
256 .priv = SCALE_640x480 | MODE_JPEG},
257 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
258 .bytesperline = 640,
259 .sizeimage = 640 * 480,
260 .colorspace = V4L2_COLORSPACE_SRGB,
261 .priv = SCALE_640x480 | MODE_RAW},
262 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
263 .bytesperline = 640,
264 .sizeimage = 960 * 480,
265 .colorspace = V4L2_COLORSPACE_SRGB,
266 .priv = SCALE_640x480},
267 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
268 .bytesperline = 1280,
269 .sizeimage = 1280 * 1024,
270 .colorspace = V4L2_COLORSPACE_SRGB,
271 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
272};
273
274static const struct v4l2_pix_format mono_mode[] = {
275 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
276 .bytesperline = 160,
277 .sizeimage = 160 * 120,
278 .colorspace = V4L2_COLORSPACE_SRGB,
279 .priv = SCALE_160x120 | MODE_RAW},
280 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
281 .bytesperline = 320,
282 .sizeimage = 320 * 240 ,
283 .colorspace = V4L2_COLORSPACE_SRGB,
284 .priv = SCALE_320x240 | MODE_RAW},
285 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
286 .bytesperline = 640,
287 .sizeimage = 640 * 480,
288 .colorspace = V4L2_COLORSPACE_SRGB,
289 .priv = SCALE_640x480 | MODE_RAW},
290 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
291 .bytesperline = 1280,
292 .sizeimage = 1280 * 1024,
293 .colorspace = V4L2_COLORSPACE_SRGB,
294 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
295};
296
297static const s16 hsv_red_x[] = {
298 41, 44, 46, 48, 50, 52, 54, 56,
299 58, 60, 62, 64, 66, 68, 70, 72,
300 74, 76, 78, 80, 81, 83, 85, 87,
301 88, 90, 92, 93, 95, 97, 98, 100,
302 101, 102, 104, 105, 107, 108, 109, 110,
303 112, 113, 114, 115, 116, 117, 118, 119,
304 120, 121, 122, 123, 123, 124, 125, 125,
305 126, 127, 127, 128, 128, 129, 129, 129,
306 130, 130, 130, 130, 131, 131, 131, 131,
307 131, 131, 131, 131, 130, 130, 130, 130,
308 129, 129, 129, 128, 128, 127, 127, 126,
309 125, 125, 124, 123, 122, 122, 121, 120,
310 119, 118, 117, 116, 115, 114, 112, 111,
311 110, 109, 107, 106, 105, 103, 102, 101,
312 99, 98, 96, 94, 93, 91, 90, 88,
313 86, 84, 83, 81, 79, 77, 75, 74,
314 72, 70, 68, 66, 64, 62, 60, 58,
315 56, 54, 52, 49, 47, 45, 43, 41,
316 39, 36, 34, 32, 30, 28, 25, 23,
317 21, 19, 16, 14, 12, 9, 7, 5,
318 3, 0, -1, -3, -6, -8, -10, -12,
319 -15, -17, -19, -22, -24, -26, -28, -30,
320 -33, -35, -37, -39, -41, -44, -46, -48,
321 -50, -52, -54, -56, -58, -60, -62, -64,
322 -66, -68, -70, -72, -74, -76, -78, -80,
323 -81, -83, -85, -87, -88, -90, -92, -93,
324 -95, -97, -98, -100, -101, -102, -104, -105,
325 -107, -108, -109, -110, -112, -113, -114, -115,
326 -116, -117, -118, -119, -120, -121, -122, -123,
327 -123, -124, -125, -125, -126, -127, -127, -128,
328 -128, -128, -128, -128, -128, -128, -128, -128,
329 -128, -128, -128, -128, -128, -128, -128, -128,
330 -128, -128, -128, -128, -128, -128, -128, -128,
331 -128, -127, -127, -126, -125, -125, -124, -123,
332 -122, -122, -121, -120, -119, -118, -117, -116,
333 -115, -114, -112, -111, -110, -109, -107, -106,
334 -105, -103, -102, -101, -99, -98, -96, -94,
335 -93, -91, -90, -88, -86, -84, -83, -81,
336 -79, -77, -75, -74, -72, -70, -68, -66,
337 -64, -62, -60, -58, -56, -54, -52, -49,
338 -47, -45, -43, -41, -39, -36, -34, -32,
339 -30, -28, -25, -23, -21, -19, -16, -14,
340 -12, -9, -7, -5, -3, 0, 1, 3,
341 6, 8, 10, 12, 15, 17, 19, 22,
342 24, 26, 28, 30, 33, 35, 37, 39, 41
343};
344
345static const s16 hsv_red_y[] = {
346 82, 80, 78, 76, 74, 73, 71, 69,
347 67, 65, 63, 61, 58, 56, 54, 52,
348 50, 48, 46, 44, 41, 39, 37, 35,
349 32, 30, 28, 26, 23, 21, 19, 16,
350 14, 12, 10, 7, 5, 3, 0, -1,
351 -3, -6, -8, -10, -13, -15, -17, -19,
352 -22, -24, -26, -29, -31, -33, -35, -38,
353 -40, -42, -44, -46, -48, -51, -53, -55,
354 -57, -59, -61, -63, -65, -67, -69, -71,
355 -73, -75, -77, -79, -81, -82, -84, -86,
356 -88, -89, -91, -93, -94, -96, -98, -99,
357 -101, -102, -104, -105, -106, -108, -109, -110,
358 -112, -113, -114, -115, -116, -117, -119, -120,
359 -120, -121, -122, -123, -124, -125, -126, -126,
360 -127, -128, -128, -128, -128, -128, -128, -128,
361 -128, -128, -128, -128, -128, -128, -128, -128,
362 -128, -128, -128, -128, -128, -128, -128, -128,
363 -128, -128, -128, -128, -128, -128, -128, -128,
364 -127, -127, -126, -125, -125, -124, -123, -122,
365 -121, -120, -119, -118, -117, -116, -115, -114,
366 -113, -111, -110, -109, -107, -106, -105, -103,
367 -102, -100, -99, -97, -96, -94, -92, -91,
368 -89, -87, -85, -84, -82, -80, -78, -76,
369 -74, -73, -71, -69, -67, -65, -63, -61,
370 -58, -56, -54, -52, -50, -48, -46, -44,
371 -41, -39, -37, -35, -32, -30, -28, -26,
372 -23, -21, -19, -16, -14, -12, -10, -7,
373 -5, -3, 0, 1, 3, 6, 8, 10,
374 13, 15, 17, 19, 22, 24, 26, 29,
375 31, 33, 35, 38, 40, 42, 44, 46,
376 48, 51, 53, 55, 57, 59, 61, 63,
377 65, 67, 69, 71, 73, 75, 77, 79,
378 81, 82, 84, 86, 88, 89, 91, 93,
379 94, 96, 98, 99, 101, 102, 104, 105,
380 106, 108, 109, 110, 112, 113, 114, 115,
381 116, 117, 119, 120, 120, 121, 122, 123,
382 124, 125, 126, 126, 127, 128, 128, 129,
383 129, 130, 130, 131, 131, 131, 131, 132,
384 132, 132, 132, 132, 132, 132, 132, 132,
385 132, 132, 132, 131, 131, 131, 130, 130,
386 130, 129, 129, 128, 127, 127, 126, 125,
387 125, 124, 123, 122, 121, 120, 119, 118,
388 117, 116, 115, 114, 113, 111, 110, 109,
389 107, 106, 105, 103, 102, 100, 99, 97,
390 96, 94, 92, 91, 89, 87, 85, 84, 82
391};
392
393static const s16 hsv_green_x[] = {
394 -124, -124, -125, -125, -125, -125, -125, -125,
395 -125, -126, -126, -125, -125, -125, -125, -125,
396 -125, -124, -124, -124, -123, -123, -122, -122,
397 -121, -121, -120, -120, -119, -118, -117, -117,
398 -116, -115, -114, -113, -112, -111, -110, -109,
399 -108, -107, -105, -104, -103, -102, -100, -99,
400 -98, -96, -95, -93, -92, -91, -89, -87,
401 -86, -84, -83, -81, -79, -77, -76, -74,
402 -72, -70, -69, -67, -65, -63, -61, -59,
403 -57, -55, -53, -51, -49, -47, -45, -43,
404 -41, -39, -37, -35, -33, -30, -28, -26,
405 -24, -22, -20, -18, -15, -13, -11, -9,
406 -7, -4, -2, 0, 1, 3, 6, 8,
407 10, 12, 14, 17, 19, 21, 23, 25,
408 27, 29, 32, 34, 36, 38, 40, 42,
409 44, 46, 48, 50, 52, 54, 56, 58,
410 60, 62, 64, 66, 68, 70, 71, 73,
411 75, 77, 78, 80, 82, 83, 85, 87,
412 88, 90, 91, 93, 94, 96, 97, 98,
413 100, 101, 102, 104, 105, 106, 107, 108,
414 109, 111, 112, 113, 113, 114, 115, 116,
415 117, 118, 118, 119, 120, 120, 121, 122,
416 122, 123, 123, 124, 124, 124, 125, 125,
417 125, 125, 125, 125, 125, 126, 126, 125,
418 125, 125, 125, 125, 125, 124, 124, 124,
419 123, 123, 122, 122, 121, 121, 120, 120,
420 119, 118, 117, 117, 116, 115, 114, 113,
421 112, 111, 110, 109, 108, 107, 105, 104,
422 103, 102, 100, 99, 98, 96, 95, 93,
423 92, 91, 89, 87, 86, 84, 83, 81,
424 79, 77, 76, 74, 72, 70, 69, 67,
425 65, 63, 61, 59, 57, 55, 53, 51,
426 49, 47, 45, 43, 41, 39, 37, 35,
427 33, 30, 28, 26, 24, 22, 20, 18,
428 15, 13, 11, 9, 7, 4, 2, 0,
429 -1, -3, -6, -8, -10, -12, -14, -17,
430 -19, -21, -23, -25, -27, -29, -32, -34,
431 -36, -38, -40, -42, -44, -46, -48, -50,
432 -52, -54, -56, -58, -60, -62, -64, -66,
433 -68, -70, -71, -73, -75, -77, -78, -80,
434 -82, -83, -85, -87, -88, -90, -91, -93,
435 -94, -96, -97, -98, -100, -101, -102, -104,
436 -105, -106, -107, -108, -109, -111, -112, -113,
437 -113, -114, -115, -116, -117, -118, -118, -119,
438 -120, -120, -121, -122, -122, -123, -123, -124, -124
439};
440
441static const s16 hsv_green_y[] = {
442 -100, -99, -98, -97, -95, -94, -93, -91,
443 -90, -89, -87, -86, -84, -83, -81, -80,
444 -78, -76, -75, -73, -71, -70, -68, -66,
445 -64, -63, -61, -59, -57, -55, -53, -51,
446 -49, -48, -46, -44, -42, -40, -38, -36,
447 -34, -32, -30, -27, -25, -23, -21, -19,
448 -17, -15, -13, -11, -9, -7, -4, -2,
449 0, 1, 3, 5, 7, 9, 11, 14,
450 16, 18, 20, 22, 24, 26, 28, 30,
451 32, 34, 36, 38, 40, 42, 44, 46,
452 48, 50, 52, 54, 56, 58, 59, 61,
453 63, 65, 67, 68, 70, 72, 74, 75,
454 77, 78, 80, 82, 83, 85, 86, 88,
455 89, 90, 92, 93, 95, 96, 97, 98,
456 100, 101, 102, 103, 104, 105, 106, 107,
457 108, 109, 110, 111, 112, 112, 113, 114,
458 115, 115, 116, 116, 117, 117, 118, 118,
459 119, 119, 119, 120, 120, 120, 120, 120,
460 121, 121, 121, 121, 121, 121, 120, 120,
461 120, 120, 120, 119, 119, 119, 118, 118,
462 117, 117, 116, 116, 115, 114, 114, 113,
463 112, 111, 111, 110, 109, 108, 107, 106,
464 105, 104, 103, 102, 100, 99, 98, 97,
465 95, 94, 93, 91, 90, 89, 87, 86,
466 84, 83, 81, 80, 78, 76, 75, 73,
467 71, 70, 68, 66, 64, 63, 61, 59,
468 57, 55, 53, 51, 49, 48, 46, 44,
469 42, 40, 38, 36, 34, 32, 30, 27,
470 25, 23, 21, 19, 17, 15, 13, 11,
471 9, 7, 4, 2, 0, -1, -3, -5,
472 -7, -9, -11, -14, -16, -18, -20, -22,
473 -24, -26, -28, -30, -32, -34, -36, -38,
474 -40, -42, -44, -46, -48, -50, -52, -54,
475 -56, -58, -59, -61, -63, -65, -67, -68,
476 -70, -72, -74, -75, -77, -78, -80, -82,
477 -83, -85, -86, -88, -89, -90, -92, -93,
478 -95, -96, -97, -98, -100, -101, -102, -103,
479 -104, -105, -106, -107, -108, -109, -110, -111,
480 -112, -112, -113, -114, -115, -115, -116, -116,
481 -117, -117, -118, -118, -119, -119, -119, -120,
482 -120, -120, -120, -120, -121, -121, -121, -121,
483 -121, -121, -120, -120, -120, -120, -120, -119,
484 -119, -119, -118, -118, -117, -117, -116, -116,
485 -115, -114, -114, -113, -112, -111, -111, -110,
486 -109, -108, -107, -106, -105, -104, -103, -102, -100
487};
488
489static const s16 hsv_blue_x[] = {
490 112, 113, 114, 114, 115, 116, 117, 117,
491 118, 118, 119, 119, 120, 120, 120, 121,
492 121, 121, 122, 122, 122, 122, 122, 122,
493 122, 122, 122, 122, 122, 122, 121, 121,
494 121, 120, 120, 120, 119, 119, 118, 118,
495 117, 116, 116, 115, 114, 113, 113, 112,
496 111, 110, 109, 108, 107, 106, 105, 104,
497 103, 102, 100, 99, 98, 97, 95, 94,
498 93, 91, 90, 88, 87, 85, 84, 82,
499 80, 79, 77, 76, 74, 72, 70, 69,
500 67, 65, 63, 61, 60, 58, 56, 54,
501 52, 50, 48, 46, 44, 42, 40, 38,
502 36, 34, 32, 30, 28, 26, 24, 22,
503 19, 17, 15, 13, 11, 9, 7, 5,
504 2, 0, -1, -3, -5, -7, -9, -12,
505 -14, -16, -18, -20, -22, -24, -26, -28,
506 -31, -33, -35, -37, -39, -41, -43, -45,
507 -47, -49, -51, -53, -54, -56, -58, -60,
508 -62, -64, -66, -67, -69, -71, -73, -74,
509 -76, -78, -79, -81, -83, -84, -86, -87,
510 -89, -90, -92, -93, -94, -96, -97, -98,
511 -99, -101, -102, -103, -104, -105, -106, -107,
512 -108, -109, -110, -111, -112, -113, -114, -114,
513 -115, -116, -117, -117, -118, -118, -119, -119,
514 -120, -120, -120, -121, -121, -121, -122, -122,
515 -122, -122, -122, -122, -122, -122, -122, -122,
516 -122, -122, -121, -121, -121, -120, -120, -120,
517 -119, -119, -118, -118, -117, -116, -116, -115,
518 -114, -113, -113, -112, -111, -110, -109, -108,
519 -107, -106, -105, -104, -103, -102, -100, -99,
520 -98, -97, -95, -94, -93, -91, -90, -88,
521 -87, -85, -84, -82, -80, -79, -77, -76,
522 -74, -72, -70, -69, -67, -65, -63, -61,
523 -60, -58, -56, -54, -52, -50, -48, -46,
524 -44, -42, -40, -38, -36, -34, -32, -30,
525 -28, -26, -24, -22, -19, -17, -15, -13,
526 -11, -9, -7, -5, -2, 0, 1, 3,
527 5, 7, 9, 12, 14, 16, 18, 20,
528 22, 24, 26, 28, 31, 33, 35, 37,
529 39, 41, 43, 45, 47, 49, 51, 53,
530 54, 56, 58, 60, 62, 64, 66, 67,
531 69, 71, 73, 74, 76, 78, 79, 81,
532 83, 84, 86, 87, 89, 90, 92, 93,
533 94, 96, 97, 98, 99, 101, 102, 103,
534 104, 105, 106, 107, 108, 109, 110, 111, 112
535};
536
537static const s16 hsv_blue_y[] = {
538 -11, -13, -15, -17, -19, -21, -23, -25,
539 -27, -29, -31, -33, -35, -37, -39, -41,
540 -43, -45, -46, -48, -50, -52, -54, -55,
541 -57, -59, -61, -62, -64, -66, -67, -69,
542 -71, -72, -74, -75, -77, -78, -80, -81,
543 -83, -84, -86, -87, -88, -90, -91, -92,
544 -93, -95, -96, -97, -98, -99, -100, -101,
545 -102, -103, -104, -105, -106, -106, -107, -108,
546 -109, -109, -110, -111, -111, -112, -112, -113,
547 -113, -114, -114, -114, -115, -115, -115, -115,
548 -116, -116, -116, -116, -116, -116, -116, -116,
549 -116, -115, -115, -115, -115, -114, -114, -114,
550 -113, -113, -112, -112, -111, -111, -110, -110,
551 -109, -108, -108, -107, -106, -105, -104, -103,
552 -102, -101, -100, -99, -98, -97, -96, -95,
553 -94, -93, -91, -90, -89, -88, -86, -85,
554 -84, -82, -81, -79, -78, -76, -75, -73,
555 -71, -70, -68, -67, -65, -63, -62, -60,
556 -58, -56, -55, -53, -51, -49, -47, -45,
557 -44, -42, -40, -38, -36, -34, -32, -30,
558 -28, -26, -24, -22, -20, -18, -16, -14,
559 -12, -10, -8, -6, -4, -2, 0, 1,
560 3, 5, 7, 9, 11, 13, 15, 17,
561 19, 21, 23, 25, 27, 29, 31, 33,
562 35, 37, 39, 41, 43, 45, 46, 48,
563 50, 52, 54, 55, 57, 59, 61, 62,
564 64, 66, 67, 69, 71, 72, 74, 75,
565 77, 78, 80, 81, 83, 84, 86, 87,
566 88, 90, 91, 92, 93, 95, 96, 97,
567 98, 99, 100, 101, 102, 103, 104, 105,
568 106, 106, 107, 108, 109, 109, 110, 111,
569 111, 112, 112, 113, 113, 114, 114, 114,
570 115, 115, 115, 115, 116, 116, 116, 116,
571 116, 116, 116, 116, 116, 115, 115, 115,
572 115, 114, 114, 114, 113, 113, 112, 112,
573 111, 111, 110, 110, 109, 108, 108, 107,
574 106, 105, 104, 103, 102, 101, 100, 99,
575 98, 97, 96, 95, 94, 93, 91, 90,
576 89, 88, 86, 85, 84, 82, 81, 79,
577 78, 76, 75, 73, 71, 70, 68, 67,
578 65, 63, 62, 60, 58, 56, 55, 53,
579 51, 49, 47, 45, 44, 42, 40, 38,
580 36, 34, 32, 30, 28, 26, 24, 22,
581 20, 18, 16, 14, 12, 10, 8, 6,
582 4, 2, 0, -1, -3, -5, -7, -9, -11
583};
584
585static const u16 i2c_ident[] = {
586 V4L2_IDENT_OV9650,
587 V4L2_IDENT_OV9655,
588 V4L2_IDENT_SOI968,
589 V4L2_IDENT_OV7660,
590 V4L2_IDENT_OV7670,
591 V4L2_IDENT_MT9V011,
592 V4L2_IDENT_MT9V111,
593 V4L2_IDENT_MT9V112,
594 V4L2_IDENT_MT9M001C12ST,
595 V4L2_IDENT_MT9M111,
596 V4L2_IDENT_MT9M112,
597 V4L2_IDENT_HV7131R,
598[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN,
599};
600
601static const u16 bridge_init[][2] = {
602 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
603 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
604 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
605 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
606 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
607 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
608 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
609 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
610 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
611 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
612 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
613 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
614 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
615 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
616 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
617 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
618 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
619 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
620 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
621 {0x1007, 0x00}
622};
623
624/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
625static const u8 ov_gain[] = {
626 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
627 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
628 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
629 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
630 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
631 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
632 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
633 0x70 /* 8x */
634};
635
636/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
637static const u16 micron1_gain[] = {
638 /* 1x 1.25x 1.5x 1.75x */
639 0x0020, 0x0028, 0x0030, 0x0038,
640 /* 2x 2.25x 2.5x 2.75x */
641 0x00a0, 0x00a4, 0x00a8, 0x00ac,
642 /* 3x 3.25x 3.5x 3.75x */
643 0x00b0, 0x00b4, 0x00b8, 0x00bc,
644 /* 4x 4.25x 4.5x 4.75x */
645 0x00c0, 0x00c4, 0x00c8, 0x00cc,
646 /* 5x 5.25x 5.5x 5.75x */
647 0x00d0, 0x00d4, 0x00d8, 0x00dc,
648 /* 6x 6.25x 6.5x 6.75x */
649 0x00e0, 0x00e4, 0x00e8, 0x00ec,
650 /* 7x 7.25x 7.5x 7.75x */
651 0x00f0, 0x00f4, 0x00f8, 0x00fc,
652 /* 8x */
653 0x01c0
654};
655
656/* mt9m001 sensor uses a different gain formula then other micron sensors */
657/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
658static const u16 micron2_gain[] = {
659 /* 1x 1.25x 1.5x 1.75x */
660 0x0008, 0x000a, 0x000c, 0x000e,
661 /* 2x 2.25x 2.5x 2.75x */
662 0x0010, 0x0012, 0x0014, 0x0016,
663 /* 3x 3.25x 3.5x 3.75x */
664 0x0018, 0x001a, 0x001c, 0x001e,
665 /* 4x 4.25x 4.5x 4.75x */
666 0x0020, 0x0051, 0x0052, 0x0053,
667 /* 5x 5.25x 5.5x 5.75x */
668 0x0054, 0x0055, 0x0056, 0x0057,
669 /* 6x 6.25x 6.5x 6.75x */
670 0x0058, 0x0059, 0x005a, 0x005b,
671 /* 7x 7.25x 7.5x 7.75x */
672 0x005c, 0x005d, 0x005e, 0x005f,
673 /* 8x */
674 0x0060
675};
676
677/* Gain = .5 + bit[7:0] / 16 */
678static const u8 hv7131r_gain[] = {
679 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
680 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
681 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
682 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
683 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
684 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
685 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
686 0x78 /* 8x */
687};
688
689static const struct i2c_reg_u8 soi968_init[] = {
690 {0x0c, 0x00}, {0x0f, 0x1f},
691 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
692 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
693 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
694 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
695 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
696 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
697 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
698 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
699 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
700 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
701};
702
703static const struct i2c_reg_u8 ov7660_init[] = {
704 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
705 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
706 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
707 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
708 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
709 {0x17, 0x10}, {0x18, 0x61},
710 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
711 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00},
712 {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50},
713};
714
715static const struct i2c_reg_u8 ov7670_init[] = {
716 {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
717 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
718 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
719 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
720 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
721 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
722 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
723 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
724 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
725 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
726 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
727 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
728 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
729 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
730 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
731 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
732 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
733 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
734 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
735 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
736 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
737 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
738 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
739 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
740 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
741 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
742 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
743 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
744 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
745 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
746 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
747 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
748 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
749 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
750 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
751 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
752 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
753 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
754 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
755 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
756 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
757 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
758 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
759 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
760 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
761 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
762 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
763 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
764 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
765 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
766 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
767 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
768 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
769 {0x93, 0x00},
770};
771
772static const struct i2c_reg_u8 ov9650_init[] = {
773 {0x00, 0x00}, {0x01, 0x78},
774 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
775 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
776 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
777 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
778 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
779 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
780 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
781 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
782 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
783 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
784 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
785 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
786 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
787 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
788 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
789 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
790 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
791 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
792 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
793 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
794 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
795 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
796 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
797 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
798 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
799 {0xaa, 0x92}, {0xab, 0x0a},
800};
801
802static const struct i2c_reg_u8 ov9655_init[] = {
803 {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
804 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
805 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
806 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
807 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
808 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
809 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
810 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
811 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
812 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
813 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
814 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
815 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
816 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
817 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
818 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
819 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
820 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
821 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
822 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
823 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
824 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
825 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
826 {0x04, 0x03}, {0x00, 0x13},
827};
828
829static const struct i2c_reg_u16 mt9v112_init[] = {
830 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
831 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
832 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
833 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
834 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
835 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
836 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
837 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
838 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
839 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
840 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
841 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
842 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
843 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
844 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
845 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
846};
847
848static const struct i2c_reg_u16 mt9v111_init[] = {
849 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
850 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
851 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
852 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
853 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
854 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
855 {0x0e, 0x0008}, {0x20, 0x0000}
856};
857
858static const struct i2c_reg_u16 mt9v011_init[] = {
859 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
860 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
861 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
862 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
863 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
864 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
865 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
866 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
867 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
868 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
869 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
870 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
871 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
872 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
873 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
874 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
875 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
876 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
877 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
878 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
879 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
880 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
881 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
882 {0x06, 0x0029}, {0x05, 0x0009},
883};
884
885static const struct i2c_reg_u16 mt9m001_init[] = {
886 {0x0d, 0x0001},
887 {0x0d, 0x0000},
888 {0x04, 0x0500}, /* hres = 1280 */
889 {0x03, 0x0400}, /* vres = 1024 */
890 {0x20, 0x1100},
891 {0x06, 0x0010},
892 {0x2b, 0x0024},
893 {0x2e, 0x0024},
894 {0x35, 0x0024},
895 {0x2d, 0x0020},
896 {0x2c, 0x0020},
897 {0x09, 0x0ad4},
898 {0x35, 0x0057},
899};
900
901static const struct i2c_reg_u16 mt9m111_init[] = {
902 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
903 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
904 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
905 {0xf0, 0x0000},
906};
907
908static const struct i2c_reg_u16 mt9m112_init[] = {
909 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
910 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
911 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
912 {0xf0, 0x0000},
913};
914
915static const struct i2c_reg_u8 hv7131r_init[] = {
916 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
917 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
918 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
919 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
920 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
921 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
922 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
923 {0x23, 0x09}, {0x01, 0x08},
924};
925
926static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
927{
928 struct usb_device *dev = gspca_dev->dev;
929 int result;
930
931 if (gspca_dev->usb_err < 0)
932 return;
933 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
934 0x00,
935 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
936 reg,
937 0x00,
938 gspca_dev->usb_buf,
939 length,
940 500);
941 if (unlikely(result < 0 || result != length)) {
942 pr_err("Read register %02x failed %d\n", reg, result);
943 gspca_dev->usb_err = result;
944 }
945}
946
947static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
948 const u8 *buffer, int length)
949{
950 struct usb_device *dev = gspca_dev->dev;
951 int result;
952
953 if (gspca_dev->usb_err < 0)
954 return;
955 memcpy(gspca_dev->usb_buf, buffer, length);
956 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
957 0x08,
958 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
959 reg,
960 0x00,
961 gspca_dev->usb_buf,
962 length,
963 500);
964 if (unlikely(result < 0 || result != length)) {
965 pr_err("Write register %02x failed %d\n", reg, result);
966 gspca_dev->usb_err = result;
967 }
968}
969
970static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
971{
972 reg_w(gspca_dev, reg, &value, 1);
973}
974
975static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
976{
977 int i;
978
979 reg_w(gspca_dev, 0x10c0, buffer, 8);
980 for (i = 0; i < 5; i++) {
981 reg_r(gspca_dev, 0x10c0, 1);
982 if (gspca_dev->usb_err < 0)
983 return;
984 if (gspca_dev->usb_buf[0] & 0x04) {
985 if (gspca_dev->usb_buf[0] & 0x08) {
986 pr_err("i2c_w error\n");
987 gspca_dev->usb_err = -EIO;
988 }
989 return;
990 }
991 msleep(10);
992 }
993 pr_err("i2c_w reg %02x no response\n", buffer[2]);
994/* gspca_dev->usb_err = -EIO; fixme: may occur */
995}
996
997static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
998{
999 struct sd *sd = (struct sd *) gspca_dev;
1000 u8 row[8];
1001
1002 /*
1003 * from the point of view of the bridge, the length
1004 * includes the address
1005 */
1006 row[0] = sd->i2c_intf | (2 << 4);
1007 row[1] = sd->i2c_addr;
1008 row[2] = reg;
1009 row[3] = val;
1010 row[4] = 0x00;
1011 row[5] = 0x00;
1012 row[6] = 0x00;
1013 row[7] = 0x10;
1014
1015 i2c_w(gspca_dev, row);
1016}
1017
1018static void i2c_w1_buf(struct gspca_dev *gspca_dev,
1019 const struct i2c_reg_u8 *buf, int sz)
1020{
1021 while (--sz >= 0) {
1022 i2c_w1(gspca_dev, buf->reg, buf->val);
1023 buf++;
1024 }
1025}
1026
1027static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
1028{
1029 struct sd *sd = (struct sd *) gspca_dev;
1030 u8 row[8];
1031
1032 /*
1033 * from the point of view of the bridge, the length
1034 * includes the address
1035 */
1036 row[0] = sd->i2c_intf | (3 << 4);
1037 row[1] = sd->i2c_addr;
1038 row[2] = reg;
1039 row[3] = val >> 8;
1040 row[4] = val;
1041 row[5] = 0x00;
1042 row[6] = 0x00;
1043 row[7] = 0x10;
1044
1045 i2c_w(gspca_dev, row);
1046}
1047
1048static void i2c_w2_buf(struct gspca_dev *gspca_dev,
1049 const struct i2c_reg_u16 *buf, int sz)
1050{
1051 while (--sz >= 0) {
1052 i2c_w2(gspca_dev, buf->reg, buf->val);
1053 buf++;
1054 }
1055}
1056
1057static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
1058{
1059 struct sd *sd = (struct sd *) gspca_dev;
1060 u8 row[8];
1061
1062 row[0] = sd->i2c_intf | (1 << 4);
1063 row[1] = sd->i2c_addr;
1064 row[2] = reg;
1065 row[3] = 0;
1066 row[4] = 0;
1067 row[5] = 0;
1068 row[6] = 0;
1069 row[7] = 0x10;
1070 i2c_w(gspca_dev, row);
1071 row[0] = sd->i2c_intf | (1 << 4) | 0x02;
1072 row[2] = 0;
1073 i2c_w(gspca_dev, row);
1074 reg_r(gspca_dev, 0x10c2, 5);
1075 *val = gspca_dev->usb_buf[4];
1076}
1077
1078static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
1079{
1080 struct sd *sd = (struct sd *) gspca_dev;
1081 u8 row[8];
1082
1083 row[0] = sd->i2c_intf | (1 << 4);
1084 row[1] = sd->i2c_addr;
1085 row[2] = reg;
1086 row[3] = 0;
1087 row[4] = 0;
1088 row[5] = 0;
1089 row[6] = 0;
1090 row[7] = 0x10;
1091 i2c_w(gspca_dev, row);
1092 row[0] = sd->i2c_intf | (2 << 4) | 0x02;
1093 row[2] = 0;
1094 i2c_w(gspca_dev, row);
1095 reg_r(gspca_dev, 0x10c2, 5);
1096 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1097}
1098
1099static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
1100{
1101 u16 id;
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 i2c_r2(gspca_dev, 0x1c, &id);
1105 if (gspca_dev->usb_err < 0)
1106 return;
1107
1108 if (id != 0x7fa2) {
1109 pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
1110 gspca_dev->usb_err = -ENODEV;
1111 return;
1112 }
1113
1114 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1115 msleep(200);
1116 i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
1117 if (gspca_dev->usb_err < 0)
1118 pr_err("OV9650 sensor initialization failed\n");
1119 sd->hstart = 1;
1120 sd->vstart = 7;
1121}
1122
1123static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
1124{
1125 struct sd *sd = (struct sd *) gspca_dev;
1126
1127 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1128 msleep(200);
1129 i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
1130 if (gspca_dev->usb_err < 0)
1131 pr_err("OV9655 sensor initialization failed\n");
1132
1133 sd->hstart = 1;
1134 sd->vstart = 2;
1135}
1136
1137static void soi968_init_sensor(struct gspca_dev *gspca_dev)
1138{
1139 struct sd *sd = (struct sd *) gspca_dev;
1140
1141 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1142 msleep(200);
1143 i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
1144 if (gspca_dev->usb_err < 0)
1145 pr_err("SOI968 sensor initialization failed\n");
1146
1147 sd->hstart = 60;
1148 sd->vstart = 11;
1149}
1150
1151static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
1152{
1153 struct sd *sd = (struct sd *) gspca_dev;
1154
1155 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1156 msleep(200);
1157 i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
1158 if (gspca_dev->usb_err < 0)
1159 pr_err("OV7660 sensor initialization failed\n");
1160 sd->hstart = 3;
1161 sd->vstart = 3;
1162}
1163
1164static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
1165{
1166 struct sd *sd = (struct sd *) gspca_dev;
1167
1168 i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */
1169 msleep(200);
1170 i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
1171 if (gspca_dev->usb_err < 0)
1172 pr_err("OV7670 sensor initialization failed\n");
1173
1174 sd->hstart = 0;
1175 sd->vstart = 1;
1176}
1177
1178static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
1179{
1180 struct sd *sd = (struct sd *) gspca_dev;
1181 u16 value;
1182
1183 sd->i2c_addr = 0x5d;
1184 i2c_r2(gspca_dev, 0xff, &value);
1185 if (gspca_dev->usb_err >= 0
1186 && value == 0x8243) {
1187 i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
1188 if (gspca_dev->usb_err < 0) {
1189 pr_err("MT9V011 sensor initialization failed\n");
1190 return;
1191 }
1192 sd->hstart = 2;
1193 sd->vstart = 2;
1194 sd->sensor = SENSOR_MT9V011;
1195 pr_info("MT9V011 sensor detected\n");
1196 return;
1197 }
1198
1199 gspca_dev->usb_err = 0;
1200 sd->i2c_addr = 0x5c;
1201 i2c_w2(gspca_dev, 0x01, 0x0004);
1202 i2c_r2(gspca_dev, 0xff, &value);
1203 if (gspca_dev->usb_err >= 0
1204 && value == 0x823a) {
1205 i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
1206 if (gspca_dev->usb_err < 0) {
1207 pr_err("MT9V111 sensor initialization failed\n");
1208 return;
1209 }
1210 sd->hstart = 2;
1211 sd->vstart = 2;
1212 sd->sensor = SENSOR_MT9V111;
1213 pr_info("MT9V111 sensor detected\n");
1214 return;
1215 }
1216
1217 gspca_dev->usb_err = 0;
1218 sd->i2c_addr = 0x5d;
1219 i2c_w2(gspca_dev, 0xf0, 0x0000);
1220 if (gspca_dev->usb_err < 0) {
1221 gspca_dev->usb_err = 0;
1222 sd->i2c_addr = 0x48;
1223 i2c_w2(gspca_dev, 0xf0, 0x0000);
1224 }
1225 i2c_r2(gspca_dev, 0x00, &value);
1226 if (gspca_dev->usb_err >= 0
1227 && value == 0x1229) {
1228 i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
1229 if (gspca_dev->usb_err < 0) {
1230 pr_err("MT9V112 sensor initialization failed\n");
1231 return;
1232 }
1233 sd->hstart = 6;
1234 sd->vstart = 2;
1235 sd->sensor = SENSOR_MT9V112;
1236 pr_info("MT9V112 sensor detected\n");
1237 return;
1238 }
1239
1240 gspca_dev->usb_err = -ENODEV;
1241}
1242
1243static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1244{
1245 struct sd *sd = (struct sd *) gspca_dev;
1246
1247 i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
1248 if (gspca_dev->usb_err < 0)
1249 pr_err("MT9M112 sensor initialization failed\n");
1250
1251 sd->hstart = 0;
1252 sd->vstart = 2;
1253}
1254
1255static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1256{
1257 struct sd *sd = (struct sd *) gspca_dev;
1258
1259 i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
1260 if (gspca_dev->usb_err < 0)
1261 pr_err("MT9M111 sensor initialization failed\n");
1262
1263 sd->hstart = 0;
1264 sd->vstart = 2;
1265}
1266
1267static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1268{
1269 struct sd *sd = (struct sd *) gspca_dev;
1270 u16 id;
1271
1272 i2c_r2(gspca_dev, 0x00, &id);
1273 if (gspca_dev->usb_err < 0)
1274 return;
1275
1276 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1277 switch (id) {
1278 case 0x8411:
1279 case 0x8421:
1280 pr_info("MT9M001 color sensor detected\n");
1281 break;
1282 case 0x8431:
1283 pr_info("MT9M001 mono sensor detected\n");
1284 break;
1285 default:
1286 pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
1287 gspca_dev->usb_err = -ENODEV;
1288 return;
1289 }
1290
1291 i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
1292 if (gspca_dev->usb_err < 0)
1293 pr_err("MT9M001 sensor initialization failed\n");
1294
1295 sd->hstart = 1;
1296 sd->vstart = 1;
1297}
1298
1299static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1300{
1301 struct sd *sd = (struct sd *) gspca_dev;
1302
1303 i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
1304 if (gspca_dev->usb_err < 0)
1305 pr_err("HV7131R Sensor initialization failed\n");
1306
1307 sd->hstart = 0;
1308 sd->vstart = 1;
1309}
1310
1311static void set_cmatrix(struct gspca_dev *gspca_dev,
1312 s32 brightness, s32 contrast, s32 satur, s32 hue)
1313{
1314 s32 hue_coord, hue_index = 180 + hue;
1315 u8 cmatrix[21];
1316
1317 memset(cmatrix, 0, sizeof cmatrix);
1318 cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26;
1319 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1320 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1321 cmatrix[18] = brightness - 0x80;
1322
1323 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
1324 cmatrix[6] = hue_coord;
1325 cmatrix[7] = (hue_coord >> 8) & 0x0f;
1326
1327 hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
1328 cmatrix[8] = hue_coord;
1329 cmatrix[9] = (hue_coord >> 8) & 0x0f;
1330
1331 hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
1332 cmatrix[10] = hue_coord;
1333 cmatrix[11] = (hue_coord >> 8) & 0x0f;
1334
1335 hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
1336 cmatrix[12] = hue_coord;
1337 cmatrix[13] = (hue_coord >> 8) & 0x0f;
1338
1339 hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
1340 cmatrix[14] = hue_coord;
1341 cmatrix[15] = (hue_coord >> 8) & 0x0f;
1342
1343 hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
1344 cmatrix[16] = hue_coord;
1345 cmatrix[17] = (hue_coord >> 8) & 0x0f;
1346
1347 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1348}
1349
1350static void set_gamma(struct gspca_dev *gspca_dev, s32 val)
1351{
1352 u8 gamma[17];
1353 u8 gval = val * 0xb8 / 0x100;
1354
1355 gamma[0] = 0x0a;
1356 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1357 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1358 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1359 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1360 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1361 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1362 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1363 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1364 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1365 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1366 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1367 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1368 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1369 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1370 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1371 gamma[16] = 0xf5;
1372
1373 reg_w(gspca_dev, 0x1190, gamma, 17);
1374}
1375
1376static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red)
1377{
1378 reg_w1(gspca_dev, 0x118c, red);
1379 reg_w1(gspca_dev, 0x118f, blue);
1380}
1381
1382static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
1383{
1384 u8 value, tslb;
1385 u16 value2;
1386 struct sd *sd = (struct sd *) gspca_dev;
1387
1388 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1389 hflip = !hflip;
1390 vflip = !vflip;
1391 }
1392
1393 switch (sd->sensor) {
1394 case SENSOR_OV7660:
1395 value = 0x01;
1396 if (hflip)
1397 value |= 0x20;
1398 if (vflip) {
1399 value |= 0x10;
1400 sd->vstart = 2;
1401 } else {
1402 sd->vstart = 3;
1403 }
1404 reg_w1(gspca_dev, 0x1182, sd->vstart);
1405 i2c_w1(gspca_dev, 0x1e, value);
1406 break;
1407 case SENSOR_OV9650:
1408 i2c_r1(gspca_dev, 0x1e, &value);
1409 value &= ~0x30;
1410 tslb = 0x01;
1411 if (hflip)
1412 value |= 0x20;
1413 if (vflip) {
1414 value |= 0x10;
1415 tslb = 0x49;
1416 }
1417 i2c_w1(gspca_dev, 0x1e, value);
1418 i2c_w1(gspca_dev, 0x3a, tslb);
1419 break;
1420 case SENSOR_MT9V111:
1421 case SENSOR_MT9V011:
1422 i2c_r2(gspca_dev, 0x20, &value2);
1423 value2 &= ~0xc0a0;
1424 if (hflip)
1425 value2 |= 0x8080;
1426 if (vflip)
1427 value2 |= 0x4020;
1428 i2c_w2(gspca_dev, 0x20, value2);
1429 break;
1430 case SENSOR_MT9M112:
1431 case SENSOR_MT9M111:
1432 case SENSOR_MT9V112:
1433 i2c_r2(gspca_dev, 0x20, &value2);
1434 value2 &= ~0x0003;
1435 if (hflip)
1436 value2 |= 0x0002;
1437 if (vflip)
1438 value2 |= 0x0001;
1439 i2c_w2(gspca_dev, 0x20, value2);
1440 break;
1441 case SENSOR_HV7131R:
1442 i2c_r1(gspca_dev, 0x01, &value);
1443 value &= ~0x03;
1444 if (vflip)
1445 value |= 0x01;
1446 if (hflip)
1447 value |= 0x02;
1448 i2c_w1(gspca_dev, 0x01, value);
1449 break;
1450 }
1451}
1452
1453static void set_exposure(struct gspca_dev *gspca_dev, s32 expo)
1454{
1455 struct sd *sd = (struct sd *) gspca_dev;
1456 u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
1457 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
1458 int expo2;
1459
1460 if (gspca_dev->streaming)
1461 exp[7] = 0x1e;
1462
1463 switch (sd->sensor) {
1464 case SENSOR_OV7660:
1465 case SENSOR_OV7670:
1466 case SENSOR_OV9655:
1467 case SENSOR_OV9650:
1468 if (expo > 547)
1469 expo2 = 547;
1470 else
1471 expo2 = expo;
1472 exp[0] |= (2 << 4);
1473 exp[2] = 0x10; /* AECH */
1474 exp[3] = expo2 >> 2;
1475 exp[7] = 0x10;
1476 i2c_w(gspca_dev, exp);
1477 exp[2] = 0x04; /* COM1 */
1478 exp[3] = expo2 & 0x0003;
1479 exp[7] = 0x10;
1480 i2c_w(gspca_dev, exp);
1481 expo -= expo2;
1482 exp[7] = 0x1e;
1483 exp[0] |= (3 << 4);
1484 exp[2] = 0x2d; /* ADVFL & ADVFH */
1485 exp[3] = expo;
1486 exp[4] = expo >> 8;
1487 break;
1488 case SENSOR_MT9M001:
1489 case SENSOR_MT9V112:
1490 case SENSOR_MT9V011:
1491 exp[0] |= (3 << 4);
1492 exp[2] = 0x09;
1493 exp[3] = expo >> 8;
1494 exp[4] = expo;
1495 break;
1496 case SENSOR_HV7131R:
1497 exp[0] |= (4 << 4);
1498 exp[2] = 0x25;
1499 exp[3] = expo >> 5;
1500 exp[4] = expo << 3;
1501 exp[5] = 0;
1502 break;
1503 default:
1504 return;
1505 }
1506 i2c_w(gspca_dev, exp);
1507}
1508
1509static void set_gain(struct gspca_dev *gspca_dev, s32 g)
1510{
1511 struct sd *sd = (struct sd *) gspca_dev;
1512 u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
1513 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
1514
1515 if (gspca_dev->streaming)
1516 gain[7] = 0x15; /* or 1d ? */
1517
1518 switch (sd->sensor) {
1519 case SENSOR_OV7660:
1520 case SENSOR_OV7670:
1521 case SENSOR_SOI968:
1522 case SENSOR_OV9655:
1523 case SENSOR_OV9650:
1524 gain[0] |= (2 << 4);
1525 gain[3] = ov_gain[g];
1526 break;
1527 case SENSOR_MT9V011:
1528 gain[0] |= (3 << 4);
1529 gain[2] = 0x35;
1530 gain[3] = micron1_gain[g] >> 8;
1531 gain[4] = micron1_gain[g];
1532 break;
1533 case SENSOR_MT9V112:
1534 gain[0] |= (3 << 4);
1535 gain[2] = 0x2f;
1536 gain[3] = micron1_gain[g] >> 8;
1537 gain[4] = micron1_gain[g];
1538 break;
1539 case SENSOR_MT9M001:
1540 gain[0] |= (3 << 4);
1541 gain[2] = 0x2f;
1542 gain[3] = micron2_gain[g] >> 8;
1543 gain[4] = micron2_gain[g];
1544 break;
1545 case SENSOR_HV7131R:
1546 gain[0] |= (2 << 4);
1547 gain[2] = 0x30;
1548 gain[3] = hv7131r_gain[g];
1549 break;
1550 default:
1551 return;
1552 }
1553 i2c_w(gspca_dev, gain);
1554}
1555
1556static void set_quality(struct gspca_dev *gspca_dev, s32 val)
1557{
1558 struct sd *sd = (struct sd *) gspca_dev;
1559
1560 jpeg_set_qual(sd->jpeg_hdr, val);
1561 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1562 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1563 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
1564 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
1565 reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */
1566 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1567 sd->fmt ^= 0x0c; /* invert QTAB use + write */
1568 reg_w1(gspca_dev, 0x10e0, sd->fmt);
1569}
1570
1571#ifdef CONFIG_VIDEO_ADV_DEBUG
1572static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1573 struct v4l2_dbg_register *reg)
1574{
1575 struct sd *sd = (struct sd *) gspca_dev;
1576
1577 switch (reg->match.type) {
1578 case V4L2_CHIP_MATCH_HOST:
1579 if (reg->match.addr != 0)
1580 return -EINVAL;
1581 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1582 return -EINVAL;
1583 reg_r(gspca_dev, reg->reg, 1);
1584 reg->val = gspca_dev->usb_buf[0];
1585 return gspca_dev->usb_err;
1586 case V4L2_CHIP_MATCH_I2C_ADDR:
1587 if (reg->match.addr != sd->i2c_addr)
1588 return -EINVAL;
1589 if (sd->sensor >= SENSOR_MT9V011 &&
1590 sd->sensor <= SENSOR_MT9M112) {
1591 i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
1592 } else {
1593 i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
1594 }
1595 return gspca_dev->usb_err;
1596 }
1597 return -EINVAL;
1598}
1599
1600static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1601 struct v4l2_dbg_register *reg)
1602{
1603 struct sd *sd = (struct sd *) gspca_dev;
1604
1605 switch (reg->match.type) {
1606 case V4L2_CHIP_MATCH_HOST:
1607 if (reg->match.addr != 0)
1608 return -EINVAL;
1609 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1610 return -EINVAL;
1611 reg_w1(gspca_dev, reg->reg, reg->val);
1612 return gspca_dev->usb_err;
1613 case V4L2_CHIP_MATCH_I2C_ADDR:
1614 if (reg->match.addr != sd->i2c_addr)
1615 return -EINVAL;
1616 if (sd->sensor >= SENSOR_MT9V011 &&
1617 sd->sensor <= SENSOR_MT9M112) {
1618 i2c_w2(gspca_dev, reg->reg, reg->val);
1619 } else {
1620 i2c_w1(gspca_dev, reg->reg, reg->val);
1621 }
1622 return gspca_dev->usb_err;
1623 }
1624 return -EINVAL;
1625}
1626#endif
1627
1628static int sd_chip_ident(struct gspca_dev *gspca_dev,
1629 struct v4l2_dbg_chip_ident *chip)
1630{
1631 struct sd *sd = (struct sd *) gspca_dev;
1632
1633 switch (chip->match.type) {
1634 case V4L2_CHIP_MATCH_HOST:
1635 if (chip->match.addr != 0)
1636 return -EINVAL;
1637 chip->revision = 0;
1638 chip->ident = V4L2_IDENT_SN9C20X;
1639 return 0;
1640 case V4L2_CHIP_MATCH_I2C_ADDR:
1641 if (chip->match.addr != sd->i2c_addr)
1642 return -EINVAL;
1643 chip->revision = 0;
1644 chip->ident = i2c_ident[sd->sensor];
1645 return 0;
1646 }
1647 return -EINVAL;
1648}
1649
1650static int sd_config(struct gspca_dev *gspca_dev,
1651 const struct usb_device_id *id)
1652{
1653 struct sd *sd = (struct sd *) gspca_dev;
1654 struct cam *cam;
1655
1656 cam = &gspca_dev->cam;
1657 cam->needs_full_bandwidth = 1;
1658
1659 sd->sensor = id->driver_info >> 8;
1660 sd->i2c_addr = id->driver_info;
1661 sd->flags = id->driver_info >> 16;
1662 sd->i2c_intf = 0x80; /* i2c 100 Kb/s */
1663
1664 switch (sd->sensor) {
1665 case SENSOR_MT9M112:
1666 case SENSOR_MT9M111:
1667 case SENSOR_OV9650:
1668 case SENSOR_SOI968:
1669 cam->cam_mode = sxga_mode;
1670 cam->nmodes = ARRAY_SIZE(sxga_mode);
1671 break;
1672 case SENSOR_MT9M001:
1673 cam->cam_mode = mono_mode;
1674 cam->nmodes = ARRAY_SIZE(mono_mode);
1675 break;
1676 case SENSOR_HV7131R:
1677 sd->i2c_intf = 0x81; /* i2c 400 Kb/s */
1678 /* fall thru */
1679 default:
1680 cam->cam_mode = vga_mode;
1681 cam->nmodes = ARRAY_SIZE(vga_mode);
1682 break;
1683 }
1684
1685 sd->old_step = 0;
1686 sd->older_step = 0;
1687 sd->exposure_step = 16;
1688
1689 INIT_WORK(&sd->work, qual_upd);
1690
1691 return 0;
1692}
1693
1694static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1695{
1696 struct gspca_dev *gspca_dev =
1697 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1698 struct sd *sd = (struct sd *)gspca_dev;
1699
1700 gspca_dev->usb_err = 0;
1701
1702 if (!gspca_dev->streaming)
1703 return 0;
1704
1705 switch (ctrl->id) {
1706 /* color control cluster */
1707 case V4L2_CID_BRIGHTNESS:
1708 set_cmatrix(gspca_dev, sd->brightness->val,
1709 sd->contrast->val, sd->saturation->val, sd->hue->val);
1710 break;
1711 case V4L2_CID_GAMMA:
1712 set_gamma(gspca_dev, ctrl->val);
1713 break;
1714 /* blue/red balance cluster */
1715 case V4L2_CID_BLUE_BALANCE:
1716 set_redblue(gspca_dev, sd->blue->val, sd->red->val);
1717 break;
1718 /* h/vflip cluster */
1719 case V4L2_CID_HFLIP:
1720 set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
1721 break;
1722 /* standalone exposure control */
1723 case V4L2_CID_EXPOSURE:
1724 set_exposure(gspca_dev, ctrl->val);
1725 break;
1726 /* standalone gain control */
1727 case V4L2_CID_GAIN:
1728 set_gain(gspca_dev, ctrl->val);
1729 break;
1730 /* autogain + exposure or gain control cluster */
1731 case V4L2_CID_AUTOGAIN:
1732 if (sd->sensor == SENSOR_SOI968)
1733 set_gain(gspca_dev, sd->gain->val);
1734 else
1735 set_exposure(gspca_dev, sd->exposure->val);
1736 break;
1737 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
1738 set_quality(gspca_dev, ctrl->val);
1739 break;
1740 }
1741 return gspca_dev->usb_err;
1742}
1743
1744static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1745 .s_ctrl = sd_s_ctrl,
1746};
1747
1748static int sd_init_controls(struct gspca_dev *gspca_dev)
1749{
1750 struct sd *sd = (struct sd *) gspca_dev;
1751 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1752
1753 gspca_dev->vdev.ctrl_handler = hdl;
1754 v4l2_ctrl_handler_init(hdl, 13);
1755
1756 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1757 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1758 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1759 V4L2_CID_CONTRAST, 0, 255, 1, 127);
1760 sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1761 V4L2_CID_SATURATION, 0, 255, 1, 127);
1762 sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1763 V4L2_CID_HUE, -180, 180, 1, 0);
1764
1765 sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1766 V4L2_CID_GAMMA, 0, 255, 1, 0x10);
1767
1768 sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1769 V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28);
1770 sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1771 V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28);
1772
1773 if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
1774 sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
1775 sd->sensor != SENSOR_MT9VPRB) {
1776 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1777 V4L2_CID_HFLIP, 0, 1, 1, 0);
1778 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1779 V4L2_CID_VFLIP, 0, 1, 1, 0);
1780 }
1781
1782 if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
1783 sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
1784 sd->sensor != SENSOR_MT9V111)
1785 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1786 V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33);
1787
1788 if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
1789 sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
1790 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1791 V4L2_CID_GAIN, 0, 28, 1, 0);
1792 sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1793 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1794 }
1795
1796 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1797 V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80);
1798 if (hdl->error) {
1799 pr_err("Could not initialize controls\n");
1800 return hdl->error;
1801 }
1802
1803 v4l2_ctrl_cluster(4, &sd->brightness);
1804 v4l2_ctrl_cluster(2, &sd->blue);
1805 if (sd->hflip)
1806 v4l2_ctrl_cluster(2, &sd->hflip);
1807 if (sd->autogain) {
1808 if (sd->sensor == SENSOR_SOI968)
1809 /* this sensor doesn't have the exposure control and
1810 autogain is clustered with gain instead. This works
1811 because sd->exposure == NULL. */
1812 v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false);
1813 else
1814 /* Otherwise autogain is clustered with exposure. */
1815 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
1816 }
1817 return 0;
1818}
1819
1820static int sd_init(struct gspca_dev *gspca_dev)
1821{
1822 struct sd *sd = (struct sd *) gspca_dev;
1823 int i;
1824 u8 value;
1825 u8 i2c_init[9] =
1826 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
1827
1828 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
1829 value = bridge_init[i][1];
1830 reg_w(gspca_dev, bridge_init[i][0], &value, 1);
1831 if (gspca_dev->usb_err < 0) {
1832 pr_err("Device initialization failed\n");
1833 return gspca_dev->usb_err;
1834 }
1835 }
1836
1837 if (sd->flags & LED_REVERSE)
1838 reg_w1(gspca_dev, 0x1006, 0x00);
1839 else
1840 reg_w1(gspca_dev, 0x1006, 0x20);
1841
1842 reg_w(gspca_dev, 0x10c0, i2c_init, 9);
1843 if (gspca_dev->usb_err < 0) {
1844 pr_err("Device initialization failed\n");
1845 return gspca_dev->usb_err;
1846 }
1847
1848 switch (sd->sensor) {
1849 case SENSOR_OV9650:
1850 ov9650_init_sensor(gspca_dev);
1851 if (gspca_dev->usb_err < 0)
1852 break;
1853 pr_info("OV9650 sensor detected\n");
1854 break;
1855 case SENSOR_OV9655:
1856 ov9655_init_sensor(gspca_dev);
1857 if (gspca_dev->usb_err < 0)
1858 break;
1859 pr_info("OV9655 sensor detected\n");
1860 break;
1861 case SENSOR_SOI968:
1862 soi968_init_sensor(gspca_dev);
1863 if (gspca_dev->usb_err < 0)
1864 break;
1865 pr_info("SOI968 sensor detected\n");
1866 break;
1867 case SENSOR_OV7660:
1868 ov7660_init_sensor(gspca_dev);
1869 if (gspca_dev->usb_err < 0)
1870 break;
1871 pr_info("OV7660 sensor detected\n");
1872 break;
1873 case SENSOR_OV7670:
1874 ov7670_init_sensor(gspca_dev);
1875 if (gspca_dev->usb_err < 0)
1876 break;
1877 pr_info("OV7670 sensor detected\n");
1878 break;
1879 case SENSOR_MT9VPRB:
1880 mt9v_init_sensor(gspca_dev);
1881 if (gspca_dev->usb_err < 0)
1882 break;
1883 pr_info("MT9VPRB sensor detected\n");
1884 break;
1885 case SENSOR_MT9M111:
1886 mt9m111_init_sensor(gspca_dev);
1887 if (gspca_dev->usb_err < 0)
1888 break;
1889 pr_info("MT9M111 sensor detected\n");
1890 break;
1891 case SENSOR_MT9M112:
1892 mt9m112_init_sensor(gspca_dev);
1893 if (gspca_dev->usb_err < 0)
1894 break;
1895 pr_info("MT9M112 sensor detected\n");
1896 break;
1897 case SENSOR_MT9M001:
1898 mt9m001_init_sensor(gspca_dev);
1899 if (gspca_dev->usb_err < 0)
1900 break;
1901 break;
1902 case SENSOR_HV7131R:
1903 hv7131r_init_sensor(gspca_dev);
1904 if (gspca_dev->usb_err < 0)
1905 break;
1906 pr_info("HV7131R sensor detected\n");
1907 break;
1908 default:
1909 pr_err("Unsupported sensor\n");
1910 gspca_dev->usb_err = -ENODEV;
1911 }
1912 return gspca_dev->usb_err;
1913}
1914
1915static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
1916{
1917 struct sd *sd = (struct sd *) gspca_dev;
1918 u8 value;
1919
1920 switch (sd->sensor) {
1921 case SENSOR_SOI968:
1922 if (mode & MODE_SXGA) {
1923 i2c_w1(gspca_dev, 0x17, 0x1d);
1924 i2c_w1(gspca_dev, 0x18, 0xbd);
1925 i2c_w1(gspca_dev, 0x19, 0x01);
1926 i2c_w1(gspca_dev, 0x1a, 0x81);
1927 i2c_w1(gspca_dev, 0x12, 0x00);
1928 sd->hstart = 140;
1929 sd->vstart = 19;
1930 } else {
1931 i2c_w1(gspca_dev, 0x17, 0x13);
1932 i2c_w1(gspca_dev, 0x18, 0x63);
1933 i2c_w1(gspca_dev, 0x19, 0x01);
1934 i2c_w1(gspca_dev, 0x1a, 0x79);
1935 i2c_w1(gspca_dev, 0x12, 0x40);
1936 sd->hstart = 60;
1937 sd->vstart = 11;
1938 }
1939 break;
1940 case SENSOR_OV9650:
1941 if (mode & MODE_SXGA) {
1942 i2c_w1(gspca_dev, 0x17, 0x1b);
1943 i2c_w1(gspca_dev, 0x18, 0xbc);
1944 i2c_w1(gspca_dev, 0x19, 0x01);
1945 i2c_w1(gspca_dev, 0x1a, 0x82);
1946 i2c_r1(gspca_dev, 0x12, &value);
1947 i2c_w1(gspca_dev, 0x12, value & 0x07);
1948 } else {
1949 i2c_w1(gspca_dev, 0x17, 0x24);
1950 i2c_w1(gspca_dev, 0x18, 0xc5);
1951 i2c_w1(gspca_dev, 0x19, 0x00);
1952 i2c_w1(gspca_dev, 0x1a, 0x3c);
1953 i2c_r1(gspca_dev, 0x12, &value);
1954 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
1955 }
1956 break;
1957 case SENSOR_MT9M112:
1958 case SENSOR_MT9M111:
1959 if (mode & MODE_SXGA) {
1960 i2c_w2(gspca_dev, 0xf0, 0x0002);
1961 i2c_w2(gspca_dev, 0xc8, 0x970b);
1962 i2c_w2(gspca_dev, 0xf0, 0x0000);
1963 } else {
1964 i2c_w2(gspca_dev, 0xf0, 0x0002);
1965 i2c_w2(gspca_dev, 0xc8, 0x8000);
1966 i2c_w2(gspca_dev, 0xf0, 0x0000);
1967 }
1968 break;
1969 }
1970}
1971
1972static int sd_isoc_init(struct gspca_dev *gspca_dev)
1973{
1974 struct usb_interface *intf;
1975 u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
1976
1977 /*
1978 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
1979 * than our regular bandwidth calculations reserve, so we force the
1980 * use of a specific altsetting when using the SN9C20X_I420 fmt.
1981 */
1982 if (!(flags & (MODE_RAW | MODE_JPEG))) {
1983 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
1984
1985 if (intf->num_altsetting != 9) {
1986 pr_warn("sn9c20x camera with unknown number of alt "
1987 "settings (%d), please report!\n",
1988 intf->num_altsetting);
1989 gspca_dev->alt = intf->num_altsetting;
1990 return 0;
1991 }
1992
1993 switch (gspca_dev->width) {
1994 case 160: /* 160x120 */
1995 gspca_dev->alt = 2;
1996 break;
1997 case 320: /* 320x240 */
1998 gspca_dev->alt = 6;
1999 break;
2000 default: /* >= 640x480 */
2001 gspca_dev->alt = 9;
2002 break;
2003 }
2004 }
2005
2006 return 0;
2007}
2008
2009#define HW_WIN(mode, hstart, vstart) \
2010((const u8 []){hstart, 0, vstart, 0, \
2011(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2012(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2013
2014#define CLR_WIN(width, height) \
2015((const u8 [])\
2016{0, width >> 2, 0, height >> 1,\
2017((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2018
2019static int sd_start(struct gspca_dev *gspca_dev)
2020{
2021 struct sd *sd = (struct sd *) gspca_dev;
2022 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2023 int width = gspca_dev->width;
2024 int height = gspca_dev->height;
2025 u8 fmt, scale = 0;
2026
2027 jpeg_define(sd->jpeg_hdr, height, width,
2028 0x21);
2029 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
2030
2031 if (mode & MODE_RAW)
2032 fmt = 0x2d;
2033 else if (mode & MODE_JPEG)
2034 fmt = 0x24;
2035 else
2036 fmt = 0x2f; /* YUV 420 */
2037 sd->fmt = fmt;
2038
2039 switch (mode & SCALE_MASK) {
2040 case SCALE_1280x1024:
2041 scale = 0xc0;
2042 pr_info("Set 1280x1024\n");
2043 break;
2044 case SCALE_640x480:
2045 scale = 0x80;
2046 pr_info("Set 640x480\n");
2047 break;
2048 case SCALE_320x240:
2049 scale = 0x90;
2050 pr_info("Set 320x240\n");
2051 break;
2052 case SCALE_160x120:
2053 scale = 0xa0;
2054 pr_info("Set 160x120\n");
2055 break;
2056 }
2057
2058 configure_sensor_output(gspca_dev, mode);
2059 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2060 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
2061 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2062 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2063 reg_w1(gspca_dev, 0x1189, scale);
2064 reg_w1(gspca_dev, 0x10e0, fmt);
2065
2066 set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
2067 v4l2_ctrl_g_ctrl(sd->contrast),
2068 v4l2_ctrl_g_ctrl(sd->saturation),
2069 v4l2_ctrl_g_ctrl(sd->hue));
2070 set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
2071 set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
2072 v4l2_ctrl_g_ctrl(sd->red));
2073 if (sd->gain)
2074 set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
2075 if (sd->exposure)
2076 set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
2077 if (sd->hflip)
2078 set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
2079 v4l2_ctrl_g_ctrl(sd->vflip));
2080
2081 reg_w1(gspca_dev, 0x1007, 0x20);
2082 reg_w1(gspca_dev, 0x1061, 0x03);
2083
2084 /* if JPEG, prepare the compression quality update */
2085 if (mode & MODE_JPEG) {
2086 sd->pktsz = sd->npkt = 0;
2087 sd->nchg = 0;
2088 sd->work_thread =
2089 create_singlethread_workqueue(KBUILD_MODNAME);
2090 }
2091
2092 return gspca_dev->usb_err;
2093}
2094
2095static void sd_stopN(struct gspca_dev *gspca_dev)
2096{
2097 reg_w1(gspca_dev, 0x1007, 0x00);
2098 reg_w1(gspca_dev, 0x1061, 0x01);
2099}
2100
2101/* called on streamoff with alt==0 and on disconnect */
2102/* the usb_lock is held at entry - restore on exit */
2103static void sd_stop0(struct gspca_dev *gspca_dev)
2104{
2105 struct sd *sd = (struct sd *) gspca_dev;
2106
2107 if (sd->work_thread != NULL) {
2108 mutex_unlock(&gspca_dev->usb_lock);
2109 destroy_workqueue(sd->work_thread);
2110 mutex_lock(&gspca_dev->usb_lock);
2111 sd->work_thread = NULL;
2112 }
2113}
2114
2115static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
2116{
2117 struct sd *sd = (struct sd *) gspca_dev;
2118 s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
2119 s32 max = sd->exposure->maximum - sd->exposure_step;
2120 s32 min = sd->exposure->minimum + sd->exposure_step;
2121 s16 new_exp;
2122
2123 /*
2124 * some hardcoded values are present
2125 * like those for maximal/minimal exposure
2126 * and exposure steps
2127 */
2128 if (avg_lum < MIN_AVG_LUM) {
2129 if (cur_exp > max)
2130 return;
2131
2132 new_exp = cur_exp + sd->exposure_step;
2133 if (new_exp > max)
2134 new_exp = max;
2135 if (new_exp < min)
2136 new_exp = min;
2137 v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
2138
2139 sd->older_step = sd->old_step;
2140 sd->old_step = 1;
2141
2142 if (sd->old_step ^ sd->older_step)
2143 sd->exposure_step /= 2;
2144 else
2145 sd->exposure_step += 2;
2146 }
2147 if (avg_lum > MAX_AVG_LUM) {
2148 if (cur_exp < min)
2149 return;
2150 new_exp = cur_exp - sd->exposure_step;
2151 if (new_exp > max)
2152 new_exp = max;
2153 if (new_exp < min)
2154 new_exp = min;
2155 v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
2156 sd->older_step = sd->old_step;
2157 sd->old_step = 0;
2158
2159 if (sd->old_step ^ sd->older_step)
2160 sd->exposure_step /= 2;
2161 else
2162 sd->exposure_step += 2;
2163 }
2164}
2165
2166static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2167{
2168 struct sd *sd = (struct sd *) gspca_dev;
2169 s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
2170
2171 if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
2172 v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1);
2173 if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
2174 v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1);
2175}
2176
2177static void sd_dqcallback(struct gspca_dev *gspca_dev)
2178{
2179 struct sd *sd = (struct sd *) gspca_dev;
2180 int avg_lum;
2181
2182 if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
2183 return;
2184
2185 avg_lum = atomic_read(&sd->avg_lum);
2186 if (sd->sensor == SENSOR_SOI968)
2187 do_autogain(gspca_dev, avg_lum);
2188 else
2189 do_autoexposure(gspca_dev, avg_lum);
2190}
2191
2192/* JPEG quality update */
2193/* This function is executed from a work queue. */
2194static void qual_upd(struct work_struct *work)
2195{
2196 struct sd *sd = container_of(work, struct sd, work);
2197 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2198 s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
2199
2200 mutex_lock(&gspca_dev->usb_lock);
2201 PDEBUG(D_STREAM, "qual_upd %d%%", qual);
2202 set_quality(gspca_dev, qual);
2203 mutex_unlock(&gspca_dev->usb_lock);
2204}
2205
2206#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2207static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2208 u8 *data, /* interrupt packet */
2209 int len) /* interrupt packet length */
2210{
2211 struct sd *sd = (struct sd *) gspca_dev;
2212
2213 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
2214 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2215 input_sync(gspca_dev->input_dev);
2216 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2217 input_sync(gspca_dev->input_dev);
2218 return 0;
2219 }
2220 return -EINVAL;
2221}
2222#endif
2223
2224/* check the JPEG compression */
2225static void transfer_check(struct gspca_dev *gspca_dev,
2226 u8 *data)
2227{
2228 struct sd *sd = (struct sd *) gspca_dev;
2229 int new_qual, r;
2230
2231 new_qual = 0;
2232
2233 /* if USB error, discard the frame and decrease the quality */
2234 if (data[6] & 0x08) { /* USB FIFO full */
2235 gspca_dev->last_packet_type = DISCARD_PACKET;
2236 new_qual = -5;
2237 } else {
2238
2239 /* else, compute the filling rate and a new JPEG quality */
2240 r = (sd->pktsz * 100) /
2241 (sd->npkt *
2242 gspca_dev->urb[0]->iso_frame_desc[0].length);
2243 if (r >= 85)
2244 new_qual = -3;
2245 else if (r < 75)
2246 new_qual = 2;
2247 }
2248 if (new_qual != 0) {
2249 sd->nchg += new_qual;
2250 if (sd->nchg < -6 || sd->nchg >= 12) {
2251 /* Note: we are in interrupt context, so we can't
2252 use v4l2_ctrl_g/s_ctrl here. Access the value
2253 directly instead. */
2254 s32 curqual = sd->jpegqual->cur.val;
2255 sd->nchg = 0;
2256 new_qual += curqual;
2257 if (new_qual < sd->jpegqual->minimum)
2258 new_qual = sd->jpegqual->minimum;
2259 else if (new_qual > sd->jpegqual->maximum)
2260 new_qual = sd->jpegqual->maximum;
2261 if (new_qual != curqual) {
2262 sd->jpegqual->cur.val = new_qual;
2263 queue_work(sd->work_thread, &sd->work);
2264 }
2265 }
2266 } else {
2267 sd->nchg = 0;
2268 }
2269 sd->pktsz = sd->npkt = 0;
2270}
2271
2272static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2273 u8 *data, /* isoc packet */
2274 int len) /* iso packet length */
2275{
2276 struct sd *sd = (struct sd *) gspca_dev;
2277 int avg_lum, is_jpeg;
2278 static const u8 frame_header[] =
2279 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2280
2281 is_jpeg = (sd->fmt & 0x03) == 0;
2282 if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
2283 avg_lum = ((data[35] >> 2) & 3) |
2284 (data[20] << 2) |
2285 (data[19] << 10);
2286 avg_lum += ((data[35] >> 4) & 3) |
2287 (data[22] << 2) |
2288 (data[21] << 10);
2289 avg_lum += ((data[35] >> 6) & 3) |
2290 (data[24] << 2) |
2291 (data[23] << 10);
2292 avg_lum += (data[36] & 3) |
2293 (data[26] << 2) |
2294 (data[25] << 10);
2295 avg_lum += ((data[36] >> 2) & 3) |
2296 (data[28] << 2) |
2297 (data[27] << 10);
2298 avg_lum += ((data[36] >> 4) & 3) |
2299 (data[30] << 2) |
2300 (data[29] << 10);
2301 avg_lum += ((data[36] >> 6) & 3) |
2302 (data[32] << 2) |
2303 (data[31] << 10);
2304 avg_lum += ((data[44] >> 4) & 3) |
2305 (data[34] << 2) |
2306 (data[33] << 10);
2307 avg_lum >>= 9;
2308 atomic_set(&sd->avg_lum, avg_lum);
2309
2310 if (is_jpeg)
2311 transfer_check(gspca_dev, data);
2312
2313 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
2314 len -= 64;
2315 if (len == 0)
2316 return;
2317 data += 64;
2318 }
2319 if (gspca_dev->last_packet_type == LAST_PACKET) {
2320 if (is_jpeg) {
2321 gspca_frame_add(gspca_dev, FIRST_PACKET,
2322 sd->jpeg_hdr, JPEG_HDR_SZ);
2323 gspca_frame_add(gspca_dev, INTER_PACKET,
2324 data, len);
2325 } else {
2326 gspca_frame_add(gspca_dev, FIRST_PACKET,
2327 data, len);
2328 }
2329 } else {
2330 /* if JPEG, count the packets and their size */
2331 if (is_jpeg) {
2332 sd->npkt++;
2333 sd->pktsz += len;
2334 }
2335 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2336 }
2337}
2338
2339/* sub-driver description */
2340static const struct sd_desc sd_desc = {
2341 .name = KBUILD_MODNAME,
2342 .config = sd_config,
2343 .init = sd_init,
2344 .init_controls = sd_init_controls,
2345 .isoc_init = sd_isoc_init,
2346 .start = sd_start,
2347 .stopN = sd_stopN,
2348 .stop0 = sd_stop0,
2349 .pkt_scan = sd_pkt_scan,
2350#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2351 .int_pkt_scan = sd_int_pkt_scan,
2352#endif
2353 .dq_callback = sd_dqcallback,
2354#ifdef CONFIG_VIDEO_ADV_DEBUG
2355 .set_register = sd_dbg_s_register,
2356 .get_register = sd_dbg_g_register,
2357#endif
2358 .get_chip_ident = sd_chip_ident,
2359};
2360
2361#define SN9C20X(sensor, i2c_addr, flags) \
2362 .driver_info = ((flags & 0xff) << 16) \
2363 | (SENSOR_ ## sensor << 8) \
2364 | (i2c_addr)
2365
2366static const struct usb_device_id device_table[] = {
2367 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2368 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2369 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
2370 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
2371 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2372 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2373 (FLIP_DETECT | HAS_NO_BUTTON))},
2374 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2375 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2376 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2377 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2378 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
2379 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2380 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2381 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2382 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
2383 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
2384 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
2385 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2386 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2387 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2388 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2389 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
2390 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
2391 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2392 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2393 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2394 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
2395 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2396 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
2397 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2398 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2399 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2400 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
2401 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
2402 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2403 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2404 {}
2405};
2406MODULE_DEVICE_TABLE(usb, device_table);
2407
2408/* -- device connect -- */
2409static int sd_probe(struct usb_interface *intf,
2410 const struct usb_device_id *id)
2411{
2412 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2413 THIS_MODULE);
2414}
2415
2416static struct usb_driver sd_driver = {
2417 .name = KBUILD_MODNAME,
2418 .id_table = device_table,
2419 .probe = sd_probe,
2420 .disconnect = gspca_disconnect,
2421#ifdef CONFIG_PM
2422 .suspend = gspca_suspend,
2423 .resume = gspca_resume,
2424 .reset_resume = gspca_resume,
2425#endif
2426};
2427
2428module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
new file mode 100644
index 00000000000..fd1f8d2d3b0
--- /dev/null
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -0,0 +1,1493 @@
1/*
2 * sonix sn9c102 (bayer) library
3 *
4 * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
5 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
6 * Add Pas106 Stefano Mozzi (C) 2004
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/* Some documentation on known sonixb registers:
24
25Reg Use
26sn9c101 / sn9c102:
270x10 high nibble red gain low nibble blue gain
280x11 low nibble green gain
29sn9c103:
300x05 red gain 0-127
310x06 blue gain 0-127
320x07 green gain 0-127
33all:
340x08-0x0f i2c / 3wire registers
350x12 hstart
360x13 vstart
370x15 hsize (hsize = register-value * 16)
380x16 vsize (vsize = register-value * 16)
390x17 bit 0 toggle compression quality (according to sn9c102 driver)
400x18 bit 7 enables compression, bit 4-5 set image down scaling:
41 00 scale 1, 01 scale 1/2, 10, scale 1/4
420x19 high-nibble is sensor clock divider, changes exposure on sensors which
43 use a clock generated by the bridge. Some sensors have their own clock.
440x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
450x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
460x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
470x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
48*/
49
50#define MODULE_NAME "sonixb"
51
52#include <linux/input.h>
53#include "gspca.h"
54
55MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
56MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
57MODULE_LICENSE("GPL");
58
59/* specific webcam descriptor */
60struct sd {
61 struct gspca_dev gspca_dev; /* !! must be the first item */
62
63 struct v4l2_ctrl *brightness;
64 struct v4l2_ctrl *plfreq;
65
66 atomic_t avg_lum;
67 int prev_avg_lum;
68 int exposure_knee;
69 int header_read;
70 u8 header[12]; /* Header without sof marker */
71
72 unsigned char autogain_ignore_frames;
73 unsigned char frames_to_drop;
74
75 __u8 bridge; /* Type of bridge */
76#define BRIDGE_101 0
77#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
78#define BRIDGE_103 1
79
80 __u8 sensor; /* Type of image sensor chip */
81#define SENSOR_HV7131D 0
82#define SENSOR_HV7131R 1
83#define SENSOR_OV6650 2
84#define SENSOR_OV7630 3
85#define SENSOR_PAS106 4
86#define SENSOR_PAS202 5
87#define SENSOR_TAS5110C 6
88#define SENSOR_TAS5110D 7
89#define SENSOR_TAS5130CXX 8
90 __u8 reg11;
91};
92
93typedef const __u8 sensor_init_t[8];
94
95struct sensor_data {
96 const __u8 *bridge_init;
97 sensor_init_t *sensor_init;
98 int sensor_init_size;
99 int flags;
100 __u8 sensor_addr;
101};
102
103/* sensor_data flags */
104#define F_SIF 0x01 /* sif or vga */
105
106/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
107#define MODE_RAW 0x10 /* raw bayer mode */
108#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
109
110#define COMP 0xc7 /* 0x87 //0x07 */
111#define COMP1 0xc9 /* 0x89 //0x09 */
112
113#define MCK_INIT 0x63
114#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
115
116#define SYS_CLK 0x04
117
118#define SENS(bridge, sensor, _flags, _sensor_addr) \
119{ \
120 .bridge_init = bridge, \
121 .sensor_init = sensor, \
122 .sensor_init_size = sizeof(sensor), \
123 .flags = _flags, .sensor_addr = _sensor_addr \
124}
125
126/* We calculate the autogain at the end of the transfer of a frame, at this
127 moment a frame with the old settings is being captured and transmitted. So
128 if we adjust the gain or exposure we must ignore atleast the next frame for
129 the new settings to come into effect before doing any other adjustments. */
130#define AUTOGAIN_IGNORE_FRAMES 1
131
132static const struct v4l2_pix_format vga_mode[] = {
133 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
134 .bytesperline = 160,
135 .sizeimage = 160 * 120,
136 .colorspace = V4L2_COLORSPACE_SRGB,
137 .priv = 2 | MODE_RAW},
138 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
139 .bytesperline = 160,
140 .sizeimage = 160 * 120 * 5 / 4,
141 .colorspace = V4L2_COLORSPACE_SRGB,
142 .priv = 2},
143 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 5 / 4,
146 .colorspace = V4L2_COLORSPACE_SRGB,
147 .priv = 1},
148 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
149 .bytesperline = 640,
150 .sizeimage = 640 * 480 * 5 / 4,
151 .colorspace = V4L2_COLORSPACE_SRGB,
152 .priv = 0},
153};
154static const struct v4l2_pix_format sif_mode[] = {
155 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
156 .bytesperline = 160,
157 .sizeimage = 160 * 120,
158 .colorspace = V4L2_COLORSPACE_SRGB,
159 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
160 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
161 .bytesperline = 160,
162 .sizeimage = 160 * 120 * 5 / 4,
163 .colorspace = V4L2_COLORSPACE_SRGB,
164 .priv = 1 | MODE_REDUCED_SIF},
165 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
166 .bytesperline = 176,
167 .sizeimage = 176 * 144,
168 .colorspace = V4L2_COLORSPACE_SRGB,
169 .priv = 1 | MODE_RAW},
170 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
171 .bytesperline = 176,
172 .sizeimage = 176 * 144 * 5 / 4,
173 .colorspace = V4L2_COLORSPACE_SRGB,
174 .priv = 1},
175 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
176 .bytesperline = 320,
177 .sizeimage = 320 * 240 * 5 / 4,
178 .colorspace = V4L2_COLORSPACE_SRGB,
179 .priv = 0 | MODE_REDUCED_SIF},
180 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
181 .bytesperline = 352,
182 .sizeimage = 352 * 288 * 5 / 4,
183 .colorspace = V4L2_COLORSPACE_SRGB,
184 .priv = 0},
185};
186
187static const __u8 initHv7131d[] = {
188 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
189 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
191 0x28, 0x1e, 0x60, 0x8e, 0x42,
192};
193static const __u8 hv7131d_sensor_init[][8] = {
194 {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
195 {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
196 {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
197 {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
198 {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
199};
200
201static const __u8 initHv7131r[] = {
202 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
203 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
205 0x28, 0x1e, 0x60, 0x8a, 0x20,
206};
207static const __u8 hv7131r_sensor_init[][8] = {
208 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
209 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
210 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
211 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
212 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
213};
214static const __u8 initOv6650[] = {
215 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
216 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
218 0x10,
219};
220static const __u8 ov6650_sensor_init[][8] = {
221 /* Bright, contrast, etc are set through SCBB interface.
222 * AVCAP on win2 do not send any data on this controls. */
223 /* Anyway, some registers appears to alter bright and constrat */
224
225 /* Reset sensor */
226 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
227 /* Set clock register 0x11 low nibble is clock divider */
228 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
229 /* Next some unknown stuff */
230 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
231/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
232 * THIS SET GREEN SCREEN
233 * (pixels could be innverted in decode kind of "brg",
234 * but blue wont be there. Avoid this data ... */
235 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
236 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
237 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
238 /* Enable rgb brightness control */
239 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
240 /* HDG: Note windows uses the line below, which sets both register 0x60
241 and 0x61 I believe these registers of the ov6650 are identical as
242 those of the ov7630, because if this is true the windows settings
243 add a bit additional red gain and a lot additional blue gain, which
244 matches my findings that the windows settings make blue much too
245 blue and red a little too red.
246 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
247 /* Some more unknown stuff */
248 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
249 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
250};
251
252static const __u8 initOv7630[] = {
253 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
254 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
255 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
256 0x28, 0x1e, /* H & V sizes r15 .. r16 */
257 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
258};
259static const __u8 ov7630_sensor_init[][8] = {
260 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
261 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
262/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
263 {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
264 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
265 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
266 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
267 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
268 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
269 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
270 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
271 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
272/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
273 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
274 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
275 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
276 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
277 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
278 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
279};
280
281static const __u8 initPas106[] = {
282 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
283 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
285 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
286};
287/* compression 0x86 mckinit1 0x2b */
288
289/* "Known" PAS106B registers:
290 0x02 clock divider
291 0x03 Variable framerate bits 4-11
292 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
293 The variable framerate control must never be set lower then 300,
294 which sets the framerate at 90 / reg02, otherwise vsync is lost.
295 0x05 Shutter Time Line Offset, this can be used as an exposure control:
296 0 = use full frame time, 255 = no exposure at all
297 Note this may never be larger then "var-framerate control" / 2 - 2.
298 When var-framerate control is < 514, no exposure is reached at the max
299 allowed value for the framerate control value, rather then at 255.
300 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
301 only a very little bit, leave at 0xcd
302 0x07 offset sign bit (bit0 1 > negative offset)
303 0x08 offset
304 0x09 Blue Gain
305 0x0a Green1 Gain
306 0x0b Green2 Gain
307 0x0c Red Gain
308 0x0e Global gain
309 0x13 Write 1 to commit settings to sensor
310*/
311
312static const __u8 pas106_sensor_init[][8] = {
313 /* Pixel Clock Divider 6 */
314 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
315 /* Frame Time MSB (also seen as 0x12) */
316 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
317 /* Frame Time LSB (also seen as 0x05) */
318 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
319 /* Shutter Time Line Offset (also seen as 0x6d) */
320 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
321 /* Shutter Time Pixel Offset (also seen as 0xb1) */
322 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
323 /* Black Level Subtract Sign (also seen 0x00) */
324 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
325 /* Black Level Subtract Level (also seen 0x01) */
326 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
327 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
328 /* Color Gain B Pixel 5 a */
329 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
330 /* Color Gain G1 Pixel 1 5 */
331 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
332 /* Color Gain G2 Pixel 1 0 5 */
333 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
334 /* Color Gain R Pixel 3 1 */
335 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
336 /* Color GainH Pixel */
337 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
338 /* Global Gain */
339 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
340 /* Contrast */
341 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
342 /* H&V synchro polarity */
343 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
344 /* ?default */
345 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
346 /* DAC scale */
347 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
348 /* ?default */
349 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
350 /* Validate Settings */
351 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
352};
353
354static const __u8 initPas202[] = {
355 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
356 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
358 0x28, 0x1e, 0x20, 0x89, 0x20,
359};
360
361/* "Known" PAS202BCB registers:
362 0x02 clock divider
363 0x04 Variable framerate bits 6-11 (*)
364 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
365 0x07 Blue Gain
366 0x08 Green Gain
367 0x09 Red Gain
368 0x0b offset sign bit (bit0 1 > negative offset)
369 0x0c offset
370 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
371 leave at 1 otherwise we get a jump in our exposure control
372 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
373 0x10 Master gain 0 - 31
374 0x11 write 1 to apply changes
375 (*) The variable framerate control must never be set lower then 500
376 which sets the framerate at 30 / reg02, otherwise vsync is lost.
377*/
378static const __u8 pas202_sensor_init[][8] = {
379 /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
380 to set it lower, but for some reason the bridge starts missing
381 vsync's then */
382 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
383 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
384 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
385 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
386 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
387 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
388 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
389 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
390 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
391 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
392};
393
394static const __u8 initTas5110c[] = {
395 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
396 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
398 0x16, 0x12, 0x60, 0x86, 0x2b,
399};
400/* Same as above, except a different hstart */
401static const __u8 initTas5110d[] = {
402 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
403 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
405 0x16, 0x12, 0x60, 0x86, 0x2b,
406};
407/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */
408static const __u8 tas5110c_sensor_init[][8] = {
409 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
410 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
411};
412/* Known TAS5110D registers
413 * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain
414 * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted)
415 * Note: writing reg03 seems to only work when written together with 02
416 */
417static const __u8 tas5110d_sensor_init[][8] = {
418 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */
419};
420
421static const __u8 initTas5130[] = {
422 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
423 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
425 0x28, 0x1e, 0x60, COMP, MCK_INIT,
426};
427static const __u8 tas5130_sensor_init[][8] = {
428/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
429 * shutter 0x47 short exposure? */
430 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
431 /* shutter 0x01 long exposure */
432 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
433};
434
435static const struct sensor_data sensor_data[] = {
436 SENS(initHv7131d, hv7131d_sensor_init, 0, 0),
437 SENS(initHv7131r, hv7131r_sensor_init, 0, 0),
438 SENS(initOv6650, ov6650_sensor_init, F_SIF, 0x60),
439 SENS(initOv7630, ov7630_sensor_init, 0, 0x21),
440 SENS(initPas106, pas106_sensor_init, F_SIF, 0),
441 SENS(initPas202, pas202_sensor_init, 0, 0),
442 SENS(initTas5110c, tas5110c_sensor_init, F_SIF, 0),
443 SENS(initTas5110d, tas5110d_sensor_init, F_SIF, 0),
444 SENS(initTas5130, tas5130_sensor_init, 0, 0),
445};
446
447/* get one byte in gspca_dev->usb_buf */
448static void reg_r(struct gspca_dev *gspca_dev,
449 __u16 value)
450{
451 int res;
452
453 if (gspca_dev->usb_err < 0)
454 return;
455
456 res = 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 if (res < 0) {
466 dev_err(gspca_dev->v4l2_dev.dev,
467 "Error reading register %02x: %d\n", value, res);
468 gspca_dev->usb_err = res;
469 }
470}
471
472static void reg_w(struct gspca_dev *gspca_dev,
473 __u16 value,
474 const __u8 *buffer,
475 int len)
476{
477 int res;
478
479 if (gspca_dev->usb_err < 0)
480 return;
481
482 memcpy(gspca_dev->usb_buf, buffer, len);
483 res = usb_control_msg(gspca_dev->dev,
484 usb_sndctrlpipe(gspca_dev->dev, 0),
485 0x08, /* request */
486 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
487 value,
488 0, /* index */
489 gspca_dev->usb_buf, len,
490 500);
491
492 if (res < 0) {
493 dev_err(gspca_dev->v4l2_dev.dev,
494 "Error writing register %02x: %d\n", value, res);
495 gspca_dev->usb_err = res;
496 }
497}
498
499static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
500{
501 int retry = 60;
502
503 if (gspca_dev->usb_err < 0)
504 return;
505
506 /* is i2c ready */
507 reg_w(gspca_dev, 0x08, buffer, 8);
508 while (retry--) {
509 if (gspca_dev->usb_err < 0)
510 return;
511 msleep(10);
512 reg_r(gspca_dev, 0x08);
513 if (gspca_dev->usb_buf[0] & 0x04) {
514 if (gspca_dev->usb_buf[0] & 0x08) {
515 dev_err(gspca_dev->v4l2_dev.dev,
516 "i2c write error\n");
517 gspca_dev->usb_err = -EIO;
518 }
519 return;
520 }
521 }
522
523 dev_err(gspca_dev->v4l2_dev.dev, "i2c write timeout\n");
524 gspca_dev->usb_err = -EIO;
525}
526
527static void i2c_w_vector(struct gspca_dev *gspca_dev,
528 const __u8 buffer[][8], int len)
529{
530 for (;;) {
531 if (gspca_dev->usb_err < 0)
532 return;
533 reg_w(gspca_dev, 0x08, *buffer, 8);
534 len -= 8;
535 if (len <= 0)
536 break;
537 buffer++;
538 }
539}
540
541static void setbrightness(struct gspca_dev *gspca_dev)
542{
543 struct sd *sd = (struct sd *) gspca_dev;
544
545 switch (sd->sensor) {
546 case SENSOR_OV6650:
547 case SENSOR_OV7630: {
548 __u8 i2cOV[] =
549 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
550
551 /* change reg 0x06 */
552 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
553 i2cOV[3] = sd->brightness->val;
554 i2c_w(gspca_dev, i2cOV);
555 break;
556 }
557 case SENSOR_PAS106:
558 case SENSOR_PAS202: {
559 __u8 i2cpbright[] =
560 {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
561 __u8 i2cpdoit[] =
562 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
563
564 /* PAS106 uses reg 7 and 8 instead of b and c */
565 if (sd->sensor == SENSOR_PAS106) {
566 i2cpbright[2] = 7;
567 i2cpdoit[2] = 0x13;
568 }
569
570 if (sd->brightness->val < 127) {
571 /* change reg 0x0b, signreg */
572 i2cpbright[3] = 0x01;
573 /* set reg 0x0c, offset */
574 i2cpbright[4] = 127 - sd->brightness->val;
575 } else
576 i2cpbright[4] = sd->brightness->val - 127;
577
578 i2c_w(gspca_dev, i2cpbright);
579 i2c_w(gspca_dev, i2cpdoit);
580 break;
581 }
582 default:
583 break;
584 }
585}
586
587static void setgain(struct gspca_dev *gspca_dev)
588{
589 struct sd *sd = (struct sd *) gspca_dev;
590 u8 gain = gspca_dev->gain->val;
591
592 switch (sd->sensor) {
593 case SENSOR_HV7131D: {
594 __u8 i2c[] =
595 {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
596
597 i2c[3] = 0x3f - gain;
598 i2c[4] = 0x3f - gain;
599 i2c[5] = 0x3f - gain;
600
601 i2c_w(gspca_dev, i2c);
602 break;
603 }
604 case SENSOR_TAS5110C:
605 case SENSOR_TAS5130CXX: {
606 __u8 i2c[] =
607 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
608
609 i2c[4] = 255 - gain;
610 i2c_w(gspca_dev, i2c);
611 break;
612 }
613 case SENSOR_TAS5110D: {
614 __u8 i2c[] = {
615 0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 };
616 gain = 255 - gain;
617 /* The bits in the register are the wrong way around!! */
618 i2c[3] |= (gain & 0x80) >> 7;
619 i2c[3] |= (gain & 0x40) >> 5;
620 i2c[3] |= (gain & 0x20) >> 3;
621 i2c[3] |= (gain & 0x10) >> 1;
622 i2c[3] |= (gain & 0x08) << 1;
623 i2c[3] |= (gain & 0x04) << 3;
624 i2c[3] |= (gain & 0x02) << 5;
625 i2c[3] |= (gain & 0x01) << 7;
626 i2c_w(gspca_dev, i2c);
627 break;
628 }
629 case SENSOR_OV6650:
630 case SENSOR_OV7630: {
631 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
632
633 /*
634 * The ov7630's gain is weird, at 32 the gain drops to the
635 * same level as at 16, so skip 32-47 (of the 0-63 scale).
636 */
637 if (sd->sensor == SENSOR_OV7630 && gain >= 32)
638 gain += 16;
639
640 i2c[1] = sensor_data[sd->sensor].sensor_addr;
641 i2c[3] = gain;
642 i2c_w(gspca_dev, i2c);
643 break;
644 }
645 case SENSOR_PAS106:
646 case SENSOR_PAS202: {
647 __u8 i2cpgain[] =
648 {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
649 __u8 i2cpcolorgain[] =
650 {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
651 __u8 i2cpdoit[] =
652 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
653
654 /* PAS106 uses different regs (and has split green gains) */
655 if (sd->sensor == SENSOR_PAS106) {
656 i2cpgain[2] = 0x0e;
657 i2cpcolorgain[0] = 0xd0;
658 i2cpcolorgain[2] = 0x09;
659 i2cpdoit[2] = 0x13;
660 }
661
662 i2cpgain[3] = gain;
663 i2cpcolorgain[3] = gain >> 1;
664 i2cpcolorgain[4] = gain >> 1;
665 i2cpcolorgain[5] = gain >> 1;
666 i2cpcolorgain[6] = gain >> 1;
667
668 i2c_w(gspca_dev, i2cpgain);
669 i2c_w(gspca_dev, i2cpcolorgain);
670 i2c_w(gspca_dev, i2cpdoit);
671 break;
672 }
673 default:
674 if (sd->bridge == BRIDGE_103) {
675 u8 buf[3] = { gain, gain, gain }; /* R, G, B */
676 reg_w(gspca_dev, 0x05, buf, 3);
677 } else {
678 u8 buf[2];
679 buf[0] = gain << 4 | gain; /* Red and blue */
680 buf[1] = gain; /* Green */
681 reg_w(gspca_dev, 0x10, buf, 2);
682 }
683 }
684}
685
686static void setexposure(struct gspca_dev *gspca_dev)
687{
688 struct sd *sd = (struct sd *) gspca_dev;
689
690 switch (sd->sensor) {
691 case SENSOR_HV7131D: {
692 /* Note the datasheet wrongly says line mode exposure uses reg
693 0x26 and 0x27, testing has shown 0x25 + 0x26 */
694 __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
695 u16 reg = gspca_dev->exposure->val;
696
697 i2c[3] = reg >> 8;
698 i2c[4] = reg & 0xff;
699 i2c_w(gspca_dev, i2c);
700 break;
701 }
702 case SENSOR_TAS5110C:
703 case SENSOR_TAS5110D: {
704 /* register 19's high nibble contains the sn9c10x clock divider
705 The high nibble configures the no fps according to the
706 formula: 60 / high_nibble. With a maximum of 30 fps */
707 u8 reg = gspca_dev->exposure->val;
708
709 reg = (reg << 4) | 0x0b;
710 reg_w(gspca_dev, 0x19, &reg, 1);
711 break;
712 }
713 case SENSOR_OV6650:
714 case SENSOR_OV7630: {
715 /* The ov6650 / ov7630 have 2 registers which both influence
716 exposure, register 11, whose low nibble sets the nr off fps
717 according to: fps = 30 / (low_nibble + 1)
718
719 The fps configures the maximum exposure setting, but it is
720 possible to use less exposure then what the fps maximum
721 allows by setting register 10. register 10 configures the
722 actual exposure as quotient of the full exposure, with 0
723 being no exposure at all (not very useful) and reg10_max
724 being max exposure possible at that framerate.
725
726 The code maps our 0 - 510 ms exposure ctrl to these 2
727 registers, trying to keep fps as high as possible.
728 */
729 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
730 int reg10, reg11, reg10_max;
731
732 /* ov6645 datasheet says reg10_max is 9a, but that uses
733 tline * 2 * reg10 as formula for calculating texpo, the
734 ov6650 probably uses the same formula as the 7730 which uses
735 tline * 4 * reg10, which explains why the reg10max we've
736 found experimentally for the ov6650 is exactly half that of
737 the ov6645. The ov7630 datasheet says the max is 0x41. */
738 if (sd->sensor == SENSOR_OV6650) {
739 reg10_max = 0x4d;
740 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
741 } else
742 reg10_max = 0x41;
743
744 reg11 = (15 * gspca_dev->exposure->val + 999) / 1000;
745 if (reg11 < 1)
746 reg11 = 1;
747 else if (reg11 > 16)
748 reg11 = 16;
749
750 /* In 640x480, if the reg11 has less than 4, the image is
751 unstable (the bridge goes into a higher compression mode
752 which we have not reverse engineered yet). */
753 if (gspca_dev->width == 640 && reg11 < 4)
754 reg11 = 4;
755
756 /* frame exposure time in ms = 1000 * reg11 / 30 ->
757 reg10 = (gspca_dev->exposure->val / 2) * reg10_max
758 / (1000 * reg11 / 30) */
759 reg10 = (gspca_dev->exposure->val * 15 * reg10_max)
760 / (1000 * reg11);
761
762 /* Don't allow this to get below 10 when using autogain, the
763 steps become very large (relatively) when below 10 causing
764 the image to oscilate from much too dark, to much too bright
765 and back again. */
766 if (gspca_dev->autogain->val && reg10 < 10)
767 reg10 = 10;
768 else if (reg10 > reg10_max)
769 reg10 = reg10_max;
770
771 /* Write reg 10 and reg11 low nibble */
772 i2c[1] = sensor_data[sd->sensor].sensor_addr;
773 i2c[3] = reg10;
774 i2c[4] |= reg11 - 1;
775
776 /* If register 11 didn't change, don't change it */
777 if (sd->reg11 == reg11)
778 i2c[0] = 0xa0;
779
780 i2c_w(gspca_dev, i2c);
781 if (gspca_dev->usb_err == 0)
782 sd->reg11 = reg11;
783 break;
784 }
785 case SENSOR_PAS202: {
786 __u8 i2cpframerate[] =
787 {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
788 __u8 i2cpexpo[] =
789 {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
790 const __u8 i2cpdoit[] =
791 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
792 int framerate_ctrl;
793
794 /* The exposure knee for the autogain algorithm is 200
795 (100 ms / 10 fps on other sensors), for values below this
796 use the control for setting the partial frame expose time,
797 above that use variable framerate. This way we run at max
798 framerate (640x480@7.5 fps, 320x240@10fps) until the knee
799 is reached. Using the variable framerate control above 200
800 is better then playing around with both clockdiv + partial
801 frame exposure times (like we are doing with the ov chips),
802 as that sometimes leads to jumps in the exposure control,
803 which are bad for auto exposure. */
804 if (gspca_dev->exposure->val < 200) {
805 i2cpexpo[3] = 255 - (gspca_dev->exposure->val * 255)
806 / 200;
807 framerate_ctrl = 500;
808 } else {
809 /* The PAS202's exposure control goes from 0 - 4095,
810 but anything below 500 causes vsync issues, so scale
811 our 200-1023 to 500-4095 */
812 framerate_ctrl = (gspca_dev->exposure->val - 200)
813 * 1000 / 229 + 500;
814 }
815
816 i2cpframerate[3] = framerate_ctrl >> 6;
817 i2cpframerate[4] = framerate_ctrl & 0x3f;
818 i2c_w(gspca_dev, i2cpframerate);
819 i2c_w(gspca_dev, i2cpexpo);
820 i2c_w(gspca_dev, i2cpdoit);
821 break;
822 }
823 case SENSOR_PAS106: {
824 __u8 i2cpframerate[] =
825 {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
826 __u8 i2cpexpo[] =
827 {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
828 const __u8 i2cpdoit[] =
829 {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
830 int framerate_ctrl;
831
832 /* For values below 150 use partial frame exposure, above
833 that use framerate ctrl */
834 if (gspca_dev->exposure->val < 150) {
835 i2cpexpo[3] = 150 - gspca_dev->exposure->val;
836 framerate_ctrl = 300;
837 } else {
838 /* The PAS106's exposure control goes from 0 - 4095,
839 but anything below 300 causes vsync issues, so scale
840 our 150-1023 to 300-4095 */
841 framerate_ctrl = (gspca_dev->exposure->val - 150)
842 * 1000 / 230 + 300;
843 }
844
845 i2cpframerate[3] = framerate_ctrl >> 4;
846 i2cpframerate[4] = framerate_ctrl & 0x0f;
847 i2c_w(gspca_dev, i2cpframerate);
848 i2c_w(gspca_dev, i2cpexpo);
849 i2c_w(gspca_dev, i2cpdoit);
850 break;
851 }
852 default:
853 break;
854 }
855}
856
857static void setfreq(struct gspca_dev *gspca_dev)
858{
859 struct sd *sd = (struct sd *) gspca_dev;
860
861 if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) {
862 /* Framerate adjust register for artificial light 50 hz flicker
863 compensation, for the ov6650 this is identical to ov6630
864 0x2b register, see ov6630 datasheet.
865 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
866 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
867 switch (sd->plfreq->val) {
868 default:
869/* case 0: * no filter*/
870/* case 2: * 60 hz */
871 i2c[3] = 0;
872 break;
873 case 1: /* 50 hz */
874 i2c[3] = (sd->sensor == SENSOR_OV6650)
875 ? 0x4f : 0x8a;
876 break;
877 }
878 i2c[1] = sensor_data[sd->sensor].sensor_addr;
879 i2c_w(gspca_dev, i2c);
880 }
881}
882
883static void do_autogain(struct gspca_dev *gspca_dev)
884{
885 struct sd *sd = (struct sd *) gspca_dev;
886 int deadzone, desired_avg_lum, avg_lum;
887
888 avg_lum = atomic_read(&sd->avg_lum);
889 if (avg_lum == -1)
890 return;
891
892 if (sd->autogain_ignore_frames > 0) {
893 sd->autogain_ignore_frames--;
894 return;
895 }
896
897 /* SIF / VGA sensors have a different autoexposure area and thus
898 different avg_lum values for the same picture brightness */
899 if (sensor_data[sd->sensor].flags & F_SIF) {
900 deadzone = 500;
901 /* SIF sensors tend to overexpose, so keep this small */
902 desired_avg_lum = 5000;
903 } else {
904 deadzone = 1500;
905 desired_avg_lum = 13000;
906 }
907
908 if (sd->brightness)
909 desired_avg_lum = sd->brightness->val * desired_avg_lum / 127;
910
911 if (gspca_dev->exposure->maximum < 500) {
912 if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
913 desired_avg_lum, deadzone))
914 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
915 } else {
916 int gain_knee = gspca_dev->gain->maximum * 9 / 10;
917 if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum,
918 deadzone, gain_knee, sd->exposure_knee))
919 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
920 }
921}
922
923/* this function is called at probe time */
924static int sd_config(struct gspca_dev *gspca_dev,
925 const struct usb_device_id *id)
926{
927 struct sd *sd = (struct sd *) gspca_dev;
928 struct cam *cam;
929
930 reg_r(gspca_dev, 0x00);
931 if (gspca_dev->usb_buf[0] != 0x10)
932 return -ENODEV;
933
934 /* copy the webcam info from the device id */
935 sd->sensor = id->driver_info >> 8;
936 sd->bridge = id->driver_info & 0xff;
937
938 cam = &gspca_dev->cam;
939 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
940 cam->cam_mode = vga_mode;
941 cam->nmodes = ARRAY_SIZE(vga_mode);
942 } else {
943 cam->cam_mode = sif_mode;
944 cam->nmodes = ARRAY_SIZE(sif_mode);
945 }
946 cam->npkt = 36; /* 36 packets per ISOC message */
947
948 return 0;
949}
950
951/* this function is called at probe and resume time */
952static int sd_init(struct gspca_dev *gspca_dev)
953{
954 const __u8 stop = 0x09; /* Disable stream turn of LED */
955
956 reg_w(gspca_dev, 0x01, &stop, 1);
957
958 return gspca_dev->usb_err;
959}
960
961static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
962{
963 struct gspca_dev *gspca_dev =
964 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
965 struct sd *sd = (struct sd *)gspca_dev;
966
967 gspca_dev->usb_err = 0;
968
969 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
970 /* when switching to autogain set defaults to make sure
971 we are on a valid point of the autogain gain /
972 exposure knee graph, and give this change time to
973 take effect before doing autogain. */
974 gspca_dev->gain->val = gspca_dev->gain->default_value;
975 gspca_dev->exposure->val = gspca_dev->exposure->default_value;
976 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
977 }
978
979 if (!gspca_dev->streaming)
980 return 0;
981
982 switch (ctrl->id) {
983 case V4L2_CID_BRIGHTNESS:
984 setbrightness(gspca_dev);
985 break;
986 case V4L2_CID_AUTOGAIN:
987 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
988 setexposure(gspca_dev);
989 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
990 setgain(gspca_dev);
991 break;
992 case V4L2_CID_POWER_LINE_FREQUENCY:
993 setfreq(gspca_dev);
994 break;
995 default:
996 return -EINVAL;
997 }
998 return gspca_dev->usb_err;
999}
1000
1001static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1002 .s_ctrl = sd_s_ctrl,
1003};
1004
1005/* this function is called at probe time */
1006static int sd_init_controls(struct gspca_dev *gspca_dev)
1007{
1008 struct sd *sd = (struct sd *) gspca_dev;
1009 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1010
1011 gspca_dev->vdev.ctrl_handler = hdl;
1012 v4l2_ctrl_handler_init(hdl, 5);
1013
1014 if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630 ||
1015 sd->sensor == SENSOR_PAS106 || sd->sensor == SENSOR_PAS202)
1016 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1017 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1018
1019 /* Gain range is sensor dependent */
1020 switch (sd->sensor) {
1021 case SENSOR_OV6650:
1022 case SENSOR_PAS106:
1023 case SENSOR_PAS202:
1024 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1025 V4L2_CID_GAIN, 0, 31, 1, 15);
1026 break;
1027 case SENSOR_OV7630:
1028 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1029 V4L2_CID_GAIN, 0, 47, 1, 31);
1030 break;
1031 case SENSOR_HV7131D:
1032 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1033 V4L2_CID_GAIN, 0, 63, 1, 31);
1034 break;
1035 case SENSOR_TAS5110C:
1036 case SENSOR_TAS5110D:
1037 case SENSOR_TAS5130CXX:
1038 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1039 V4L2_CID_GAIN, 0, 255, 1, 127);
1040 break;
1041 default:
1042 if (sd->bridge == BRIDGE_103) {
1043 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1044 V4L2_CID_GAIN, 0, 127, 1, 63);
1045 } else {
1046 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1047 V4L2_CID_GAIN, 0, 15, 1, 7);
1048 }
1049 }
1050
1051 /* Exposure range is sensor dependent, and not all have exposure */
1052 switch (sd->sensor) {
1053 case SENSOR_HV7131D:
1054 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1055 V4L2_CID_EXPOSURE, 0, 8191, 1, 482);
1056 sd->exposure_knee = 964;
1057 break;
1058 case SENSOR_OV6650:
1059 case SENSOR_OV7630:
1060 case SENSOR_PAS106:
1061 case SENSOR_PAS202:
1062 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1063 V4L2_CID_EXPOSURE, 0, 1023, 1, 66);
1064 sd->exposure_knee = 200;
1065 break;
1066 case SENSOR_TAS5110C:
1067 case SENSOR_TAS5110D:
1068 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1069 V4L2_CID_EXPOSURE, 2, 15, 1, 2);
1070 break;
1071 }
1072
1073 if (gspca_dev->exposure) {
1074 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1075 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1076 }
1077
1078 if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630)
1079 sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
1080 V4L2_CID_POWER_LINE_FREQUENCY,
1081 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
1082 V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
1083
1084 if (hdl->error) {
1085 pr_err("Could not initialize controls\n");
1086 return hdl->error;
1087 }
1088
1089 if (gspca_dev->autogain)
1090 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
1091
1092 return 0;
1093}
1094
1095/* -- start the camera -- */
1096static int sd_start(struct gspca_dev *gspca_dev)
1097{
1098 struct sd *sd = (struct sd *) gspca_dev;
1099 struct cam *cam = &gspca_dev->cam;
1100 int i, mode;
1101 __u8 regs[0x31];
1102
1103 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
1104 /* Copy registers 0x01 - 0x19 from the template */
1105 memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
1106 /* Set the mode */
1107 regs[0x18] |= mode << 4;
1108
1109 /* Set bridge gain to 1.0 */
1110 if (sd->bridge == BRIDGE_103) {
1111 regs[0x05] = 0x20; /* Red */
1112 regs[0x06] = 0x20; /* Green */
1113 regs[0x07] = 0x20; /* Blue */
1114 } else {
1115 regs[0x10] = 0x00; /* Red and blue */
1116 regs[0x11] = 0x00; /* Green */
1117 }
1118
1119 /* Setup pixel numbers and auto exposure window */
1120 if (sensor_data[sd->sensor].flags & F_SIF) {
1121 regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
1122 regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
1123 regs[0x1c] = 0x02; /* AE H-start 64 */
1124 regs[0x1d] = 0x02; /* AE V-start 64 */
1125 regs[0x1e] = 0x09; /* AE H-end 288 */
1126 regs[0x1f] = 0x07; /* AE V-end 224 */
1127 } else {
1128 regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
1129 regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
1130 regs[0x1c] = 0x05; /* AE H-start 160 */
1131 regs[0x1d] = 0x03; /* AE V-start 96 */
1132 regs[0x1e] = 0x0f; /* AE H-end 480 */
1133 regs[0x1f] = 0x0c; /* AE V-end 384 */
1134 }
1135
1136 /* Setup the gamma table (only used with the sn9c103 bridge) */
1137 for (i = 0; i < 16; i++)
1138 regs[0x20 + i] = i * 16;
1139 regs[0x20 + i] = 255;
1140
1141 /* Special cases where some regs depend on mode or bridge */
1142 switch (sd->sensor) {
1143 case SENSOR_TAS5130CXX:
1144 /* FIXME / TESTME
1145 probably not mode specific at all most likely the upper
1146 nibble of 0x19 is exposure (clock divider) just as with
1147 the tas5110, we need someone to test this. */
1148 regs[0x19] = mode ? 0x23 : 0x43;
1149 break;
1150 case SENSOR_OV7630:
1151 /* FIXME / TESTME for some reason with the 101/102 bridge the
1152 clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
1153 Also the hstart needs to go from 1 to 2 when using a 103,
1154 which is likely related. This does not seem right. */
1155 if (sd->bridge == BRIDGE_103) {
1156 regs[0x01] = 0x44; /* Select 24 Mhz clock */
1157 regs[0x12] = 0x02; /* Set hstart to 2 */
1158 }
1159 }
1160 /* Disable compression when the raw bayer format has been selected */
1161 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
1162 regs[0x18] &= ~0x80;
1163
1164 /* Vga mode emulation on SIF sensor? */
1165 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
1166 regs[0x12] += 16; /* hstart adjust */
1167 regs[0x13] += 24; /* vstart adjust */
1168 regs[0x15] = 320 / 16; /* hsize */
1169 regs[0x16] = 240 / 16; /* vsize */
1170 }
1171
1172 /* reg 0x01 bit 2 video transfert on */
1173 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
1174 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1175 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
1176 /* Set the registers from the template */
1177 reg_w(gspca_dev, 0x01, &regs[0x01],
1178 (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
1179
1180 /* Init the sensor */
1181 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
1182 sensor_data[sd->sensor].sensor_init_size);
1183
1184 /* Mode / bridge specific sensor setup */
1185 switch (sd->sensor) {
1186 case SENSOR_PAS202: {
1187 const __u8 i2cpclockdiv[] =
1188 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
1189 /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
1190 if (mode)
1191 i2c_w(gspca_dev, i2cpclockdiv);
1192 break;
1193 }
1194 case SENSOR_OV7630:
1195 /* FIXME / TESTME We should be able to handle this identical
1196 for the 101/102 and the 103 case */
1197 if (sd->bridge == BRIDGE_103) {
1198 const __u8 i2c[] = { 0xa0, 0x21, 0x13,
1199 0x80, 0x00, 0x00, 0x00, 0x10 };
1200 i2c_w(gspca_dev, i2c);
1201 }
1202 break;
1203 }
1204 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1205 reg_w(gspca_dev, 0x15, &regs[0x15], 2);
1206 /* compression register */
1207 reg_w(gspca_dev, 0x18, &regs[0x18], 1);
1208 /* H_start */
1209 reg_w(gspca_dev, 0x12, &regs[0x12], 1);
1210 /* V_START */
1211 reg_w(gspca_dev, 0x13, &regs[0x13], 1);
1212 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1213 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1214 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
1215 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1216 reg_w(gspca_dev, 0x19, &regs[0x19], 1);
1217 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1218 reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
1219 /* Enable video transfert */
1220 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
1221 /* Compression */
1222 reg_w(gspca_dev, 0x18, &regs[0x18], 2);
1223 msleep(20);
1224
1225 sd->reg11 = -1;
1226
1227 setgain(gspca_dev);
1228 setbrightness(gspca_dev);
1229 setexposure(gspca_dev);
1230 setfreq(gspca_dev);
1231
1232 sd->frames_to_drop = 0;
1233 sd->autogain_ignore_frames = 0;
1234 gspca_dev->exp_too_high_cnt = 0;
1235 gspca_dev->exp_too_low_cnt = 0;
1236 atomic_set(&sd->avg_lum, -1);
1237 return gspca_dev->usb_err;
1238}
1239
1240static void sd_stopN(struct gspca_dev *gspca_dev)
1241{
1242 sd_init(gspca_dev);
1243}
1244
1245static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
1246{
1247 struct sd *sd = (struct sd *) gspca_dev;
1248 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
1249
1250 /* frames start with:
1251 * ff ff 00 c4 c4 96 synchro
1252 * 00 (unknown)
1253 * xx (frame sequence / size / compression)
1254 * (xx) (idem - extra byte for sn9c103)
1255 * ll mm brightness sum inside auto exposure
1256 * ll mm brightness sum outside auto exposure
1257 * (xx xx xx xx xx) audio values for snc103
1258 */
1259 for (i = 0; i < len; i++) {
1260 switch (sd->header_read) {
1261 case 0:
1262 if (data[i] == 0xff)
1263 sd->header_read++;
1264 break;
1265 case 1:
1266 if (data[i] == 0xff)
1267 sd->header_read++;
1268 else
1269 sd->header_read = 0;
1270 break;
1271 case 2:
1272 if (data[i] == 0x00)
1273 sd->header_read++;
1274 else if (data[i] != 0xff)
1275 sd->header_read = 0;
1276 break;
1277 case 3:
1278 if (data[i] == 0xc4)
1279 sd->header_read++;
1280 else if (data[i] == 0xff)
1281 sd->header_read = 1;
1282 else
1283 sd->header_read = 0;
1284 break;
1285 case 4:
1286 if (data[i] == 0xc4)
1287 sd->header_read++;
1288 else if (data[i] == 0xff)
1289 sd->header_read = 1;
1290 else
1291 sd->header_read = 0;
1292 break;
1293 case 5:
1294 if (data[i] == 0x96)
1295 sd->header_read++;
1296 else if (data[i] == 0xff)
1297 sd->header_read = 1;
1298 else
1299 sd->header_read = 0;
1300 break;
1301 default:
1302 sd->header[sd->header_read - 6] = data[i];
1303 sd->header_read++;
1304 if (sd->header_read == header_size) {
1305 sd->header_read = 0;
1306 return data + i + 1;
1307 }
1308 }
1309 }
1310 return NULL;
1311}
1312
1313static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1314 u8 *data, /* isoc packet */
1315 int len) /* iso packet length */
1316{
1317 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1318 struct sd *sd = (struct sd *) gspca_dev;
1319 struct cam *cam = &gspca_dev->cam;
1320 u8 *sof;
1321
1322 sof = find_sof(gspca_dev, data, len);
1323 if (sof) {
1324 if (sd->bridge == BRIDGE_103) {
1325 fr_h_sz = 18;
1326 lum_offset = 3;
1327 } else {
1328 fr_h_sz = 12;
1329 lum_offset = 2;
1330 }
1331
1332 len_after_sof = len - (sof - data);
1333 len = (sof - data) - fr_h_sz;
1334 if (len < 0)
1335 len = 0;
1336 }
1337
1338 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1339 /* In raw mode we sometimes get some garbage after the frame
1340 ignore this */
1341 int used;
1342 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1343
1344 used = gspca_dev->image_len;
1345 if (used + len > size)
1346 len = size - used;
1347 }
1348
1349 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1350
1351 if (sof) {
1352 int lum = sd->header[lum_offset] +
1353 (sd->header[lum_offset + 1] << 8);
1354
1355 /* When exposure changes midway a frame we
1356 get a lum of 0 in this case drop 2 frames
1357 as the frames directly after an exposure
1358 change have an unstable image. Sometimes lum
1359 *really* is 0 (cam used in low light with
1360 low exposure setting), so do not drop frames
1361 if the previous lum was 0 too. */
1362 if (lum == 0 && sd->prev_avg_lum != 0) {
1363 lum = -1;
1364 sd->frames_to_drop = 2;
1365 sd->prev_avg_lum = 0;
1366 } else
1367 sd->prev_avg_lum = lum;
1368 atomic_set(&sd->avg_lum, lum);
1369
1370 if (sd->frames_to_drop)
1371 sd->frames_to_drop--;
1372 else
1373 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1374
1375 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1376 }
1377}
1378
1379static int sd_querymenu(struct gspca_dev *gspca_dev,
1380 struct v4l2_querymenu *menu)
1381{
1382 switch (menu->id) {
1383 case V4L2_CID_POWER_LINE_FREQUENCY:
1384 switch (menu->index) {
1385 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1386 strcpy((char *) menu->name, "NoFliker");
1387 return 0;
1388 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1389 strcpy((char *) menu->name, "50 Hz");
1390 return 0;
1391 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1392 strcpy((char *) menu->name, "60 Hz");
1393 return 0;
1394 }
1395 break;
1396 }
1397 return -EINVAL;
1398}
1399
1400#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1401static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1402 u8 *data, /* interrupt packet data */
1403 int len) /* interrupt packet length */
1404{
1405 int ret = -EINVAL;
1406
1407 if (len == 1 && data[0] == 1) {
1408 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1409 input_sync(gspca_dev->input_dev);
1410 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1411 input_sync(gspca_dev->input_dev);
1412 ret = 0;
1413 }
1414
1415 return ret;
1416}
1417#endif
1418
1419/* sub-driver description */
1420static const struct sd_desc sd_desc = {
1421 .name = MODULE_NAME,
1422 .config = sd_config,
1423 .init = sd_init,
1424 .init_controls = sd_init_controls,
1425 .start = sd_start,
1426 .stopN = sd_stopN,
1427 .pkt_scan = sd_pkt_scan,
1428 .querymenu = sd_querymenu,
1429 .dq_callback = do_autogain,
1430#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1431 .int_pkt_scan = sd_int_pkt_scan,
1432#endif
1433};
1434
1435/* -- module initialisation -- */
1436#define SB(sensor, bridge) \
1437 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1438
1439
1440static const struct usb_device_id device_table[] = {
1441 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1442 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
1443 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
1444 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1445 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
1446 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
1447 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1448#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1449 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1450 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1451#endif
1452 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1453 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
1454 {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
1455 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
1456 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
1457 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
1458 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
1459 /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
1460 /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */
1461 {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)},
1462 {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)},
1463 /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */
1464 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1465 {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)},
1466 {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)},
1467 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1468 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
1469 {}
1470};
1471MODULE_DEVICE_TABLE(usb, device_table);
1472
1473/* -- device connect -- */
1474static int sd_probe(struct usb_interface *intf,
1475 const struct usb_device_id *id)
1476{
1477 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1478 THIS_MODULE);
1479}
1480
1481static struct usb_driver sd_driver = {
1482 .name = MODULE_NAME,
1483 .id_table = device_table,
1484 .probe = sd_probe,
1485 .disconnect = gspca_disconnect,
1486#ifdef CONFIG_PM
1487 .suspend = gspca_suspend,
1488 .resume = gspca_resume,
1489 .reset_resume = gspca_resume,
1490#endif
1491};
1492
1493module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c
new file mode 100644
index 00000000000..150b2df40f7
--- /dev/null
+++ b/drivers/media/usb/gspca/sonixj.c
@@ -0,0 +1,3206 @@
1/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
3 *
4 * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
5 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "sonixj"
25
26#include <linux/input.h>
27#include "gspca.h"
28#include "jpeg.h"
29
30MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
31MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* controls */
35enum e_ctrl {
36 BRIGHTNESS,
37 CONTRAST,
38 COLORS,
39 BLUE,
40 RED,
41 GAMMA,
42 EXPOSURE,
43 AUTOGAIN,
44 GAIN,
45 HFLIP,
46 VFLIP,
47 SHARPNESS,
48 ILLUM,
49 FREQ,
50 NCTRLS /* number of controls */
51};
52
53/* specific webcam descriptor */
54struct sd {
55 struct gspca_dev gspca_dev; /* !! must be the first item */
56
57 struct gspca_ctrl ctrls[NCTRLS];
58
59 atomic_t avg_lum;
60 u32 exposure;
61
62 struct work_struct work;
63 struct workqueue_struct *work_thread;
64
65 u32 pktsz; /* (used by pkt_scan) */
66 u16 npkt;
67 s8 nchg;
68 s8 short_mark;
69
70 u8 quality; /* image quality */
71#define QUALITY_MIN 25
72#define QUALITY_MAX 90
73#define QUALITY_DEF 70
74
75 u8 reg01;
76 u8 reg17;
77 u8 reg18;
78 u8 flags;
79
80 s8 ag_cnt;
81#define AG_CNT_START 13
82
83 u8 bridge;
84#define BRIDGE_SN9C102P 0
85#define BRIDGE_SN9C105 1
86#define BRIDGE_SN9C110 2
87#define BRIDGE_SN9C120 3
88 u8 sensor; /* Type of image sensor chip */
89 u8 i2c_addr;
90
91 u8 jpeg_hdr[JPEG_HDR_SZ];
92};
93enum sensors {
94 SENSOR_ADCM1700,
95 SENSOR_GC0307,
96 SENSOR_HV7131R,
97 SENSOR_MI0360,
98 SENSOR_MI0360B,
99 SENSOR_MO4000,
100 SENSOR_MT9V111,
101 SENSOR_OM6802,
102 SENSOR_OV7630,
103 SENSOR_OV7648,
104 SENSOR_OV7660,
105 SENSOR_PO1030,
106 SENSOR_PO2030N,
107 SENSOR_SOI768,
108 SENSOR_SP80708,
109};
110
111static void qual_upd(struct work_struct *work);
112
113/* device flags */
114#define F_PDN_INV 0x01 /* inverse pin S_PWR_DN / sn_xxx tables */
115#define F_ILLUM 0x02 /* presence of illuminator */
116
117/* sn9c1xx definitions */
118/* register 0x01 */
119#define S_PWR_DN 0x01 /* sensor power down */
120#define S_PDN_INV 0x02 /* inverse pin S_PWR_DN */
121#define V_TX_EN 0x04 /* video transfer enable */
122#define LED 0x08 /* output to pin LED */
123#define SCL_SEL_OD 0x20 /* open-drain mode */
124#define SYS_SEL_48M 0x40 /* system clock 0: 24MHz, 1: 48MHz */
125/* register 0x17 */
126#define MCK_SIZE_MASK 0x1f /* sensor master clock */
127#define SEN_CLK_EN 0x20 /* enable sensor clock */
128#define DEF_EN 0x80 /* defect pixel by 0: soft, 1: hard */
129
130/* V4L2 controls supported by the driver */
131static void setbrightness(struct gspca_dev *gspca_dev);
132static void setcontrast(struct gspca_dev *gspca_dev);
133static void setcolors(struct gspca_dev *gspca_dev);
134static void setredblue(struct gspca_dev *gspca_dev);
135static void setgamma(struct gspca_dev *gspca_dev);
136static void setexposure(struct gspca_dev *gspca_dev);
137static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
138static void setgain(struct gspca_dev *gspca_dev);
139static void sethvflip(struct gspca_dev *gspca_dev);
140static void setsharpness(struct gspca_dev *gspca_dev);
141static void setillum(struct gspca_dev *gspca_dev);
142static void setfreq(struct gspca_dev *gspca_dev);
143
144static const struct ctrl sd_ctrls[NCTRLS] = {
145[BRIGHTNESS] = {
146 {
147 .id = V4L2_CID_BRIGHTNESS,
148 .type = V4L2_CTRL_TYPE_INTEGER,
149 .name = "Brightness",
150 .minimum = 0,
151 .maximum = 0xff,
152 .step = 1,
153 .default_value = 0x80,
154 },
155 .set_control = setbrightness
156 },
157[CONTRAST] = {
158 {
159 .id = V4L2_CID_CONTRAST,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Contrast",
162 .minimum = 0,
163#define CONTRAST_MAX 127
164 .maximum = CONTRAST_MAX,
165 .step = 1,
166 .default_value = 20,
167 },
168 .set_control = setcontrast
169 },
170[COLORS] = {
171 {
172 .id = V4L2_CID_SATURATION,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 .name = "Saturation",
175 .minimum = 0,
176 .maximum = 40,
177 .step = 1,
178#define COLORS_DEF 25
179 .default_value = COLORS_DEF,
180 },
181 .set_control = setcolors
182 },
183[BLUE] = {
184 {
185 .id = V4L2_CID_BLUE_BALANCE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Blue Balance",
188 .minimum = 24,
189 .maximum = 40,
190 .step = 1,
191 .default_value = 32,
192 },
193 .set_control = setredblue
194 },
195[RED] = {
196 {
197 .id = V4L2_CID_RED_BALANCE,
198 .type = V4L2_CTRL_TYPE_INTEGER,
199 .name = "Red Balance",
200 .minimum = 24,
201 .maximum = 40,
202 .step = 1,
203 .default_value = 32,
204 },
205 .set_control = setredblue
206 },
207[GAMMA] = {
208 {
209 .id = V4L2_CID_GAMMA,
210 .type = V4L2_CTRL_TYPE_INTEGER,
211 .name = "Gamma",
212 .minimum = 0,
213 .maximum = 40,
214 .step = 1,
215#define GAMMA_DEF 20
216 .default_value = GAMMA_DEF,
217 },
218 .set_control = setgamma
219 },
220[EXPOSURE] = {
221 {
222 .id = V4L2_CID_EXPOSURE,
223 .type = V4L2_CTRL_TYPE_INTEGER,
224 .name = "Exposure",
225 .minimum = 500,
226 .maximum = 1500,
227 .step = 1,
228 .default_value = 1024
229 },
230 .set_control = setexposure
231 },
232[AUTOGAIN] = {
233 {
234 .id = V4L2_CID_AUTOGAIN,
235 .type = V4L2_CTRL_TYPE_BOOLEAN,
236 .name = "Auto Gain",
237 .minimum = 0,
238 .maximum = 1,
239 .step = 1,
240 .default_value = 1
241 },
242 .set = sd_setautogain,
243 },
244[GAIN] = {
245 {
246 .id = V4L2_CID_GAIN,
247 .type = V4L2_CTRL_TYPE_INTEGER,
248 .name = "Gain",
249 .minimum = 4,
250 .maximum = 49,
251 .step = 1,
252 .default_value = 15
253 },
254 .set_control = setgain
255 },
256[HFLIP] = {
257 {
258 .id = V4L2_CID_HFLIP,
259 .type = V4L2_CTRL_TYPE_BOOLEAN,
260 .name = "Mirror",
261 .minimum = 0,
262 .maximum = 1,
263 .step = 1,
264 .default_value = 0,
265 },
266 .set_control = sethvflip
267 },
268[VFLIP] = {
269 {
270 .id = V4L2_CID_VFLIP,
271 .type = V4L2_CTRL_TYPE_BOOLEAN,
272 .name = "Vflip",
273 .minimum = 0,
274 .maximum = 1,
275 .step = 1,
276 .default_value = 0,
277 },
278 .set_control = sethvflip
279 },
280[SHARPNESS] = {
281 {
282 .id = V4L2_CID_SHARPNESS,
283 .type = V4L2_CTRL_TYPE_INTEGER,
284 .name = "Sharpness",
285 .minimum = 0,
286 .maximum = 255,
287 .step = 1,
288 .default_value = 90,
289 },
290 .set_control = setsharpness
291 },
292[ILLUM] = {
293 {
294 .id = V4L2_CID_ILLUMINATORS_1,
295 .type = V4L2_CTRL_TYPE_BOOLEAN,
296 .name = "Illuminator / infrared",
297 .minimum = 0,
298 .maximum = 1,
299 .step = 1,
300 .default_value = 0,
301 },
302 .set_control = setillum
303 },
304/* ov7630/ov7648/ov7660 only */
305[FREQ] = {
306 {
307 .id = V4L2_CID_POWER_LINE_FREQUENCY,
308 .type = V4L2_CTRL_TYPE_MENU,
309 .name = "Light frequency filter",
310 .minimum = 0,
311 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
312 .step = 1,
313 .default_value = 1,
314 },
315 .set_control = setfreq
316 },
317};
318
319/* table of the disabled controls */
320static const __u32 ctrl_dis[] = {
321[SENSOR_ADCM1700] = (1 << EXPOSURE) |
322 (1 << AUTOGAIN) |
323 (1 << GAIN) |
324 (1 << HFLIP) |
325 (1 << VFLIP) |
326 (1 << FREQ),
327
328[SENSOR_GC0307] = (1 << EXPOSURE) |
329 (1 << GAIN) |
330 (1 << HFLIP) |
331 (1 << VFLIP) |
332 (1 << FREQ),
333
334[SENSOR_HV7131R] = (1 << EXPOSURE) |
335 (1 << GAIN) |
336 (1 << HFLIP) |
337 (1 << FREQ),
338
339[SENSOR_MI0360] = (1 << EXPOSURE) |
340 (1 << GAIN) |
341 (1 << HFLIP) |
342 (1 << VFLIP) |
343 (1 << FREQ),
344
345[SENSOR_MI0360B] = (1 << EXPOSURE) |
346 (1 << GAIN) |
347 (1 << HFLIP) |
348 (1 << VFLIP) |
349 (1 << FREQ),
350
351[SENSOR_MO4000] = (1 << EXPOSURE) |
352 (1 << GAIN) |
353 (1 << HFLIP) |
354 (1 << VFLIP) |
355 (1 << FREQ),
356
357[SENSOR_MT9V111] = (1 << EXPOSURE) |
358 (1 << GAIN) |
359 (1 << HFLIP) |
360 (1 << VFLIP) |
361 (1 << FREQ),
362
363[SENSOR_OM6802] = (1 << EXPOSURE) |
364 (1 << GAIN) |
365 (1 << HFLIP) |
366 (1 << VFLIP) |
367 (1 << FREQ),
368
369[SENSOR_OV7630] = (1 << EXPOSURE) |
370 (1 << GAIN) |
371 (1 << HFLIP),
372
373[SENSOR_OV7648] = (1 << EXPOSURE) |
374 (1 << GAIN) |
375 (1 << HFLIP),
376
377[SENSOR_OV7660] = (1 << EXPOSURE) |
378 (1 << AUTOGAIN) |
379 (1 << GAIN) |
380 (1 << HFLIP) |
381 (1 << VFLIP),
382
383[SENSOR_PO1030] = (1 << EXPOSURE) |
384 (1 << AUTOGAIN) |
385 (1 << GAIN) |
386 (1 << HFLIP) |
387 (1 << VFLIP) |
388 (1 << FREQ),
389
390[SENSOR_PO2030N] = (1 << FREQ),
391
392[SENSOR_SOI768] = (1 << EXPOSURE) |
393 (1 << AUTOGAIN) |
394 (1 << GAIN) |
395 (1 << HFLIP) |
396 (1 << VFLIP) |
397 (1 << FREQ),
398
399[SENSOR_SP80708] = (1 << EXPOSURE) |
400 (1 << AUTOGAIN) |
401 (1 << GAIN) |
402 (1 << HFLIP) |
403 (1 << VFLIP) |
404 (1 << FREQ),
405};
406
407static const struct v4l2_pix_format cif_mode[] = {
408 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
409 .bytesperline = 352,
410 .sizeimage = 352 * 288 * 4 / 8 + 590,
411 .colorspace = V4L2_COLORSPACE_JPEG,
412 .priv = 0},
413};
414static const struct v4l2_pix_format vga_mode[] = {
415 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
416 .bytesperline = 160,
417 .sizeimage = 160 * 120 * 4 / 8 + 590,
418 .colorspace = V4L2_COLORSPACE_JPEG,
419 .priv = 2},
420 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
421 .bytesperline = 320,
422 .sizeimage = 320 * 240 * 3 / 8 + 590,
423 .colorspace = V4L2_COLORSPACE_JPEG,
424 .priv = 1},
425 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
426 .bytesperline = 640,
427 /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
428 .sizeimage = 640 * 480 * 3 / 4 + 590,
429 .colorspace = V4L2_COLORSPACE_JPEG,
430 .priv = 0},
431};
432
433static const u8 sn_adcm1700[0x1c] = {
434/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
435 0x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00,
436/* reg8 reg9 rega regb regc regd rege regf */
437 0x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
439 0x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42,
440/* reg18 reg19 reg1a reg1b */
441 0x06, 0x00, 0x00, 0x00
442};
443
444static const u8 sn_gc0307[0x1c] = {
445/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
446 0x00, 0x61, 0x62, 0x00, 0x1a, 0x00, 0x00, 0x00,
447/* reg8 reg9 rega regb regc regd rege regf */
448 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
450 0x03, 0x00, 0x03, 0x01, 0x08, 0x28, 0x1e, 0x02,
451/* reg18 reg19 reg1a reg1b */
452 0x06, 0x00, 0x00, 0x00
453};
454
455static const u8 sn_hv7131[0x1c] = {
456/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
457 0x00, 0x03, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20,
458/* reg8 reg9 rega regb regc regd rege regf */
459 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
461 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
462/* reg18 reg19 reg1a reg1b */
463 0x0a, 0x00, 0x00, 0x00
464};
465
466static const u8 sn_mi0360[0x1c] = {
467/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
468 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
469/* reg8 reg9 rega regb regc regd rege regf */
470 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
471/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
472 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
473/* reg18 reg19 reg1a reg1b */
474 0x06, 0x00, 0x00, 0x00
475};
476
477static const u8 sn_mi0360b[0x1c] = {
478/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
479 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
480/* reg8 reg9 rega regb regc regd rege regf */
481 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
483 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x40,
484/* reg18 reg19 reg1a reg1b */
485 0x06, 0x00, 0x00, 0x00
486};
487
488static const u8 sn_mo4000[0x1c] = {
489/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
490 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
491/* reg8 reg9 rega regb regc regd rege regf */
492 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
494 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
495/* reg18 reg19 reg1a reg1b */
496 0x08, 0x00, 0x00, 0x00
497};
498
499static const u8 sn_mt9v111[0x1c] = {
500/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
501 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
502/* reg8 reg9 rega regb regc regd rege regf */
503 0x81, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
505 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40,
506/* reg18 reg19 reg1a reg1b */
507 0x06, 0x00, 0x00, 0x00
508};
509
510static const u8 sn_om6802[0x1c] = {
511/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
512 0x00, 0x23, 0x72, 0x00, 0x1a, 0x20, 0x20, 0x19,
513/* reg8 reg9 rega regb regc regd rege regf */
514 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
516 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
517/* reg18 reg19 reg1a reg1b */
518 0x05, 0x00, 0x00, 0x00
519};
520
521static const u8 sn_ov7630[0x1c] = {
522/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
523 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
524/* reg8 reg9 rega regb regc regd rege regf */
525 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
527 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
528/* reg18 reg19 reg1a reg1b */
529 0x0b, 0x00, 0x00, 0x00
530};
531
532static const u8 sn_ov7648[0x1c] = {
533/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
534 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
535/* reg8 reg9 rega regb regc regd rege regf */
536 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
537/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
538 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
539/* reg18 reg19 reg1a reg1b */
540 0x0b, 0x00, 0x00, 0x00
541};
542
543static const u8 sn_ov7660[0x1c] = {
544/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
545 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
546/* reg8 reg9 rega regb regc regd rege regf */
547 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
549 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
550/* reg18 reg19 reg1a reg1b */
551 0x07, 0x00, 0x00, 0x00
552};
553
554static const u8 sn_po1030[0x1c] = {
555/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
556 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
557/* reg8 reg9 rega regb regc regd rege regf */
558 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
560 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x00,
561/* reg18 reg19 reg1a reg1b */
562 0x07, 0x00, 0x00, 0x00
563};
564
565static const u8 sn_po2030n[0x1c] = {
566/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
567 0x00, 0x63, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
568/* reg8 reg9 rega regb regc regd rege regf */
569 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
570/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
571 0x03, 0x00, 0x00, 0x01, 0x14, 0x28, 0x1e, 0x00,
572/* reg18 reg19 reg1a reg1b */
573 0x07, 0x00, 0x00, 0x00
574};
575
576static const u8 sn_soi768[0x1c] = {
577/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
578 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
579/* reg8 reg9 rega regb regc regd rege regf */
580 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
582 0x03, 0x00, 0x00, 0x01, 0x08, 0x28, 0x1e, 0x00,
583/* reg18 reg19 reg1a reg1b */
584 0x07, 0x00, 0x00, 0x00
585};
586
587static const u8 sn_sp80708[0x1c] = {
588/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
589 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20,
590/* reg8 reg9 rega regb regc regd rege regf */
591 0x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
593 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00,
594/* reg18 reg19 reg1a reg1b */
595 0x07, 0x00, 0x00, 0x00
596};
597
598/* sequence specific to the sensors - !! index = SENSOR_xxx */
599static const u8 *sn_tb[] = {
600[SENSOR_ADCM1700] = sn_adcm1700,
601[SENSOR_GC0307] = sn_gc0307,
602[SENSOR_HV7131R] = sn_hv7131,
603[SENSOR_MI0360] = sn_mi0360,
604[SENSOR_MI0360B] = sn_mi0360b,
605[SENSOR_MO4000] = sn_mo4000,
606[SENSOR_MT9V111] = sn_mt9v111,
607[SENSOR_OM6802] = sn_om6802,
608[SENSOR_OV7630] = sn_ov7630,
609[SENSOR_OV7648] = sn_ov7648,
610[SENSOR_OV7660] = sn_ov7660,
611[SENSOR_PO1030] = sn_po1030,
612[SENSOR_PO2030N] = sn_po2030n,
613[SENSOR_SOI768] = sn_soi768,
614[SENSOR_SP80708] = sn_sp80708,
615};
616
617/* default gamma table */
618static const u8 gamma_def[17] = {
619 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
620 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
621};
622/* gamma for sensor ADCM1700 */
623static const u8 gamma_spec_0[17] = {
624 0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
625 0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
626};
627/* gamma for sensors HV7131R and MT9V111 */
628static const u8 gamma_spec_1[17] = {
629 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
630 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
631};
632/* gamma for sensor GC0307 */
633static const u8 gamma_spec_2[17] = {
634 0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
635 0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
636};
637/* gamma for sensor SP80708 */
638static const u8 gamma_spec_3[17] = {
639 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
640 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
641};
642
643/* color matrix and offsets */
644static const u8 reg84[] = {
645 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
646 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
647 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
648 0x00, 0x00, 0x00 /* YUV offsets */
649};
650
651#define DELAY 0xdd
652
653static const u8 adcm1700_sensor_init[][8] = {
654 {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
655 {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */
656 {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
657 {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
658 {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
659 {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
660 {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
661 {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
662 {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
663 {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
664 {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
665 {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
666 {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
667 {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
668 {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
669 {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
670 {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
671 {}
672};
673static const u8 adcm1700_sensor_param1[][8] = {
674 {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */
675 {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
676
677 {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
678 {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
679 {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
680 {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
681 {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */
682
683 {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
684 {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
685 {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
686 {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
687 {}
688};
689static const u8 gc0307_sensor_init[][8] = {
690 {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
691 {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
692 {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
693 {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
694 {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
695 {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
696 {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
697 {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
698 {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
699 {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
700 {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
701 {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
702 {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
703 {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
704 {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
705 {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
706 {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
707 {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
708 {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
709 {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
710 {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
711 {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
712 {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
713 {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
714 {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
715 {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
716 {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
717 {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
718 {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
719 {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
720 {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
721 {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
722 {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
723 {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
724 {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
725 {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
726 {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
727 {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
728 {}
729};
730static const u8 gc0307_sensor_param1[][8] = {
731 {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
732 {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
733 {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
734 {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
735/*param3*/
736 {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
737 {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
738 {}
739};
740
741static const u8 hv7131r_sensor_init[][8] = {
742 {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
743 {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
744 {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
745/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
746 {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
747 {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
748/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
749
750 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
751 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
752 {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
753 {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
754 {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
755 {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
756 {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
757 {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
758
759 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
760 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
761 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
762 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
763 {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
764
765 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
766 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
767 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
768 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
769 {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
770 {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
771 /* set sensor clock */
772 {}
773};
774static const u8 mi0360_sensor_init[][8] = {
775 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
776 {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
777 {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
778 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
779 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
780 {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
781 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
782 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
783 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
784 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
785 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
786 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
787 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
788 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
789 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
790 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
791 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
792 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
793 {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
794 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
795 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
796 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
797 {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
798 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
799 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
800 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
801 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
802 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
803 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
804 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
805 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
806 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
807 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
808
809 {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
810 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
811 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
812 {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
813 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
814
815 {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
816 {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
817 {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
818 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
819
820 {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
821 {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
822/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
823/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
824 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
825 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
826 {}
827};
828static const u8 mi0360b_sensor_init[][8] = {
829 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
830 {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
831 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
832 {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
833 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
834 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
835 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
836 {0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
837 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
838 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
839 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
840 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
841 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
842 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
843 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
844 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
845 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
846 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
847 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
848 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
849 {0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
850 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
851 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
852 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
853 {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
854 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
855 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
856 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
857 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
858 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
859 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
860 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
861 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
862 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
863 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
864
865 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
866 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
867 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
868 {0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
869 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
870 {}
871};
872static const u8 mi0360b_sensor_param1[][8] = {
873 {0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
874 {0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
875 {0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
876 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
877
878 {0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
879 {0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
880 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
881 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
882 {}
883};
884static const u8 mo4000_sensor_init[][8] = {
885 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
886 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
887 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
888 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
889 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
890 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
891 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
892 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
893 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
894 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
895 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
896 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
897 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
898 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
899 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
900 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
901 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
902 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
903 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
904 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
905 {}
906};
907static const u8 mt9v111_sensor_init[][8] = {
908 {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
909 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
910 {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
911 {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
912 {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
913 {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
914 {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
915 {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
916 {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
917 {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
918 {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
919 {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
920 {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
921 {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
922 {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
923 {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
924 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
925 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
926 {}
927};
928static const u8 mt9v111_sensor_param1[][8] = {
929 {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
930 {0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
931 {0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
932 {0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
933 {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
934 {}
935};
936static const u8 om6802_init0[2][8] = {
937/*fixme: variable*/
938 {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
939 {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
940};
941static const u8 om6802_sensor_init[][8] = {
942 {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
943 /* factory mode */
944 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
945 /* output raw RGB */
946 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
947/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
948 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
949 /* auto-exposure speed (0) / white balance mode (auto RGB) */
950/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
951 * set color mode */
952/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
953 * max AGC value in AE */
954/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
955 * preset AGC */
956/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
957 * preset brightness */
958/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
959 * preset contrast */
960/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
961 * preset gamma */
962 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
963 /* luminance mode (0x4f -> AutoExpo on) */
964 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
965 /* preset shutter */
966/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
967 * auto frame rate */
968/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
969 {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
970 {}
971};
972static const u8 om6802_sensor_param1[][8] = {
973 {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
974 {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
975 {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
976 {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
977 {}
978};
979static const u8 ov7630_sensor_init[][8] = {
980 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
981 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
982 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
983 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
984 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
985 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
986 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
987/* win: i2c_r from 00 to 80 */
988 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
989 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
990/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
991 0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
992 {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
993 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
994 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
995 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
996 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
997 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
998 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
999 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
1000 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
1001 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
1002 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
1003 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
1004 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
1005 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
1006 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
1007 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
1008 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
1009 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
1010 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
1011 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
1012 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
1013 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
1014 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
1015 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
1016 {}
1017};
1018static const u8 ov7630_sensor_param1[][8] = {
1019 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
1020 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
1021/*fixme: + 0x12, 0x04*/
1022/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
1023 * set by setvflip */
1024 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
1025 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1026 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
1027/* */
1028/* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
1029/* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
1030/* */
1031 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
1032/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
1033 {}
1034};
1035
1036static const u8 ov7648_sensor_init[][8] = {
1037 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
1038 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
1039 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1040 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
1041 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
1042 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
1043 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
1044 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
1045 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
1046 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
1047 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
1048 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
1049 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
1050 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
1051 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
1052 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
1053 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
1054 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
1055 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
1056 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
1057 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
1058 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
1059
1060 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
1061/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
1062/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
1063/* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
1064 {}
1065};
1066static const u8 ov7648_sensor_param1[][8] = {
1067/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
1068/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN
1069 * set by setvflip */
1070 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
1071 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
1072/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1073/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
1074/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
1075/*...*/
1076 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
1077/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1078/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1079/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
1080/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1081/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
1082
1083 {}
1084};
1085
1086static const u8 ov7660_sensor_init[][8] = {
1087 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
1088 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1089 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
1090 /* Outformat = rawRGB */
1091 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
1092 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
1093 /* GAIN BLUE RED VREF */
1094 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
1095 /* COM 1 BAVE GEAVE AECHH */
1096 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
1097 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
1098 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
1099 /* AECH CLKRC COM7 COM8 */
1100 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
1101 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
1102 /* HSTART HSTOP VSTRT VSTOP */
1103 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
1104 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
1105 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
1106 /* BOS GBOS GROS ROS (BGGR offset) */
1107/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
1108 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
1109 /* AEW AEB VPT BBIAS */
1110 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
1111 /* GbBIAS RSVD EXHCH EXHCL */
1112 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
1113 /* RBIAS ADVFL ASDVFH YAVE */
1114 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
1115 /* HSYST HSYEN HREF */
1116 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
1117 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
1118 /* ADC ACOM OFON TSLB */
1119 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
1120 /* COM11 COM12 COM13 COM14 */
1121 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
1122 /* EDGE COM15 COM16 COM17 */
1123 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
1124 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
1125 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
1126 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
1127 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
1128 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
1129 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
1130 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
1131 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
1132 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
1133 /* LCC1 LCC2 LCC3 LCC4 */
1134 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
1135 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
1136 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
1137 /* band gap reference [0:3] DBLV */
1138 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
1139 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
1140 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
1141 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
1142 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
1143 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
1144 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
1145 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
1146 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
1147 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
1148/* not in all ms-win traces*/
1149 {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
1150 {}
1151};
1152static const u8 ov7660_sensor_param1[][8] = {
1153 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
1154 /* bits[3..0]reserved */
1155 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
1156 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
1157 /* VREF vertical frame ctrl */
1158 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
1159 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
1160 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
1161 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
1162 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
1163/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
1164/****** (some exchanges in the win trace) ******/
1165/*fixme:param2*/
1166 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
1167 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
1168 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
1169 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
1170/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
1171/****** (some exchanges in the win trace) ******/
1172/******!! startsensor KO if changed !!****/
1173/*fixme: param3*/
1174 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
1175 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
1176 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
1177 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
1178 {}
1179};
1180
1181static const u8 po1030_sensor_init[][8] = {
1182/* the sensor registers are described in m5602/m5602_po1030.h */
1183 {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
1184 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1185 {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
1186 {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
1187 {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
1188 {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
1189 {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
1190 {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
1191 {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
1192 {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
1193 {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
1194 {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
1195 {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
1196 {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
1197 {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
1198 {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
1199 {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
1200 {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
1201 {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
1202 {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
1203 {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
1204 {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
1205 {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
1206 {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
1207 {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
1208 {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
1209 {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
1210 {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},
1211
1212 {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
1213 {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
1214 {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
1215 {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
1216 {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
1217 {}
1218};
1219static const u8 po1030_sensor_param1[][8] = {
1220/* from ms-win traces - these values change with auto gain/expo/wb.. */
1221 {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
1222 {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
1223/* mean values */
1224 {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
1225 {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
1226 {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */
1227
1228 {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
1229 {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
1230 {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
1231/* {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
1232 {}
1233};
1234
1235static const u8 po2030n_sensor_init[][8] = {
1236 {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
1237 {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
1238 {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
1239 {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
1240 {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
1241 {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
1242 {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
1243 {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
1244 {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
1245 {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
1246 {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
1247 {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
1248 {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
1249 {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
1250 {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
1251 {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
1252 {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
1253 {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
1254 {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
1255 {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
1256 {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
1257 {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
1258 {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
1259 {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
1260 {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
1261 {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
1262 {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
1263 {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
1264 {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
1265 {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
1266 {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
1267 {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
1268 {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
1269 {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
1270 {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
1271 {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
1272 {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
1273 {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
1274 {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
1275 {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
1276 {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
1277 {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
1278 {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
1279 {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
1280 {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
1281 {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
1282 {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
1283 {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
1284 {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
1285 {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
1286 {}
1287};
1288static const u8 po2030n_sensor_param1[][8] = {
1289 {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
1290 {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
1291 {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
1292 {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
1293 {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
1294/*param2*/
1295 {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
1296 {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
1297 {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
1298 {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
1299 {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
1300 {}
1301};
1302
1303static const u8 soi768_sensor_init[][8] = {
1304 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
1305 {DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
1306 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
1307 {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
1308 {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
1309 {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
1310 {}
1311};
1312static const u8 soi768_sensor_param1[][8] = {
1313 {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
1314 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
1315 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
1316 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1317 {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
1318/* */
1319/* {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
1320/* {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
1321 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
1322/* {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
1323 {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
1324/* the next sequence should be used for auto gain */
1325 {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
1326 /* global gain ? : 07 - change with 0x15 at the end */
1327 {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
1328 {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
1329 {0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
1330 /* exposure ? : 0200 - change with 0x1e at the end */
1331 {}
1332};
1333
1334static const u8 sp80708_sensor_init[][8] = {
1335 {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
1336 {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
1337 {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
1338 {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
1339 {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
1340 {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
1341 {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
1342 {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
1343 {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
1344 {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
1345 {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
1346 {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
1347 {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
1348 {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
1349 {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
1350 {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
1351 {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
1352 {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
1353 {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
1354 {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
1355 {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
1356 {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
1357 {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
1358 {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
1359 {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
1360 {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
1361 {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
1362 {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
1363 {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
1364 {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
1365 {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
1366 {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
1367 {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
1368 {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
1369 {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
1370 {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
1371 {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
1372 {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
1373 {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
1374 {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
1375 {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
1376 {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
1377 {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
1378 {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
1379 {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
1380 {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
1381 {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
1382 {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
1383 {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
1384 {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
1385 {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
1386 {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
1387 {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
1388 {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
1389 {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
1390 {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
1391 {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
1392 {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
1393 {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
1394 {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
1395 {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
1396 {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
1397 {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
1398 {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
1399 {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
1400 {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
1401 {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
1402 {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
1403 {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
1404 {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
1405 {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
1406 {}
1407};
1408static const u8 sp80708_sensor_param1[][8] = {
1409 {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
1410 {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
1411 {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
1412 {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
1413 {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
1414 {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
1415 {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
1416 {}
1417};
1418
1419static const u8 (*sensor_init[])[8] = {
1420[SENSOR_ADCM1700] = adcm1700_sensor_init,
1421[SENSOR_GC0307] = gc0307_sensor_init,
1422[SENSOR_HV7131R] = hv7131r_sensor_init,
1423[SENSOR_MI0360] = mi0360_sensor_init,
1424[SENSOR_MI0360B] = mi0360b_sensor_init,
1425[SENSOR_MO4000] = mo4000_sensor_init,
1426[SENSOR_MT9V111] = mt9v111_sensor_init,
1427[SENSOR_OM6802] = om6802_sensor_init,
1428[SENSOR_OV7630] = ov7630_sensor_init,
1429[SENSOR_OV7648] = ov7648_sensor_init,
1430[SENSOR_OV7660] = ov7660_sensor_init,
1431[SENSOR_PO1030] = po1030_sensor_init,
1432[SENSOR_PO2030N] = po2030n_sensor_init,
1433[SENSOR_SOI768] = soi768_sensor_init,
1434[SENSOR_SP80708] = sp80708_sensor_init,
1435};
1436
1437/* read <len> bytes to gspca_dev->usb_buf */
1438static void reg_r(struct gspca_dev *gspca_dev,
1439 u16 value, int len)
1440{
1441 int ret;
1442
1443 if (gspca_dev->usb_err < 0)
1444 return;
1445#ifdef GSPCA_DEBUG
1446 if (len > USB_BUF_SZ) {
1447 pr_err("reg_r: buffer overflow\n");
1448 return;
1449 }
1450#endif
1451 ret = usb_control_msg(gspca_dev->dev,
1452 usb_rcvctrlpipe(gspca_dev->dev, 0),
1453 0,
1454 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1455 value, 0,
1456 gspca_dev->usb_buf, len,
1457 500);
1458 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
1459 if (ret < 0) {
1460 pr_err("reg_r err %d\n", ret);
1461 gspca_dev->usb_err = ret;
1462 }
1463}
1464
1465static void reg_w1(struct gspca_dev *gspca_dev,
1466 u16 value,
1467 u8 data)
1468{
1469 int ret;
1470
1471 if (gspca_dev->usb_err < 0)
1472 return;
1473 PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
1474 gspca_dev->usb_buf[0] = data;
1475 ret = usb_control_msg(gspca_dev->dev,
1476 usb_sndctrlpipe(gspca_dev->dev, 0),
1477 0x08,
1478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1479 value,
1480 0,
1481 gspca_dev->usb_buf, 1,
1482 500);
1483 if (ret < 0) {
1484 pr_err("reg_w1 err %d\n", ret);
1485 gspca_dev->usb_err = ret;
1486 }
1487}
1488static void reg_w(struct gspca_dev *gspca_dev,
1489 u16 value,
1490 const u8 *buffer,
1491 int len)
1492{
1493 int ret;
1494
1495 if (gspca_dev->usb_err < 0)
1496 return;
1497 PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
1498 value, buffer[0], buffer[1]);
1499#ifdef GSPCA_DEBUG
1500 if (len > USB_BUF_SZ) {
1501 pr_err("reg_w: buffer overflow\n");
1502 return;
1503 }
1504#endif
1505 memcpy(gspca_dev->usb_buf, buffer, len);
1506 ret = usb_control_msg(gspca_dev->dev,
1507 usb_sndctrlpipe(gspca_dev->dev, 0),
1508 0x08,
1509 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1510 value, 0,
1511 gspca_dev->usb_buf, len,
1512 500);
1513 if (ret < 0) {
1514 pr_err("reg_w err %d\n", ret);
1515 gspca_dev->usb_err = ret;
1516 }
1517}
1518
1519/* I2C write 1 byte */
1520static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1521{
1522 struct sd *sd = (struct sd *) gspca_dev;
1523 int ret;
1524
1525 if (gspca_dev->usb_err < 0)
1526 return;
1527 PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val);
1528 switch (sd->sensor) {
1529 case SENSOR_ADCM1700:
1530 case SENSOR_OM6802:
1531 case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */
1532 gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
1533 break;
1534 default: /* i2c command = a1 (400 kHz) */
1535 gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
1536 break;
1537 }
1538 gspca_dev->usb_buf[1] = sd->i2c_addr;
1539 gspca_dev->usb_buf[2] = reg;
1540 gspca_dev->usb_buf[3] = val;
1541 gspca_dev->usb_buf[4] = 0;
1542 gspca_dev->usb_buf[5] = 0;
1543 gspca_dev->usb_buf[6] = 0;
1544 gspca_dev->usb_buf[7] = 0x10;
1545 ret = usb_control_msg(gspca_dev->dev,
1546 usb_sndctrlpipe(gspca_dev->dev, 0),
1547 0x08,
1548 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1549 0x08, /* value = i2c */
1550 0,
1551 gspca_dev->usb_buf, 8,
1552 500);
1553 if (ret < 0) {
1554 pr_err("i2c_w1 err %d\n", ret);
1555 gspca_dev->usb_err = ret;
1556 }
1557}
1558
1559/* I2C write 8 bytes */
1560static void i2c_w8(struct gspca_dev *gspca_dev,
1561 const u8 *buffer)
1562{
1563 int ret;
1564
1565 if (gspca_dev->usb_err < 0)
1566 return;
1567 PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..",
1568 buffer[2], buffer[3]);
1569 memcpy(gspca_dev->usb_buf, buffer, 8);
1570 ret = usb_control_msg(gspca_dev->dev,
1571 usb_sndctrlpipe(gspca_dev->dev, 0),
1572 0x08,
1573 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1574 0x08, 0, /* value, index */
1575 gspca_dev->usb_buf, 8,
1576 500);
1577 msleep(2);
1578 if (ret < 0) {
1579 pr_err("i2c_w8 err %d\n", ret);
1580 gspca_dev->usb_err = ret;
1581 }
1582}
1583
1584/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
1585static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
1586{
1587 struct sd *sd = (struct sd *) gspca_dev;
1588 u8 mode[8];
1589
1590 switch (sd->sensor) {
1591 case SENSOR_ADCM1700:
1592 case SENSOR_OM6802:
1593 case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */
1594 mode[0] = 0x80 | 0x10;
1595 break;
1596 default: /* i2c command = 91 (400 kHz) */
1597 mode[0] = 0x81 | 0x10;
1598 break;
1599 }
1600 mode[1] = sd->i2c_addr;
1601 mode[2] = reg;
1602 mode[3] = 0;
1603 mode[4] = 0;
1604 mode[5] = 0;
1605 mode[6] = 0;
1606 mode[7] = 0x10;
1607 i2c_w8(gspca_dev, mode);
1608 msleep(2);
1609 mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
1610 mode[2] = 0;
1611 i2c_w8(gspca_dev, mode);
1612 msleep(2);
1613 reg_r(gspca_dev, 0x0a, 5);
1614}
1615
1616static void i2c_w_seq(struct gspca_dev *gspca_dev,
1617 const u8 (*data)[8])
1618{
1619 while ((*data)[0] != 0) {
1620 if ((*data)[0] != DELAY)
1621 i2c_w8(gspca_dev, *data);
1622 else
1623 msleep((*data)[1]);
1624 data++;
1625 }
1626}
1627
1628/* check the ID of the hv7131 sensor */
1629/* this sequence is needed because it activates the sensor */
1630static void hv7131r_probe(struct gspca_dev *gspca_dev)
1631{
1632 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
1633 msleep(10);
1634 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
1635 msleep(10);
1636 i2c_r(gspca_dev, 0, 5); /* read sensor id */
1637 if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */
1638 && gspca_dev->usb_buf[1] == 0x09
1639 && gspca_dev->usb_buf[2] == 0x01) {
1640 PDEBUG(D_PROBE, "Sensor HV7131R found");
1641 return;
1642 }
1643 pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
1644 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
1645 gspca_dev->usb_buf[2]);
1646}
1647
1648static void mi0360_probe(struct gspca_dev *gspca_dev)
1649{
1650 struct sd *sd = (struct sd *) gspca_dev;
1651 int i, j;
1652 u16 val = 0;
1653 static const u8 probe_tb[][4][8] = {
1654 { /* mi0360 */
1655 {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
1656 {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1657 {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1658 {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
1659 },
1660 { /* mt9v111 */
1661 {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
1662 {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
1663 {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1664 {}
1665 },
1666 };
1667
1668 for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
1669 reg_w1(gspca_dev, 0x17, 0x62);
1670 reg_w1(gspca_dev, 0x01, 0x08);
1671 for (j = 0; j < 3; j++)
1672 i2c_w8(gspca_dev, probe_tb[i][j]);
1673 msleep(2);
1674 reg_r(gspca_dev, 0x0a, 5);
1675 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1676 if (probe_tb[i][3][0] != 0)
1677 i2c_w8(gspca_dev, probe_tb[i][3]);
1678 reg_w1(gspca_dev, 0x01, 0x29);
1679 reg_w1(gspca_dev, 0x17, 0x42);
1680 if (val != 0xffff)
1681 break;
1682 }
1683 if (gspca_dev->usb_err < 0)
1684 return;
1685 switch (val) {
1686 case 0x8221:
1687 PDEBUG(D_PROBE, "Sensor mi0360b");
1688 sd->sensor = SENSOR_MI0360B;
1689 break;
1690 case 0x823a:
1691 PDEBUG(D_PROBE, "Sensor mt9v111");
1692 sd->sensor = SENSOR_MT9V111;
1693 break;
1694 case 0x8243:
1695 PDEBUG(D_PROBE, "Sensor mi0360");
1696 break;
1697 default:
1698 PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
1699 break;
1700 }
1701}
1702
1703static void ov7630_probe(struct gspca_dev *gspca_dev)
1704{
1705 struct sd *sd = (struct sd *) gspca_dev;
1706 u16 val;
1707
1708 /* check ov76xx */
1709 reg_w1(gspca_dev, 0x17, 0x62);
1710 reg_w1(gspca_dev, 0x01, 0x08);
1711 sd->i2c_addr = 0x21;
1712 i2c_r(gspca_dev, 0x0a, 2);
1713 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1714 reg_w1(gspca_dev, 0x01, 0x29);
1715 reg_w1(gspca_dev, 0x17, 0x42);
1716 if (gspca_dev->usb_err < 0)
1717 return;
1718 if (val == 0x7628) { /* soi768 */
1719 sd->sensor = SENSOR_SOI768;
1720/*fixme: only valid for 0c45:613e?*/
1721 gspca_dev->cam.input_flags =
1722 V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
1723 PDEBUG(D_PROBE, "Sensor soi768");
1724 return;
1725 }
1726 PDEBUG(D_PROBE, "Sensor ov%04x", val);
1727}
1728
1729static void ov7648_probe(struct gspca_dev *gspca_dev)
1730{
1731 struct sd *sd = (struct sd *) gspca_dev;
1732 u16 val;
1733
1734 /* check ov76xx */
1735 reg_w1(gspca_dev, 0x17, 0x62);
1736 reg_w1(gspca_dev, 0x01, 0x08);
1737 sd->i2c_addr = 0x21;
1738 i2c_r(gspca_dev, 0x0a, 2);
1739 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1740 reg_w1(gspca_dev, 0x01, 0x29);
1741 reg_w1(gspca_dev, 0x17, 0x42);
1742 if ((val & 0xff00) == 0x7600) { /* ov76xx */
1743 PDEBUG(D_PROBE, "Sensor ov%04x", val);
1744 return;
1745 }
1746
1747 /* check po1030 */
1748 reg_w1(gspca_dev, 0x17, 0x62);
1749 reg_w1(gspca_dev, 0x01, 0x08);
1750 sd->i2c_addr = 0x6e;
1751 i2c_r(gspca_dev, 0x00, 2);
1752 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1753 reg_w1(gspca_dev, 0x01, 0x29);
1754 reg_w1(gspca_dev, 0x17, 0x42);
1755 if (gspca_dev->usb_err < 0)
1756 return;
1757 if (val == 0x1030) { /* po1030 */
1758 PDEBUG(D_PROBE, "Sensor po1030");
1759 sd->sensor = SENSOR_PO1030;
1760 return;
1761 }
1762 pr_err("Unknown sensor %04x\n", val);
1763}
1764
1765/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
1766static void po2030n_probe(struct gspca_dev *gspca_dev)
1767{
1768 struct sd *sd = (struct sd *) gspca_dev;
1769 u16 val;
1770
1771 /* check gc0307 */
1772 reg_w1(gspca_dev, 0x17, 0x62);
1773 reg_w1(gspca_dev, 0x01, 0x08);
1774 reg_w1(gspca_dev, 0x02, 0x22);
1775 sd->i2c_addr = 0x21;
1776 i2c_r(gspca_dev, 0x00, 1);
1777 val = gspca_dev->usb_buf[4];
1778 reg_w1(gspca_dev, 0x01, 0x29); /* reset */
1779 reg_w1(gspca_dev, 0x17, 0x42);
1780 if (val == 0x99) { /* gc0307 (?) */
1781 PDEBUG(D_PROBE, "Sensor gc0307");
1782 sd->sensor = SENSOR_GC0307;
1783 return;
1784 }
1785
1786 /* check po2030n */
1787 reg_w1(gspca_dev, 0x17, 0x62);
1788 reg_w1(gspca_dev, 0x01, 0x0a);
1789 sd->i2c_addr = 0x6e;
1790 i2c_r(gspca_dev, 0x00, 2);
1791 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1792 reg_w1(gspca_dev, 0x01, 0x29);
1793 reg_w1(gspca_dev, 0x17, 0x42);
1794 if (gspca_dev->usb_err < 0)
1795 return;
1796 if (val == 0x2030) {
1797 PDEBUG(D_PROBE, "Sensor po2030n");
1798/* sd->sensor = SENSOR_PO2030N; */
1799 } else {
1800 pr_err("Unknown sensor ID %04x\n", val);
1801 }
1802}
1803
1804/* this function is called at probe time */
1805static int sd_config(struct gspca_dev *gspca_dev,
1806 const struct usb_device_id *id)
1807{
1808 struct sd *sd = (struct sd *) gspca_dev;
1809 struct cam *cam;
1810
1811 sd->bridge = id->driver_info >> 16;
1812 sd->sensor = id->driver_info >> 8;
1813 sd->flags = id->driver_info;
1814
1815 cam = &gspca_dev->cam;
1816 if (sd->sensor == SENSOR_ADCM1700) {
1817 cam->cam_mode = cif_mode;
1818 cam->nmodes = ARRAY_SIZE(cif_mode);
1819 } else {
1820 cam->cam_mode = vga_mode;
1821 cam->nmodes = ARRAY_SIZE(vga_mode);
1822 }
1823 cam->npkt = 24; /* 24 packets per ISOC message */
1824 cam->ctrls = sd->ctrls;
1825
1826 sd->ag_cnt = -1;
1827 sd->quality = QUALITY_DEF;
1828
1829 INIT_WORK(&sd->work, qual_upd);
1830
1831 return 0;
1832}
1833
1834/* this function is called at probe and resume time */
1835static int sd_init(struct gspca_dev *gspca_dev)
1836{
1837 struct sd *sd = (struct sd *) gspca_dev;
1838 const u8 *sn9c1xx;
1839 u8 regGpio[] = { 0x29, 0x70 }; /* no audio */
1840 u8 regF1;
1841
1842 /* setup a selector by bridge */
1843 reg_w1(gspca_dev, 0xf1, 0x01);
1844 reg_r(gspca_dev, 0x00, 1);
1845 reg_w1(gspca_dev, 0xf1, 0x00);
1846 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
1847 regF1 = gspca_dev->usb_buf[0];
1848 if (gspca_dev->usb_err < 0)
1849 return gspca_dev->usb_err;
1850 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1851 if (gspca_dev->audio)
1852 regGpio[1] |= 0x04; /* with audio */
1853 switch (sd->bridge) {
1854 case BRIDGE_SN9C102P:
1855 case BRIDGE_SN9C105:
1856 if (regF1 != 0x11)
1857 return -ENODEV;
1858 break;
1859 default:
1860/* case BRIDGE_SN9C110: */
1861/* case BRIDGE_SN9C120: */
1862 if (regF1 != 0x12)
1863 return -ENODEV;
1864 }
1865
1866 switch (sd->sensor) {
1867 case SENSOR_MI0360:
1868 mi0360_probe(gspca_dev);
1869 break;
1870 case SENSOR_OV7630:
1871 ov7630_probe(gspca_dev);
1872 break;
1873 case SENSOR_OV7648:
1874 ov7648_probe(gspca_dev);
1875 break;
1876 case SENSOR_PO2030N:
1877 po2030n_probe(gspca_dev);
1878 break;
1879 }
1880
1881 switch (sd->bridge) {
1882 case BRIDGE_SN9C102P:
1883 reg_w1(gspca_dev, 0x02, regGpio[1]);
1884 break;
1885 default:
1886 reg_w(gspca_dev, 0x01, regGpio, 2);
1887 break;
1888 }
1889
1890 if (sd->sensor == SENSOR_OM6802)
1891 sd->ctrls[SHARPNESS].def = 0x10;
1892
1893 /* Note we do not disable the sensor clock here (power saving mode),
1894 as that also disables the button on the cam. */
1895 reg_w1(gspca_dev, 0xf1, 0x00);
1896
1897 /* set the i2c address */
1898 sn9c1xx = sn_tb[sd->sensor];
1899 sd->i2c_addr = sn9c1xx[9];
1900
1901 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
1902 if (!(sd->flags & F_ILLUM))
1903 gspca_dev->ctrl_dis |= (1 << ILLUM);
1904
1905 return gspca_dev->usb_err;
1906}
1907
1908static u32 expo_adjust(struct gspca_dev *gspca_dev,
1909 u32 expo)
1910{
1911 struct sd *sd = (struct sd *) gspca_dev;
1912
1913 switch (sd->sensor) {
1914 case SENSOR_GC0307: {
1915 int a, b;
1916
1917 /* expo = 0..255 -> a = 19..43 */
1918 a = 19 + expo * 25 / 256;
1919 i2c_w1(gspca_dev, 0x68, a);
1920 a -= 12;
1921 b = a * a * 4; /* heuristic */
1922 i2c_w1(gspca_dev, 0x03, b >> 8);
1923 i2c_w1(gspca_dev, 0x04, b);
1924 break;
1925 }
1926 case SENSOR_HV7131R: {
1927 u8 Expodoit[] =
1928 { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
1929
1930 Expodoit[3] = expo >> 16;
1931 Expodoit[4] = expo >> 8;
1932 Expodoit[5] = expo;
1933 i2c_w8(gspca_dev, Expodoit);
1934 break;
1935 }
1936 case SENSOR_MI0360:
1937 case SENSOR_MI0360B: {
1938 u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1939 { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
1940 static const u8 doit[] = /* update sensor */
1941 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1942 static const u8 sensorgo[] = /* sensor on */
1943 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1944
1945 if (expo > 0x0635)
1946 expo = 0x0635;
1947 else if (expo < 0x0001)
1948 expo = 0x0001;
1949 expoMi[3] = expo >> 8;
1950 expoMi[4] = expo;
1951 i2c_w8(gspca_dev, expoMi);
1952 i2c_w8(gspca_dev, doit);
1953 i2c_w8(gspca_dev, sensorgo);
1954 break;
1955 }
1956 case SENSOR_MO4000: {
1957 u8 expoMof[] =
1958 { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
1959 u8 expoMo10[] =
1960 { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
1961 static const u8 gainMo[] =
1962 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1963
1964 if (expo > 0x1fff)
1965 expo = 0x1fff;
1966 else if (expo < 0x0001)
1967 expo = 0x0001;
1968 expoMof[3] = (expo & 0x03fc) >> 2;
1969 i2c_w8(gspca_dev, expoMof);
1970 expoMo10[3] = ((expo & 0x1c00) >> 10)
1971 | ((expo & 0x0003) << 4);
1972 i2c_w8(gspca_dev, expoMo10);
1973 i2c_w8(gspca_dev, gainMo);
1974 PDEBUG(D_FRAM, "set exposure %d",
1975 ((expoMo10[3] & 0x07) << 10)
1976 | (expoMof[3] << 2)
1977 | ((expoMo10[3] & 0x30) >> 4));
1978 break;
1979 }
1980 case SENSOR_MT9V111: {
1981 u8 expo_c1[] =
1982 { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
1983
1984 if (expo > 0x0390)
1985 expo = 0x0390;
1986 else if (expo < 0x0060)
1987 expo = 0x0060;
1988 expo_c1[3] = expo >> 8;
1989 expo_c1[4] = expo;
1990 i2c_w8(gspca_dev, expo_c1);
1991 break;
1992 }
1993 case SENSOR_OM6802: {
1994 u8 gainOm[] =
1995 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1996 /* preset AGC - works when AutoExpo = off */
1997
1998 if (expo > 0x03ff)
1999 expo = 0x03ff;
2000 if (expo < 0x0001)
2001 expo = 0x0001;
2002 gainOm[3] = expo >> 2;
2003 i2c_w8(gspca_dev, gainOm);
2004 reg_w1(gspca_dev, 0x96, expo >> 5);
2005 PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
2006 break;
2007 }
2008 }
2009 return expo;
2010}
2011
2012static void setbrightness(struct gspca_dev *gspca_dev)
2013{
2014 struct sd *sd = (struct sd *) gspca_dev;
2015 unsigned int expo;
2016 int brightness;
2017 u8 k2;
2018
2019 brightness = sd->ctrls[BRIGHTNESS].val;
2020 k2 = (brightness - 0x80) >> 2;
2021 switch (sd->sensor) {
2022 case SENSOR_ADCM1700:
2023 if (k2 > 0x1f)
2024 k2 = 0; /* only positive Y offset */
2025 break;
2026 case SENSOR_HV7131R:
2027 expo = brightness << 12;
2028 if (expo > 0x002dc6c0)
2029 expo = 0x002dc6c0;
2030 else if (expo < 0x02a0)
2031 expo = 0x02a0;
2032 sd->exposure = expo_adjust(gspca_dev, expo);
2033 break;
2034 case SENSOR_MI0360:
2035 case SENSOR_MO4000:
2036 expo = brightness << 4;
2037 sd->exposure = expo_adjust(gspca_dev, expo);
2038 break;
2039 case SENSOR_MI0360B:
2040 expo = brightness << 2;
2041 sd->exposure = expo_adjust(gspca_dev, expo);
2042 break;
2043 case SENSOR_GC0307:
2044 expo = brightness;
2045 sd->exposure = expo_adjust(gspca_dev, expo);
2046 return; /* don't set the Y offset */
2047 case SENSOR_MT9V111:
2048 expo = brightness << 2;
2049 sd->exposure = expo_adjust(gspca_dev, expo);
2050 return; /* don't set the Y offset */
2051 case SENSOR_OM6802:
2052 expo = brightness << 2;
2053 sd->exposure = expo_adjust(gspca_dev, expo);
2054 return; /* Y offset already set */
2055 }
2056
2057 reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
2058}
2059
2060static void setcontrast(struct gspca_dev *gspca_dev)
2061{
2062 struct sd *sd = (struct sd *) gspca_dev;
2063 u8 k2;
2064 u8 contrast[6];
2065
2066 k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
2067 + 37; /* 37..73 */
2068 contrast[0] = (k2 + 1) / 2; /* red */
2069 contrast[1] = 0;
2070 contrast[2] = k2; /* green */
2071 contrast[3] = 0;
2072 contrast[4] = k2 / 5; /* blue */
2073 contrast[5] = 0;
2074 reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
2075}
2076
2077static void setcolors(struct gspca_dev *gspca_dev)
2078{
2079 struct sd *sd = (struct sd *) gspca_dev;
2080 int i, v, colors;
2081 const s16 *uv;
2082 u8 reg8a[12]; /* U & V gains */
2083 static const s16 uv_com[6] = { /* same as reg84 in signed decimal */
2084 -24, -38, 64, /* UR UG UB */
2085 62, -51, -9 /* VR VG VB */
2086 };
2087 static const s16 uv_mi0360b[6] = {
2088 -20, -38, 64, /* UR UG UB */
2089 60, -51, -9 /* VR VG VB */
2090 };
2091
2092 colors = sd->ctrls[COLORS].val;
2093 if (sd->sensor == SENSOR_MI0360B)
2094 uv = uv_mi0360b;
2095 else
2096 uv = uv_com;
2097 for (i = 0; i < 6; i++) {
2098 v = uv[i] * colors / COLORS_DEF;
2099 reg8a[i * 2] = v;
2100 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
2101 }
2102 reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
2103}
2104
2105static void setredblue(struct gspca_dev *gspca_dev)
2106{
2107 struct sd *sd = (struct sd *) gspca_dev;
2108
2109 if (sd->sensor == SENSOR_PO2030N) {
2110 u8 rg1b[] = /* red green1 blue (no g2) */
2111 {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
2112
2113 /* 0x40 = normal value = gain x 1 */
2114 rg1b[3] = sd->ctrls[RED].val * 2;
2115 rg1b[5] = sd->ctrls[BLUE].val * 2;
2116 i2c_w8(gspca_dev, rg1b);
2117 return;
2118 }
2119 reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
2120/* reg_w1(gspca_dev, 0x07, 32); */
2121 reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
2122}
2123
2124static void setgamma(struct gspca_dev *gspca_dev)
2125{
2126 struct sd *sd = (struct sd *) gspca_dev;
2127 int i, val;
2128 u8 gamma[17];
2129 const u8 *gamma_base;
2130 static const u8 delta[17] = {
2131 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
2132 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
2133 };
2134
2135 switch (sd->sensor) {
2136 case SENSOR_ADCM1700:
2137 gamma_base = gamma_spec_0;
2138 break;
2139 case SENSOR_HV7131R:
2140 case SENSOR_MI0360B:
2141 case SENSOR_MT9V111:
2142 gamma_base = gamma_spec_1;
2143 break;
2144 case SENSOR_GC0307:
2145 gamma_base = gamma_spec_2;
2146 break;
2147 case SENSOR_SP80708:
2148 gamma_base = gamma_spec_3;
2149 break;
2150 default:
2151 gamma_base = gamma_def;
2152 break;
2153 }
2154
2155 val = sd->ctrls[GAMMA].val;
2156 for (i = 0; i < sizeof gamma; i++)
2157 gamma[i] = gamma_base[i]
2158 + delta[i] * (val - GAMMA_DEF) / 32;
2159 reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
2160}
2161
2162static void setexposure(struct gspca_dev *gspca_dev)
2163{
2164 struct sd *sd = (struct sd *) gspca_dev;
2165
2166 if (sd->sensor == SENSOR_PO2030N) {
2167 u8 rexpo[] = /* 1a: expo H, 1b: expo M */
2168 {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10};
2169
2170 rexpo[3] = sd->ctrls[EXPOSURE].val >> 8;
2171 i2c_w8(gspca_dev, rexpo);
2172 msleep(6);
2173 rexpo[2] = 0x1b;
2174 rexpo[3] = sd->ctrls[EXPOSURE].val;
2175 i2c_w8(gspca_dev, rexpo);
2176 }
2177}
2178
2179static void setautogain(struct gspca_dev *gspca_dev)
2180{
2181 struct sd *sd = (struct sd *) gspca_dev;
2182
2183 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
2184 return;
2185 switch (sd->sensor) {
2186 case SENSOR_OV7630:
2187 case SENSOR_OV7648: {
2188 u8 comb;
2189
2190 if (sd->sensor == SENSOR_OV7630)
2191 comb = 0xc0;
2192 else
2193 comb = 0xa0;
2194 if (sd->ctrls[AUTOGAIN].val)
2195 comb |= 0x03;
2196 i2c_w1(&sd->gspca_dev, 0x13, comb);
2197 return;
2198 }
2199 }
2200 if (sd->ctrls[AUTOGAIN].val)
2201 sd->ag_cnt = AG_CNT_START;
2202 else
2203 sd->ag_cnt = -1;
2204}
2205
2206static void setgain(struct gspca_dev *gspca_dev)
2207{
2208 struct sd *sd = (struct sd *) gspca_dev;
2209
2210 if (sd->sensor == SENSOR_PO2030N) {
2211 u8 rgain[] = /* 15: gain */
2212 {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15};
2213
2214 rgain[3] = sd->ctrls[GAIN].val;
2215 i2c_w8(gspca_dev, rgain);
2216 }
2217}
2218
2219static void sethvflip(struct gspca_dev *gspca_dev)
2220{
2221 struct sd *sd = (struct sd *) gspca_dev;
2222 u8 comn;
2223
2224 switch (sd->sensor) {
2225 case SENSOR_HV7131R:
2226 comn = 0x18; /* clkdiv = 1, ablcen = 1 */
2227 if (sd->ctrls[VFLIP].val)
2228 comn |= 0x01;
2229 i2c_w1(gspca_dev, 0x01, comn); /* sctra */
2230 break;
2231 case SENSOR_OV7630:
2232 comn = 0x02;
2233 if (!sd->ctrls[VFLIP].val)
2234 comn |= 0x80;
2235 i2c_w1(gspca_dev, 0x75, comn);
2236 break;
2237 case SENSOR_OV7648:
2238 comn = 0x06;
2239 if (sd->ctrls[VFLIP].val)
2240 comn |= 0x80;
2241 i2c_w1(gspca_dev, 0x75, comn);
2242 break;
2243 case SENSOR_PO2030N:
2244 /* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
2245 * (reset value: 0x0A)
2246 * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
2247 * bit6: VM: Vertical Mirror: 0: disable, 1: enable
2248 * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
2249 * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
2250 * bit3-0: X
2251 */
2252 comn = 0x0a;
2253 if (sd->ctrls[HFLIP].val)
2254 comn |= 0x80;
2255 if (sd->ctrls[VFLIP].val)
2256 comn |= 0x40;
2257 i2c_w1(&sd->gspca_dev, 0x1e, comn);
2258 break;
2259 }
2260}
2261
2262static void setsharpness(struct gspca_dev *gspca_dev)
2263{
2264 struct sd *sd = (struct sd *) gspca_dev;
2265
2266 reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
2267}
2268
2269static void setillum(struct gspca_dev *gspca_dev)
2270{
2271 struct sd *sd = (struct sd *) gspca_dev;
2272
2273 if (gspca_dev->ctrl_dis & (1 << ILLUM))
2274 return;
2275 switch (sd->sensor) {
2276 case SENSOR_ADCM1700:
2277 reg_w1(gspca_dev, 0x02, /* gpio */
2278 sd->ctrls[ILLUM].val ? 0x64 : 0x60);
2279 break;
2280 case SENSOR_MT9V111:
2281 reg_w1(gspca_dev, 0x02,
2282 sd->ctrls[ILLUM].val ? 0x77 : 0x74);
2283/* should have been: */
2284/* 0x55 : 0x54); * 370i */
2285/* 0x66 : 0x64); * Clip */
2286 break;
2287 }
2288}
2289
2290static void setfreq(struct gspca_dev *gspca_dev)
2291{
2292 struct sd *sd = (struct sd *) gspca_dev;
2293
2294 if (gspca_dev->ctrl_dis & (1 << FREQ))
2295 return;
2296 if (sd->sensor == SENSOR_OV7660) {
2297 u8 com8;
2298
2299 com8 = 0xdf; /* auto gain/wb/expo */
2300 switch (sd->ctrls[FREQ].val) {
2301 case 0: /* Banding filter disabled */
2302 i2c_w1(gspca_dev, 0x13, com8 | 0x20);
2303 break;
2304 case 1: /* 50 hz */
2305 i2c_w1(gspca_dev, 0x13, com8);
2306 i2c_w1(gspca_dev, 0x3b, 0x0a);
2307 break;
2308 case 2: /* 60 hz */
2309 i2c_w1(gspca_dev, 0x13, com8);
2310 i2c_w1(gspca_dev, 0x3b, 0x02);
2311 break;
2312 }
2313 } else {
2314 u8 reg2a = 0, reg2b = 0, reg2d = 0;
2315
2316 /* Get reg2a / reg2d base values */
2317 switch (sd->sensor) {
2318 case SENSOR_OV7630:
2319 reg2a = 0x08;
2320 reg2d = 0x01;
2321 break;
2322 case SENSOR_OV7648:
2323 reg2a = 0x11;
2324 reg2d = 0x81;
2325 break;
2326 }
2327
2328 switch (sd->ctrls[FREQ].val) {
2329 case 0: /* Banding filter disabled */
2330 break;
2331 case 1: /* 50 hz (filter on and framerate adj) */
2332 reg2a |= 0x80;
2333 reg2b = 0xac;
2334 reg2d |= 0x04;
2335 break;
2336 case 2: /* 60 hz (filter on, no framerate adj) */
2337 reg2a |= 0x80;
2338 reg2d |= 0x04;
2339 break;
2340 }
2341 i2c_w1(gspca_dev, 0x2a, reg2a);
2342 i2c_w1(gspca_dev, 0x2b, reg2b);
2343 i2c_w1(gspca_dev, 0x2d, reg2d);
2344 }
2345}
2346
2347static void setjpegqual(struct gspca_dev *gspca_dev)
2348{
2349 struct sd *sd = (struct sd *) gspca_dev;
2350
2351 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2352#if USB_BUF_SZ < 64
2353#error "No room enough in usb_buf for quantization table"
2354#endif
2355 memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2356 usb_control_msg(gspca_dev->dev,
2357 usb_sndctrlpipe(gspca_dev->dev, 0),
2358 0x08,
2359 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2360 0x0100, 0,
2361 gspca_dev->usb_buf, 64,
2362 500);
2363 memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
2364 usb_control_msg(gspca_dev->dev,
2365 usb_sndctrlpipe(gspca_dev->dev, 0),
2366 0x08,
2367 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2368 0x0140, 0,
2369 gspca_dev->usb_buf, 64,
2370 500);
2371
2372 sd->reg18 ^= 0x40;
2373 reg_w1(gspca_dev, 0x18, sd->reg18);
2374}
2375
2376/* JPEG quality update */
2377/* This function is executed from a work queue. */
2378static void qual_upd(struct work_struct *work)
2379{
2380 struct sd *sd = container_of(work, struct sd, work);
2381 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2382
2383 mutex_lock(&gspca_dev->usb_lock);
2384 PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
2385 setjpegqual(gspca_dev);
2386 mutex_unlock(&gspca_dev->usb_lock);
2387}
2388
2389/* -- start the camera -- */
2390static int sd_start(struct gspca_dev *gspca_dev)
2391{
2392 struct sd *sd = (struct sd *) gspca_dev;
2393 int i;
2394 u8 reg01, reg17;
2395 u8 reg0102[2];
2396 const u8 *sn9c1xx;
2397 const u8 (*init)[8];
2398 const u8 *reg9a;
2399 int mode;
2400 static const u8 reg9a_def[] =
2401 {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
2402 static const u8 reg9a_spec[] =
2403 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
2404 static const u8 regd4[] = {0x60, 0x00, 0x00};
2405 static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
2406 static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
2407 static const u8 CA_adcm1700[] =
2408 { 0x14, 0xec, 0x0a, 0xf6 };
2409 static const u8 CA_po2030n[] =
2410 { 0x1e, 0xe2, 0x14, 0xec };
2411 static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
2412 static const u8 CE_gc0307[] =
2413 { 0x32, 0xce, 0x2d, 0xd3 };
2414 static const u8 CE_ov76xx[] =
2415 { 0x32, 0xdd, 0x32, 0xdd };
2416 static const u8 CE_po2030n[] =
2417 { 0x14, 0xe7, 0x1e, 0xdd };
2418
2419 /* create the JPEG header */
2420 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
2421 0x21); /* JPEG 422 */
2422
2423 /* initialize the bridge */
2424 sn9c1xx = sn_tb[sd->sensor];
2425
2426 /* sensor clock already enabled in sd_init */
2427 /* reg_w1(gspca_dev, 0xf1, 0x00); */
2428 reg01 = sn9c1xx[1];
2429 if (sd->flags & F_PDN_INV)
2430 reg01 ^= S_PDN_INV; /* power down inverted */
2431 reg_w1(gspca_dev, 0x01, reg01);
2432
2433 /* configure gpio */
2434 reg0102[0] = reg01;
2435 reg0102[1] = sn9c1xx[2];
2436 if (gspca_dev->audio)
2437 reg0102[1] |= 0x04; /* keep the audio connection */
2438 reg_w(gspca_dev, 0x01, reg0102, 2);
2439 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
2440 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
2441 switch (sd->sensor) {
2442 case SENSOR_GC0307:
2443 case SENSOR_OV7660:
2444 case SENSOR_PO1030:
2445 case SENSOR_PO2030N:
2446 case SENSOR_SOI768:
2447 case SENSOR_SP80708:
2448 reg9a = reg9a_spec;
2449 break;
2450 default:
2451 reg9a = reg9a_def;
2452 break;
2453 }
2454 reg_w(gspca_dev, 0x9a, reg9a, 6);
2455
2456 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
2457
2458 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
2459
2460 reg17 = sn9c1xx[0x17];
2461 switch (sd->sensor) {
2462 case SENSOR_GC0307:
2463 msleep(50); /*fixme: is it useful? */
2464 break;
2465 case SENSOR_OM6802:
2466 msleep(10);
2467 reg_w1(gspca_dev, 0x02, 0x73);
2468 reg17 |= SEN_CLK_EN;
2469 reg_w1(gspca_dev, 0x17, reg17);
2470 reg_w1(gspca_dev, 0x01, 0x22);
2471 msleep(100);
2472 reg01 = SCL_SEL_OD | S_PDN_INV;
2473 reg17 &= ~MCK_SIZE_MASK;
2474 reg17 |= 0x04; /* clock / 4 */
2475 break;
2476 }
2477 reg01 |= SYS_SEL_48M;
2478 reg_w1(gspca_dev, 0x01, reg01);
2479 reg17 |= SEN_CLK_EN;
2480 reg_w1(gspca_dev, 0x17, reg17);
2481 reg01 &= ~S_PWR_DN; /* sensor power on */
2482 reg_w1(gspca_dev, 0x01, reg01);
2483 reg01 &= ~SCL_SEL_OD; /* remove open-drain mode */
2484 reg_w1(gspca_dev, 0x01, reg01);
2485
2486 switch (sd->sensor) {
2487 case SENSOR_HV7131R:
2488 hv7131r_probe(gspca_dev); /*fixme: is it useful? */
2489 break;
2490 case SENSOR_OM6802:
2491 msleep(10);
2492 reg_w1(gspca_dev, 0x01, reg01);
2493 i2c_w8(gspca_dev, om6802_init0[0]);
2494 i2c_w8(gspca_dev, om6802_init0[1]);
2495 msleep(15);
2496 reg_w1(gspca_dev, 0x02, 0x71);
2497 msleep(150);
2498 break;
2499 case SENSOR_SP80708:
2500 msleep(100);
2501 reg_w1(gspca_dev, 0x02, 0x62);
2502 break;
2503 }
2504
2505 /* initialize the sensor */
2506 i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
2507
2508 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
2509 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
2510 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
2511 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
2512 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
2513 if (sd->sensor == SENSOR_ADCM1700) {
2514 reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */
2515 reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */
2516 } else {
2517 reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */
2518 reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */
2519 }
2520 reg_w1(gspca_dev, 0xc6, 0x00);
2521 reg_w1(gspca_dev, 0xc7, 0x00);
2522 if (sd->sensor == SENSOR_ADCM1700) {
2523 reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */
2524 reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */
2525 } else {
2526 reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */
2527 reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */
2528 }
2529 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
2530 switch (sd->sensor) {
2531 case SENSOR_OM6802:
2532/* case SENSOR_OV7648: * fixme: sometimes */
2533 break;
2534 default:
2535 reg17 |= DEF_EN;
2536 break;
2537 }
2538 reg_w1(gspca_dev, 0x17, reg17);
2539
2540 reg_w1(gspca_dev, 0x05, 0x00); /* red */
2541 reg_w1(gspca_dev, 0x07, 0x00); /* green */
2542 reg_w1(gspca_dev, 0x06, 0x00); /* blue */
2543 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
2544
2545 setgamma(gspca_dev);
2546
2547/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
2548 for (i = 0; i < 8; i++)
2549 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
2550 switch (sd->sensor) {
2551 case SENSOR_ADCM1700:
2552 case SENSOR_OV7660:
2553 case SENSOR_SP80708:
2554 reg_w1(gspca_dev, 0x9a, 0x05);
2555 break;
2556 case SENSOR_GC0307:
2557 case SENSOR_MT9V111:
2558 case SENSOR_MI0360B:
2559 reg_w1(gspca_dev, 0x9a, 0x07);
2560 break;
2561 case SENSOR_OV7630:
2562 case SENSOR_OV7648:
2563 reg_w1(gspca_dev, 0x9a, 0x0a);
2564 break;
2565 case SENSOR_PO2030N:
2566 case SENSOR_SOI768:
2567 reg_w1(gspca_dev, 0x9a, 0x06);
2568 break;
2569 default:
2570 reg_w1(gspca_dev, 0x9a, 0x08);
2571 break;
2572 }
2573 setsharpness(gspca_dev);
2574
2575 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
2576 reg_w1(gspca_dev, 0x05, 0x20); /* red */
2577 reg_w1(gspca_dev, 0x07, 0x20); /* green */
2578 reg_w1(gspca_dev, 0x06, 0x20); /* blue */
2579
2580 init = NULL;
2581 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
2582 reg01 |= SYS_SEL_48M | V_TX_EN;
2583 reg17 &= ~MCK_SIZE_MASK;
2584 reg17 |= 0x02; /* clock / 2 */
2585 switch (sd->sensor) {
2586 case SENSOR_ADCM1700:
2587 init = adcm1700_sensor_param1;
2588 break;
2589 case SENSOR_GC0307:
2590 init = gc0307_sensor_param1;
2591 break;
2592 case SENSOR_HV7131R:
2593 case SENSOR_MI0360:
2594 if (!mode)
2595 reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */
2596 reg17 &= ~MCK_SIZE_MASK;
2597 reg17 |= 0x01; /* clock / 1 */
2598 break;
2599 case SENSOR_MI0360B:
2600 init = mi0360b_sensor_param1;
2601 break;
2602 case SENSOR_MO4000:
2603 if (mode) { /* if 320x240 */
2604 reg01 &= ~SYS_SEL_48M; /* clk 24Mz */
2605 reg17 &= ~MCK_SIZE_MASK;
2606 reg17 |= 0x01; /* clock / 1 */
2607 }
2608 break;
2609 case SENSOR_MT9V111:
2610 init = mt9v111_sensor_param1;
2611 break;
2612 case SENSOR_OM6802:
2613 init = om6802_sensor_param1;
2614 if (!mode) { /* if 640x480 */
2615 reg17 &= ~MCK_SIZE_MASK;
2616 reg17 |= 0x04; /* clock / 4 */
2617 } else {
2618 reg01 &= ~SYS_SEL_48M; /* clk 24Mz */
2619 reg17 &= ~MCK_SIZE_MASK;
2620 reg17 |= 0x02; /* clock / 2 */
2621 }
2622 break;
2623 case SENSOR_OV7630:
2624 init = ov7630_sensor_param1;
2625 break;
2626 case SENSOR_OV7648:
2627 init = ov7648_sensor_param1;
2628 reg17 &= ~MCK_SIZE_MASK;
2629 reg17 |= 0x01; /* clock / 1 */
2630 break;
2631 case SENSOR_OV7660:
2632 init = ov7660_sensor_param1;
2633 break;
2634 case SENSOR_PO1030:
2635 init = po1030_sensor_param1;
2636 break;
2637 case SENSOR_PO2030N:
2638 init = po2030n_sensor_param1;
2639 break;
2640 case SENSOR_SOI768:
2641 init = soi768_sensor_param1;
2642 break;
2643 case SENSOR_SP80708:
2644 init = sp80708_sensor_param1;
2645 break;
2646 }
2647
2648 /* more sensor initialization - param1 */
2649 if (init != NULL) {
2650 i2c_w_seq(gspca_dev, init);
2651/* init = NULL; */
2652 }
2653
2654 reg_w(gspca_dev, 0xc0, C0, 6);
2655 switch (sd->sensor) {
2656 case SENSOR_ADCM1700:
2657 case SENSOR_GC0307:
2658 case SENSOR_SOI768:
2659 reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
2660 break;
2661 case SENSOR_PO2030N:
2662 reg_w(gspca_dev, 0xca, CA_po2030n, 4);
2663 break;
2664 default:
2665 reg_w(gspca_dev, 0xca, CA, 4);
2666 break;
2667 }
2668 switch (sd->sensor) {
2669 case SENSOR_ADCM1700:
2670 case SENSOR_OV7630:
2671 case SENSOR_OV7648:
2672 case SENSOR_OV7660:
2673 case SENSOR_SOI768:
2674 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
2675 break;
2676 case SENSOR_GC0307:
2677 reg_w(gspca_dev, 0xce, CE_gc0307, 4);
2678 break;
2679 case SENSOR_PO2030N:
2680 reg_w(gspca_dev, 0xce, CE_po2030n, 4);
2681 break;
2682 default:
2683 reg_w(gspca_dev, 0xce, CE, 4);
2684 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
2685 break;
2686 }
2687
2688 /* here change size mode 0 -> VGA; 1 -> CIF */
2689 sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
2690 reg_w1(gspca_dev, 0x18, sd->reg18);
2691 setjpegqual(gspca_dev);
2692
2693 reg_w1(gspca_dev, 0x17, reg17);
2694 reg_w1(gspca_dev, 0x01, reg01);
2695 sd->reg01 = reg01;
2696 sd->reg17 = reg17;
2697
2698 sethvflip(gspca_dev);
2699 setbrightness(gspca_dev);
2700 setcontrast(gspca_dev);
2701 setcolors(gspca_dev);
2702 setautogain(gspca_dev);
2703 if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) {
2704 setexposure(gspca_dev);
2705 setgain(gspca_dev);
2706 }
2707 setfreq(gspca_dev);
2708
2709 sd->pktsz = sd->npkt = 0;
2710 sd->nchg = sd->short_mark = 0;
2711 sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
2712
2713 return gspca_dev->usb_err;
2714}
2715
2716static void sd_stopN(struct gspca_dev *gspca_dev)
2717{
2718 struct sd *sd = (struct sd *) gspca_dev;
2719 static const u8 stophv7131[] =
2720 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
2721 static const u8 stopmi0360[] =
2722 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
2723 static const u8 stopov7648[] =
2724 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
2725 static const u8 stopsoi768[] =
2726 { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
2727 u8 reg01;
2728 u8 reg17;
2729
2730 reg01 = sd->reg01;
2731 reg17 = sd->reg17 & ~SEN_CLK_EN;
2732 switch (sd->sensor) {
2733 case SENSOR_ADCM1700:
2734 case SENSOR_GC0307:
2735 case SENSOR_PO2030N:
2736 case SENSOR_SP80708:
2737 reg01 |= LED;
2738 reg_w1(gspca_dev, 0x01, reg01);
2739 reg01 &= ~(LED | V_TX_EN);
2740 reg_w1(gspca_dev, 0x01, reg01);
2741/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */
2742 break;
2743 case SENSOR_HV7131R:
2744 reg01 &= ~V_TX_EN;
2745 reg_w1(gspca_dev, 0x01, reg01);
2746 i2c_w8(gspca_dev, stophv7131);
2747 break;
2748 case SENSOR_MI0360:
2749 case SENSOR_MI0360B:
2750 reg01 &= ~V_TX_EN;
2751 reg_w1(gspca_dev, 0x01, reg01);
2752/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */
2753 i2c_w8(gspca_dev, stopmi0360);
2754 break;
2755 case SENSOR_MT9V111:
2756 case SENSOR_OM6802:
2757 case SENSOR_PO1030:
2758 reg01 &= ~V_TX_EN;
2759 reg_w1(gspca_dev, 0x01, reg01);
2760 break;
2761 case SENSOR_OV7630:
2762 case SENSOR_OV7648:
2763 reg01 &= ~V_TX_EN;
2764 reg_w1(gspca_dev, 0x01, reg01);
2765 i2c_w8(gspca_dev, stopov7648);
2766 break;
2767 case SENSOR_OV7660:
2768 reg01 &= ~V_TX_EN;
2769 reg_w1(gspca_dev, 0x01, reg01);
2770 break;
2771 case SENSOR_SOI768:
2772 i2c_w8(gspca_dev, stopsoi768);
2773 break;
2774 }
2775
2776 reg01 |= SCL_SEL_OD;
2777 reg_w1(gspca_dev, 0x01, reg01);
2778 reg01 |= S_PWR_DN; /* sensor power down */
2779 reg_w1(gspca_dev, 0x01, reg01);
2780 reg_w1(gspca_dev, 0x17, reg17);
2781 reg01 &= ~SYS_SEL_48M; /* clock 24MHz */
2782 reg_w1(gspca_dev, 0x01, reg01);
2783 reg01 |= LED;
2784 reg_w1(gspca_dev, 0x01, reg01);
2785 /* Don't disable sensor clock as that disables the button on the cam */
2786 /* reg_w1(gspca_dev, 0xf1, 0x01); */
2787}
2788
2789/* called on streamoff with alt==0 and on disconnect */
2790/* the usb_lock is held at entry - restore on exit */
2791static void sd_stop0(struct gspca_dev *gspca_dev)
2792{
2793 struct sd *sd = (struct sd *) gspca_dev;
2794
2795 if (sd->work_thread != NULL) {
2796 mutex_unlock(&gspca_dev->usb_lock);
2797 destroy_workqueue(sd->work_thread);
2798 mutex_lock(&gspca_dev->usb_lock);
2799 sd->work_thread = NULL;
2800 }
2801}
2802
2803#define WANT_REGULAR_AUTOGAIN
2804#include "autogain_functions.h"
2805
2806static void do_autogain(struct gspca_dev *gspca_dev)
2807{
2808 struct sd *sd = (struct sd *) gspca_dev;
2809 int delta;
2810 int expotimes;
2811 u8 luma_mean = 130;
2812 u8 luma_delta = 20;
2813
2814 /* Thanks S., without your advice, autobright should not work :) */
2815 if (sd->ag_cnt < 0)
2816 return;
2817 if (--sd->ag_cnt >= 0)
2818 return;
2819 sd->ag_cnt = AG_CNT_START;
2820
2821 delta = atomic_read(&sd->avg_lum);
2822 PDEBUG(D_FRAM, "mean lum %d", delta);
2823
2824 if (sd->sensor == SENSOR_PO2030N) {
2825 auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta,
2826 15, 1024);
2827 return;
2828 }
2829
2830 if (delta < luma_mean - luma_delta ||
2831 delta > luma_mean + luma_delta) {
2832 switch (sd->sensor) {
2833 case SENSOR_GC0307:
2834 expotimes = sd->exposure;
2835 expotimes += (luma_mean - delta) >> 6;
2836 if (expotimes < 0)
2837 expotimes = 0;
2838 sd->exposure = expo_adjust(gspca_dev,
2839 (unsigned int) expotimes);
2840 break;
2841 case SENSOR_HV7131R:
2842 expotimes = sd->exposure >> 8;
2843 expotimes += (luma_mean - delta) >> 4;
2844 if (expotimes < 0)
2845 expotimes = 0;
2846 sd->exposure = expo_adjust(gspca_dev,
2847 (unsigned int) (expotimes << 8));
2848 break;
2849 case SENSOR_OM6802:
2850 case SENSOR_MT9V111:
2851 expotimes = sd->exposure;
2852 expotimes += (luma_mean - delta) >> 2;
2853 if (expotimes < 0)
2854 expotimes = 0;
2855 sd->exposure = expo_adjust(gspca_dev,
2856 (unsigned int) expotimes);
2857 setredblue(gspca_dev);
2858 break;
2859 default:
2860/* case SENSOR_MO4000: */
2861/* case SENSOR_MI0360: */
2862/* case SENSOR_MI0360B: */
2863 expotimes = sd->exposure;
2864 expotimes += (luma_mean - delta) >> 6;
2865 if (expotimes < 0)
2866 expotimes = 0;
2867 sd->exposure = expo_adjust(gspca_dev,
2868 (unsigned int) expotimes);
2869 setredblue(gspca_dev);
2870 break;
2871 }
2872 }
2873}
2874
2875/* set the average luminosity from an isoc marker */
2876static void set_lum(struct sd *sd,
2877 u8 *data)
2878{
2879 int avg_lum;
2880
2881 /* w0 w1 w2
2882 * w3 w4 w5
2883 * w6 w7 w8
2884 */
2885 avg_lum = (data[27] << 8) + data[28] /* w3 */
2886
2887 + (data[31] << 8) + data[32] /* w5 */
2888
2889 + (data[23] << 8) + data[24] /* w1 */
2890
2891 + (data[35] << 8) + data[36] /* w7 */
2892
2893 + (data[29] << 10) + (data[30] << 2); /* w4 * 4 */
2894 avg_lum >>= 10;
2895 atomic_set(&sd->avg_lum, avg_lum);
2896}
2897
2898/* scan the URB packets */
2899/* This function is run at interrupt level. */
2900static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2901 u8 *data, /* isoc packet */
2902 int len) /* iso packet length */
2903{
2904 struct sd *sd = (struct sd *) gspca_dev;
2905 int i, new_qual;
2906
2907 /*
2908 * A frame ends on the marker
2909 * ff ff 00 c4 c4 96 ..
2910 * which is 62 bytes long and is followed by various information
2911 * including statuses and luminosity.
2912 *
2913 * A marker may be splitted on two packets.
2914 *
2915 * The 6th byte of a marker contains the bits:
2916 * 0x08: USB full
2917 * 0xc0: frame sequence
2918 * When the bit 'USB full' is set, the frame must be discarded;
2919 * this is also the case when the 2 bytes before the marker are
2920 * not the JPEG end of frame ('ff d9').
2921 */
2922
2923 /* count the packets and their size */
2924 sd->npkt++;
2925 sd->pktsz += len;
2926
2927/*fixme: assumption about the following code:
2928 * - there can be only one marker in a packet
2929 */
2930
2931 /* skip the remaining bytes of a short marker */
2932 i = sd->short_mark;
2933 if (i != 0) {
2934 sd->short_mark = 0;
2935 if (i < 0 /* if 'ff' at end of previous packet */
2936 && data[0] == 0xff
2937 && data[1] == 0x00)
2938 goto marker_found;
2939 if (data[0] == 0xff && data[1] == 0xff) {
2940 i = 0;
2941 goto marker_found;
2942 }
2943 len -= i;
2944 if (len <= 0)
2945 return;
2946 data += i;
2947 }
2948
2949 /* search backwards if there is a marker in the packet */
2950 for (i = len - 1; --i >= 0; ) {
2951 if (data[i] != 0xff) {
2952 i--;
2953 continue;
2954 }
2955 if (data[i + 1] == 0xff) {
2956
2957 /* (there may be 'ff ff' inside a marker) */
2958 if (i + 2 >= len || data[i + 2] == 0x00)
2959 goto marker_found;
2960 }
2961 }
2962
2963 /* no marker found */
2964 /* add the JPEG header if first fragment */
2965 if (data[len - 1] == 0xff)
2966 sd->short_mark = -1;
2967 if (gspca_dev->last_packet_type == LAST_PACKET)
2968 gspca_frame_add(gspca_dev, FIRST_PACKET,
2969 sd->jpeg_hdr, JPEG_HDR_SZ);
2970 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2971 return;
2972
2973 /* marker found */
2974 /* if some error, discard the frame and decrease the quality */
2975marker_found:
2976 new_qual = 0;
2977 if (i > 2) {
2978 if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
2979 gspca_dev->last_packet_type = DISCARD_PACKET;
2980 new_qual = -3;
2981 }
2982 } else if (i + 6 < len) {
2983 if (data[i + 6] & 0x08) {
2984 gspca_dev->last_packet_type = DISCARD_PACKET;
2985 new_qual = -5;
2986 }
2987 }
2988
2989 gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
2990
2991 /* compute the filling rate and a new JPEG quality */
2992 if (new_qual == 0) {
2993 int r;
2994
2995 r = (sd->pktsz * 100) /
2996 (sd->npkt *
2997 gspca_dev->urb[0]->iso_frame_desc[0].length);
2998 if (r >= 85)
2999 new_qual = -3;
3000 else if (r < 75)
3001 new_qual = 2;
3002 }
3003 if (new_qual != 0) {
3004 sd->nchg += new_qual;
3005 if (sd->nchg < -6 || sd->nchg >= 12) {
3006 sd->nchg = 0;
3007 new_qual += sd->quality;
3008 if (new_qual < QUALITY_MIN)
3009 new_qual = QUALITY_MIN;
3010 else if (new_qual > QUALITY_MAX)
3011 new_qual = QUALITY_MAX;
3012 if (new_qual != sd->quality) {
3013 sd->quality = new_qual;
3014 queue_work(sd->work_thread, &sd->work);
3015 }
3016 }
3017 } else {
3018 sd->nchg = 0;
3019 }
3020 sd->pktsz = sd->npkt = 0;
3021
3022 /* if the marker is smaller than 62 bytes,
3023 * memorize the number of bytes to skip in the next packet */
3024 if (i + 62 > len) { /* no more usable data */
3025 sd->short_mark = i + 62 - len;
3026 return;
3027 }
3028 if (sd->ag_cnt >= 0)
3029 set_lum(sd, data + i);
3030
3031 /* if more data, start a new frame */
3032 i += 62;
3033 if (i < len) {
3034 data += i;
3035 len -= i;
3036 gspca_frame_add(gspca_dev, FIRST_PACKET,
3037 sd->jpeg_hdr, JPEG_HDR_SZ);
3038 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
3039 }
3040}
3041
3042static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
3043{
3044 struct sd *sd = (struct sd *) gspca_dev;
3045
3046 sd->ctrls[AUTOGAIN].val = val;
3047 if (val)
3048 gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
3049 else
3050 gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN);
3051 if (gspca_dev->streaming)
3052 setautogain(gspca_dev);
3053 return gspca_dev->usb_err;
3054}
3055
3056static int sd_querymenu(struct gspca_dev *gspca_dev,
3057 struct v4l2_querymenu *menu)
3058{
3059 switch (menu->id) {
3060 case V4L2_CID_POWER_LINE_FREQUENCY:
3061 switch (menu->index) {
3062 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
3063 strcpy((char *) menu->name, "NoFliker");
3064 return 0;
3065 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
3066 strcpy((char *) menu->name, "50 Hz");
3067 return 0;
3068 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
3069 strcpy((char *) menu->name, "60 Hz");
3070 return 0;
3071 }
3072 break;
3073 }
3074 return -EINVAL;
3075}
3076
3077#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3078static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
3079 u8 *data, /* interrupt packet data */
3080 int len) /* interrupt packet length */
3081{
3082 int ret = -EINVAL;
3083
3084 if (len == 1 && data[0] == 1) {
3085 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
3086 input_sync(gspca_dev->input_dev);
3087 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
3088 input_sync(gspca_dev->input_dev);
3089 ret = 0;
3090 }
3091
3092 return ret;
3093}
3094#endif
3095
3096/* sub-driver description */
3097static const struct sd_desc sd_desc = {
3098 .name = MODULE_NAME,
3099 .ctrls = sd_ctrls,
3100 .nctrls = NCTRLS,
3101 .config = sd_config,
3102 .init = sd_init,
3103 .start = sd_start,
3104 .stopN = sd_stopN,
3105 .stop0 = sd_stop0,
3106 .pkt_scan = sd_pkt_scan,
3107 .dq_callback = do_autogain,
3108 .querymenu = sd_querymenu,
3109#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3110 .int_pkt_scan = sd_int_pkt_scan,
3111#endif
3112};
3113
3114/* -- module initialisation -- */
3115#define BS(bridge, sensor) \
3116 .driver_info = (BRIDGE_ ## bridge << 16) \
3117 | (SENSOR_ ## sensor << 8)
3118#define BSF(bridge, sensor, flags) \
3119 .driver_info = (BRIDGE_ ## bridge << 16) \
3120 | (SENSOR_ ## sensor << 8) \
3121 | (flags)
3122static const struct usb_device_id device_table[] = {
3123 {USB_DEVICE(0x0458, 0x7025), BSF(SN9C120, MI0360B, F_PDN_INV)},
3124 {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
3125 {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
3126 {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
3127 {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
3128 {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
3129 {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
3130 {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
3131 {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
3132/* {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
3133 {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
3134/* {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
3135/* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
3136 {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
3137/* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
3138 {USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
3139 /* or MT9V111 */
3140/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
3141/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
3142/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
3143 {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
3144 {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
3145/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
3146/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
3147/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
3148 {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
3149 {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
3150 {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
3151 {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/
3152 {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, /* /GC0305*/
3153/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
3154 {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/
3155 {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/
3156 {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)}, /*sn9c128*/
3157 {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)}, /*sn9c128*/
3158/* {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
3159/* {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
3160/* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
3161 {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/
3162/*bw600.inf:*/
3163 {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c325?*/
3164 {USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
3165 {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
3166 {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
3167/* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
3168 {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
3169 /* or MT9V111 / MI0360B */
3170/* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
3171 {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
3172 {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
3173 {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
3174 {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
3175 {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
3176 {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/
3177 /* or GC0305 / GC0307 */
3178 {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/
3179 {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/
3180 {USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
3181/* {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */ /*sn9c120b*/
3182 {}
3183};
3184MODULE_DEVICE_TABLE(usb, device_table);
3185
3186/* -- device connect -- */
3187static int sd_probe(struct usb_interface *intf,
3188 const struct usb_device_id *id)
3189{
3190 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
3191 THIS_MODULE);
3192}
3193
3194static struct usb_driver sd_driver = {
3195 .name = MODULE_NAME,
3196 .id_table = device_table,
3197 .probe = sd_probe,
3198 .disconnect = gspca_disconnect,
3199#ifdef CONFIG_PM
3200 .suspend = gspca_suspend,
3201 .resume = gspca_resume,
3202 .reset_resume = gspca_resume,
3203#endif
3204};
3205
3206module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca1528.c b/drivers/media/usb/gspca/spca1528.c
new file mode 100644
index 00000000000..14d635277d7
--- /dev/null
+++ b/drivers/media/usb/gspca/spca1528.c
@@ -0,0 +1,444 @@
1/*
2 * spca1528 subdriver
3 *
4 * Copyright (C) 2010-2011 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "spca1528"
24
25#include "gspca.h"
26#include "jpeg.h"
27
28MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
29MODULE_DESCRIPTION("SPCA1528 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 u8 pkt_seq;
37
38 u8 jpeg_hdr[JPEG_HDR_SZ];
39};
40
41static const struct v4l2_pix_format vga_mode[] = {
42/* (does not work correctly)
43 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
44 .bytesperline = 176,
45 .sizeimage = 176 * 144 * 5 / 8 + 590,
46 .colorspace = V4L2_COLORSPACE_JPEG,
47 .priv = 3},
48*/
49 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
50 .bytesperline = 320,
51 .sizeimage = 320 * 240 * 4 / 8 + 590,
52 .colorspace = V4L2_COLORSPACE_JPEG,
53 .priv = 2},
54 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
55 .bytesperline = 640,
56 .sizeimage = 640 * 480 * 3 / 8 + 590,
57 .colorspace = V4L2_COLORSPACE_JPEG,
58 .priv = 1},
59};
60
61/* read <len> bytes to gspca usb_buf */
62static void reg_r(struct gspca_dev *gspca_dev,
63 u8 req,
64 u16 index,
65 int len)
66{
67#if USB_BUF_SZ < 64
68#error "USB buffer too small"
69#endif
70 struct usb_device *dev = gspca_dev->dev;
71 int ret;
72
73 if (gspca_dev->usb_err < 0)
74 return;
75 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
76 req,
77 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
78 0x0000, /* value */
79 index,
80 gspca_dev->usb_buf, len,
81 500);
82 PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
83 gspca_dev->usb_buf[0]);
84 if (ret < 0) {
85 pr_err("reg_r err %d\n", ret);
86 gspca_dev->usb_err = ret;
87 }
88}
89
90static void reg_w(struct gspca_dev *gspca_dev,
91 u8 req,
92 u16 value,
93 u16 index)
94{
95 struct usb_device *dev = gspca_dev->dev;
96 int ret;
97
98 if (gspca_dev->usb_err < 0)
99 return;
100 PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
101 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
102 req,
103 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
104 value, index,
105 NULL, 0, 500);
106 if (ret < 0) {
107 pr_err("reg_w err %d\n", ret);
108 gspca_dev->usb_err = ret;
109 }
110}
111
112static void reg_wb(struct gspca_dev *gspca_dev,
113 u8 req,
114 u16 value,
115 u16 index,
116 u8 byte)
117{
118 struct usb_device *dev = gspca_dev->dev;
119 int ret;
120
121 if (gspca_dev->usb_err < 0)
122 return;
123 PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
124 gspca_dev->usb_buf[0] = byte;
125 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
126 req,
127 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
128 value, index,
129 gspca_dev->usb_buf, 1, 500);
130 if (ret < 0) {
131 pr_err("reg_w err %d\n", ret);
132 gspca_dev->usb_err = ret;
133 }
134}
135
136static void wait_status_0(struct gspca_dev *gspca_dev)
137{
138 int i, w;
139
140 i = 16;
141 w = 0;
142 do {
143 reg_r(gspca_dev, 0x21, 0x0000, 1);
144 if (gspca_dev->usb_buf[0] == 0)
145 return;
146 w += 15;
147 msleep(w);
148 } while (--i > 0);
149 PDEBUG(D_ERR, "wait_status_0 timeout");
150 gspca_dev->usb_err = -ETIME;
151}
152
153static void wait_status_1(struct gspca_dev *gspca_dev)
154{
155 int i;
156
157 i = 10;
158 do {
159 reg_r(gspca_dev, 0x21, 0x0001, 1);
160 msleep(10);
161 if (gspca_dev->usb_buf[0] == 1) {
162 reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
163 reg_r(gspca_dev, 0x21, 0x0001, 1);
164 return;
165 }
166 } while (--i > 0);
167 PDEBUG(D_ERR, "wait_status_1 timeout");
168 gspca_dev->usb_err = -ETIME;
169}
170
171static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
172{
173 reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, val);
174}
175
176static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
177{
178 reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, val);
179}
180
181static void sethue(struct gspca_dev *gspca_dev, s32 val)
182{
183 reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, val);
184}
185
186static void setcolor(struct gspca_dev *gspca_dev, s32 val)
187{
188 reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, val);
189}
190
191static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
192{
193 reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, val);
194}
195
196/* this function is called at probe time */
197static int sd_config(struct gspca_dev *gspca_dev,
198 const struct usb_device_id *id)
199{
200 gspca_dev->cam.cam_mode = vga_mode;
201 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
202 gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
203 /*fixme: 256 in ms-win traces*/
204
205 return 0;
206}
207
208/* this function is called at probe and resume time */
209static int sd_init(struct gspca_dev *gspca_dev)
210{
211 reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
212 reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
213 reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
214 reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
215 msleep(8);
216 reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
217 reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
218 reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
219
220 reg_r(gspca_dev, 0x20, 0x0000, 1);
221 reg_r(gspca_dev, 0x20, 0x0000, 5);
222 reg_r(gspca_dev, 0x23, 0x0000, 64);
223 PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
224 &gspca_dev->usb_buf[0x30]);
225 reg_r(gspca_dev, 0x23, 0x0001, 64);
226 return gspca_dev->usb_err;
227}
228
229/* function called at start time before URB creation */
230static int sd_isoc_init(struct gspca_dev *gspca_dev)
231{
232 u8 mode;
233
234 reg_r(gspca_dev, 0x00, 0x2520, 1);
235 wait_status_0(gspca_dev);
236 reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
237 wait_status_1(gspca_dev);
238
239 wait_status_0(gspca_dev);
240 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
241 reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
242 reg_r(gspca_dev, 0x25, 0x0004, 1);
243 reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06); /* 420 */
244 reg_r(gspca_dev, 0x27, 0x0000, 1);
245
246/* not useful..
247 gspca_dev->alt = 4; * use alternate setting 3 */
248
249 return gspca_dev->usb_err;
250}
251
252/* -- start the camera -- */
253static int sd_start(struct gspca_dev *gspca_dev)
254{
255 struct sd *sd = (struct sd *) gspca_dev;
256
257 /* initialize the JPEG header */
258 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
259 0x22); /* JPEG 411 */
260
261 /* the JPEG quality shall be 85% */
262 jpeg_set_qual(sd->jpeg_hdr, 85);
263
264 reg_r(gspca_dev, 0x00, 0x2520, 1);
265 msleep(8);
266
267 /* start the capture */
268 wait_status_0(gspca_dev);
269 reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */
270 wait_status_1(gspca_dev);
271 wait_status_0(gspca_dev);
272 msleep(200);
273
274 sd->pkt_seq = 0;
275 return gspca_dev->usb_err;
276}
277
278static void sd_stopN(struct gspca_dev *gspca_dev)
279{
280 /* stop the capture */
281 wait_status_0(gspca_dev);
282 reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */
283 wait_status_1(gspca_dev);
284 wait_status_0(gspca_dev);
285}
286
287/* move a packet adding 0x00 after 0xff */
288static void add_packet(struct gspca_dev *gspca_dev,
289 u8 *data,
290 int len)
291{
292 int i;
293
294 i = 0;
295 do {
296 if (data[i] == 0xff) {
297 gspca_frame_add(gspca_dev, INTER_PACKET,
298 data, i + 1);
299 len -= i;
300 data += i;
301 *data = 0x00;
302 i = 0;
303 }
304 } while (++i < len);
305 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
306}
307
308static void sd_pkt_scan(struct gspca_dev *gspca_dev,
309 u8 *data, /* isoc packet */
310 int len) /* iso packet length */
311{
312 struct sd *sd = (struct sd *) gspca_dev;
313 static const u8 ffd9[] = {0xff, 0xd9};
314
315 /* image packets start with:
316 * 02 8n
317 * with <n> bit:
318 * 0x01: even (0) / odd (1) image
319 * 0x02: end of image when set
320 */
321 if (len < 3)
322 return; /* empty packet */
323 if (*data == 0x02) {
324 if (data[1] & 0x02) {
325 sd->pkt_seq = !(data[1] & 1);
326 add_packet(gspca_dev, data + 2, len - 2);
327 gspca_frame_add(gspca_dev, LAST_PACKET,
328 ffd9, 2);
329 return;
330 }
331 if ((data[1] & 1) != sd->pkt_seq)
332 goto err;
333 if (gspca_dev->last_packet_type == LAST_PACKET)
334 gspca_frame_add(gspca_dev, FIRST_PACKET,
335 sd->jpeg_hdr, JPEG_HDR_SZ);
336 add_packet(gspca_dev, data + 2, len - 2);
337 return;
338 }
339err:
340 gspca_dev->last_packet_type = DISCARD_PACKET;
341}
342
343static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
344{
345 struct gspca_dev *gspca_dev =
346 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
347
348 gspca_dev->usb_err = 0;
349
350 if (!gspca_dev->streaming)
351 return 0;
352
353 switch (ctrl->id) {
354 case V4L2_CID_BRIGHTNESS:
355 setbrightness(gspca_dev, ctrl->val);
356 break;
357 case V4L2_CID_CONTRAST:
358 setcontrast(gspca_dev, ctrl->val);
359 break;
360 case V4L2_CID_HUE:
361 sethue(gspca_dev, ctrl->val);
362 break;
363 case V4L2_CID_SATURATION:
364 setcolor(gspca_dev, ctrl->val);
365 break;
366 case V4L2_CID_SHARPNESS:
367 setsharpness(gspca_dev, ctrl->val);
368 break;
369 }
370 return gspca_dev->usb_err;
371}
372
373static const struct v4l2_ctrl_ops sd_ctrl_ops = {
374 .s_ctrl = sd_s_ctrl,
375};
376
377static int sd_init_controls(struct gspca_dev *gspca_dev)
378{
379 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
380
381 gspca_dev->vdev.ctrl_handler = hdl;
382 v4l2_ctrl_handler_init(hdl, 5);
383 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
384 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
385 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
386 V4L2_CID_CONTRAST, 0, 8, 1, 1);
387 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
388 V4L2_CID_HUE, 0, 255, 1, 0);
389 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
390 V4L2_CID_SATURATION, 0, 8, 1, 1);
391 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
392 V4L2_CID_SHARPNESS, 0, 255, 1, 0);
393
394 if (hdl->error) {
395 pr_err("Could not initialize controls\n");
396 return hdl->error;
397 }
398 return 0;
399}
400
401/* sub-driver description */
402static const struct sd_desc sd_desc = {
403 .name = MODULE_NAME,
404 .config = sd_config,
405 .init = sd_init,
406 .init_controls = sd_init_controls,
407 .isoc_init = sd_isoc_init,
408 .start = sd_start,
409 .stopN = sd_stopN,
410 .pkt_scan = sd_pkt_scan,
411};
412
413/* -- module initialisation -- */
414static const struct usb_device_id device_table[] = {
415 {USB_DEVICE(0x04fc, 0x1528)},
416 {}
417};
418MODULE_DEVICE_TABLE(usb, device_table);
419
420/* -- device connect -- */
421static int sd_probe(struct usb_interface *intf,
422 const struct usb_device_id *id)
423{
424 /* the video interface for isochronous transfer is 1 */
425 if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
426 return -ENODEV;
427
428 return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
429 THIS_MODULE);
430}
431
432static struct usb_driver sd_driver = {
433 .name = MODULE_NAME,
434 .id_table = device_table,
435 .probe = sd_probe,
436 .disconnect = gspca_disconnect,
437#ifdef CONFIG_PM
438 .suspend = gspca_suspend,
439 .resume = gspca_resume,
440 .reset_resume = gspca_resume,
441#endif
442};
443
444module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca500.c b/drivers/media/usb/gspca/spca500.c
new file mode 100644
index 00000000000..25cb68d0556
--- /dev/null
+++ b/drivers/media/usb/gspca/spca500.c
@@ -0,0 +1,990 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "spca500"
25
26#include "gspca.h"
27#include "jpeg.h"
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33#define QUALITY 85
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 char subtype;
40#define AgfaCl20 0
41#define AiptekPocketDV 1
42#define BenqDC1016 2
43#define CreativePCCam300 3
44#define DLinkDSC350 4
45#define Gsmartmini 5
46#define IntelPocketPCCamera 6
47#define KodakEZ200 7
48#define LogitechClickSmart310 8
49#define LogitechClickSmart510 9
50#define LogitechTraveler 10
51#define MustekGsmart300 11
52#define Optimedia 12
53#define PalmPixDC85 13
54#define ToptroIndus 14
55
56 u8 jpeg_hdr[JPEG_HDR_SZ];
57};
58
59static const struct v4l2_pix_format vga_mode[] = {
60 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
61 .bytesperline = 320,
62 .sizeimage = 320 * 240 * 3 / 8 + 590,
63 .colorspace = V4L2_COLORSPACE_JPEG,
64 .priv = 1},
65 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
66 .bytesperline = 640,
67 .sizeimage = 640 * 480 * 3 / 8 + 590,
68 .colorspace = V4L2_COLORSPACE_JPEG,
69 .priv = 0},
70};
71
72static const struct v4l2_pix_format sif_mode[] = {
73 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
74 .bytesperline = 176,
75 .sizeimage = 176 * 144 * 3 / 8 + 590,
76 .colorspace = V4L2_COLORSPACE_JPEG,
77 .priv = 1},
78 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
79 .bytesperline = 352,
80 .sizeimage = 352 * 288 * 3 / 8 + 590,
81 .colorspace = V4L2_COLORSPACE_JPEG,
82 .priv = 0},
83};
84
85/* Frame packet header offsets for the spca500 */
86#define SPCA500_OFFSET_PADDINGLB 2
87#define SPCA500_OFFSET_PADDINGHB 3
88#define SPCA500_OFFSET_MODE 4
89#define SPCA500_OFFSET_IMGWIDTH 5
90#define SPCA500_OFFSET_IMGHEIGHT 6
91#define SPCA500_OFFSET_IMGMODE 7
92#define SPCA500_OFFSET_QTBLINDEX 8
93#define SPCA500_OFFSET_FRAMSEQ 9
94#define SPCA500_OFFSET_CDSPINFO 10
95#define SPCA500_OFFSET_GPIO 11
96#define SPCA500_OFFSET_AUGPIO 12
97#define SPCA500_OFFSET_DATA 16
98
99
100static const __u16 spca500_visual_defaults[][3] = {
101 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
102 * hue (H byte) = 0,
103 * saturation/hue enable,
104 * brightness/contrast enable.
105 */
106 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
107 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
108 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
109 * hue (H byte) = 0, saturation/hue enable,
110 * brightness/contrast enable.
111 * was 0x0003, now 0x0000.
112 */
113 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
114 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
115 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
116 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
117 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
118 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
119 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
120 {0x0c, 0x0004, 0x0000},
121 /* set interface */
122 {}
123};
124static const __u16 Clicksmart510_defaults[][3] = {
125 {0x00, 0x00, 0x8211},
126 {0x00, 0x01, 0x82c0},
127 {0x00, 0x10, 0x82cb},
128 {0x00, 0x0f, 0x800d},
129 {0x00, 0x82, 0x8225},
130 {0x00, 0x21, 0x8228},
131 {0x00, 0x00, 0x8203},
132 {0x00, 0x00, 0x8204},
133 {0x00, 0x08, 0x8205},
134 {0x00, 0xf8, 0x8206},
135 {0x00, 0x28, 0x8207},
136 {0x00, 0xa0, 0x8208},
137 {0x00, 0x08, 0x824a},
138 {0x00, 0x08, 0x8214},
139 {0x00, 0x80, 0x82c1},
140 {0x00, 0x00, 0x82c2},
141 {0x00, 0x00, 0x82ca},
142 {0x00, 0x80, 0x82c1},
143 {0x00, 0x04, 0x82c2},
144 {0x00, 0x00, 0x82ca},
145 {0x00, 0xfc, 0x8100},
146 {0x00, 0xfc, 0x8105},
147 {0x00, 0x30, 0x8101},
148 {0x00, 0x00, 0x8102},
149 {0x00, 0x00, 0x8103},
150 {0x00, 0x66, 0x8107},
151 {0x00, 0x00, 0x816b},
152 {0x00, 0x00, 0x8155},
153 {0x00, 0x01, 0x8156},
154 {0x00, 0x60, 0x8157},
155 {0x00, 0x40, 0x8158},
156 {0x00, 0x0a, 0x8159},
157 {0x00, 0x06, 0x815a},
158 {0x00, 0x00, 0x813f},
159 {0x00, 0x00, 0x8200},
160 {0x00, 0x19, 0x8201},
161 {0x00, 0x00, 0x82c1},
162 {0x00, 0xa0, 0x82c2},
163 {0x00, 0x00, 0x82ca},
164 {0x00, 0x00, 0x8117},
165 {0x00, 0x00, 0x8118},
166 {0x00, 0x65, 0x8119},
167 {0x00, 0x00, 0x811a},
168 {0x00, 0x00, 0x811b},
169 {0x00, 0x55, 0x811c},
170 {0x00, 0x65, 0x811d},
171 {0x00, 0x55, 0x811e},
172 {0x00, 0x16, 0x811f},
173 {0x00, 0x19, 0x8120},
174 {0x00, 0x80, 0x8103},
175 {0x00, 0x83, 0x816b},
176 {0x00, 0x25, 0x8168},
177 {0x00, 0x01, 0x820f},
178 {0x00, 0xff, 0x8115},
179 {0x00, 0x48, 0x8116},
180 {0x00, 0x50, 0x8151},
181 {0x00, 0x40, 0x8152},
182 {0x00, 0x78, 0x8153},
183 {0x00, 0x40, 0x8154},
184 {0x00, 0x00, 0x8167},
185 {0x00, 0x20, 0x8168},
186 {0x00, 0x00, 0x816a},
187 {0x00, 0x03, 0x816b},
188 {0x00, 0x20, 0x8169},
189 {0x00, 0x60, 0x8157},
190 {0x00, 0x00, 0x8190},
191 {0x00, 0x00, 0x81a1},
192 {0x00, 0x00, 0x81b2},
193 {0x00, 0x27, 0x8191},
194 {0x00, 0x27, 0x81a2},
195 {0x00, 0x27, 0x81b3},
196 {0x00, 0x4b, 0x8192},
197 {0x00, 0x4b, 0x81a3},
198 {0x00, 0x4b, 0x81b4},
199 {0x00, 0x66, 0x8193},
200 {0x00, 0x66, 0x81a4},
201 {0x00, 0x66, 0x81b5},
202 {0x00, 0x79, 0x8194},
203 {0x00, 0x79, 0x81a5},
204 {0x00, 0x79, 0x81b6},
205 {0x00, 0x8a, 0x8195},
206 {0x00, 0x8a, 0x81a6},
207 {0x00, 0x8a, 0x81b7},
208 {0x00, 0x9b, 0x8196},
209 {0x00, 0x9b, 0x81a7},
210 {0x00, 0x9b, 0x81b8},
211 {0x00, 0xa6, 0x8197},
212 {0x00, 0xa6, 0x81a8},
213 {0x00, 0xa6, 0x81b9},
214 {0x00, 0xb2, 0x8198},
215 {0x00, 0xb2, 0x81a9},
216 {0x00, 0xb2, 0x81ba},
217 {0x00, 0xbe, 0x8199},
218 {0x00, 0xbe, 0x81aa},
219 {0x00, 0xbe, 0x81bb},
220 {0x00, 0xc8, 0x819a},
221 {0x00, 0xc8, 0x81ab},
222 {0x00, 0xc8, 0x81bc},
223 {0x00, 0xd2, 0x819b},
224 {0x00, 0xd2, 0x81ac},
225 {0x00, 0xd2, 0x81bd},
226 {0x00, 0xdb, 0x819c},
227 {0x00, 0xdb, 0x81ad},
228 {0x00, 0xdb, 0x81be},
229 {0x00, 0xe4, 0x819d},
230 {0x00, 0xe4, 0x81ae},
231 {0x00, 0xe4, 0x81bf},
232 {0x00, 0xed, 0x819e},
233 {0x00, 0xed, 0x81af},
234 {0x00, 0xed, 0x81c0},
235 {0x00, 0xf7, 0x819f},
236 {0x00, 0xf7, 0x81b0},
237 {0x00, 0xf7, 0x81c1},
238 {0x00, 0xff, 0x81a0},
239 {0x00, 0xff, 0x81b1},
240 {0x00, 0xff, 0x81c2},
241 {0x00, 0x03, 0x8156},
242 {0x00, 0x00, 0x8211},
243 {0x00, 0x20, 0x8168},
244 {0x00, 0x01, 0x8202},
245 {0x00, 0x30, 0x8101},
246 {0x00, 0x00, 0x8111},
247 {0x00, 0x00, 0x8112},
248 {0x00, 0x00, 0x8113},
249 {0x00, 0x00, 0x8114},
250 {}
251};
252
253static const __u8 qtable_creative_pccam[2][64] = {
254 { /* Q-table Y-components */
255 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
256 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
257 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
258 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
259 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
260 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
261 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
262 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
263 { /* Q-table C-components */
264 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
265 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
266 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
267 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
268 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
269 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
270 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
271 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
272};
273
274static const __u8 qtable_kodak_ez200[2][64] = {
275 { /* Q-table Y-components */
276 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
277 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
278 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
279 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
280 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
281 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
282 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
283 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
284 { /* Q-table C-components */
285 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
286 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
287 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
288 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
289 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
290 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
291 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
292 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
293};
294
295static const __u8 qtable_pocketdv[2][64] = {
296 { /* Q-table Y-components start registers 0x8800 */
297 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
298 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
299 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
300 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
301 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
302 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
303 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
304 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
305 },
306 { /* Q-table C-components start registers 0x8840 */
307 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
308 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
309 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
310 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
311 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
312 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
313 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
314 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
315};
316
317/* read 'len' bytes to gspca_dev->usb_buf */
318static void reg_r(struct gspca_dev *gspca_dev,
319 __u16 index,
320 __u16 length)
321{
322 usb_control_msg(gspca_dev->dev,
323 usb_rcvctrlpipe(gspca_dev->dev, 0),
324 0,
325 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
326 0, /* value */
327 index, gspca_dev->usb_buf, length, 500);
328}
329
330static int reg_w(struct gspca_dev *gspca_dev,
331 __u16 req, __u16 index, __u16 value)
332{
333 int ret;
334
335 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
336 ret = usb_control_msg(gspca_dev->dev,
337 usb_sndctrlpipe(gspca_dev->dev, 0),
338 req,
339 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
340 value, index, NULL, 0, 500);
341 if (ret < 0)
342 pr_err("reg write: error %d\n", ret);
343 return ret;
344}
345
346/* returns: negative is error, pos or zero is data */
347static int reg_r_12(struct gspca_dev *gspca_dev,
348 __u16 req, /* bRequest */
349 __u16 index, /* wIndex */
350 __u16 length) /* wLength (1 or 2 only) */
351{
352 int ret;
353
354 gspca_dev->usb_buf[1] = 0;
355 ret = usb_control_msg(gspca_dev->dev,
356 usb_rcvctrlpipe(gspca_dev->dev, 0),
357 req,
358 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
359 0, /* value */
360 index,
361 gspca_dev->usb_buf, length,
362 500); /* timeout */
363 if (ret < 0) {
364 pr_err("reg_r_12 err %d\n", ret);
365 return ret;
366 }
367 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
368}
369
370/*
371 * Simple function to wait for a given 8-bit value to be returned from
372 * a reg_read call.
373 * Returns: negative is error or timeout, zero is success.
374 */
375static int reg_r_wait(struct gspca_dev *gspca_dev,
376 __u16 reg, __u16 index, __u16 value)
377{
378 int ret, cnt = 20;
379
380 while (--cnt > 0) {
381 ret = reg_r_12(gspca_dev, reg, index, 1);
382 if (ret == value)
383 return 0;
384 msleep(50);
385 }
386 return -EIO;
387}
388
389static int write_vector(struct gspca_dev *gspca_dev,
390 const __u16 data[][3])
391{
392 int ret, i = 0;
393
394 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
395 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
396 if (ret < 0)
397 return ret;
398 i++;
399 }
400 return 0;
401}
402
403static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
404 unsigned int request,
405 unsigned int ybase,
406 unsigned int cbase,
407 const __u8 qtable[2][64])
408{
409 int i, err;
410
411 /* loop over y components */
412 for (i = 0; i < 64; i++) {
413 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
414 if (err < 0)
415 return err;
416 }
417
418 /* loop over c components */
419 for (i = 0; i < 64; i++) {
420 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
421 if (err < 0)
422 return err;
423 }
424 return 0;
425}
426
427static void spca500_ping310(struct gspca_dev *gspca_dev)
428{
429 reg_r(gspca_dev, 0x0d04, 2);
430 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
431 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
432}
433
434static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
435{
436 reg_r(gspca_dev, 0x0d05, 2);
437 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
438 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
439 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
440 spca500_ping310(gspca_dev);
441
442 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
443 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
444 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
445 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
446 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
447 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
448 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
449 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
450 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
451 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
452 /* 00 for adjust shutter */
453 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
454 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
455 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
456}
457
458static void spca500_setmode(struct gspca_dev *gspca_dev,
459 __u8 xmult, __u8 ymult)
460{
461 int mode;
462
463 /* set x multiplier */
464 reg_w(gspca_dev, 0, 0x8001, xmult);
465
466 /* set y multiplier */
467 reg_w(gspca_dev, 0, 0x8002, ymult);
468
469 /* use compressed mode, VGA, with mode specific subsample */
470 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
471 reg_w(gspca_dev, 0, 0x8003, mode << 4);
472}
473
474static int spca500_full_reset(struct gspca_dev *gspca_dev)
475{
476 int err;
477
478 /* send the reset command */
479 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
480 if (err < 0)
481 return err;
482
483 /* wait for the reset to complete */
484 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
485 if (err < 0)
486 return err;
487 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
488 if (err < 0)
489 return err;
490 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
491 if (err < 0) {
492 PDEBUG(D_ERR, "reg_r_wait() failed");
493 return err;
494 }
495 /* all ok */
496 return 0;
497}
498
499/* Synchro the Bridge with sensor */
500/* Maybe that will work on all spca500 chip */
501/* because i only own a clicksmart310 try for that chip */
502/* using spca50x_set_packet_size() cause an Ooops here */
503/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
504/* up-port the same feature as in 2.4.x kernel */
505static int spca500_synch310(struct gspca_dev *gspca_dev)
506{
507 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
508 PDEBUG(D_ERR, "Set packet size: set interface error");
509 goto error;
510 }
511 spca500_ping310(gspca_dev);
512
513 reg_r(gspca_dev, 0x0d00, 1);
514
515 /* need alt setting here */
516 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
517
518 /* Windoze use pipe with altsetting 6 why 7 here */
519 if (usb_set_interface(gspca_dev->dev,
520 gspca_dev->iface,
521 gspca_dev->alt) < 0) {
522 PDEBUG(D_ERR, "Set packet size: set interface error");
523 goto error;
524 }
525 return 0;
526error:
527 return -EBUSY;
528}
529
530static void spca500_reinit(struct gspca_dev *gspca_dev)
531{
532 int err;
533 __u8 Data;
534
535 /* some unknown command from Aiptek pocket dv and family300 */
536
537 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
538 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
539 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
540
541 /* enable drop packet */
542 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
543
544 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
545 qtable_pocketdv);
546 if (err < 0)
547 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
548
549 /* set qtable index */
550 reg_w(gspca_dev, 0x00, 0x8880, 2);
551 /* family cam Quicksmart stuff */
552 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
553 /* Set agc transfer: synced between frames */
554 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
555 /* Init SDRAM - needed for SDRAM access */
556 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
557 /*Start init sequence or stream */
558 reg_w(gspca_dev, 0, 0x8003, 0x00);
559 /* switch to video camera mode */
560 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
561 msleep(2000);
562 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
563 reg_r(gspca_dev, 0x816b, 1);
564 Data = gspca_dev->usb_buf[0];
565 reg_w(gspca_dev, 0x00, 0x816b, Data);
566 }
567}
568
569/* this function is called at probe time */
570static int sd_config(struct gspca_dev *gspca_dev,
571 const struct usb_device_id *id)
572{
573 struct sd *sd = (struct sd *) gspca_dev;
574 struct cam *cam;
575
576 cam = &gspca_dev->cam;
577 sd->subtype = id->driver_info;
578 if (sd->subtype != LogitechClickSmart310) {
579 cam->cam_mode = vga_mode;
580 cam->nmodes = ARRAY_SIZE(vga_mode);
581 } else {
582 cam->cam_mode = sif_mode;
583 cam->nmodes = ARRAY_SIZE(sif_mode);
584 }
585 return 0;
586}
587
588/* this function is called at probe and resume time */
589static int sd_init(struct gspca_dev *gspca_dev)
590{
591 struct sd *sd = (struct sd *) gspca_dev;
592
593 /* initialisation of spca500 based cameras is deferred */
594 PDEBUG(D_STREAM, "SPCA500 init");
595 if (sd->subtype == LogitechClickSmart310)
596 spca500_clksmart310_init(gspca_dev);
597/* else
598 spca500_initialise(gspca_dev); */
599 PDEBUG(D_STREAM, "SPCA500 init done");
600 return 0;
601}
602
603static int sd_start(struct gspca_dev *gspca_dev)
604{
605 struct sd *sd = (struct sd *) gspca_dev;
606 int err;
607 __u8 Data;
608 __u8 xmult, ymult;
609
610 /* create the JPEG header */
611 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
612 0x22); /* JPEG 411 */
613 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
614
615 if (sd->subtype == LogitechClickSmart310) {
616 xmult = 0x16;
617 ymult = 0x12;
618 } else {
619 xmult = 0x28;
620 ymult = 0x1e;
621 }
622
623 /* is there a sensor here ? */
624 reg_r(gspca_dev, 0x8a04, 1);
625 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
626 gspca_dev->usb_buf[0]);
627 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
628 gspca_dev->curr_mode, xmult, ymult);
629
630 /* setup qtable */
631 switch (sd->subtype) {
632 case LogitechClickSmart310:
633 spca500_setmode(gspca_dev, xmult, ymult);
634
635 /* enable drop packet */
636 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
637 reg_w(gspca_dev, 0x00, 0x8880, 3);
638 err = spca50x_setup_qtable(gspca_dev,
639 0x00, 0x8800, 0x8840,
640 qtable_creative_pccam);
641 if (err < 0)
642 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
643 /* Init SDRAM - needed for SDRAM access */
644 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
645
646 /* switch to video camera mode */
647 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
648 msleep(500);
649 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
650 PDEBUG(D_ERR, "reg_r_wait() failed");
651
652 reg_r(gspca_dev, 0x816b, 1);
653 Data = gspca_dev->usb_buf[0];
654 reg_w(gspca_dev, 0x00, 0x816b, Data);
655
656 spca500_synch310(gspca_dev);
657
658 write_vector(gspca_dev, spca500_visual_defaults);
659 spca500_setmode(gspca_dev, xmult, ymult);
660 /* enable drop packet */
661 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
662 if (err < 0)
663 PDEBUG(D_ERR, "failed to enable drop packet");
664 reg_w(gspca_dev, 0x00, 0x8880, 3);
665 err = spca50x_setup_qtable(gspca_dev,
666 0x00, 0x8800, 0x8840,
667 qtable_creative_pccam);
668 if (err < 0)
669 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
670
671 /* Init SDRAM - needed for SDRAM access */
672 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
673
674 /* switch to video camera mode */
675 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
676
677 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
678 PDEBUG(D_ERR, "reg_r_wait() failed");
679
680 reg_r(gspca_dev, 0x816b, 1);
681 Data = gspca_dev->usb_buf[0];
682 reg_w(gspca_dev, 0x00, 0x816b, Data);
683 break;
684 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
685 case IntelPocketPCCamera: /* FIXME: Temporary fix for
686 * Intel Pocket PC Camera
687 * - NWG (Sat 29th March 2003) */
688
689 /* do a full reset */
690 err = spca500_full_reset(gspca_dev);
691 if (err < 0)
692 PDEBUG(D_ERR, "spca500_full_reset failed");
693
694 /* enable drop packet */
695 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
696 if (err < 0)
697 PDEBUG(D_ERR, "failed to enable drop packet");
698 reg_w(gspca_dev, 0x00, 0x8880, 3);
699 err = spca50x_setup_qtable(gspca_dev,
700 0x00, 0x8800, 0x8840,
701 qtable_creative_pccam);
702 if (err < 0)
703 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
704
705 spca500_setmode(gspca_dev, xmult, ymult);
706 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
707
708 /* switch to video camera mode */
709 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
710
711 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
712 PDEBUG(D_ERR, "reg_r_wait() failed");
713
714 reg_r(gspca_dev, 0x816b, 1);
715 Data = gspca_dev->usb_buf[0];
716 reg_w(gspca_dev, 0x00, 0x816b, Data);
717
718/* write_vector(gspca_dev, spca500_visual_defaults); */
719 break;
720 case KodakEZ200: /* Kodak EZ200 */
721
722 /* do a full reset */
723 err = spca500_full_reset(gspca_dev);
724 if (err < 0)
725 PDEBUG(D_ERR, "spca500_full_reset failed");
726 /* enable drop packet */
727 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
728 reg_w(gspca_dev, 0x00, 0x8880, 0);
729 err = spca50x_setup_qtable(gspca_dev,
730 0x00, 0x8800, 0x8840,
731 qtable_kodak_ez200);
732 if (err < 0)
733 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
734 spca500_setmode(gspca_dev, xmult, ymult);
735
736 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
737
738 /* switch to video camera mode */
739 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
740
741 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
742 PDEBUG(D_ERR, "reg_r_wait() failed");
743
744 reg_r(gspca_dev, 0x816b, 1);
745 Data = gspca_dev->usb_buf[0];
746 reg_w(gspca_dev, 0x00, 0x816b, Data);
747
748/* write_vector(gspca_dev, spca500_visual_defaults); */
749 break;
750
751 case BenqDC1016:
752 case DLinkDSC350: /* FamilyCam 300 */
753 case AiptekPocketDV: /* Aiptek PocketDV */
754 case Gsmartmini: /*Mustek Gsmart Mini */
755 case MustekGsmart300: /* Mustek Gsmart 300 */
756 case PalmPixDC85:
757 case Optimedia:
758 case ToptroIndus:
759 case AgfaCl20:
760 spca500_reinit(gspca_dev);
761 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
762 /* enable drop packet */
763 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
764
765 err = spca50x_setup_qtable(gspca_dev,
766 0x00, 0x8800, 0x8840, qtable_pocketdv);
767 if (err < 0)
768 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
769 reg_w(gspca_dev, 0x00, 0x8880, 2);
770
771 /* familycam Quicksmart pocketDV stuff */
772 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
773 /* Set agc transfer: synced between frames */
774 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
775 /* Init SDRAM - needed for SDRAM access */
776 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
777
778 spca500_setmode(gspca_dev, xmult, ymult);
779 /* switch to video camera mode */
780 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
781
782 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
783
784 reg_r(gspca_dev, 0x816b, 1);
785 Data = gspca_dev->usb_buf[0];
786 reg_w(gspca_dev, 0x00, 0x816b, Data);
787 break;
788 case LogitechTraveler:
789 case LogitechClickSmart510:
790 reg_w(gspca_dev, 0x02, 0x00, 0x00);
791 /* enable drop packet */
792 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
793
794 err = spca50x_setup_qtable(gspca_dev,
795 0x00, 0x8800,
796 0x8840, qtable_creative_pccam);
797 if (err < 0)
798 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
799 reg_w(gspca_dev, 0x00, 0x8880, 3);
800 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
801 /* Init SDRAM - needed for SDRAM access */
802 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
803
804 spca500_setmode(gspca_dev, xmult, ymult);
805
806 /* switch to video camera mode */
807 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
808 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
809
810 reg_r(gspca_dev, 0x816b, 1);
811 Data = gspca_dev->usb_buf[0];
812 reg_w(gspca_dev, 0x00, 0x816b, Data);
813 write_vector(gspca_dev, Clicksmart510_defaults);
814 break;
815 }
816 return 0;
817}
818
819static void sd_stopN(struct gspca_dev *gspca_dev)
820{
821 reg_w(gspca_dev, 0, 0x8003, 0x00);
822
823 /* switch to video camera mode */
824 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
825 reg_r(gspca_dev, 0x8000, 1);
826 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
827 gspca_dev->usb_buf[0]);
828}
829
830static void sd_pkt_scan(struct gspca_dev *gspca_dev,
831 u8 *data, /* isoc packet */
832 int len) /* iso packet length */
833{
834 struct sd *sd = (struct sd *) gspca_dev;
835 int i;
836 static __u8 ffd9[] = {0xff, 0xd9};
837
838/* frames are jpeg 4.1.1 without 0xff escape */
839 if (data[0] == 0xff) {
840 if (data[1] != 0x01) { /* drop packet */
841/* gspca_dev->last_packet_type = DISCARD_PACKET; */
842 return;
843 }
844 gspca_frame_add(gspca_dev, LAST_PACKET,
845 ffd9, 2);
846
847 /* put the JPEG header in the new frame */
848 gspca_frame_add(gspca_dev, FIRST_PACKET,
849 sd->jpeg_hdr, JPEG_HDR_SZ);
850
851 data += SPCA500_OFFSET_DATA;
852 len -= SPCA500_OFFSET_DATA;
853 } else {
854 data += 1;
855 len -= 1;
856 }
857
858 /* add 0x00 after 0xff */
859 i = 0;
860 do {
861 if (data[i] == 0xff) {
862 gspca_frame_add(gspca_dev, INTER_PACKET,
863 data, i + 1);
864 len -= i;
865 data += i;
866 *data = 0x00;
867 i = 0;
868 }
869 i++;
870 } while (i < len);
871 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
872}
873
874static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
875{
876 reg_w(gspca_dev, 0x00, 0x8167,
877 (__u8) (val - 128));
878}
879
880static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
881{
882 reg_w(gspca_dev, 0x00, 0x8168, val);
883}
884
885static void setcolors(struct gspca_dev *gspca_dev, s32 val)
886{
887 reg_w(gspca_dev, 0x00, 0x8169, val);
888}
889
890static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
891{
892 struct gspca_dev *gspca_dev =
893 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
894
895 gspca_dev->usb_err = 0;
896
897 if (!gspca_dev->streaming)
898 return 0;
899
900 switch (ctrl->id) {
901 case V4L2_CID_BRIGHTNESS:
902 setbrightness(gspca_dev, ctrl->val);
903 break;
904 case V4L2_CID_CONTRAST:
905 setcontrast(gspca_dev, ctrl->val);
906 break;
907 case V4L2_CID_SATURATION:
908 setcolors(gspca_dev, ctrl->val);
909 break;
910 }
911 return gspca_dev->usb_err;
912}
913
914static const struct v4l2_ctrl_ops sd_ctrl_ops = {
915 .s_ctrl = sd_s_ctrl,
916};
917
918static int sd_init_controls(struct gspca_dev *gspca_dev)
919{
920 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
921
922 gspca_dev->vdev.ctrl_handler = hdl;
923 v4l2_ctrl_handler_init(hdl, 3);
924 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
925 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
926 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
927 V4L2_CID_CONTRAST, 0, 63, 1, 31);
928 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
929 V4L2_CID_SATURATION, 0, 63, 1, 31);
930
931 if (hdl->error) {
932 pr_err("Could not initialize controls\n");
933 return hdl->error;
934 }
935 return 0;
936}
937
938/* sub-driver description */
939static const struct sd_desc sd_desc = {
940 .name = MODULE_NAME,
941 .config = sd_config,
942 .init = sd_init,
943 .init_controls = sd_init_controls,
944 .start = sd_start,
945 .stopN = sd_stopN,
946 .pkt_scan = sd_pkt_scan,
947};
948
949/* -- module initialisation -- */
950static const struct usb_device_id device_table[] = {
951 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
952 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
953 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
954 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
955 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
956 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
957 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
958 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
959 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
960 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
961 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
962 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
963 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
964 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
965 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
966 {}
967};
968MODULE_DEVICE_TABLE(usb, device_table);
969
970/* -- device connect -- */
971static int sd_probe(struct usb_interface *intf,
972 const struct usb_device_id *id)
973{
974 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
975 THIS_MODULE);
976}
977
978static struct usb_driver sd_driver = {
979 .name = MODULE_NAME,
980 .id_table = device_table,
981 .probe = sd_probe,
982 .disconnect = gspca_disconnect,
983#ifdef CONFIG_PM
984 .suspend = gspca_suspend,
985 .resume = gspca_resume,
986 .reset_resume = gspca_resume,
987#endif
988};
989
990module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca501.c b/drivers/media/usb/gspca/spca501.c
new file mode 100644
index 00000000000..3b7f777785b
--- /dev/null
+++ b/drivers/media/usb/gspca/spca501.c
@@ -0,0 +1,2054 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "spca501"
25
26#include "gspca.h"
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA501 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 short contrast;
37 __u8 brightness;
38 __u8 colors;
39 __u8 blue_balance;
40 __u8 red_balance;
41
42 char subtype;
43#define Arowana300KCMOSCamera 0
44#define IntelCreateAndShare 1
45#define KodakDVC325 2
46#define MystFromOriUnknownCamera 3
47#define SmileIntlCamera 4
48#define ThreeComHomeConnectLite 5
49#define ViewQuestM318B 6
50};
51
52static const struct v4l2_pix_format vga_mode[] = {
53 {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
54 .bytesperline = 160,
55 .sizeimage = 160 * 120 * 3 / 2,
56 .colorspace = V4L2_COLORSPACE_SRGB,
57 .priv = 2},
58 {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
59 .bytesperline = 320,
60 .sizeimage = 320 * 240 * 3 / 2,
61 .colorspace = V4L2_COLORSPACE_SRGB,
62 .priv = 1},
63 {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
64 .bytesperline = 640,
65 .sizeimage = 640 * 480 * 3 / 2,
66 .colorspace = V4L2_COLORSPACE_SRGB,
67 .priv = 0},
68};
69
70#define SPCA50X_REG_USB 0x2 /* spca505 501 */
71/*
72 * Data to initialize a SPCA501. From a capture file provided by Bill Roehl
73 * With SPCA501 chip description
74 */
75#define CCDSP_SET /* set CCDSP parameters */
76#define TG_SET /* set time generator set */
77#undef DSPWIN_SET /* set DSP windows parameters */
78#undef ALTER_GAMA /* Set alternate set to YUV transform coeffs. */
79#define SPCA501_SNAPBIT 0x80
80#define SPCA501_SNAPCTRL 0x10
81/* Frame packet header offsets for the spca501 */
82#define SPCA501_OFFSET_GPIO 1
83#define SPCA501_OFFSET_TYPE 2
84#define SPCA501_OFFSET_TURN3A 3
85#define SPCA501_OFFSET_FRAMSEQ 4
86#define SPCA501_OFFSET_COMPRESS 5
87#define SPCA501_OFFSET_QUANT 6
88#define SPCA501_OFFSET_QUANT2 7
89#define SPCA501_OFFSET_DATA 8
90
91#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1)
92#define SPCA501_PROP_SNAP(d) ((d) & 0x40)
93#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10)
94#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1)
95#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4)
96
97/* SPCA501 CCDSP control */
98#define SPCA501_REG_CCDSP 0x01
99/* SPCA501 control/status registers */
100#define SPCA501_REG_CTLRL 0x02
101
102/* registers for color correction and YUV transformation */
103#define SPCA501_A11 0x08
104#define SPCA501_A12 0x09
105#define SPCA501_A13 0x0A
106#define SPCA501_A21 0x0B
107#define SPCA501_A22 0x0C
108#define SPCA501_A23 0x0D
109#define SPCA501_A31 0x0E
110#define SPCA501_A32 0x0F
111#define SPCA501_A33 0x10
112
113/* Data for video camera initialization before capturing */
114static const __u16 spca501_open_data[][3] = {
115 /* bmRequest,value,index */
116
117 {0x2, 0x50, 0x00}, /* C/S enable soft reset */
118 {0x2, 0x40, 0x00}, /* C/S disable soft reset */
119 {0x2, 0x02, 0x05}, /* C/S general purpose I/O data */
120 {0x2, 0x03, 0x05}, /* C/S general purpose I/O data */
121
122#ifdef CCDSP_SET
123 {0x1, 0x38, 0x01}, /* CCDSP options */
124 {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */
125 {0x1, 0xC0, 0x03}, /* CCDSP Optical black settings */
126
127 {0x1, 0x67, 0x07},
128 {0x1, 0x63, 0x3f}, /* CCDSP CCD gamma enable */
129 {0x1, 0x03, 0x56}, /* Add gamma correction */
130
131 {0x1, 0xFF, 0x15}, /* CCDSP High luminance for white balance */
132 {0x1, 0x01, 0x16}, /* CCDSP Low luminance for white balance */
133
134/* Color correction and RGB-to-YUV transformation coefficients changing */
135#ifdef ALTER_GAMA
136 {0x0, 0x00, 0x08}, /* A11 */
137 {0x0, 0x00, 0x09}, /* A12 */
138 {0x0, 0x90, 0x0A}, /* A13 */
139 {0x0, 0x12, 0x0B}, /* A21 */
140 {0x0, 0x00, 0x0C}, /* A22 */
141 {0x0, 0x00, 0x0D}, /* A23 */
142 {0x0, 0x00, 0x0E}, /* A31 */
143 {0x0, 0x02, 0x0F}, /* A32 */
144 {0x0, 0x00, 0x10}, /* A33 */
145#else
146 {0x1, 0x2a, 0x08}, /* A11 0x31 */
147 {0x1, 0xf8, 0x09}, /* A12 f8 */
148 {0x1, 0xf8, 0x0A}, /* A13 f8 */
149 {0x1, 0xf8, 0x0B}, /* A21 f8 */
150 {0x1, 0x14, 0x0C}, /* A22 0x14 */
151 {0x1, 0xf8, 0x0D}, /* A23 f8 */
152 {0x1, 0xf8, 0x0E}, /* A31 f8 */
153 {0x1, 0xf8, 0x0F}, /* A32 f8 */
154 {0x1, 0x20, 0x10}, /* A33 0x20 */
155#endif
156 {0x1, 0x00, 0x11}, /* R offset */
157 {0x1, 0x00, 0x12}, /* G offset */
158 {0x1, 0x00, 0x13}, /* B offset */
159 {0x1, 0x00, 0x14}, /* GB offset */
160
161#endif
162
163#ifdef TG_SET
164 /* Time generator manipulations */
165 {0x0, 0xfc, 0x0}, /* Set up high bits of shutter speed */
166 {0x0, 0x01, 0x1}, /* Set up low bits of shutter speed */
167
168 {0x0, 0xe4, 0x04}, /* DCLK*2 clock phase adjustment */
169 {0x0, 0x08, 0x05}, /* ADCK phase adjustment, inv. ext. VB */
170 {0x0, 0x03, 0x06}, /* FR phase adjustment */
171 {0x0, 0x01, 0x07}, /* FCDS phase adjustment */
172 {0x0, 0x39, 0x08}, /* FS phase adjustment */
173 {0x0, 0x88, 0x0a}, /* FH1 phase and delay adjustment */
174 {0x0, 0x03, 0x0f}, /* pixel identification */
175 {0x0, 0x00, 0x11}, /* clock source selection (default) */
176
177 /*VERY strange manipulations with
178 * select DMCLP or OBPX to be ADCLP output (0x0C)
179 * OPB always toggle or not (0x0D) but they allow
180 * us to set up brightness
181 */
182 {0x0, 0x01, 0x0c},
183 {0x0, 0xe0, 0x0d},
184 /* Done */
185#endif
186
187#ifdef DSPWIN_SET
188 {0x1, 0xa0, 0x01}, /* Setting image processing parameters */
189 {0x1, 0x1c, 0x17}, /* Changing Windows positions X1 */
190 {0x1, 0xe2, 0x19}, /* X2 */
191 {0x1, 0x1c, 0x1b}, /* X3 */
192 {0x1, 0xe2, 0x1d}, /* X4 */
193 {0x1, 0x5f, 0x1f}, /* X5 */
194 {0x1, 0x32, 0x20}, /* Y5 */
195 {0x1, 0x01, 0x10}, /* Changing A33 */
196#endif
197
198 {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */
199 {0x2, 0x94, 0x06}, /* Setting video no compression */
200 {}
201};
202
203/*
204 The SPCAxxx docs from Sunplus document these values
205 in tables, one table per register number. In the data
206 below, dmRequest is the register number, index is the Addr,
207 and value is a combination of Bit values.
208 Bit Value (hex)
209 0 01
210 1 02
211 2 04
212 3 08
213 4 10
214 5 20
215 6 40
216 7 80
217 */
218
219/* Data for chip initialization (set default values) */
220static const __u16 spca501_init_data[][3] = {
221 /* Set all the values to powerup defaults */
222 /* bmRequest,value,index */
223 {0x0, 0xAA, 0x00},
224 {0x0, 0x02, 0x01},
225 {0x0, 0x01, 0x02},
226 {0x0, 0x02, 0x03},
227 {0x0, 0xCE, 0x04},
228 {0x0, 0x00, 0x05},
229 {0x0, 0x00, 0x06},
230 {0x0, 0x00, 0x07},
231 {0x0, 0x00, 0x08},
232 {0x0, 0x00, 0x09},
233 {0x0, 0x90, 0x0A},
234 {0x0, 0x12, 0x0B},
235 {0x0, 0x00, 0x0C},
236 {0x0, 0x00, 0x0D},
237 {0x0, 0x00, 0x0E},
238 {0x0, 0x02, 0x0F},
239 {0x0, 0x00, 0x10},
240 {0x0, 0x00, 0x11},
241 {0x0, 0x00, 0x12},
242 {0x0, 0x00, 0x13},
243 {0x0, 0x00, 0x14},
244 {0x0, 0x00, 0x15},
245 {0x0, 0x00, 0x16},
246 {0x0, 0x00, 0x17},
247 {0x0, 0x00, 0x18},
248 {0x0, 0x00, 0x19},
249 {0x0, 0x00, 0x1A},
250 {0x0, 0x00, 0x1B},
251 {0x0, 0x00, 0x1C},
252 {0x0, 0x00, 0x1D},
253 {0x0, 0x00, 0x1E},
254 {0x0, 0x00, 0x1F},
255 {0x0, 0x00, 0x20},
256 {0x0, 0x00, 0x21},
257 {0x0, 0x00, 0x22},
258 {0x0, 0x00, 0x23},
259 {0x0, 0x00, 0x24},
260 {0x0, 0x00, 0x25},
261 {0x0, 0x00, 0x26},
262 {0x0, 0x00, 0x27},
263 {0x0, 0x00, 0x28},
264 {0x0, 0x00, 0x29},
265 {0x0, 0x00, 0x2A},
266 {0x0, 0x00, 0x2B},
267 {0x0, 0x00, 0x2C},
268 {0x0, 0x00, 0x2D},
269 {0x0, 0x00, 0x2E},
270 {0x0, 0x00, 0x2F},
271 {0x0, 0x00, 0x30},
272 {0x0, 0x00, 0x31},
273 {0x0, 0x00, 0x32},
274 {0x0, 0x00, 0x33},
275 {0x0, 0x00, 0x34},
276 {0x0, 0x00, 0x35},
277 {0x0, 0x00, 0x36},
278 {0x0, 0x00, 0x37},
279 {0x0, 0x00, 0x38},
280 {0x0, 0x00, 0x39},
281 {0x0, 0x00, 0x3A},
282 {0x0, 0x00, 0x3B},
283 {0x0, 0x00, 0x3C},
284 {0x0, 0x00, 0x3D},
285 {0x0, 0x00, 0x3E},
286 {0x0, 0x00, 0x3F},
287 {0x0, 0x00, 0x40},
288 {0x0, 0x00, 0x41},
289 {0x0, 0x00, 0x42},
290 {0x0, 0x00, 0x43},
291 {0x0, 0x00, 0x44},
292 {0x0, 0x00, 0x45},
293 {0x0, 0x00, 0x46},
294 {0x0, 0x00, 0x47},
295 {0x0, 0x00, 0x48},
296 {0x0, 0x00, 0x49},
297 {0x0, 0x00, 0x4A},
298 {0x0, 0x00, 0x4B},
299 {0x0, 0x00, 0x4C},
300 {0x0, 0x00, 0x4D},
301 {0x0, 0x00, 0x4E},
302 {0x0, 0x00, 0x4F},
303 {0x0, 0x00, 0x50},
304 {0x0, 0x00, 0x51},
305 {0x0, 0x00, 0x52},
306 {0x0, 0x00, 0x53},
307 {0x0, 0x00, 0x54},
308 {0x0, 0x00, 0x55},
309 {0x0, 0x00, 0x56},
310 {0x0, 0x00, 0x57},
311 {0x0, 0x00, 0x58},
312 {0x0, 0x00, 0x59},
313 {0x0, 0x00, 0x5A},
314 {0x0, 0x00, 0x5B},
315 {0x0, 0x00, 0x5C},
316 {0x0, 0x00, 0x5D},
317 {0x0, 0x00, 0x5E},
318 {0x0, 0x00, 0x5F},
319 {0x0, 0x00, 0x60},
320 {0x0, 0x00, 0x61},
321 {0x0, 0x00, 0x62},
322 {0x0, 0x00, 0x63},
323 {0x0, 0x00, 0x64},
324 {0x0, 0x00, 0x65},
325 {0x0, 0x00, 0x66},
326 {0x0, 0x00, 0x67},
327 {0x0, 0x00, 0x68},
328 {0x0, 0x00, 0x69},
329 {0x0, 0x00, 0x6A},
330 {0x0, 0x00, 0x6B},
331 {0x0, 0x00, 0x6C},
332 {0x0, 0x00, 0x6D},
333 {0x0, 0x00, 0x6E},
334 {0x0, 0x00, 0x6F},
335 {0x0, 0x00, 0x70},
336 {0x0, 0x00, 0x71},
337 {0x0, 0x00, 0x72},
338 {0x0, 0x00, 0x73},
339 {0x0, 0x00, 0x74},
340 {0x0, 0x00, 0x75},
341 {0x0, 0x00, 0x76},
342 {0x0, 0x00, 0x77},
343 {0x0, 0x00, 0x78},
344 {0x0, 0x00, 0x79},
345 {0x0, 0x00, 0x7A},
346 {0x0, 0x00, 0x7B},
347 {0x0, 0x00, 0x7C},
348 {0x0, 0x00, 0x7D},
349 {0x0, 0x00, 0x7E},
350 {0x0, 0x00, 0x7F},
351 {0x0, 0x00, 0x80},
352 {0x0, 0x00, 0x81},
353 {0x0, 0x00, 0x82},
354 {0x0, 0x00, 0x83},
355 {0x0, 0x00, 0x84},
356 {0x0, 0x00, 0x85},
357 {0x0, 0x00, 0x86},
358 {0x0, 0x00, 0x87},
359 {0x0, 0x00, 0x88},
360 {0x0, 0x00, 0x89},
361 {0x0, 0x00, 0x8A},
362 {0x0, 0x00, 0x8B},
363 {0x0, 0x00, 0x8C},
364 {0x0, 0x00, 0x8D},
365 {0x0, 0x00, 0x8E},
366 {0x0, 0x00, 0x8F},
367 {0x0, 0x00, 0x90},
368 {0x0, 0x00, 0x91},
369 {0x0, 0x00, 0x92},
370 {0x0, 0x00, 0x93},
371 {0x0, 0x00, 0x94},
372 {0x0, 0x00, 0x95},
373 {0x0, 0x00, 0x96},
374 {0x0, 0x00, 0x97},
375 {0x0, 0x00, 0x98},
376 {0x0, 0x00, 0x99},
377 {0x0, 0x00, 0x9A},
378 {0x0, 0x00, 0x9B},
379 {0x0, 0x00, 0x9C},
380 {0x0, 0x00, 0x9D},
381 {0x0, 0x00, 0x9E},
382 {0x0, 0x00, 0x9F},
383 {0x0, 0x00, 0xA0},
384 {0x0, 0x00, 0xA1},
385 {0x0, 0x00, 0xA2},
386 {0x0, 0x00, 0xA3},
387 {0x0, 0x00, 0xA4},
388 {0x0, 0x00, 0xA5},
389 {0x0, 0x00, 0xA6},
390 {0x0, 0x00, 0xA7},
391 {0x0, 0x00, 0xA8},
392 {0x0, 0x00, 0xA9},
393 {0x0, 0x00, 0xAA},
394 {0x0, 0x00, 0xAB},
395 {0x0, 0x00, 0xAC},
396 {0x0, 0x00, 0xAD},
397 {0x0, 0x00, 0xAE},
398 {0x0, 0x00, 0xAF},
399 {0x0, 0x00, 0xB0},
400 {0x0, 0x00, 0xB1},
401 {0x0, 0x00, 0xB2},
402 {0x0, 0x00, 0xB3},
403 {0x0, 0x00, 0xB4},
404 {0x0, 0x00, 0xB5},
405 {0x0, 0x00, 0xB6},
406 {0x0, 0x00, 0xB7},
407 {0x0, 0x00, 0xB8},
408 {0x0, 0x00, 0xB9},
409 {0x0, 0x00, 0xBA},
410 {0x0, 0x00, 0xBB},
411 {0x0, 0x00, 0xBC},
412 {0x0, 0x00, 0xBD},
413 {0x0, 0x00, 0xBE},
414 {0x0, 0x00, 0xBF},
415 {0x0, 0x00, 0xC0},
416 {0x0, 0x00, 0xC1},
417 {0x0, 0x00, 0xC2},
418 {0x0, 0x00, 0xC3},
419 {0x0, 0x00, 0xC4},
420 {0x0, 0x00, 0xC5},
421 {0x0, 0x00, 0xC6},
422 {0x0, 0x00, 0xC7},
423 {0x0, 0x00, 0xC8},
424 {0x0, 0x00, 0xC9},
425 {0x0, 0x00, 0xCA},
426 {0x0, 0x00, 0xCB},
427 {0x0, 0x00, 0xCC},
428 {0x1, 0xF4, 0x00},
429 {0x1, 0x38, 0x01},
430 {0x1, 0x40, 0x02},
431 {0x1, 0x0A, 0x03},
432 {0x1, 0x40, 0x04},
433 {0x1, 0x40, 0x05},
434 {0x1, 0x40, 0x06},
435 {0x1, 0x67, 0x07},
436 {0x1, 0x31, 0x08},
437 {0x1, 0x00, 0x09},
438 {0x1, 0x00, 0x0A},
439 {0x1, 0x00, 0x0B},
440 {0x1, 0x14, 0x0C},
441 {0x1, 0x00, 0x0D},
442 {0x1, 0x00, 0x0E},
443 {0x1, 0x00, 0x0F},
444 {0x1, 0x1E, 0x10},
445 {0x1, 0x00, 0x11},
446 {0x1, 0x00, 0x12},
447 {0x1, 0x00, 0x13},
448 {0x1, 0x00, 0x14},
449 {0x1, 0xFF, 0x15},
450 {0x1, 0x01, 0x16},
451 {0x1, 0x32, 0x17},
452 {0x1, 0x23, 0x18},
453 {0x1, 0xCE, 0x19},
454 {0x1, 0x23, 0x1A},
455 {0x1, 0x32, 0x1B},
456 {0x1, 0x8D, 0x1C},
457 {0x1, 0xCE, 0x1D},
458 {0x1, 0x8D, 0x1E},
459 {0x1, 0x00, 0x1F},
460 {0x1, 0x00, 0x20},
461 {0x1, 0xFF, 0x3E},
462 {0x1, 0x02, 0x3F},
463 {0x1, 0x00, 0x40},
464 {0x1, 0x00, 0x41},
465 {0x1, 0x00, 0x42},
466 {0x1, 0x00, 0x43},
467 {0x1, 0x00, 0x44},
468 {0x1, 0x00, 0x45},
469 {0x1, 0x00, 0x46},
470 {0x1, 0x00, 0x47},
471 {0x1, 0x00, 0x48},
472 {0x1, 0x00, 0x49},
473 {0x1, 0x00, 0x4A},
474 {0x1, 0x00, 0x4B},
475 {0x1, 0x00, 0x4C},
476 {0x1, 0x00, 0x4D},
477 {0x1, 0x00, 0x4E},
478 {0x1, 0x00, 0x4F},
479 {0x1, 0x00, 0x50},
480 {0x1, 0x00, 0x51},
481 {0x1, 0x00, 0x52},
482 {0x1, 0x00, 0x53},
483 {0x1, 0x00, 0x54},
484 {0x1, 0x00, 0x55},
485 {0x1, 0x00, 0x56},
486 {0x1, 0x00, 0x57},
487 {0x1, 0x00, 0x58},
488 {0x1, 0x00, 0x59},
489 {0x1, 0x00, 0x5A},
490 {0x2, 0x03, 0x00},
491 {0x2, 0x00, 0x01},
492 {0x2, 0x00, 0x05},
493 {0x2, 0x00, 0x06},
494 {0x2, 0x00, 0x07},
495 {0x2, 0x00, 0x10},
496 {0x2, 0x00, 0x11},
497 /* Strange - looks like the 501 driver doesn't do anything
498 * at insert time except read the EEPROM
499 */
500 {}
501};
502
503/* Data for video camera init before capture.
504 * Capture and decoding by Colin Peart.
505 * This is is for the 3com HomeConnect Lite which is spca501a based.
506 */
507static const __u16 spca501_3com_open_data[][3] = {
508 /* bmRequest,value,index */
509 {0x2, 0x0050, 0x0000}, /* C/S Enable TG soft reset, timing mode=010 */
510 {0x2, 0x0043, 0x0000}, /* C/S Disable TG soft reset, timing mode=010 */
511 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
512 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
513
514#ifdef CCDSP_SET
515 {0x1, 0x0020, 0x0001}, /* CCDSP Options */
516
517 {0x1, 0x0020, 0x0002}, /* CCDSP Black Level */
518 {0x1, 0x006e, 0x0007}, /* CCDSP Gamma options */
519 {0x1, 0x0090, 0x0015}, /* CCDSP Luminance Low */
520 {0x1, 0x00ff, 0x0016}, /* CCDSP Luminance High */
521 {0x1, 0x0003, 0x003F}, /* CCDSP Gamma correction toggle */
522
523#ifdef ALTER_GAMMA
524 {0x1, 0x0010, 0x0008}, /* CCDSP YUV A11 */
525 {0x1, 0x0000, 0x0009}, /* CCDSP YUV A12 */
526 {0x1, 0x0000, 0x000a}, /* CCDSP YUV A13 */
527 {0x1, 0x0000, 0x000b}, /* CCDSP YUV A21 */
528 {0x1, 0x0010, 0x000c}, /* CCDSP YUV A22 */
529 {0x1, 0x0000, 0x000d}, /* CCDSP YUV A23 */
530 {0x1, 0x0000, 0x000e}, /* CCDSP YUV A31 */
531 {0x1, 0x0000, 0x000f}, /* CCDSP YUV A32 */
532 {0x1, 0x0010, 0x0010}, /* CCDSP YUV A33 */
533 {0x1, 0x0000, 0x0011}, /* CCDSP R Offset */
534 {0x1, 0x0000, 0x0012}, /* CCDSP G Offset */
535 {0x1, 0x0001, 0x0013}, /* CCDSP B Offset */
536 {0x1, 0x0001, 0x0014}, /* CCDSP BG Offset */
537 {0x1, 0x003f, 0x00C1}, /* CCDSP Gamma Correction Enable */
538#endif
539#endif
540
541#ifdef TG_SET
542 {0x0, 0x00fc, 0x0000}, /* TG Shutter Speed High Bits */
543 {0x0, 0x0000, 0x0001}, /* TG Shutter Speed Low Bits */
544 {0x0, 0x00e4, 0x0004}, /* TG DCLK*2 Adjust */
545 {0x0, 0x0008, 0x0005}, /* TG ADCK Adjust */
546 {0x0, 0x0003, 0x0006}, /* TG FR Phase Adjust */
547 {0x0, 0x0001, 0x0007}, /* TG FCDS Phase Adjust */
548 {0x0, 0x0039, 0x0008}, /* TG FS Phase Adjust */
549 {0x0, 0x0088, 0x000a}, /* TG MH1 */
550 {0x0, 0x0003, 0x000f}, /* TG Pixel ID */
551
552 /* Like below, unexplained toglleing */
553 {0x0, 0x0080, 0x000c},
554 {0x0, 0x0000, 0x000d},
555 {0x0, 0x0080, 0x000c},
556 {0x0, 0x0004, 0x000d},
557 {0x0, 0x0000, 0x000c},
558 {0x0, 0x0000, 0x000d},
559 {0x0, 0x0040, 0x000c},
560 {0x0, 0x0017, 0x000d},
561 {0x0, 0x00c0, 0x000c},
562 {0x0, 0x0000, 0x000d},
563 {0x0, 0x0080, 0x000c},
564 {0x0, 0x0006, 0x000d},
565 {0x0, 0x0080, 0x000c},
566 {0x0, 0x0004, 0x000d},
567 {0x0, 0x0002, 0x0003},
568#endif
569
570#ifdef DSPWIN_SET
571 {0x1, 0x001c, 0x0017}, /* CCDSP W1 Start X */
572 {0x1, 0x00e2, 0x0019}, /* CCDSP W2 Start X */
573 {0x1, 0x001c, 0x001b}, /* CCDSP W3 Start X */
574 {0x1, 0x00e2, 0x001d}, /* CCDSP W4 Start X */
575 {0x1, 0x00aa, 0x001f}, /* CCDSP W5 Start X */
576 {0x1, 0x0070, 0x0020}, /* CCDSP W5 Start Y */
577#endif
578 {0x0, 0x0001, 0x0010}, /* TG Start Clock */
579
580/* {0x2, 0x006a, 0x0001}, * C/S Enable ISOSYNCH Packet Engine */
581 {0x2, 0x0068, 0x0001}, /* C/S Diable ISOSYNCH Packet Engine */
582 {0x2, 0x0000, 0x0005},
583 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
584 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
585 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
586 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
587
588 {0x2, 0x006a, 0x0001}, /* C/S Enable ISOSYNCH Packet Engine */
589 {}
590};
591
592/*
593 * Data used to initialize a SPCA501C with HV7131B sensor.
594 * From a capture file taken with USBSnoop v 1.5
595 * I have a "SPCA501C pc camera chipset" manual by sunplus, but some
596 * of the value meanings are obscure or simply "reserved".
597 * to do list:
598 * 1) Understand what every value means
599 * 2) Understand why some values seem to appear more than once
600 * 3) Write a small comment for each line of the following arrays.
601 */
602static const __u16 spca501c_arowana_open_data[][3] = {
603 /* bmRequest,value,index */
604 {0x02, 0x0007, 0x0005},
605 {0x02, 0xa048, 0x0000},
606 {0x05, 0x0022, 0x0004},
607 {0x01, 0x0006, 0x0011},
608 {0x01, 0x00ff, 0x0012},
609 {0x01, 0x0014, 0x0013},
610 {0x01, 0x0000, 0x0014},
611 {0x01, 0x0042, 0x0051},
612 {0x01, 0x0040, 0x0052},
613 {0x01, 0x0051, 0x0053},
614 {0x01, 0x0040, 0x0054},
615 {0x01, 0x0000, 0x0055},
616 {0x00, 0x0025, 0x0000},
617 {0x00, 0x0026, 0x0000},
618 {0x00, 0x0001, 0x0000},
619 {0x00, 0x0027, 0x0000},
620 {0x00, 0x008a, 0x0000},
621 {}
622};
623
624static const __u16 spca501c_arowana_init_data[][3] = {
625 /* bmRequest,value,index */
626 {0x02, 0x0007, 0x0005},
627 {0x02, 0xa048, 0x0000},
628 {0x05, 0x0022, 0x0004},
629 {0x01, 0x0006, 0x0011},
630 {0x01, 0x00ff, 0x0012},
631 {0x01, 0x0014, 0x0013},
632 {0x01, 0x0000, 0x0014},
633 {0x01, 0x0042, 0x0051},
634 {0x01, 0x0040, 0x0052},
635 {0x01, 0x0051, 0x0053},
636 {0x01, 0x0040, 0x0054},
637 {0x01, 0x0000, 0x0055},
638 {0x00, 0x0025, 0x0000},
639 {0x00, 0x0026, 0x0000},
640 {0x00, 0x0001, 0x0000},
641 {0x00, 0x0027, 0x0000},
642 {0x00, 0x008a, 0x0000},
643 {0x02, 0x0000, 0x0005},
644 {0x02, 0x0007, 0x0005},
645 {0x02, 0x2000, 0x0000},
646 {0x05, 0x0022, 0x0004},
647 {0x05, 0x0015, 0x0001},
648 {0x05, 0x00ea, 0x0000},
649 {0x05, 0x0021, 0x0001},
650 {0x05, 0x00d2, 0x0000},
651 {0x05, 0x0023, 0x0001},
652 {0x05, 0x0003, 0x0000},
653 {0x05, 0x0030, 0x0001},
654 {0x05, 0x002b, 0x0000},
655 {0x05, 0x0031, 0x0001},
656 {0x05, 0x0023, 0x0000},
657 {0x05, 0x0032, 0x0001},
658 {0x05, 0x0023, 0x0000},
659 {0x05, 0x0033, 0x0001},
660 {0x05, 0x0023, 0x0000},
661 {0x05, 0x0034, 0x0001},
662 {0x05, 0x0002, 0x0000},
663 {0x05, 0x0050, 0x0001},
664 {0x05, 0x0000, 0x0000},
665 {0x05, 0x0051, 0x0001},
666 {0x05, 0x0000, 0x0000},
667 {0x05, 0x0052, 0x0001},
668 {0x05, 0x0000, 0x0000},
669 {0x05, 0x0054, 0x0001},
670 {0x05, 0x0001, 0x0000},
671 {0x00, 0x0000, 0x0001},
672 {0x00, 0x0000, 0x0002},
673 {0x00, 0x000c, 0x0003},
674 {0x00, 0x0000, 0x0004},
675 {0x00, 0x0090, 0x0005},
676 {0x00, 0x0000, 0x0006},
677 {0x00, 0x0040, 0x0007},
678 {0x00, 0x00c0, 0x0008},
679 {0x00, 0x004a, 0x0009},
680 {0x00, 0x0000, 0x000a},
681 {0x00, 0x0000, 0x000b},
682 {0x00, 0x0001, 0x000c},
683 {0x00, 0x0001, 0x000d},
684 {0x00, 0x0000, 0x000e},
685 {0x00, 0x0002, 0x000f},
686 {0x00, 0x0001, 0x0010},
687 {0x00, 0x0000, 0x0011},
688 {0x00, 0x0000, 0x0012},
689 {0x00, 0x0002, 0x0020},
690 {0x00, 0x0080, 0x0021},
691 {0x00, 0x0001, 0x0022},
692 {0x00, 0x00e0, 0x0023},
693 {0x00, 0x0000, 0x0024},
694 {0x00, 0x00d5, 0x0025},
695 {0x00, 0x0000, 0x0026},
696 {0x00, 0x000b, 0x0027},
697 {0x00, 0x0000, 0x0046},
698 {0x00, 0x0000, 0x0047},
699 {0x00, 0x0000, 0x0048},
700 {0x00, 0x0000, 0x0049},
701 {0x00, 0x0008, 0x004a},
702 {0xff, 0x0000, 0x00d0},
703 {0xff, 0x00d8, 0x00d1},
704 {0xff, 0x0000, 0x00d4},
705 {0xff, 0x0000, 0x00d5},
706 {0x01, 0x00a6, 0x0000},
707 {0x01, 0x0028, 0x0001},
708 {0x01, 0x0000, 0x0002},
709 {0x01, 0x000a, 0x0003},
710 {0x01, 0x0040, 0x0004},
711 {0x01, 0x0066, 0x0007},
712 {0x01, 0x0011, 0x0008},
713 {0x01, 0x0032, 0x0009},
714 {0x01, 0x00fd, 0x000a},
715 {0x01, 0x0038, 0x000b},
716 {0x01, 0x00d1, 0x000c},
717 {0x01, 0x00f7, 0x000d},
718 {0x01, 0x00ed, 0x000e},
719 {0x01, 0x00d8, 0x000f},
720 {0x01, 0x0038, 0x0010},
721 {0x01, 0x00ff, 0x0015},
722 {0x01, 0x0001, 0x0016},
723 {0x01, 0x0032, 0x0017},
724 {0x01, 0x0023, 0x0018},
725 {0x01, 0x00ce, 0x0019},
726 {0x01, 0x0023, 0x001a},
727 {0x01, 0x0032, 0x001b},
728 {0x01, 0x008d, 0x001c},
729 {0x01, 0x00ce, 0x001d},
730 {0x01, 0x008d, 0x001e},
731 {0x01, 0x0000, 0x001f},
732 {0x01, 0x0000, 0x0020},
733 {0x01, 0x00ff, 0x003e},
734 {0x01, 0x0003, 0x003f},
735 {0x01, 0x0000, 0x0040},
736 {0x01, 0x0035, 0x0041},
737 {0x01, 0x0053, 0x0042},
738 {0x01, 0x0069, 0x0043},
739 {0x01, 0x007c, 0x0044},
740 {0x01, 0x008c, 0x0045},
741 {0x01, 0x009a, 0x0046},
742 {0x01, 0x00a8, 0x0047},
743 {0x01, 0x00b4, 0x0048},
744 {0x01, 0x00bf, 0x0049},
745 {0x01, 0x00ca, 0x004a},
746 {0x01, 0x00d4, 0x004b},
747 {0x01, 0x00dd, 0x004c},
748 {0x01, 0x00e7, 0x004d},
749 {0x01, 0x00ef, 0x004e},
750 {0x01, 0x00f8, 0x004f},
751 {0x01, 0x00ff, 0x0050},
752 {0x01, 0x0001, 0x0056},
753 {0x01, 0x0060, 0x0057},
754 {0x01, 0x0040, 0x0058},
755 {0x01, 0x0011, 0x0059},
756 {0x01, 0x0001, 0x005a},
757 {0x02, 0x0007, 0x0005},
758 {0x02, 0xa048, 0x0000},
759 {0x02, 0x0007, 0x0005},
760 {0x02, 0x0015, 0x0006},
761 {0x02, 0x100a, 0x0007},
762 {0x02, 0xa048, 0x0000},
763 {0x02, 0xc002, 0x0001},
764 {0x02, 0x000f, 0x0005},
765 {0x02, 0xa048, 0x0000},
766 {0x05, 0x0022, 0x0004},
767 {0x05, 0x0025, 0x0001},
768 {0x05, 0x0000, 0x0000},
769 {0x05, 0x0026, 0x0001},
770 {0x05, 0x0001, 0x0000},
771 {0x05, 0x0027, 0x0001},
772 {0x05, 0x0000, 0x0000},
773 {0x05, 0x0001, 0x0001},
774 {0x05, 0x0000, 0x0000},
775 {0x05, 0x0021, 0x0001},
776 {0x05, 0x00d2, 0x0000},
777 {0x05, 0x0020, 0x0001},
778 {0x05, 0x0000, 0x0000},
779 {0x00, 0x0090, 0x0005},
780 {0x01, 0x00a6, 0x0000},
781 {0x02, 0x0007, 0x0005},
782 {0x02, 0x2000, 0x0000},
783 {0x05, 0x0022, 0x0004},
784 {0x05, 0x0015, 0x0001},
785 {0x05, 0x00ea, 0x0000},
786 {0x05, 0x0021, 0x0001},
787 {0x05, 0x00d2, 0x0000},
788 {0x05, 0x0023, 0x0001},
789 {0x05, 0x0003, 0x0000},
790 {0x05, 0x0030, 0x0001},
791 {0x05, 0x002b, 0x0000},
792 {0x05, 0x0031, 0x0001},
793 {0x05, 0x0023, 0x0000},
794 {0x05, 0x0032, 0x0001},
795 {0x05, 0x0023, 0x0000},
796 {0x05, 0x0033, 0x0001},
797 {0x05, 0x0023, 0x0000},
798 {0x05, 0x0034, 0x0001},
799 {0x05, 0x0002, 0x0000},
800 {0x05, 0x0050, 0x0001},
801 {0x05, 0x0000, 0x0000},
802 {0x05, 0x0051, 0x0001},
803 {0x05, 0x0000, 0x0000},
804 {0x05, 0x0052, 0x0001},
805 {0x05, 0x0000, 0x0000},
806 {0x05, 0x0054, 0x0001},
807 {0x05, 0x0001, 0x0000},
808 {0x00, 0x0000, 0x0001},
809 {0x00, 0x0000, 0x0002},
810 {0x00, 0x000c, 0x0003},
811 {0x00, 0x0000, 0x0004},
812 {0x00, 0x0090, 0x0005},
813 {0x00, 0x0000, 0x0006},
814 {0x00, 0x0040, 0x0007},
815 {0x00, 0x00c0, 0x0008},
816 {0x00, 0x004a, 0x0009},
817 {0x00, 0x0000, 0x000a},
818 {0x00, 0x0000, 0x000b},
819 {0x00, 0x0001, 0x000c},
820 {0x00, 0x0001, 0x000d},
821 {0x00, 0x0000, 0x000e},
822 {0x00, 0x0002, 0x000f},
823 {0x00, 0x0001, 0x0010},
824 {0x00, 0x0000, 0x0011},
825 {0x00, 0x0000, 0x0012},
826 {0x00, 0x0002, 0x0020},
827 {0x00, 0x0080, 0x0021},
828 {0x00, 0x0001, 0x0022},
829 {0x00, 0x00e0, 0x0023},
830 {0x00, 0x0000, 0x0024},
831 {0x00, 0x00d5, 0x0025},
832 {0x00, 0x0000, 0x0026},
833 {0x00, 0x000b, 0x0027},
834 {0x00, 0x0000, 0x0046},
835 {0x00, 0x0000, 0x0047},
836 {0x00, 0x0000, 0x0048},
837 {0x00, 0x0000, 0x0049},
838 {0x00, 0x0008, 0x004a},
839 {0xff, 0x0000, 0x00d0},
840 {0xff, 0x00d8, 0x00d1},
841 {0xff, 0x0000, 0x00d4},
842 {0xff, 0x0000, 0x00d5},
843 {0x01, 0x00a6, 0x0000},
844 {0x01, 0x0028, 0x0001},
845 {0x01, 0x0000, 0x0002},
846 {0x01, 0x000a, 0x0003},
847 {0x01, 0x0040, 0x0004},
848 {0x01, 0x0066, 0x0007},
849 {0x01, 0x0011, 0x0008},
850 {0x01, 0x0032, 0x0009},
851 {0x01, 0x00fd, 0x000a},
852 {0x01, 0x0038, 0x000b},
853 {0x01, 0x00d1, 0x000c},
854 {0x01, 0x00f7, 0x000d},
855 {0x01, 0x00ed, 0x000e},
856 {0x01, 0x00d8, 0x000f},
857 {0x01, 0x0038, 0x0010},
858 {0x01, 0x00ff, 0x0015},
859 {0x01, 0x0001, 0x0016},
860 {0x01, 0x0032, 0x0017},
861 {0x01, 0x0023, 0x0018},
862 {0x01, 0x00ce, 0x0019},
863 {0x01, 0x0023, 0x001a},
864 {0x01, 0x0032, 0x001b},
865 {0x01, 0x008d, 0x001c},
866 {0x01, 0x00ce, 0x001d},
867 {0x01, 0x008d, 0x001e},
868 {0x01, 0x0000, 0x001f},
869 {0x01, 0x0000, 0x0020},
870 {0x01, 0x00ff, 0x003e},
871 {0x01, 0x0003, 0x003f},
872 {0x01, 0x0000, 0x0040},
873 {0x01, 0x0035, 0x0041},
874 {0x01, 0x0053, 0x0042},
875 {0x01, 0x0069, 0x0043},
876 {0x01, 0x007c, 0x0044},
877 {0x01, 0x008c, 0x0045},
878 {0x01, 0x009a, 0x0046},
879 {0x01, 0x00a8, 0x0047},
880 {0x01, 0x00b4, 0x0048},
881 {0x01, 0x00bf, 0x0049},
882 {0x01, 0x00ca, 0x004a},
883 {0x01, 0x00d4, 0x004b},
884 {0x01, 0x00dd, 0x004c},
885 {0x01, 0x00e7, 0x004d},
886 {0x01, 0x00ef, 0x004e},
887 {0x01, 0x00f8, 0x004f},
888 {0x01, 0x00ff, 0x0050},
889 {0x01, 0x0001, 0x0056},
890 {0x01, 0x0060, 0x0057},
891 {0x01, 0x0040, 0x0058},
892 {0x01, 0x0011, 0x0059},
893 {0x01, 0x0001, 0x005a},
894 {0x02, 0x0007, 0x0005},
895 {0x02, 0xa048, 0x0000},
896 {0x02, 0x0007, 0x0005},
897 {0x02, 0x0015, 0x0006},
898 {0x02, 0x100a, 0x0007},
899 {0x02, 0xa048, 0x0000},
900 {0x02, 0xc002, 0x0001},
901 {0x02, 0x000f, 0x0005},
902 {0x02, 0xa048, 0x0000},
903 {0x05, 0x0022, 0x0004},
904 {0x05, 0x0025, 0x0001},
905 {0x05, 0x0000, 0x0000},
906 {0x05, 0x0026, 0x0001},
907 {0x05, 0x0001, 0x0000},
908 {0x05, 0x0027, 0x0001},
909 {0x05, 0x0000, 0x0000},
910 {0x05, 0x0001, 0x0001},
911 {0x05, 0x0000, 0x0000},
912 {0x05, 0x0021, 0x0001},
913 {0x05, 0x00d2, 0x0000},
914 {0x05, 0x0020, 0x0001},
915 {0x05, 0x0000, 0x0000},
916 {0x00, 0x0090, 0x0005},
917 {0x01, 0x00a6, 0x0000},
918 {0x01, 0x0003, 0x003f},
919 {0x01, 0x0001, 0x0056},
920 {0x01, 0x0011, 0x0008},
921 {0x01, 0x0032, 0x0009},
922 {0x01, 0xfffd, 0x000a},
923 {0x01, 0x0023, 0x000b},
924 {0x01, 0xffea, 0x000c},
925 {0x01, 0xfff4, 0x000d},
926 {0x01, 0xfffc, 0x000e},
927 {0x01, 0xffe3, 0x000f},
928 {0x01, 0x001f, 0x0010},
929 {0x01, 0x00a8, 0x0001},
930 {0x01, 0x0067, 0x0007},
931 {0x01, 0x0032, 0x0017},
932 {0x01, 0x0023, 0x0018},
933 {0x01, 0x00ce, 0x0019},
934 {0x01, 0x0023, 0x001a},
935 {0x01, 0x0032, 0x001b},
936 {0x01, 0x008d, 0x001c},
937 {0x01, 0x00ce, 0x001d},
938 {0x01, 0x008d, 0x001e},
939 {0x01, 0x00c8, 0x0015},
940 {0x01, 0x0032, 0x0016},
941 {0x01, 0x0000, 0x0011},
942 {0x01, 0x0000, 0x0012},
943 {0x01, 0x0000, 0x0013},
944 {0x01, 0x000a, 0x0003},
945 {0x02, 0xc002, 0x0001},
946 {0x02, 0x0007, 0x0005},
947 {0x02, 0xc000, 0x0001},
948 {0x02, 0x0000, 0x0005},
949 {0x02, 0x0007, 0x0005},
950 {0x02, 0x2000, 0x0000},
951 {0x05, 0x0022, 0x0004},
952 {0x05, 0x0015, 0x0001},
953 {0x05, 0x00ea, 0x0000},
954 {0x05, 0x0021, 0x0001},
955 {0x05, 0x00d2, 0x0000},
956 {0x05, 0x0023, 0x0001},
957 {0x05, 0x0003, 0x0000},
958 {0x05, 0x0030, 0x0001},
959 {0x05, 0x002b, 0x0000},
960 {0x05, 0x0031, 0x0001},
961 {0x05, 0x0023, 0x0000},
962 {0x05, 0x0032, 0x0001},
963 {0x05, 0x0023, 0x0000},
964 {0x05, 0x0033, 0x0001},
965 {0x05, 0x0023, 0x0000},
966 {0x05, 0x0034, 0x0001},
967 {0x05, 0x0002, 0x0000},
968 {0x05, 0x0050, 0x0001},
969 {0x05, 0x0000, 0x0000},
970 {0x05, 0x0051, 0x0001},
971 {0x05, 0x0000, 0x0000},
972 {0x05, 0x0052, 0x0001},
973 {0x05, 0x0000, 0x0000},
974 {0x05, 0x0054, 0x0001},
975 {0x05, 0x0001, 0x0000},
976 {0x00, 0x0000, 0x0001},
977 {0x00, 0x0000, 0x0002},
978 {0x00, 0x000c, 0x0003},
979 {0x00, 0x0000, 0x0004},
980 {0x00, 0x0090, 0x0005},
981 {0x00, 0x0000, 0x0006},
982 {0x00, 0x0040, 0x0007},
983 {0x00, 0x00c0, 0x0008},
984 {0x00, 0x004a, 0x0009},
985 {0x00, 0x0000, 0x000a},
986 {0x00, 0x0000, 0x000b},
987 {0x00, 0x0001, 0x000c},
988 {0x00, 0x0001, 0x000d},
989 {0x00, 0x0000, 0x000e},
990 {0x00, 0x0002, 0x000f},
991 {0x00, 0x0001, 0x0010},
992 {0x00, 0x0000, 0x0011},
993 {0x00, 0x0000, 0x0012},
994 {0x00, 0x0002, 0x0020},
995 {0x00, 0x0080, 0x0021},
996 {0x00, 0x0001, 0x0022},
997 {0x00, 0x00e0, 0x0023},
998 {0x00, 0x0000, 0x0024},
999 {0x00, 0x00d5, 0x0025},
1000 {0x00, 0x0000, 0x0026},
1001 {0x00, 0x000b, 0x0027},
1002 {0x00, 0x0000, 0x0046},
1003 {0x00, 0x0000, 0x0047},
1004 {0x00, 0x0000, 0x0048},
1005 {0x00, 0x0000, 0x0049},
1006 {0x00, 0x0008, 0x004a},
1007 {0xff, 0x0000, 0x00d0},
1008 {0xff, 0x00d8, 0x00d1},
1009 {0xff, 0x0000, 0x00d4},
1010 {0xff, 0x0000, 0x00d5},
1011 {0x01, 0x00a6, 0x0000},
1012 {0x01, 0x0028, 0x0001},
1013 {0x01, 0x0000, 0x0002},
1014 {0x01, 0x000a, 0x0003},
1015 {0x01, 0x0040, 0x0004},
1016 {0x01, 0x0066, 0x0007},
1017 {0x01, 0x0011, 0x0008},
1018 {0x01, 0x0032, 0x0009},
1019 {0x01, 0x00fd, 0x000a},
1020 {0x01, 0x0038, 0x000b},
1021 {0x01, 0x00d1, 0x000c},
1022 {0x01, 0x00f7, 0x000d},
1023 {0x01, 0x00ed, 0x000e},
1024 {0x01, 0x00d8, 0x000f},
1025 {0x01, 0x0038, 0x0010},
1026 {0x01, 0x00ff, 0x0015},
1027 {0x01, 0x0001, 0x0016},
1028 {0x01, 0x0032, 0x0017},
1029 {0x01, 0x0023, 0x0018},
1030 {0x01, 0x00ce, 0x0019},
1031 {0x01, 0x0023, 0x001a},
1032 {0x01, 0x0032, 0x001b},
1033 {0x01, 0x008d, 0x001c},
1034 {0x01, 0x00ce, 0x001d},
1035 {0x01, 0x008d, 0x001e},
1036 {0x01, 0x0000, 0x001f},
1037 {0x01, 0x0000, 0x0020},
1038 {0x01, 0x00ff, 0x003e},
1039 {0x01, 0x0003, 0x003f},
1040 {0x01, 0x0000, 0x0040},
1041 {0x01, 0x0035, 0x0041},
1042 {0x01, 0x0053, 0x0042},
1043 {0x01, 0x0069, 0x0043},
1044 {0x01, 0x007c, 0x0044},
1045 {0x01, 0x008c, 0x0045},
1046 {0x01, 0x009a, 0x0046},
1047 {0x01, 0x00a8, 0x0047},
1048 {0x01, 0x00b4, 0x0048},
1049 {0x01, 0x00bf, 0x0049},
1050 {0x01, 0x00ca, 0x004a},
1051 {0x01, 0x00d4, 0x004b},
1052 {0x01, 0x00dd, 0x004c},
1053 {0x01, 0x00e7, 0x004d},
1054 {0x01, 0x00ef, 0x004e},
1055 {0x01, 0x00f8, 0x004f},
1056 {0x01, 0x00ff, 0x0050},
1057 {0x01, 0x0001, 0x0056},
1058 {0x01, 0x0060, 0x0057},
1059 {0x01, 0x0040, 0x0058},
1060 {0x01, 0x0011, 0x0059},
1061 {0x01, 0x0001, 0x005a},
1062 {0x02, 0x0007, 0x0005},
1063 {0x02, 0xa048, 0x0000},
1064 {0x02, 0x0007, 0x0005},
1065 {0x02, 0x0015, 0x0006},
1066 {0x02, 0x100a, 0x0007},
1067 {0x02, 0xa048, 0x0000},
1068 {0x02, 0xc002, 0x0001},
1069 {0x02, 0x000f, 0x0005},
1070 {0x02, 0xa048, 0x0000},
1071 {0x05, 0x0022, 0x0004},
1072 {0x05, 0x0025, 0x0001},
1073 {0x05, 0x0000, 0x0000},
1074 {0x05, 0x0026, 0x0001},
1075 {0x05, 0x0001, 0x0000},
1076 {0x05, 0x0027, 0x0001},
1077 {0x05, 0x0000, 0x0000},
1078 {0x05, 0x0001, 0x0001},
1079 {0x05, 0x0000, 0x0000},
1080 {0x05, 0x0021, 0x0001},
1081 {0x05, 0x00d2, 0x0000},
1082 {0x05, 0x0020, 0x0001},
1083 {0x05, 0x0000, 0x0000},
1084 {0x00, 0x0090, 0x0005},
1085 {0x01, 0x00a6, 0x0000},
1086 {0x02, 0x0007, 0x0005},
1087 {0x02, 0x2000, 0x0000},
1088 {0x05, 0x0022, 0x0004},
1089 {0x05, 0x0015, 0x0001},
1090 {0x05, 0x00ea, 0x0000},
1091 {0x05, 0x0021, 0x0001},
1092 {0x05, 0x00d2, 0x0000},
1093 {0x05, 0x0023, 0x0001},
1094 {0x05, 0x0003, 0x0000},
1095 {0x05, 0x0030, 0x0001},
1096 {0x05, 0x002b, 0x0000},
1097 {0x05, 0x0031, 0x0001},
1098 {0x05, 0x0023, 0x0000},
1099 {0x05, 0x0032, 0x0001},
1100 {0x05, 0x0023, 0x0000},
1101 {0x05, 0x0033, 0x0001},
1102 {0x05, 0x0023, 0x0000},
1103 {0x05, 0x0034, 0x0001},
1104 {0x05, 0x0002, 0x0000},
1105 {0x05, 0x0050, 0x0001},
1106 {0x05, 0x0000, 0x0000},
1107 {0x05, 0x0051, 0x0001},
1108 {0x05, 0x0000, 0x0000},
1109 {0x05, 0x0052, 0x0001},
1110 {0x05, 0x0000, 0x0000},
1111 {0x05, 0x0054, 0x0001},
1112 {0x05, 0x0001, 0x0000},
1113 {0x00, 0x0000, 0x0001},
1114 {0x00, 0x0000, 0x0002},
1115 {0x00, 0x000c, 0x0003},
1116 {0x00, 0x0000, 0x0004},
1117 {0x00, 0x0090, 0x0005},
1118 {0x00, 0x0000, 0x0006},
1119 {0x00, 0x0040, 0x0007},
1120 {0x00, 0x00c0, 0x0008},
1121 {0x00, 0x004a, 0x0009},
1122 {0x00, 0x0000, 0x000a},
1123 {0x00, 0x0000, 0x000b},
1124 {0x00, 0x0001, 0x000c},
1125 {0x00, 0x0001, 0x000d},
1126 {0x00, 0x0000, 0x000e},
1127 {0x00, 0x0002, 0x000f},
1128 {0x00, 0x0001, 0x0010},
1129 {0x00, 0x0000, 0x0011},
1130 {0x00, 0x0000, 0x0012},
1131 {0x00, 0x0002, 0x0020},
1132 {0x00, 0x0080, 0x0021},
1133 {0x00, 0x0001, 0x0022},
1134 {0x00, 0x00e0, 0x0023},
1135 {0x00, 0x0000, 0x0024},
1136 {0x00, 0x00d5, 0x0025},
1137 {0x00, 0x0000, 0x0026},
1138 {0x00, 0x000b, 0x0027},
1139 {0x00, 0x0000, 0x0046},
1140 {0x00, 0x0000, 0x0047},
1141 {0x00, 0x0000, 0x0048},
1142 {0x00, 0x0000, 0x0049},
1143 {0x00, 0x0008, 0x004a},
1144 {0xff, 0x0000, 0x00d0},
1145 {0xff, 0x00d8, 0x00d1},
1146 {0xff, 0x0000, 0x00d4},
1147 {0xff, 0x0000, 0x00d5},
1148 {0x01, 0x00a6, 0x0000},
1149 {0x01, 0x0028, 0x0001},
1150 {0x01, 0x0000, 0x0002},
1151 {0x01, 0x000a, 0x0003},
1152 {0x01, 0x0040, 0x0004},
1153 {0x01, 0x0066, 0x0007},
1154 {0x01, 0x0011, 0x0008},
1155 {0x01, 0x0032, 0x0009},
1156 {0x01, 0x00fd, 0x000a},
1157 {0x01, 0x0038, 0x000b},
1158 {0x01, 0x00d1, 0x000c},
1159 {0x01, 0x00f7, 0x000d},
1160 {0x01, 0x00ed, 0x000e},
1161 {0x01, 0x00d8, 0x000f},
1162 {0x01, 0x0038, 0x0010},
1163 {0x01, 0x00ff, 0x0015},
1164 {0x01, 0x0001, 0x0016},
1165 {0x01, 0x0032, 0x0017},
1166 {0x01, 0x0023, 0x0018},
1167 {0x01, 0x00ce, 0x0019},
1168 {0x01, 0x0023, 0x001a},
1169 {0x01, 0x0032, 0x001b},
1170 {0x01, 0x008d, 0x001c},
1171 {0x01, 0x00ce, 0x001d},
1172 {0x01, 0x008d, 0x001e},
1173 {0x01, 0x0000, 0x001f},
1174 {0x01, 0x0000, 0x0020},
1175 {0x01, 0x00ff, 0x003e},
1176 {0x01, 0x0003, 0x003f},
1177 {0x01, 0x0000, 0x0040},
1178 {0x01, 0x0035, 0x0041},
1179 {0x01, 0x0053, 0x0042},
1180 {0x01, 0x0069, 0x0043},
1181 {0x01, 0x007c, 0x0044},
1182 {0x01, 0x008c, 0x0045},
1183 {0x01, 0x009a, 0x0046},
1184 {0x01, 0x00a8, 0x0047},
1185 {0x01, 0x00b4, 0x0048},
1186 {0x01, 0x00bf, 0x0049},
1187 {0x01, 0x00ca, 0x004a},
1188 {0x01, 0x00d4, 0x004b},
1189 {0x01, 0x00dd, 0x004c},
1190 {0x01, 0x00e7, 0x004d},
1191 {0x01, 0x00ef, 0x004e},
1192 {0x01, 0x00f8, 0x004f},
1193 {0x01, 0x00ff, 0x0050},
1194 {0x01, 0x0001, 0x0056},
1195 {0x01, 0x0060, 0x0057},
1196 {0x01, 0x0040, 0x0058},
1197 {0x01, 0x0011, 0x0059},
1198 {0x01, 0x0001, 0x005a},
1199 {0x02, 0x0007, 0x0005},
1200 {0x02, 0xa048, 0x0000},
1201 {0x02, 0x0007, 0x0005},
1202 {0x02, 0x0015, 0x0006},
1203 {0x02, 0x100a, 0x0007},
1204 {0x02, 0xa048, 0x0000},
1205 {0x02, 0xc002, 0x0001},
1206 {0x02, 0x000f, 0x0005},
1207 {0x02, 0xa048, 0x0000},
1208 {0x05, 0x0022, 0x0004},
1209 {0x05, 0x0025, 0x0001},
1210 {0x05, 0x0000, 0x0000},
1211 {0x05, 0x0026, 0x0001},
1212 {0x05, 0x0001, 0x0000},
1213 {0x05, 0x0027, 0x0001},
1214 {0x05, 0x0000, 0x0000},
1215 {0x05, 0x0001, 0x0001},
1216 {0x05, 0x0000, 0x0000},
1217 {0x05, 0x0021, 0x0001},
1218 {0x05, 0x00d2, 0x0000},
1219 {0x05, 0x0020, 0x0001},
1220 {0x05, 0x0000, 0x0000},
1221 {0x00, 0x0090, 0x0005},
1222 {0x01, 0x00a6, 0x0000},
1223 {0x05, 0x0026, 0x0001},
1224 {0x05, 0x0001, 0x0000},
1225 {0x05, 0x0027, 0x0001},
1226 {0x05, 0x000f, 0x0000},
1227 {0x01, 0x0003, 0x003f},
1228 {0x01, 0x0001, 0x0056},
1229 {0x01, 0x0011, 0x0008},
1230 {0x01, 0x0032, 0x0009},
1231 {0x01, 0xfffd, 0x000a},
1232 {0x01, 0x0023, 0x000b},
1233 {0x01, 0xffea, 0x000c},
1234 {0x01, 0xfff4, 0x000d},
1235 {0x01, 0xfffc, 0x000e},
1236 {0x01, 0xffe3, 0x000f},
1237 {0x01, 0x001f, 0x0010},
1238 {0x01, 0x00a8, 0x0001},
1239 {0x01, 0x0067, 0x0007},
1240 {0x01, 0x0042, 0x0051},
1241 {0x01, 0x0051, 0x0053},
1242 {0x01, 0x000a, 0x0003},
1243 {0x02, 0xc002, 0x0001},
1244 {0x02, 0x0007, 0x0005},
1245 {0x02, 0xc000, 0x0001},
1246 {0x02, 0x0000, 0x0005},
1247 {0x02, 0x0007, 0x0005},
1248 {0x02, 0x2000, 0x0000},
1249 {0x05, 0x0022, 0x0004},
1250 {0x05, 0x0015, 0x0001},
1251 {0x05, 0x00ea, 0x0000},
1252 {0x05, 0x0021, 0x0001},
1253 {0x05, 0x00d2, 0x0000},
1254 {0x05, 0x0023, 0x0001},
1255 {0x05, 0x0003, 0x0000},
1256 {0x05, 0x0030, 0x0001},
1257 {0x05, 0x002b, 0x0000},
1258 {0x05, 0x0031, 0x0001},
1259 {0x05, 0x0023, 0x0000},
1260 {0x05, 0x0032, 0x0001},
1261 {0x05, 0x0023, 0x0000},
1262 {0x05, 0x0033, 0x0001},
1263 {0x05, 0x0023, 0x0000},
1264 {0x05, 0x0034, 0x0001},
1265 {0x05, 0x0002, 0x0000},
1266 {0x05, 0x0050, 0x0001},
1267 {0x05, 0x0000, 0x0000},
1268 {0x05, 0x0051, 0x0001},
1269 {0x05, 0x0000, 0x0000},
1270 {0x05, 0x0052, 0x0001},
1271 {0x05, 0x0000, 0x0000},
1272 {0x05, 0x0054, 0x0001},
1273 {0x05, 0x0001, 0x0000},
1274 {0x00, 0x0000, 0x0001},
1275 {0x00, 0x0000, 0x0002},
1276 {0x00, 0x000c, 0x0003},
1277 {0x00, 0x0000, 0x0004},
1278 {0x00, 0x0090, 0x0005},
1279 {0x00, 0x0000, 0x0006},
1280 {0x00, 0x0040, 0x0007},
1281 {0x00, 0x00c0, 0x0008},
1282 {0x00, 0x004a, 0x0009},
1283 {0x00, 0x0000, 0x000a},
1284 {0x00, 0x0000, 0x000b},
1285 {0x00, 0x0001, 0x000c},
1286 {0x00, 0x0001, 0x000d},
1287 {0x00, 0x0000, 0x000e},
1288 {0x00, 0x0002, 0x000f},
1289 {0x00, 0x0001, 0x0010},
1290 {0x00, 0x0000, 0x0011},
1291 {0x00, 0x0000, 0x0012},
1292 {0x00, 0x0002, 0x0020},
1293 {0x00, 0x0080, 0x0021},
1294 {0x00, 0x0001, 0x0022},
1295 {0x00, 0x00e0, 0x0023},
1296 {0x00, 0x0000, 0x0024},
1297 {0x00, 0x00d5, 0x0025},
1298 {0x00, 0x0000, 0x0026},
1299 {0x00, 0x000b, 0x0027},
1300 {0x00, 0x0000, 0x0046},
1301 {0x00, 0x0000, 0x0047},
1302 {0x00, 0x0000, 0x0048},
1303 {0x00, 0x0000, 0x0049},
1304 {0x00, 0x0008, 0x004a},
1305 {0xff, 0x0000, 0x00d0},
1306 {0xff, 0x00d8, 0x00d1},
1307 {0xff, 0x0000, 0x00d4},
1308 {0xff, 0x0000, 0x00d5},
1309 {0x01, 0x00a6, 0x0000},
1310 {0x01, 0x0028, 0x0001},
1311 {0x01, 0x0000, 0x0002},
1312 {0x01, 0x000a, 0x0003},
1313 {0x01, 0x0040, 0x0004},
1314 {0x01, 0x0066, 0x0007},
1315 {0x01, 0x0011, 0x0008},
1316 {0x01, 0x0032, 0x0009},
1317 {0x01, 0x00fd, 0x000a},
1318 {0x01, 0x0038, 0x000b},
1319 {0x01, 0x00d1, 0x000c},
1320 {0x01, 0x00f7, 0x000d},
1321 {0x01, 0x00ed, 0x000e},
1322 {0x01, 0x00d8, 0x000f},
1323 {0x01, 0x0038, 0x0010},
1324 {0x01, 0x00ff, 0x0015},
1325 {0x01, 0x0001, 0x0016},
1326 {0x01, 0x0032, 0x0017},
1327 {0x01, 0x0023, 0x0018},
1328 {0x01, 0x00ce, 0x0019},
1329 {0x01, 0x0023, 0x001a},
1330 {0x01, 0x0032, 0x001b},
1331 {0x01, 0x008d, 0x001c},
1332 {0x01, 0x00ce, 0x001d},
1333 {0x01, 0x008d, 0x001e},
1334 {0x01, 0x0000, 0x001f},
1335 {0x01, 0x0000, 0x0020},
1336 {0x01, 0x00ff, 0x003e},
1337 {0x01, 0x0003, 0x003f},
1338 {0x01, 0x0000, 0x0040},
1339 {0x01, 0x0035, 0x0041},
1340 {0x01, 0x0053, 0x0042},
1341 {0x01, 0x0069, 0x0043},
1342 {0x01, 0x007c, 0x0044},
1343 {0x01, 0x008c, 0x0045},
1344 {0x01, 0x009a, 0x0046},
1345 {0x01, 0x00a8, 0x0047},
1346 {0x01, 0x00b4, 0x0048},
1347 {0x01, 0x00bf, 0x0049},
1348 {0x01, 0x00ca, 0x004a},
1349 {0x01, 0x00d4, 0x004b},
1350 {0x01, 0x00dd, 0x004c},
1351 {0x01, 0x00e7, 0x004d},
1352 {0x01, 0x00ef, 0x004e},
1353 {0x01, 0x00f8, 0x004f},
1354 {0x01, 0x00ff, 0x0050},
1355 {0x01, 0x0001, 0x0056},
1356 {0x01, 0x0060, 0x0057},
1357 {0x01, 0x0040, 0x0058},
1358 {0x01, 0x0011, 0x0059},
1359 {0x01, 0x0001, 0x005a},
1360 {0x02, 0x0007, 0x0005},
1361 {0x02, 0xa048, 0x0000},
1362 {0x02, 0x0007, 0x0005},
1363 {0x02, 0x0015, 0x0006},
1364 {0x02, 0x100a, 0x0007},
1365 {0x02, 0xa048, 0x0000},
1366 {0x02, 0xc002, 0x0001},
1367 {0x02, 0x000f, 0x0005},
1368 {0x02, 0xa048, 0x0000},
1369 {0x05, 0x0022, 0x0004},
1370 {0x05, 0x0025, 0x0001},
1371 {0x05, 0x0000, 0x0000},
1372 {0x05, 0x0026, 0x0001},
1373 {0x05, 0x0001, 0x0000},
1374 {0x05, 0x0027, 0x0001},
1375 {0x05, 0x0000, 0x0000},
1376 {0x05, 0x0001, 0x0001},
1377 {0x05, 0x0000, 0x0000},
1378 {0x05, 0x0021, 0x0001},
1379 {0x05, 0x00d2, 0x0000},
1380 {0x05, 0x0020, 0x0001},
1381 {0x05, 0x0000, 0x0000},
1382 {0x00, 0x0090, 0x0005},
1383 {0x01, 0x00a6, 0x0000},
1384 {0x02, 0x0007, 0x0005},
1385 {0x02, 0x2000, 0x0000},
1386 {0x05, 0x0022, 0x0004},
1387 {0x05, 0x0015, 0x0001},
1388 {0x05, 0x00ea, 0x0000},
1389 {0x05, 0x0021, 0x0001},
1390 {0x05, 0x00d2, 0x0000},
1391 {0x05, 0x0023, 0x0001},
1392 {0x05, 0x0003, 0x0000},
1393 {0x05, 0x0030, 0x0001},
1394 {0x05, 0x002b, 0x0000},
1395 {0x05, 0x0031, 0x0001},
1396 {0x05, 0x0023, 0x0000},
1397 {0x05, 0x0032, 0x0001},
1398 {0x05, 0x0023, 0x0000},
1399 {0x05, 0x0033, 0x0001},
1400 {0x05, 0x0023, 0x0000},
1401 {0x05, 0x0034, 0x0001},
1402 {0x05, 0x0002, 0x0000},
1403 {0x05, 0x0050, 0x0001},
1404 {0x05, 0x0000, 0x0000},
1405 {0x05, 0x0051, 0x0001},
1406 {0x05, 0x0000, 0x0000},
1407 {0x05, 0x0052, 0x0001},
1408 {0x05, 0x0000, 0x0000},
1409 {0x05, 0x0054, 0x0001},
1410 {0x05, 0x0001, 0x0000},
1411 {0x00, 0x0000, 0x0001},
1412 {0x00, 0x0000, 0x0002},
1413 {0x00, 0x000c, 0x0003},
1414 {0x00, 0x0000, 0x0004},
1415 {0x00, 0x0090, 0x0005},
1416 {0x00, 0x0000, 0x0006},
1417 {0x00, 0x0040, 0x0007},
1418 {0x00, 0x00c0, 0x0008},
1419 {0x00, 0x004a, 0x0009},
1420 {0x00, 0x0000, 0x000a},
1421 {0x00, 0x0000, 0x000b},
1422 {0x00, 0x0001, 0x000c},
1423 {0x00, 0x0001, 0x000d},
1424 {0x00, 0x0000, 0x000e},
1425 {0x00, 0x0002, 0x000f},
1426 {0x00, 0x0001, 0x0010},
1427 {0x00, 0x0000, 0x0011},
1428 {0x00, 0x0000, 0x0012},
1429 {0x00, 0x0002, 0x0020},
1430 {0x00, 0x0080, 0x0021},
1431 {0x00, 0x0001, 0x0022},
1432 {0x00, 0x00e0, 0x0023},
1433 {0x00, 0x0000, 0x0024},
1434 {0x00, 0x00d5, 0x0025},
1435 {0x00, 0x0000, 0x0026},
1436 {0x00, 0x000b, 0x0027},
1437 {0x00, 0x0000, 0x0046},
1438 {0x00, 0x0000, 0x0047},
1439 {0x00, 0x0000, 0x0048},
1440 {0x00, 0x0000, 0x0049},
1441 {0x00, 0x0008, 0x004a},
1442 {0xff, 0x0000, 0x00d0},
1443 {0xff, 0x00d8, 0x00d1},
1444 {0xff, 0x0000, 0x00d4},
1445 {0xff, 0x0000, 0x00d5},
1446 {0x01, 0x00a6, 0x0000},
1447 {0x01, 0x0028, 0x0001},
1448 {0x01, 0x0000, 0x0002},
1449 {0x01, 0x000a, 0x0003},
1450 {0x01, 0x0040, 0x0004},
1451 {0x01, 0x0066, 0x0007},
1452 {0x01, 0x0011, 0x0008},
1453 {0x01, 0x0032, 0x0009},
1454 {0x01, 0x00fd, 0x000a},
1455 {0x01, 0x0038, 0x000b},
1456 {0x01, 0x00d1, 0x000c},
1457 {0x01, 0x00f7, 0x000d},
1458 {0x01, 0x00ed, 0x000e},
1459 {0x01, 0x00d8, 0x000f},
1460 {0x01, 0x0038, 0x0010},
1461 {0x01, 0x00ff, 0x0015},
1462 {0x01, 0x0001, 0x0016},
1463 {0x01, 0x0032, 0x0017},
1464 {0x01, 0x0023, 0x0018},
1465 {0x01, 0x00ce, 0x0019},
1466 {0x01, 0x0023, 0x001a},
1467 {0x01, 0x0032, 0x001b},
1468 {0x01, 0x008d, 0x001c},
1469 {0x01, 0x00ce, 0x001d},
1470 {0x01, 0x008d, 0x001e},
1471 {0x01, 0x0000, 0x001f},
1472 {0x01, 0x0000, 0x0020},
1473 {0x01, 0x00ff, 0x003e},
1474 {0x01, 0x0003, 0x003f},
1475 {0x01, 0x0000, 0x0040},
1476 {0x01, 0x0035, 0x0041},
1477 {0x01, 0x0053, 0x0042},
1478 {0x01, 0x0069, 0x0043},
1479 {0x01, 0x007c, 0x0044},
1480 {0x01, 0x008c, 0x0045},
1481 {0x01, 0x009a, 0x0046},
1482 {0x01, 0x00a8, 0x0047},
1483 {0x01, 0x00b4, 0x0048},
1484 {0x01, 0x00bf, 0x0049},
1485 {0x01, 0x00ca, 0x004a},
1486 {0x01, 0x00d4, 0x004b},
1487 {0x01, 0x00dd, 0x004c},
1488 {0x01, 0x00e7, 0x004d},
1489 {0x01, 0x00ef, 0x004e},
1490 {0x01, 0x00f8, 0x004f},
1491 {0x01, 0x00ff, 0x0050},
1492 {0x01, 0x0001, 0x0056},
1493 {0x01, 0x0060, 0x0057},
1494 {0x01, 0x0040, 0x0058},
1495 {0x01, 0x0011, 0x0059},
1496 {0x01, 0x0001, 0x005a},
1497 {0x02, 0x0007, 0x0005},
1498 {0x02, 0xa048, 0x0000},
1499 {0x02, 0x0007, 0x0005},
1500 {0x02, 0x0015, 0x0006},
1501 {0x02, 0x100a, 0x0007},
1502 {0x02, 0xa048, 0x0000},
1503 {0x02, 0xc002, 0x0001},
1504 {0x02, 0x000f, 0x0005},
1505 {0x02, 0xa048, 0x0000},
1506 {0x05, 0x0022, 0x0004},
1507 {0x05, 0x0025, 0x0001},
1508 {0x05, 0x0000, 0x0000},
1509 {0x05, 0x0026, 0x0001},
1510 {0x05, 0x0001, 0x0000},
1511 {0x05, 0x0027, 0x0001},
1512 {0x05, 0x0000, 0x0000},
1513 {0x05, 0x0001, 0x0001},
1514 {0x05, 0x0000, 0x0000},
1515 {0x05, 0x0021, 0x0001},
1516 {0x05, 0x00d2, 0x0000},
1517 {0x05, 0x0020, 0x0001},
1518 {0x05, 0x0000, 0x0000},
1519 {0x00, 0x0090, 0x0005},
1520 {0x01, 0x00a6, 0x0000},
1521 {0x05, 0x0026, 0x0001},
1522 {0x05, 0x0001, 0x0000},
1523 {0x05, 0x0027, 0x0001},
1524 {0x05, 0x001e, 0x0000},
1525 {0x01, 0x0003, 0x003f},
1526 {0x01, 0x0001, 0x0056},
1527 {0x01, 0x0011, 0x0008},
1528 {0x01, 0x0032, 0x0009},
1529 {0x01, 0xfffd, 0x000a},
1530 {0x01, 0x0023, 0x000b},
1531 {0x01, 0xffea, 0x000c},
1532 {0x01, 0xfff4, 0x000d},
1533 {0x01, 0xfffc, 0x000e},
1534 {0x01, 0xffe3, 0x000f},
1535 {0x01, 0x001f, 0x0010},
1536 {0x01, 0x00a8, 0x0001},
1537 {0x01, 0x0067, 0x0007},
1538 {0x01, 0x0042, 0x0051},
1539 {0x01, 0x0051, 0x0053},
1540 {0x01, 0x000a, 0x0003},
1541 {0x02, 0xc002, 0x0001},
1542 {0x02, 0x0007, 0x0005},
1543 {0x01, 0x0042, 0x0051},
1544 {0x01, 0x0051, 0x0053},
1545 {0x05, 0x0026, 0x0001},
1546 {0x05, 0x0001, 0x0000},
1547 {0x05, 0x0027, 0x0001},
1548 {0x05, 0x002d, 0x0000},
1549 {0x01, 0x0003, 0x003f},
1550 {0x01, 0x0001, 0x0056},
1551 {0x02, 0xc000, 0x0001},
1552 {0x02, 0x0000, 0x0005},
1553 {}
1554};
1555
1556/* Unknown camera from Ori Usbid 0x0000:0x0000 */
1557/* Based on snoops from Ori Cohen */
1558static const __u16 spca501c_mysterious_open_data[][3] = {
1559 {0x02, 0x000f, 0x0005},
1560 {0x02, 0xa048, 0x0000},
1561 {0x05, 0x0022, 0x0004},
1562/* DSP Registers */
1563 {0x01, 0x0016, 0x0011}, /* RGB offset */
1564 {0x01, 0x0000, 0x0012},
1565 {0x01, 0x0006, 0x0013},
1566 {0x01, 0x0078, 0x0051},
1567 {0x01, 0x0040, 0x0052},
1568 {0x01, 0x0046, 0x0053},
1569 {0x01, 0x0040, 0x0054},
1570 {0x00, 0x0025, 0x0000},
1571/* {0x00, 0x0000, 0x0000 }, */
1572/* Part 2 */
1573/* TG Registers */
1574 {0x00, 0x0026, 0x0000},
1575 {0x00, 0x0001, 0x0000},
1576 {0x00, 0x0027, 0x0000},
1577 {0x00, 0x008a, 0x0000},
1578 {0x02, 0x0007, 0x0005},
1579 {0x02, 0x2000, 0x0000},
1580 {0x05, 0x0022, 0x0004},
1581 {0x05, 0x0015, 0x0001},
1582 {0x05, 0x00ea, 0x0000},
1583 {0x05, 0x0021, 0x0001},
1584 {0x05, 0x00d2, 0x0000},
1585 {0x05, 0x0023, 0x0001},
1586 {0x05, 0x0003, 0x0000},
1587 {0x05, 0x0030, 0x0001},
1588 {0x05, 0x002b, 0x0000},
1589 {0x05, 0x0031, 0x0001},
1590 {0x05, 0x0023, 0x0000},
1591 {0x05, 0x0032, 0x0001},
1592 {0x05, 0x0023, 0x0000},
1593 {0x05, 0x0033, 0x0001},
1594 {0x05, 0x0023, 0x0000},
1595 {0x05, 0x0034, 0x0001},
1596 {0x05, 0x0002, 0x0000},
1597 {0x05, 0x0050, 0x0001},
1598 {0x05, 0x0000, 0x0000},
1599 {0x05, 0x0051, 0x0001},
1600 {0x05, 0x0000, 0x0000},
1601 {0x05, 0x0052, 0x0001},
1602 {0x05, 0x0000, 0x0000},
1603 {0x05, 0x0054, 0x0001},
1604 {0x05, 0x0001, 0x0000},
1605 {}
1606};
1607
1608/* Based on snoops from Ori Cohen */
1609static const __u16 spca501c_mysterious_init_data[][3] = {
1610/* Part 3 */
1611/* TG registers */
1612/* {0x00, 0x0000, 0x0000}, */
1613 {0x00, 0x0000, 0x0001},
1614 {0x00, 0x0000, 0x0002},
1615 {0x00, 0x0006, 0x0003},
1616 {0x00, 0x0000, 0x0004},
1617 {0x00, 0x0090, 0x0005},
1618 {0x00, 0x0000, 0x0006},
1619 {0x00, 0x0040, 0x0007},
1620 {0x00, 0x00c0, 0x0008},
1621 {0x00, 0x004a, 0x0009},
1622 {0x00, 0x0000, 0x000a},
1623 {0x00, 0x0000, 0x000b},
1624 {0x00, 0x0001, 0x000c},
1625 {0x00, 0x0001, 0x000d},
1626 {0x00, 0x0000, 0x000e},
1627 {0x00, 0x0002, 0x000f},
1628 {0x00, 0x0001, 0x0010},
1629 {0x00, 0x0000, 0x0011},
1630 {0x00, 0x0001, 0x0012},
1631 {0x00, 0x0002, 0x0020},
1632 {0x00, 0x0080, 0x0021}, /* 640 */
1633 {0x00, 0x0001, 0x0022},
1634 {0x00, 0x00e0, 0x0023}, /* 480 */
1635 {0x00, 0x0000, 0x0024}, /* Offset H hight */
1636 {0x00, 0x00d3, 0x0025}, /* low */
1637 {0x00, 0x0000, 0x0026}, /* Offset V */
1638 {0x00, 0x000d, 0x0027}, /* low */
1639 {0x00, 0x0000, 0x0046},
1640 {0x00, 0x0000, 0x0047},
1641 {0x00, 0x0000, 0x0048},
1642 {0x00, 0x0000, 0x0049},
1643 {0x00, 0x0008, 0x004a},
1644/* DSP Registers */
1645 {0x01, 0x00a6, 0x0000},
1646 {0x01, 0x0028, 0x0001},
1647 {0x01, 0x0000, 0x0002},
1648 {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */
1649 {0x01, 0x0040, 0x0004},
1650 {0x01, 0x0066, 0x0007},
1651 {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */
1652 {0x01, 0x002d, 0x0009}, /* A12 */
1653 {0x01, 0x0005, 0x000a}, /* A13 */
1654 {0x01, 0x0023, 0x000b}, /* A21 */
1655 {0x01, 0x00e0, 0x000c}, /* A22 */
1656 {0x01, 0x00fd, 0x000d}, /* A23 */
1657 {0x01, 0x00f4, 0x000e}, /* A31 */
1658 {0x01, 0x00e4, 0x000f}, /* A32 */
1659 {0x01, 0x0028, 0x0010}, /* A33 */
1660 {0x01, 0x00ff, 0x0015}, /* Reserved */
1661 {0x01, 0x0001, 0x0016}, /* Reserved */
1662 {0x01, 0x0032, 0x0017}, /* Win1 Start begin */
1663 {0x01, 0x0023, 0x0018},
1664 {0x01, 0x00ce, 0x0019},
1665 {0x01, 0x0023, 0x001a},
1666 {0x01, 0x0032, 0x001b},
1667 {0x01, 0x008d, 0x001c},
1668 {0x01, 0x00ce, 0x001d},
1669 {0x01, 0x008d, 0x001e},
1670 {0x01, 0x0000, 0x001f},
1671 {0x01, 0x0000, 0x0020}, /* Win1 Start end */
1672 {0x01, 0x00ff, 0x003e}, /* Reserved begin */
1673 {0x01, 0x0002, 0x003f},
1674 {0x01, 0x0000, 0x0040},
1675 {0x01, 0x0035, 0x0041},
1676 {0x01, 0x0053, 0x0042},
1677 {0x01, 0x0069, 0x0043},
1678 {0x01, 0x007c, 0x0044},
1679 {0x01, 0x008c, 0x0045},
1680 {0x01, 0x009a, 0x0046},
1681 {0x01, 0x00a8, 0x0047},
1682 {0x01, 0x00b4, 0x0048},
1683 {0x01, 0x00bf, 0x0049},
1684 {0x01, 0x00ca, 0x004a},
1685 {0x01, 0x00d4, 0x004b},
1686 {0x01, 0x00dd, 0x004c},
1687 {0x01, 0x00e7, 0x004d},
1688 {0x01, 0x00ef, 0x004e},
1689 {0x01, 0x00f8, 0x004f},
1690 {0x01, 0x00ff, 0x0050},
1691 {0x01, 0x0003, 0x0056}, /* Reserved end */
1692 {0x01, 0x0060, 0x0057}, /* Edge Gain */
1693 {0x01, 0x0040, 0x0058},
1694 {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */
1695 {0x01, 0x0001, 0x005a},
1696 {0x02, 0x0007, 0x0005},
1697 {0x02, 0xa048, 0x0000},
1698 {0x02, 0x0007, 0x0005},
1699 {0x02, 0x0015, 0x0006},
1700 {0x02, 0x200a, 0x0007},
1701 {0x02, 0xa048, 0x0000},
1702 {0x02, 0xc000, 0x0001},
1703 {0x02, 0x000f, 0x0005},
1704 {0x02, 0xa048, 0x0000},
1705 {0x05, 0x0022, 0x0004},
1706 {0x05, 0x0025, 0x0001},
1707 {0x05, 0x0000, 0x0000},
1708/* Part 4 */
1709 {0x05, 0x0026, 0x0001},
1710 {0x05, 0x0001, 0x0000},
1711 {0x05, 0x0027, 0x0001},
1712 {0x05, 0x0000, 0x0000},
1713 {0x05, 0x0001, 0x0001},
1714 {0x05, 0x0000, 0x0000},
1715 {0x05, 0x0021, 0x0001},
1716 {0x05, 0x00d2, 0x0000},
1717 {0x05, 0x0020, 0x0001},
1718 {0x05, 0x0000, 0x0000},
1719 {0x00, 0x0090, 0x0005},
1720 {0x01, 0x00a6, 0x0000},
1721 {0x02, 0x0000, 0x0005},
1722 {0x05, 0x0026, 0x0001},
1723 {0x05, 0x0001, 0x0000},
1724 {0x05, 0x0027, 0x0001},
1725 {0x05, 0x004e, 0x0000},
1726/* Part 5 */
1727 {0x01, 0x0003, 0x003f},
1728 {0x01, 0x0001, 0x0056},
1729 {0x01, 0x000f, 0x0008},
1730 {0x01, 0x002d, 0x0009},
1731 {0x01, 0x0005, 0x000a},
1732 {0x01, 0x0023, 0x000b},
1733 {0x01, 0xffe0, 0x000c},
1734 {0x01, 0xfffd, 0x000d},
1735 {0x01, 0xfff4, 0x000e},
1736 {0x01, 0xffe4, 0x000f},
1737 {0x01, 0x0028, 0x0010},
1738 {0x01, 0x00a8, 0x0001},
1739 {0x01, 0x0066, 0x0007},
1740 {0x01, 0x0032, 0x0017},
1741 {0x01, 0x0023, 0x0018},
1742 {0x01, 0x00ce, 0x0019},
1743 {0x01, 0x0023, 0x001a},
1744 {0x01, 0x0032, 0x001b},
1745 {0x01, 0x008d, 0x001c},
1746 {0x01, 0x00ce, 0x001d},
1747 {0x01, 0x008d, 0x001e},
1748 {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */
1749 {0x01, 0x0032, 0x0016}, /* 32 */
1750 {0x01, 0x0016, 0x0011}, /* R 00 */
1751 {0x01, 0x0016, 0x0012}, /* G 00 */
1752 {0x01, 0x0016, 0x0013}, /* B 00 */
1753 {0x01, 0x000a, 0x0003},
1754 {0x02, 0xc002, 0x0001},
1755 {0x02, 0x0007, 0x0005},
1756 {}
1757};
1758
1759static int reg_write(struct usb_device *dev,
1760 __u16 req, __u16 index, __u16 value)
1761{
1762 int ret;
1763
1764 ret = usb_control_msg(dev,
1765 usb_sndctrlpipe(dev, 0),
1766 req,
1767 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1768 value, index, NULL, 0, 500);
1769 PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
1770 req, index, value);
1771 if (ret < 0)
1772 pr_err("reg write: error %d\n", ret);
1773 return ret;
1774}
1775
1776
1777static int write_vector(struct gspca_dev *gspca_dev,
1778 const __u16 data[][3])
1779{
1780 struct usb_device *dev = gspca_dev->dev;
1781 int ret, i = 0;
1782
1783 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
1784 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
1785 if (ret < 0) {
1786 PDEBUG(D_ERR,
1787 "Reg write failed for 0x%02x,0x%02x,0x%02x",
1788 data[i][0], data[i][1], data[i][2]);
1789 return ret;
1790 }
1791 i++;
1792 }
1793 return 0;
1794}
1795
1796static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
1797{
1798 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, val);
1799}
1800
1801static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
1802{
1803 reg_write(gspca_dev->dev, 0x00, 0x00,
1804 (val >> 8) & 0xff);
1805 reg_write(gspca_dev->dev, 0x00, 0x01,
1806 val & 0xff);
1807}
1808
1809static void setcolors(struct gspca_dev *gspca_dev, s32 val)
1810{
1811 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, val);
1812}
1813
1814static void setblue_balance(struct gspca_dev *gspca_dev, s32 val)
1815{
1816 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, val);
1817}
1818
1819static void setred_balance(struct gspca_dev *gspca_dev, s32 val)
1820{
1821 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, val);
1822}
1823
1824/* this function is called at probe time */
1825static int sd_config(struct gspca_dev *gspca_dev,
1826 const struct usb_device_id *id)
1827{
1828 struct sd *sd = (struct sd *) gspca_dev;
1829 struct cam *cam;
1830
1831 cam = &gspca_dev->cam;
1832 cam->cam_mode = vga_mode;
1833 cam->nmodes = ARRAY_SIZE(vga_mode);
1834 sd->subtype = id->driver_info;
1835
1836 return 0;
1837}
1838
1839/* this function is called at probe and resume time */
1840static int sd_init(struct gspca_dev *gspca_dev)
1841{
1842 struct sd *sd = (struct sd *) gspca_dev;
1843
1844 switch (sd->subtype) {
1845 case Arowana300KCMOSCamera:
1846 case SmileIntlCamera:
1847 /* Arowana 300k CMOS Camera data */
1848 if (write_vector(gspca_dev, spca501c_arowana_init_data))
1849 goto error;
1850 break;
1851 case MystFromOriUnknownCamera:
1852 /* Unknown Ori CMOS Camera data */
1853 if (write_vector(gspca_dev, spca501c_mysterious_open_data))
1854 goto error;
1855 break;
1856 default:
1857 /* generic spca501 init data */
1858 if (write_vector(gspca_dev, spca501_init_data))
1859 goto error;
1860 break;
1861 }
1862 PDEBUG(D_STREAM, "Initializing SPCA501 finished");
1863 return 0;
1864error:
1865 return -EINVAL;
1866}
1867
1868static int sd_start(struct gspca_dev *gspca_dev)
1869{
1870 struct sd *sd = (struct sd *) gspca_dev;
1871 struct usb_device *dev = gspca_dev->dev;
1872 int mode;
1873
1874 switch (sd->subtype) {
1875 case ThreeComHomeConnectLite:
1876 /* Special handling for 3com data */
1877 write_vector(gspca_dev, spca501_3com_open_data);
1878 break;
1879 case Arowana300KCMOSCamera:
1880 case SmileIntlCamera:
1881 /* Arowana 300k CMOS Camera data */
1882 write_vector(gspca_dev, spca501c_arowana_open_data);
1883 break;
1884 case MystFromOriUnknownCamera:
1885 /* Unknown CMOS Camera data */
1886 write_vector(gspca_dev, spca501c_mysterious_init_data);
1887 break;
1888 default:
1889 /* Generic 501 open data */
1890 write_vector(gspca_dev, spca501_open_data);
1891 }
1892
1893 /* memorize the wanted pixel format */
1894 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1895
1896 /* Enable ISO packet machine CTRL reg=2,
1897 * index=1 bitmask=0x2 (bit ordinal 1) */
1898 reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
1899 switch (mode) {
1900 case 0: /* 640x480 */
1901 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
1902 break;
1903 case 1: /* 320x240 */
1904 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
1905 break;
1906 default:
1907/* case 2: * 160x120 */
1908 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
1909 break;
1910 }
1911 reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
1912
1913 return 0;
1914}
1915
1916static void sd_stopN(struct gspca_dev *gspca_dev)
1917{
1918 /* Disable ISO packet
1919 * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
1920 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
1921}
1922
1923/* called on streamoff with alt 0 and on disconnect */
1924static void sd_stop0(struct gspca_dev *gspca_dev)
1925{
1926 if (!gspca_dev->present)
1927 return;
1928 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
1929}
1930
1931static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1932 u8 *data, /* isoc packet */
1933 int len) /* iso packet length */
1934{
1935 switch (data[0]) {
1936 case 0: /* start of frame */
1937 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1938 data += SPCA501_OFFSET_DATA;
1939 len -= SPCA501_OFFSET_DATA;
1940 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1941 return;
1942 case 0xff: /* drop */
1943/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1944 return;
1945 }
1946 data++;
1947 len--;
1948 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1949}
1950
1951static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1952{
1953 struct gspca_dev *gspca_dev =
1954 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1955
1956 gspca_dev->usb_err = 0;
1957
1958 if (!gspca_dev->streaming)
1959 return 0;
1960
1961 switch (ctrl->id) {
1962 case V4L2_CID_BRIGHTNESS:
1963 setbrightness(gspca_dev, ctrl->val);
1964 break;
1965 case V4L2_CID_CONTRAST:
1966 setcontrast(gspca_dev, ctrl->val);
1967 break;
1968 case V4L2_CID_SATURATION:
1969 setcolors(gspca_dev, ctrl->val);
1970 break;
1971 case V4L2_CID_BLUE_BALANCE:
1972 setblue_balance(gspca_dev, ctrl->val);
1973 break;
1974 case V4L2_CID_RED_BALANCE:
1975 setred_balance(gspca_dev, ctrl->val);
1976 break;
1977 }
1978 return gspca_dev->usb_err;
1979}
1980
1981static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1982 .s_ctrl = sd_s_ctrl,
1983};
1984
1985static int sd_init_controls(struct gspca_dev *gspca_dev)
1986{
1987 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1988
1989 gspca_dev->vdev.ctrl_handler = hdl;
1990 v4l2_ctrl_handler_init(hdl, 5);
1991 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1992 V4L2_CID_BRIGHTNESS, 0, 127, 1, 0);
1993 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1994 V4L2_CID_CONTRAST, 0, 64725, 1, 64725);
1995 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1996 V4L2_CID_SATURATION, 0, 63, 1, 20);
1997 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1998 V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0);
1999 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
2000 V4L2_CID_RED_BALANCE, 0, 127, 1, 0);
2001
2002 if (hdl->error) {
2003 pr_err("Could not initialize controls\n");
2004 return hdl->error;
2005 }
2006 return 0;
2007}
2008
2009/* sub-driver description */
2010static const struct sd_desc sd_desc = {
2011 .name = MODULE_NAME,
2012 .config = sd_config,
2013 .init = sd_init,
2014 .init_controls = sd_init_controls,
2015 .start = sd_start,
2016 .stopN = sd_stopN,
2017 .stop0 = sd_stop0,
2018 .pkt_scan = sd_pkt_scan,
2019};
2020
2021/* -- module initialisation -- */
2022static const struct usb_device_id device_table[] = {
2023 {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325},
2024 {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera},
2025 {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite},
2026 {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare},
2027 {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B},
2028 {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera},
2029 {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera},
2030 {}
2031};
2032MODULE_DEVICE_TABLE(usb, device_table);
2033
2034/* -- device connect -- */
2035static int sd_probe(struct usb_interface *intf,
2036 const struct usb_device_id *id)
2037{
2038 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2039 THIS_MODULE);
2040}
2041
2042static struct usb_driver sd_driver = {
2043 .name = MODULE_NAME,
2044 .id_table = device_table,
2045 .probe = sd_probe,
2046 .disconnect = gspca_disconnect,
2047#ifdef CONFIG_PM
2048 .suspend = gspca_suspend,
2049 .resume = gspca_resume,
2050 .reset_resume = gspca_resume,
2051#endif
2052};
2053
2054module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca505.c b/drivers/media/usb/gspca/spca505.c
new file mode 100644
index 00000000000..bc7d67c3cb0
--- /dev/null
+++ b/drivers/media/usb/gspca/spca505.c
@@ -0,0 +1,807 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "spca505"
25
26#include "gspca.h"
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA505 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 u8 subtype;
37#define IntelPCCameraPro 0
38#define Nxultra 1
39};
40
41static const struct v4l2_pix_format vga_mode[] = {
42 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
43 .bytesperline = 160,
44 .sizeimage = 160 * 120 * 3 / 2,
45 .colorspace = V4L2_COLORSPACE_SRGB,
46 .priv = 4},
47 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
48 .bytesperline = 176,
49 .sizeimage = 176 * 144 * 3 / 2,
50 .colorspace = V4L2_COLORSPACE_SRGB,
51 .priv = 3},
52 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
53 .bytesperline = 320,
54 .sizeimage = 320 * 240 * 3 / 2,
55 .colorspace = V4L2_COLORSPACE_SRGB,
56 .priv = 2},
57 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
58 .bytesperline = 352,
59 .sizeimage = 352 * 288 * 3 / 2,
60 .colorspace = V4L2_COLORSPACE_SRGB,
61 .priv = 1},
62 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
63 .bytesperline = 640,
64 .sizeimage = 640 * 480 * 3 / 2,
65 .colorspace = V4L2_COLORSPACE_SRGB,
66 .priv = 0},
67};
68
69#define SPCA50X_OFFSET_DATA 10
70
71#define SPCA50X_REG_USB 0x02 /* spca505 501 */
72
73#define SPCA50X_USB_CTRL 0x00 /* spca505 */
74#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
75
76#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
77#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
78#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
79
80#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
81#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
82#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
83
84/* Image format and compression control */
85#define SPCA50X_REG_COMPRESS 0x04
86
87/*
88 * Data to initialize a SPCA505. Common to the CCD and external modes
89 */
90static const u8 spca505_init_data[][3] = {
91 /* bmRequest,value,index */
92 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
93 /* Sensor reset */
94 {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
95 {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
96 /* Block USB reset */
97 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
98
99 {0x05, 0x01, 0x10},
100 /* Maybe power down some stuff */
101 {0x05, 0x0f, 0x11},
102
103 /* Setup internal CCD ? */
104 {0x06, 0x10, 0x08},
105 {0x06, 0x00, 0x09},
106 {0x06, 0x00, 0x0a},
107 {0x06, 0x00, 0x0b},
108 {0x06, 0x10, 0x0c},
109 {0x06, 0x00, 0x0d},
110 {0x06, 0x00, 0x0e},
111 {0x06, 0x00, 0x0f},
112 {0x06, 0x10, 0x10},
113 {0x06, 0x02, 0x11},
114 {0x06, 0x00, 0x12},
115 {0x06, 0x04, 0x13},
116 {0x06, 0x02, 0x14},
117 {0x06, 0x8a, 0x51},
118 {0x06, 0x40, 0x52},
119 {0x06, 0xb6, 0x53},
120 {0x06, 0x3d, 0x54},
121 {}
122};
123
124/*
125 * Data to initialize the camera using the internal CCD
126 */
127static const u8 spca505_open_data_ccd[][3] = {
128 /* bmRequest,value,index */
129 /* Internal CCD data set */
130 {0x03, 0x04, 0x01},
131 /* This could be a reset */
132 {0x03, 0x00, 0x01},
133
134 /* Setup compression and image registers. 0x6 and 0x7 seem to be
135 related to H&V hold, and are resolution mode specific */
136 {0x04, 0x10, 0x01},
137 /* DIFF(0x50), was (0x10) */
138 {0x04, 0x00, 0x04},
139 {0x04, 0x00, 0x05},
140 {0x04, 0x20, 0x06},
141 {0x04, 0x20, 0x07},
142
143 {0x08, 0x0a, 0x00},
144 /* DIFF (0x4a), was (0xa) */
145
146 {0x05, 0x00, 0x10},
147 {0x05, 0x00, 0x11},
148 {0x05, 0x00, 0x00},
149 /* DIFF not written */
150 {0x05, 0x00, 0x01},
151 /* DIFF not written */
152 {0x05, 0x00, 0x02},
153 /* DIFF not written */
154 {0x05, 0x00, 0x03},
155 /* DIFF not written */
156 {0x05, 0x00, 0x04},
157 /* DIFF not written */
158 {0x05, 0x80, 0x05},
159 /* DIFF not written */
160 {0x05, 0xe0, 0x06},
161 /* DIFF not written */
162 {0x05, 0x20, 0x07},
163 /* DIFF not written */
164 {0x05, 0xa0, 0x08},
165 /* DIFF not written */
166 {0x05, 0x0, 0x12},
167 /* DIFF not written */
168 {0x05, 0x02, 0x0f},
169 /* DIFF not written */
170 {0x05, 0x10, 0x46},
171 /* DIFF not written */
172 {0x05, 0x8, 0x4a},
173 /* DIFF not written */
174
175 {0x03, 0x08, 0x03},
176 /* DIFF (0x3,0x28,0x3) */
177 {0x03, 0x08, 0x01},
178 {0x03, 0x0c, 0x03},
179 /* DIFF not written */
180 {0x03, 0x21, 0x00},
181 /* DIFF (0x39) */
182
183/* Extra block copied from init to hopefully ensure CCD is in a sane state */
184 {0x06, 0x10, 0x08},
185 {0x06, 0x00, 0x09},
186 {0x06, 0x00, 0x0a},
187 {0x06, 0x00, 0x0b},
188 {0x06, 0x10, 0x0c},
189 {0x06, 0x00, 0x0d},
190 {0x06, 0x00, 0x0e},
191 {0x06, 0x00, 0x0f},
192 {0x06, 0x10, 0x10},
193 {0x06, 0x02, 0x11},
194 {0x06, 0x00, 0x12},
195 {0x06, 0x04, 0x13},
196 {0x06, 0x02, 0x14},
197 {0x06, 0x8a, 0x51},
198 {0x06, 0x40, 0x52},
199 {0x06, 0xb6, 0x53},
200 {0x06, 0x3d, 0x54},
201 /* End of extra block */
202
203 {0x06, 0x3f, 0x1},
204 /* Block skipped */
205 {0x06, 0x10, 0x02},
206 {0x06, 0x64, 0x07},
207 {0x06, 0x10, 0x08},
208 {0x06, 0x00, 0x09},
209 {0x06, 0x00, 0x0a},
210 {0x06, 0x00, 0x0b},
211 {0x06, 0x10, 0x0c},
212 {0x06, 0x00, 0x0d},
213 {0x06, 0x00, 0x0e},
214 {0x06, 0x00, 0x0f},
215 {0x06, 0x10, 0x10},
216 {0x06, 0x02, 0x11},
217 {0x06, 0x00, 0x12},
218 {0x06, 0x04, 0x13},
219 {0x06, 0x02, 0x14},
220 {0x06, 0x8a, 0x51},
221 {0x06, 0x40, 0x52},
222 {0x06, 0xb6, 0x53},
223 {0x06, 0x3d, 0x54},
224 {0x06, 0x60, 0x57},
225 {0x06, 0x20, 0x58},
226 {0x06, 0x15, 0x59},
227 {0x06, 0x05, 0x5a},
228
229 {0x05, 0x01, 0xc0},
230 {0x05, 0x10, 0xcb},
231 {0x05, 0x80, 0xc1},
232 /* */
233 {0x05, 0x0, 0xc2},
234 /* 4 was 0 */
235 {0x05, 0x00, 0xca},
236 {0x05, 0x80, 0xc1},
237 /* */
238 {0x05, 0x04, 0xc2},
239 {0x05, 0x00, 0xca},
240 {0x05, 0x0, 0xc1},
241 /* */
242 {0x05, 0x00, 0xc2},
243 {0x05, 0x00, 0xca},
244 {0x05, 0x40, 0xc1},
245 /* */
246 {0x05, 0x17, 0xc2},
247 {0x05, 0x00, 0xca},
248 {0x05, 0x80, 0xc1},
249 /* */
250 {0x05, 0x06, 0xc2},
251 {0x05, 0x00, 0xca},
252 {0x05, 0x80, 0xc1},
253 /* */
254 {0x05, 0x04, 0xc2},
255 {0x05, 0x00, 0xca},
256
257 {0x03, 0x4c, 0x3},
258 {0x03, 0x18, 0x1},
259
260 {0x06, 0x70, 0x51},
261 {0x06, 0xbe, 0x53},
262 {0x06, 0x71, 0x57},
263 {0x06, 0x20, 0x58},
264 {0x06, 0x05, 0x59},
265 {0x06, 0x15, 0x5a},
266
267 {0x04, 0x00, 0x08},
268 /* Compress = OFF (0x1 to turn on) */
269 {0x04, 0x12, 0x09},
270 {0x04, 0x21, 0x0a},
271 {0x04, 0x10, 0x0b},
272 {0x04, 0x21, 0x0c},
273 {0x04, 0x05, 0x00},
274 /* was 5 (Image Type ? ) */
275 {0x04, 0x00, 0x01},
276
277 {0x06, 0x3f, 0x01},
278
279 {0x04, 0x00, 0x04},
280 {0x04, 0x00, 0x05},
281 {0x04, 0x40, 0x06},
282 {0x04, 0x40, 0x07},
283
284 {0x06, 0x1c, 0x17},
285 {0x06, 0xe2, 0x19},
286 {0x06, 0x1c, 0x1b},
287 {0x06, 0xe2, 0x1d},
288 {0x06, 0xaa, 0x1f},
289 {0x06, 0x70, 0x20},
290
291 {0x05, 0x01, 0x10},
292 {0x05, 0x00, 0x11},
293 {0x05, 0x01, 0x00},
294 {0x05, 0x05, 0x01},
295 {0x05, 0x00, 0xc1},
296 /* */
297 {0x05, 0x00, 0xc2},
298 {0x05, 0x00, 0xca},
299
300 {0x06, 0x70, 0x51},
301 {0x06, 0xbe, 0x53},
302 {}
303};
304
305/*
306 * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
307 * SPCA505b chip based cameras initialization data
308 */
309/* jfm */
310#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
311/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
312/*
313 * Data to initialize a SPCA505. Common to the CCD and external modes
314 */
315static const u8 spca505b_init_data[][3] = {
316/* start */
317 {0x02, 0x00, 0x00}, /* init */
318 {0x02, 0x00, 0x01},
319 {0x02, 0x00, 0x02},
320 {0x02, 0x00, 0x03},
321 {0x02, 0x00, 0x04},
322 {0x02, 0x00, 0x05},
323 {0x02, 0x00, 0x06},
324 {0x02, 0x00, 0x07},
325 {0x02, 0x00, 0x08},
326 {0x02, 0x00, 0x09},
327 {0x03, 0x00, 0x00},
328 {0x03, 0x00, 0x01},
329 {0x03, 0x00, 0x02},
330 {0x03, 0x00, 0x03},
331 {0x03, 0x00, 0x04},
332 {0x03, 0x00, 0x05},
333 {0x03, 0x00, 0x06},
334 {0x04, 0x00, 0x00},
335 {0x04, 0x00, 0x02},
336 {0x04, 0x00, 0x04},
337 {0x04, 0x00, 0x05},
338 {0x04, 0x00, 0x06},
339 {0x04, 0x00, 0x07},
340 {0x04, 0x00, 0x08},
341 {0x04, 0x00, 0x09},
342 {0x04, 0x00, 0x0a},
343 {0x04, 0x00, 0x0b},
344 {0x04, 0x00, 0x0c},
345 {0x07, 0x00, 0x00},
346 {0x07, 0x00, 0x03},
347 {0x08, 0x00, 0x00},
348 {0x08, 0x00, 0x01},
349 {0x08, 0x00, 0x02},
350 {0x06, 0x18, 0x08},
351 {0x06, 0xfc, 0x09},
352 {0x06, 0xfc, 0x0a},
353 {0x06, 0xfc, 0x0b},
354 {0x06, 0x18, 0x0c},
355 {0x06, 0xfc, 0x0d},
356 {0x06, 0xfc, 0x0e},
357 {0x06, 0xfc, 0x0f},
358 {0x06, 0x18, 0x10},
359 {0x06, 0xfe, 0x12},
360 {0x06, 0x00, 0x11},
361 {0x06, 0x00, 0x14},
362 {0x06, 0x00, 0x13},
363 {0x06, 0x28, 0x51},
364 {0x06, 0xff, 0x53},
365 {0x02, 0x00, 0x08},
366
367 {0x03, 0x00, 0x03},
368 {0x03, 0x10, 0x03},
369 {}
370};
371
372/*
373 * Data to initialize the camera using the internal CCD
374 */
375static const u8 spca505b_open_data_ccd[][3] = {
376
377/* {0x02,0x00,0x00}, */
378 {0x03, 0x04, 0x01}, /* rst */
379 {0x03, 0x00, 0x01},
380 {0x03, 0x00, 0x00},
381 {0x03, 0x21, 0x00},
382 {0x03, 0x00, 0x04},
383 {0x03, 0x00, 0x03},
384 {0x03, 0x18, 0x03},
385 {0x03, 0x08, 0x01},
386 {0x03, 0x1c, 0x03},
387 {0x03, 0x5c, 0x03},
388 {0x03, 0x5c, 0x03},
389 {0x03, 0x18, 0x01},
390
391/* same as 505 */
392 {0x04, 0x10, 0x01},
393 {0x04, 0x00, 0x04},
394 {0x04, 0x00, 0x05},
395 {0x04, 0x20, 0x06},
396 {0x04, 0x20, 0x07},
397
398 {0x08, 0x0a, 0x00},
399
400 {0x05, 0x00, 0x10},
401 {0x05, 0x00, 0x11},
402 {0x05, 0x00, 0x12},
403 {0x05, 0x6f, 0x00},
404 {0x05, initial_brightness >> 6, 0x00},
405 {0x05, (initial_brightness << 2) & 0xff, 0x01},
406 {0x05, 0x00, 0x02},
407 {0x05, 0x01, 0x03},
408 {0x05, 0x00, 0x04},
409 {0x05, 0x03, 0x05},
410 {0x05, 0xe0, 0x06},
411 {0x05, 0x20, 0x07},
412 {0x05, 0xa0, 0x08},
413 {0x05, 0x00, 0x12},
414 {0x05, 0x02, 0x0f},
415 {0x05, 0x80, 0x14}, /* max exposure off (0=on) */
416 {0x05, 0x01, 0xb0},
417 {0x05, 0x01, 0xbf},
418 {0x03, 0x02, 0x06},
419 {0x05, 0x10, 0x46},
420 {0x05, 0x08, 0x4a},
421
422 {0x06, 0x00, 0x01},
423 {0x06, 0x10, 0x02},
424 {0x06, 0x64, 0x07},
425 {0x06, 0x18, 0x08},
426 {0x06, 0xfc, 0x09},
427 {0x06, 0xfc, 0x0a},
428 {0x06, 0xfc, 0x0b},
429 {0x04, 0x00, 0x01},
430 {0x06, 0x18, 0x0c},
431 {0x06, 0xfc, 0x0d},
432 {0x06, 0xfc, 0x0e},
433 {0x06, 0xfc, 0x0f},
434 {0x06, 0x11, 0x10}, /* contrast */
435 {0x06, 0x00, 0x11},
436 {0x06, 0xfe, 0x12},
437 {0x06, 0x00, 0x13},
438 {0x06, 0x00, 0x14},
439 {0x06, 0x9d, 0x51},
440 {0x06, 0x40, 0x52},
441 {0x06, 0x7c, 0x53},
442 {0x06, 0x40, 0x54},
443 {0x06, 0x02, 0x57},
444 {0x06, 0x03, 0x58},
445 {0x06, 0x15, 0x59},
446 {0x06, 0x05, 0x5a},
447 {0x06, 0x03, 0x56},
448 {0x06, 0x02, 0x3f},
449 {0x06, 0x00, 0x40},
450 {0x06, 0x39, 0x41},
451 {0x06, 0x69, 0x42},
452 {0x06, 0x87, 0x43},
453 {0x06, 0x9e, 0x44},
454 {0x06, 0xb1, 0x45},
455 {0x06, 0xbf, 0x46},
456 {0x06, 0xcc, 0x47},
457 {0x06, 0xd5, 0x48},
458 {0x06, 0xdd, 0x49},
459 {0x06, 0xe3, 0x4a},
460 {0x06, 0xe8, 0x4b},
461 {0x06, 0xed, 0x4c},
462 {0x06, 0xf2, 0x4d},
463 {0x06, 0xf7, 0x4e},
464 {0x06, 0xfc, 0x4f},
465 {0x06, 0xff, 0x50},
466
467 {0x05, 0x01, 0xc0},
468 {0x05, 0x10, 0xcb},
469 {0x05, 0x40, 0xc1},
470 {0x05, 0x04, 0xc2},
471 {0x05, 0x00, 0xca},
472 {0x05, 0x40, 0xc1},
473 {0x05, 0x09, 0xc2},
474 {0x05, 0x00, 0xca},
475 {0x05, 0xc0, 0xc1},
476 {0x05, 0x09, 0xc2},
477 {0x05, 0x00, 0xca},
478 {0x05, 0x40, 0xc1},
479 {0x05, 0x59, 0xc2},
480 {0x05, 0x00, 0xca},
481 {0x04, 0x00, 0x01},
482 {0x05, 0x80, 0xc1},
483 {0x05, 0xec, 0xc2},
484 {0x05, 0x0, 0xca},
485
486 {0x06, 0x02, 0x57},
487 {0x06, 0x01, 0x58},
488 {0x06, 0x15, 0x59},
489 {0x06, 0x0a, 0x5a},
490 {0x06, 0x01, 0x57},
491 {0x06, 0x8a, 0x03},
492 {0x06, 0x0a, 0x6c},
493 {0x06, 0x30, 0x01},
494 {0x06, 0x20, 0x02},
495 {0x06, 0x00, 0x03},
496
497 {0x05, 0x8c, 0x25},
498
499 {0x06, 0x4d, 0x51}, /* maybe saturation (4d) */
500 {0x06, 0x84, 0x53}, /* making green (84) */
501 {0x06, 0x00, 0x57}, /* sharpness (1) */
502 {0x06, 0x18, 0x08},
503 {0x06, 0xfc, 0x09},
504 {0x06, 0xfc, 0x0a},
505 {0x06, 0xfc, 0x0b},
506 {0x06, 0x18, 0x0c}, /* maybe hue (18) */
507 {0x06, 0xfc, 0x0d},
508 {0x06, 0xfc, 0x0e},
509 {0x06, 0xfc, 0x0f},
510 {0x06, 0x18, 0x10}, /* maybe contrast (18) */
511
512 {0x05, 0x01, 0x02},
513
514 {0x04, 0x00, 0x08}, /* compression */
515 {0x04, 0x12, 0x09},
516 {0x04, 0x21, 0x0a},
517 {0x04, 0x10, 0x0b},
518 {0x04, 0x21, 0x0c},
519 {0x04, 0x1d, 0x00}, /* imagetype (1d) */
520 {0x04, 0x41, 0x01}, /* hardware snapcontrol */
521
522 {0x04, 0x00, 0x04},
523 {0x04, 0x00, 0x05},
524 {0x04, 0x10, 0x06},
525 {0x04, 0x10, 0x07},
526 {0x04, 0x40, 0x06},
527 {0x04, 0x40, 0x07},
528 {0x04, 0x00, 0x04},
529 {0x04, 0x00, 0x05},
530
531 {0x06, 0x1c, 0x17},
532 {0x06, 0xe2, 0x19},
533 {0x06, 0x1c, 0x1b},
534 {0x06, 0xe2, 0x1d},
535 {0x06, 0x5f, 0x1f},
536 {0x06, 0x32, 0x20},
537
538 {0x05, initial_brightness >> 6, 0x00},
539 {0x05, (initial_brightness << 2) & 0xff, 0x01},
540 {0x05, 0x06, 0xc1},
541 {0x05, 0x58, 0xc2},
542 {0x05, 0x00, 0xca},
543 {0x05, 0x00, 0x11},
544 {}
545};
546
547static int reg_write(struct usb_device *dev,
548 u16 req, u16 index, u16 value)
549{
550 int ret;
551
552 ret = usb_control_msg(dev,
553 usb_sndctrlpipe(dev, 0),
554 req,
555 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
556 value, index, NULL, 0, 500);
557 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
558 req, index, value, ret);
559 if (ret < 0)
560 pr_err("reg write: error %d\n", ret);
561 return ret;
562}
563
564/* returns: negative is error, pos or zero is data */
565static int reg_read(struct gspca_dev *gspca_dev,
566 u16 req, /* bRequest */
567 u16 index) /* wIndex */
568{
569 int ret;
570
571 ret = usb_control_msg(gspca_dev->dev,
572 usb_rcvctrlpipe(gspca_dev->dev, 0),
573 req,
574 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
575 0, /* value */
576 index,
577 gspca_dev->usb_buf, 2,
578 500); /* timeout */
579 if (ret < 0)
580 return ret;
581 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
582}
583
584static int write_vector(struct gspca_dev *gspca_dev,
585 const u8 data[][3])
586{
587 struct usb_device *dev = gspca_dev->dev;
588 int ret, i = 0;
589
590 while (data[i][0] != 0) {
591 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
592 if (ret < 0)
593 return ret;
594 i++;
595 }
596 return 0;
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
606 cam = &gspca_dev->cam;
607 cam->cam_mode = vga_mode;
608 sd->subtype = id->driver_info;
609 if (sd->subtype != IntelPCCameraPro)
610 cam->nmodes = ARRAY_SIZE(vga_mode);
611 else /* no 640x480 for IntelPCCameraPro */
612 cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
613
614 return 0;
615}
616
617/* this function is called at probe and resume time */
618static int sd_init(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621
622 if (write_vector(gspca_dev,
623 sd->subtype == Nxultra
624 ? spca505b_init_data
625 : spca505_init_data))
626 return -EIO;
627 return 0;
628}
629
630static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
631{
632 reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
633 reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
634}
635
636static int sd_start(struct gspca_dev *gspca_dev)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639 struct usb_device *dev = gspca_dev->dev;
640 int ret, mode;
641 static u8 mode_tb[][3] = {
642 /* r00 r06 r07 */
643 {0x00, 0x10, 0x10}, /* 640x480 */
644 {0x01, 0x1a, 0x1a}, /* 352x288 */
645 {0x02, 0x1c, 0x1d}, /* 320x240 */
646 {0x04, 0x34, 0x34}, /* 176x144 */
647 {0x05, 0x40, 0x40} /* 160x120 */
648 };
649
650 if (sd->subtype == Nxultra)
651 write_vector(gspca_dev, spca505b_open_data_ccd);
652 else
653 write_vector(gspca_dev, spca505_open_data_ccd);
654 ret = reg_read(gspca_dev, 0x06, 0x16);
655
656 if (ret < 0) {
657 PDEBUG(D_ERR|D_CONF,
658 "register read failed err: %d",
659 ret);
660 return ret;
661 }
662 if (ret != 0x0101) {
663 pr_err("After vector read returns 0x%04x should be 0x0101\n",
664 ret);
665 }
666
667 ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
668 if (ret < 0)
669 return ret;
670 reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
671
672 /* necessary because without it we can see stream
673 * only once after loading module */
674 /* stopping usb registers Tomasz change */
675 reg_write(dev, 0x02, 0x00, 0x00);
676
677 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
678 reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
679 reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
680 reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
681
682 return reg_write(dev, SPCA50X_REG_USB,
683 SPCA50X_USB_CTRL,
684 SPCA50X_CUSB_ENABLE);
685}
686
687static void sd_stopN(struct gspca_dev *gspca_dev)
688{
689 /* Disable ISO packet machine */
690 reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
691}
692
693/* called on streamoff with alt 0 and on disconnect */
694static void sd_stop0(struct gspca_dev *gspca_dev)
695{
696 if (!gspca_dev->present)
697 return;
698
699 /* This maybe reset or power control */
700 reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
701 reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
702 reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
703 reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
704 reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
705}
706
707static void sd_pkt_scan(struct gspca_dev *gspca_dev,
708 u8 *data, /* isoc packet */
709 int len) /* iso packet length */
710{
711 switch (data[0]) {
712 case 0: /* start of frame */
713 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
714 data += SPCA50X_OFFSET_DATA;
715 len -= SPCA50X_OFFSET_DATA;
716 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
717 break;
718 case 0xff: /* drop */
719 break;
720 default:
721 data += 1;
722 len -= 1;
723 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
724 break;
725 }
726}
727
728static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
729{
730 struct gspca_dev *gspca_dev =
731 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
732
733 gspca_dev->usb_err = 0;
734
735 if (!gspca_dev->streaming)
736 return 0;
737
738 switch (ctrl->id) {
739 case V4L2_CID_BRIGHTNESS:
740 setbrightness(gspca_dev, ctrl->val);
741 break;
742 }
743 return gspca_dev->usb_err;
744}
745
746static const struct v4l2_ctrl_ops sd_ctrl_ops = {
747 .s_ctrl = sd_s_ctrl,
748};
749
750static int sd_init_controls(struct gspca_dev *gspca_dev)
751{
752 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
753
754 gspca_dev->vdev.ctrl_handler = hdl;
755 v4l2_ctrl_handler_init(hdl, 5);
756 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
757 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
758
759 if (hdl->error) {
760 pr_err("Could not initialize controls\n");
761 return hdl->error;
762 }
763 return 0;
764}
765
766/* sub-driver description */
767static const struct sd_desc sd_desc = {
768 .name = MODULE_NAME,
769 .config = sd_config,
770 .init_controls = sd_init_controls,
771 .init = sd_init,
772 .start = sd_start,
773 .stopN = sd_stopN,
774 .stop0 = sd_stop0,
775 .pkt_scan = sd_pkt_scan,
776};
777
778/* -- module initialisation -- */
779static const struct usb_device_id device_table[] = {
780 {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
781 {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
782/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
783 {}
784};
785MODULE_DEVICE_TABLE(usb, device_table);
786
787/* -- device connect -- */
788static int sd_probe(struct usb_interface *intf,
789 const struct usb_device_id *id)
790{
791 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
792 THIS_MODULE);
793}
794
795static struct usb_driver sd_driver = {
796 .name = MODULE_NAME,
797 .id_table = device_table,
798 .probe = sd_probe,
799 .disconnect = gspca_disconnect,
800#ifdef CONFIG_PM
801 .suspend = gspca_suspend,
802 .resume = gspca_resume,
803 .reset_resume = gspca_resume,
804#endif
805};
806
807module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca506.c b/drivers/media/usb/gspca/spca506.c
new file mode 100644
index 00000000000..969bb5a4cd9
--- /dev/null
+++ b/drivers/media/usb/gspca/spca506.c
@@ -0,0 +1,612 @@
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
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA506 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 char norme;
37 char channel;
38};
39
40static const struct v4l2_pix_format vga_mode[] = {
41 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
42 .bytesperline = 160,
43 .sizeimage = 160 * 120 * 3 / 2,
44 .colorspace = V4L2_COLORSPACE_SRGB,
45 .priv = 5},
46 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
47 .bytesperline = 176,
48 .sizeimage = 176 * 144 * 3 / 2,
49 .colorspace = V4L2_COLORSPACE_SRGB,
50 .priv = 4},
51 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
52 .bytesperline = 320,
53 .sizeimage = 320 * 240 * 3 / 2,
54 .colorspace = V4L2_COLORSPACE_SRGB,
55 .priv = 2},
56 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
57 .bytesperline = 352,
58 .sizeimage = 352 * 288 * 3 / 2,
59 .colorspace = V4L2_COLORSPACE_SRGB,
60 .priv = 1},
61 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
62 .bytesperline = 640,
63 .sizeimage = 640 * 480 * 3 / 2,
64 .colorspace = V4L2_COLORSPACE_SRGB,
65 .priv = 0},
66};
67
68#define SPCA50X_OFFSET_DATA 10
69
70#define SAA7113_bright 0x0a /* defaults 0x80 */
71#define SAA7113_contrast 0x0b /* defaults 0x47 */
72#define SAA7113_saturation 0x0c /* defaults 0x40 */
73#define SAA7113_hue 0x0d /* defaults 0x00 */
74#define SAA7113_I2C_BASE_WRITE 0x4a
75
76/* read 'len' bytes to gspca_dev->usb_buf */
77static void reg_r(struct gspca_dev *gspca_dev,
78 __u16 req,
79 __u16 index,
80 __u16 length)
81{
82 usb_control_msg(gspca_dev->dev,
83 usb_rcvctrlpipe(gspca_dev->dev, 0),
84 req,
85 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
86 0, /* value */
87 index, gspca_dev->usb_buf, length,
88 500);
89}
90
91static void reg_w(struct usb_device *dev,
92 __u16 req,
93 __u16 value,
94 __u16 index)
95{
96 usb_control_msg(dev,
97 usb_sndctrlpipe(dev, 0),
98 req,
99 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
100 value, index,
101 NULL, 0, 500);
102}
103
104static void spca506_Initi2c(struct gspca_dev *gspca_dev)
105{
106 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
107}
108
109static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
110 __u16 reg)
111{
112 int retry = 60;
113
114 reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
115 reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
116 while (retry--) {
117 reg_r(gspca_dev, 0x07, 0x0003, 2);
118 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
119 break;
120 }
121}
122
123static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
124 __u16 norme,
125 __u16 channel)
126{
127 struct sd *sd = (struct sd *) gspca_dev;
128/* fixme: check if channel == 0..3 and 6..9 (8 values) */
129 __u8 setbit0 = 0x00;
130 __u8 setbit1 = 0x00;
131 __u8 videomask = 0x00;
132
133 PDEBUG(D_STREAM, "** Open Set Norme **");
134 spca506_Initi2c(gspca_dev);
135 /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
136 /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
137 /* and exclude SAA7113 reserved channel set default 0 otherwise */
138 if (norme & V4L2_STD_NTSC)
139 setbit0 = 0x01;
140 if (channel == 4 || channel == 5 || channel > 9)
141 channel = 0;
142 if (channel < 4)
143 setbit1 = 0x02;
144 videomask = (0x48 | setbit0 | setbit1);
145 reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
146 spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
147
148 if (norme & V4L2_STD_NTSC)
149 spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
150 /* Chrominance Control NTSC N */
151 else if (norme & V4L2_STD_SECAM)
152 spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
153 /* Chrominance Control SECAM */
154 else
155 spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
156 /* Chrominance Control PAL BGHIV */
157
158 sd->norme = norme;
159 sd->channel = channel;
160 PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
161 PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
162}
163
164static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
165 __u16 *norme, __u16 *channel)
166{
167 struct sd *sd = (struct sd *) gspca_dev;
168
169 /* Read the register is not so good value change so
170 we use your own copy in spca50x struct */
171 *norme = sd->norme;
172 *channel = sd->channel;
173 PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
174}
175
176static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
177 __u16 xmult, __u16 ymult)
178{
179 struct usb_device *dev = gspca_dev->dev;
180
181 PDEBUG(D_STREAM, "** SetSize **");
182 reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
183 /* Soft snap 0x40 Hard 0x41 */
184 reg_w(dev, 0x04, 0x41, 0x0001);
185 reg_w(dev, 0x04, 0x00, 0x0002);
186 /* reserved */
187 reg_w(dev, 0x04, 0x00, 0x0003);
188
189 /* reserved */
190 reg_w(dev, 0x04, 0x00, 0x0004);
191 /* reserved */
192 reg_w(dev, 0x04, 0x01, 0x0005);
193 /* reserced */
194 reg_w(dev, 0x04, xmult, 0x0006);
195 /* reserved */
196 reg_w(dev, 0x04, ymult, 0x0007);
197 /* compression 1 */
198 reg_w(dev, 0x04, 0x00, 0x0008);
199 /* T=64 -> 2 */
200 reg_w(dev, 0x04, 0x00, 0x0009);
201 /* threshold2D */
202 reg_w(dev, 0x04, 0x21, 0x000a);
203 /* quantization */
204 reg_w(dev, 0x04, 0x00, 0x000b);
205}
206
207/* this function is called at probe time */
208static int sd_config(struct gspca_dev *gspca_dev,
209 const struct usb_device_id *id)
210{
211 struct cam *cam;
212
213 cam = &gspca_dev->cam;
214 cam->cam_mode = vga_mode;
215 cam->nmodes = ARRAY_SIZE(vga_mode);
216 return 0;
217}
218
219/* this function is called at probe and resume time */
220static int sd_init(struct gspca_dev *gspca_dev)
221{
222 struct usb_device *dev = gspca_dev->dev;
223
224 reg_w(dev, 0x03, 0x00, 0x0004);
225 reg_w(dev, 0x03, 0xFF, 0x0003);
226 reg_w(dev, 0x03, 0x00, 0x0000);
227 reg_w(dev, 0x03, 0x1c, 0x0001);
228 reg_w(dev, 0x03, 0x18, 0x0001);
229 /* Init on PAL and composite input0 */
230 spca506_SetNormeInput(gspca_dev, 0, 0);
231 reg_w(dev, 0x03, 0x1c, 0x0001);
232 reg_w(dev, 0x03, 0x18, 0x0001);
233 reg_w(dev, 0x05, 0x00, 0x0000);
234 reg_w(dev, 0x05, 0xef, 0x0001);
235 reg_w(dev, 0x05, 0x00, 0x00c1);
236 reg_w(dev, 0x05, 0x00, 0x00c2);
237 reg_w(dev, 0x06, 0x18, 0x0002);
238 reg_w(dev, 0x06, 0xf5, 0x0011);
239 reg_w(dev, 0x06, 0x02, 0x0012);
240 reg_w(dev, 0x06, 0xfb, 0x0013);
241 reg_w(dev, 0x06, 0x00, 0x0014);
242 reg_w(dev, 0x06, 0xa4, 0x0051);
243 reg_w(dev, 0x06, 0x40, 0x0052);
244 reg_w(dev, 0x06, 0x71, 0x0053);
245 reg_w(dev, 0x06, 0x40, 0x0054);
246 /************************************************/
247 reg_w(dev, 0x03, 0x00, 0x0004);
248 reg_w(dev, 0x03, 0x00, 0x0003);
249 reg_w(dev, 0x03, 0x00, 0x0004);
250 reg_w(dev, 0x03, 0xFF, 0x0003);
251 reg_w(dev, 0x02, 0x00, 0x0000);
252 reg_w(dev, 0x03, 0x60, 0x0000);
253 reg_w(dev, 0x03, 0x18, 0x0001);
254 /* for a better reading mx :) */
255 /*sdca506_WriteI2c(value,register) */
256 spca506_Initi2c(gspca_dev);
257 spca506_WriteI2c(gspca_dev, 0x08, 0x01);
258 spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
259 /* input composite video */
260 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
261 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
262 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
263 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
264 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
265 spca506_WriteI2c(gspca_dev, 0x98, 0x08);
266 spca506_WriteI2c(gspca_dev, 0x03, 0x09);
267 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
268 spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
269 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
270 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
271 spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */
272 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
273 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
274 spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
275 spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
276 spca506_WriteI2c(gspca_dev, 0x01, 0x13);
277 spca506_WriteI2c(gspca_dev, 0x00, 0x14);
278 spca506_WriteI2c(gspca_dev, 0x00, 0x15);
279 spca506_WriteI2c(gspca_dev, 0x00, 0x16);
280 spca506_WriteI2c(gspca_dev, 0x00, 0x17);
281 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
282 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
283 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
284 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
285 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
286 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
287 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
288 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
289 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
290 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
291 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
292 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
293 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
294 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
295 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
296 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
297 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
298 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
299 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
300 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
301 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
302 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
303 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
304 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
305 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
306 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
307 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
308 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
309 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
310 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
311 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
312 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
313 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
314 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
315 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
316 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
317 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
318 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
319 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
320 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
321 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
322 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
323 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
324 PDEBUG(D_STREAM, "** Close Init *");
325 return 0;
326}
327
328static int sd_start(struct gspca_dev *gspca_dev)
329{
330 struct usb_device *dev = gspca_dev->dev;
331 __u16 norme;
332 __u16 channel;
333
334 /**************************************/
335 reg_w(dev, 0x03, 0x00, 0x0004);
336 reg_w(dev, 0x03, 0x00, 0x0003);
337 reg_w(dev, 0x03, 0x00, 0x0004);
338 reg_w(dev, 0x03, 0xFF, 0x0003);
339 reg_w(dev, 0x02, 0x00, 0x0000);
340 reg_w(dev, 0x03, 0x60, 0x0000);
341 reg_w(dev, 0x03, 0x18, 0x0001);
342
343 /*sdca506_WriteI2c(value,register) */
344 spca506_Initi2c(gspca_dev);
345 spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */
346/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
347 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
348 /* Analog Input Control 2 */
349 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
350 /* Analog Input Control 3 */
351 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
352 /* Analog Input Control 4 */
353 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
354 /* Horizontal Sync Start 0xe9-0x0d */
355 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
356 /* Horizontal Sync Stop 0x0d-0xf0 */
357
358 spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */
359/* Defaults value */
360 spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */
361 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
362 /* Luminance Brightness */
363 spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */
364 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
365 /* Chrominance Saturation */
366 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
367 /* Chrominance Hue Control */
368 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
369 /* Chrominance Gain Control */
370 /**************************************/
371 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
372 /* Format/Delay Control */
373 spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */
374 spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */
375 spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */
376 spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */
377 spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */
378 spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */
379 spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */
380 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
381 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
382 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
383 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
384 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
385 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
386 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
387 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
388 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
389 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
390 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
391 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
392 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
393 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
394 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
395 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
396 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
397 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
398 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
399 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
400 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
401 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
402 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
403 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
404 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
405 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
406 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
407 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
408 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
409 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
410 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
411 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
412 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
413 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
414 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
415 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
416 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
417 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
418 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
419 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
420 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
421 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
422 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
423 /**************************************/
424 reg_w(dev, 0x05, 0x00, 0x0003);
425 reg_w(dev, 0x05, 0x00, 0x0004);
426 reg_w(dev, 0x03, 0x10, 0x0001);
427 reg_w(dev, 0x03, 0x78, 0x0000);
428 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
429 case 0:
430 spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
431 break;
432 case 1:
433 spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
434 break;
435 case 2:
436 spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
437 break;
438 case 4:
439 spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
440 break;
441 default:
442/* case 5: */
443 spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
444 break;
445 }
446
447 /* compress setting and size */
448 /* set i2c luma */
449 reg_w(dev, 0x02, 0x01, 0x0000);
450 reg_w(dev, 0x03, 0x12, 0x0000);
451 reg_r(gspca_dev, 0x04, 0x0001, 2);
452 PDEBUG(D_STREAM, "webcam started");
453 spca506_GetNormeInput(gspca_dev, &norme, &channel);
454 spca506_SetNormeInput(gspca_dev, norme, channel);
455 return 0;
456}
457
458static void sd_stopN(struct gspca_dev *gspca_dev)
459{
460 struct usb_device *dev = gspca_dev->dev;
461
462 reg_w(dev, 0x02, 0x00, 0x0000);
463 reg_w(dev, 0x03, 0x00, 0x0004);
464 reg_w(dev, 0x03, 0x00, 0x0003);
465}
466
467static void sd_pkt_scan(struct gspca_dev *gspca_dev,
468 u8 *data, /* isoc packet */
469 int len) /* iso packet length */
470{
471 switch (data[0]) {
472 case 0: /* start of frame */
473 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
474 data += SPCA50X_OFFSET_DATA;
475 len -= SPCA50X_OFFSET_DATA;
476 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
477 break;
478 case 0xff: /* drop */
479/* gspca_dev->last_packet_type = DISCARD_PACKET; */
480 break;
481 default:
482 data += 1;
483 len -= 1;
484 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
485 break;
486 }
487}
488
489static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
490{
491 spca506_Initi2c(gspca_dev);
492 spca506_WriteI2c(gspca_dev, val, SAA7113_bright);
493 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
494}
495
496static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
497{
498 spca506_Initi2c(gspca_dev);
499 spca506_WriteI2c(gspca_dev, val, SAA7113_contrast);
500 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
501}
502
503static void setcolors(struct gspca_dev *gspca_dev, s32 val)
504{
505 spca506_Initi2c(gspca_dev);
506 spca506_WriteI2c(gspca_dev, val, SAA7113_saturation);
507 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
508}
509
510static void sethue(struct gspca_dev *gspca_dev, s32 val)
511{
512 spca506_Initi2c(gspca_dev);
513 spca506_WriteI2c(gspca_dev, val, SAA7113_hue);
514 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
515}
516
517static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
518{
519 struct gspca_dev *gspca_dev =
520 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
521
522 gspca_dev->usb_err = 0;
523
524 if (!gspca_dev->streaming)
525 return 0;
526
527 switch (ctrl->id) {
528 case V4L2_CID_BRIGHTNESS:
529 setbrightness(gspca_dev, ctrl->val);
530 break;
531 case V4L2_CID_CONTRAST:
532 setcontrast(gspca_dev, ctrl->val);
533 break;
534 case V4L2_CID_SATURATION:
535 setcolors(gspca_dev, ctrl->val);
536 break;
537 case V4L2_CID_HUE:
538 sethue(gspca_dev, ctrl->val);
539 break;
540 }
541 return gspca_dev->usb_err;
542}
543
544static const struct v4l2_ctrl_ops sd_ctrl_ops = {
545 .s_ctrl = sd_s_ctrl,
546};
547
548static int sd_init_controls(struct gspca_dev *gspca_dev)
549{
550 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
551
552 gspca_dev->vdev.ctrl_handler = hdl;
553 v4l2_ctrl_handler_init(hdl, 4);
554 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
555 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
556 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
557 V4L2_CID_CONTRAST, 0, 255, 1, 0x47);
558 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
559 V4L2_CID_SATURATION, 0, 255, 1, 0x40);
560 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
561 V4L2_CID_HUE, 0, 255, 1, 0);
562
563 if (hdl->error) {
564 pr_err("Could not initialize controls\n");
565 return hdl->error;
566 }
567 return 0;
568}
569
570/* sub-driver description */
571static const struct sd_desc sd_desc = {
572 .name = MODULE_NAME,
573 .config = sd_config,
574 .init = sd_init,
575 .init_controls = sd_init_controls,
576 .start = sd_start,
577 .stopN = sd_stopN,
578 .pkt_scan = sd_pkt_scan,
579};
580
581/* -- module initialisation -- */
582static const struct usb_device_id device_table[] __devinitconst = {
583 {USB_DEVICE(0x06e1, 0xa190)},
584/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
585 {USB_DEVICE(0x0733, 0x0430)}, */
586 {USB_DEVICE(0x0734, 0x043b)},
587 {USB_DEVICE(0x99fa, 0x8988)},
588 {}
589};
590MODULE_DEVICE_TABLE(usb, device_table);
591
592/* -- device connect -- */
593static int __devinit 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#ifdef CONFIG_PM
606 .suspend = gspca_suspend,
607 .resume = gspca_resume,
608 .reset_resume = gspca_resume,
609#endif
610};
611
612module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca508.c b/drivers/media/usb/gspca/spca508.c
new file mode 100644
index 00000000000..1286b4170b8
--- /dev/null
+++ b/drivers/media/usb/gspca/spca508.c
@@ -0,0 +1,1540 @@
1/*
2 * SPCA508 chip based cameras subdriver
3 *
4 * Copyright (C) 2009 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "spca508"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
35 u8 subtype;
36#define CreativeVista 0
37#define HamaUSBSightcam 1
38#define HamaUSBSightcam2 2
39#define IntelEasyPCCamera 3
40#define MicroInnovationIC200 4
41#define ViewQuestVQ110 5
42};
43
44static const struct v4l2_pix_format sif_mode[] = {
45 {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
46 .bytesperline = 160,
47 .sizeimage = 160 * 120 * 3 / 2,
48 .colorspace = V4L2_COLORSPACE_SRGB,
49 .priv = 3},
50 {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
51 .bytesperline = 176,
52 .sizeimage = 176 * 144 * 3 / 2,
53 .colorspace = V4L2_COLORSPACE_SRGB,
54 .priv = 2},
55 {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
56 .bytesperline = 320,
57 .sizeimage = 320 * 240 * 3 / 2,
58 .colorspace = V4L2_COLORSPACE_SRGB,
59 .priv = 1},
60 {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
61 .bytesperline = 352,
62 .sizeimage = 352 * 288 * 3 / 2,
63 .colorspace = V4L2_COLORSPACE_SRGB,
64 .priv = 0},
65};
66
67/* Frame packet header offsets for the spca508 */
68#define SPCA508_OFFSET_DATA 37
69
70/*
71 * Initialization data: this is the first set-up data written to the
72 * device (before the open data).
73 */
74static const u16 spca508_init_data[][2] = {
75 {0x0000, 0x870b},
76
77 {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */
78 {0x0003, 0x8111}, /* Reset compression & memory */
79 {0x0000, 0x8110}, /* Disable all outputs */
80 /* READ {0x0000, 0x8114} -> 0000: 00 */
81 {0x0000, 0x8114}, /* SW GPIO data */
82 {0x0008, 0x8110}, /* Enable charge pump output */
83 {0x0002, 0x8116}, /* 200 kHz pump clock */
84 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
85 {0x0003, 0x8111}, /* Reset compression & memory */
86 {0x0000, 0x8111}, /* Normal mode (not reset) */
87 {0x0098, 0x8110},
88 /* Enable charge pump output, sync.serial,external 2x clock */
89 {0x000d, 0x8114}, /* SW GPIO data */
90 {0x0002, 0x8116}, /* 200 kHz pump clock */
91 {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */
92/* --------------------------------------- */
93 {0x000f, 0x8402}, /* memory bank */
94 {0x0000, 0x8403}, /* ... address */
95/* --------------------------------------- */
96/* 0x88__ is Synchronous Serial Interface. */
97/* TBD: This table could be expressed more compactly */
98/* using spca508_write_i2c_vector(). */
99/* TBD: Should see if the values in spca50x_i2c_data */
100/* would work with the VQ110 instead of the values */
101/* below. */
102 {0x00c0, 0x8804}, /* SSI slave addr */
103 {0x0008, 0x8802}, /* 375 Khz SSI clock */
104 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
105 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
106 {0x0008, 0x8802}, /* 375 Khz SSI clock */
107 {0x0012, 0x8801}, /* SSI reg addr */
108 {0x0080, 0x8800}, /* SSI data to write */
109 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
110 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
111 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
112 {0x0008, 0x8802}, /* 375 Khz SSI clock */
113 {0x0012, 0x8801}, /* SSI reg addr */
114 {0x0000, 0x8800}, /* SSI data to write */
115 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
116 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
117 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
118 {0x0008, 0x8802}, /* 375 Khz SSI clock */
119 {0x0011, 0x8801}, /* SSI reg addr */
120 {0x0040, 0x8800}, /* SSI data to write */
121 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
122 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
123 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
124 {0x0008, 0x8802},
125 {0x0013, 0x8801},
126 {0x0000, 0x8800},
127 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
128 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
129 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
130 {0x0008, 0x8802},
131 {0x0014, 0x8801},
132 {0x0000, 0x8800},
133 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
134 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
135 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
136 {0x0008, 0x8802},
137 {0x0015, 0x8801},
138 {0x0001, 0x8800},
139 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
140 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
141 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
142 {0x0008, 0x8802},
143 {0x0016, 0x8801},
144 {0x0003, 0x8800},
145 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
146 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
147 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
148 {0x0008, 0x8802},
149 {0x0017, 0x8801},
150 {0x0036, 0x8800},
151 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
152 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
153 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
154 {0x0008, 0x8802},
155 {0x0018, 0x8801},
156 {0x00ec, 0x8800},
157 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
158 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
159 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
160 {0x0008, 0x8802},
161 {0x001a, 0x8801},
162 {0x0094, 0x8800},
163 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
164 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
165 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
166 {0x0008, 0x8802},
167 {0x001b, 0x8801},
168 {0x0000, 0x8800},
169 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
170 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
171 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
172 {0x0008, 0x8802},
173 {0x0027, 0x8801},
174 {0x00a2, 0x8800},
175 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
176 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
177 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
178 {0x0008, 0x8802},
179 {0x0028, 0x8801},
180 {0x0040, 0x8800},
181 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
182 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
183 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
184 {0x0008, 0x8802},
185 {0x002a, 0x8801},
186 {0x0084, 0x8800},
187 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
188 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
189 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
190 {0x0008, 0x8802},
191 {0x002b, 0x8801},
192 {0x00a8, 0x8800},
193 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
194 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
195 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
196 {0x0008, 0x8802},
197 {0x002c, 0x8801},
198 {0x00fe, 0x8800},
199 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
200 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
201 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
202 {0x0008, 0x8802},
203 {0x002d, 0x8801},
204 {0x0003, 0x8800},
205 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
206 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
207 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
208 {0x0008, 0x8802},
209 {0x0038, 0x8801},
210 {0x0083, 0x8800},
211 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
212 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
213 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
214 {0x0008, 0x8802},
215 {0x0033, 0x8801},
216 {0x0081, 0x8800},
217 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
218 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
219 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
220 {0x0008, 0x8802},
221 {0x0034, 0x8801},
222 {0x004a, 0x8800},
223 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
224 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
225 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
226 {0x0008, 0x8802},
227 {0x0039, 0x8801},
228 {0x0000, 0x8800},
229 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
230 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
231 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
232 {0x0008, 0x8802},
233 {0x0010, 0x8801},
234 {0x00a8, 0x8800},
235 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
236 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
237 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
238 {0x0008, 0x8802},
239 {0x0006, 0x8801},
240 {0x0058, 0x8800},
241 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
242 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
243 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
244 {0x0008, 0x8802},
245 {0x0000, 0x8801},
246 {0x0004, 0x8800},
247 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
248 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
249 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
250 {0x0008, 0x8802},
251 {0x0040, 0x8801},
252 {0x0080, 0x8800},
253 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
254 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
255 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
256 {0x0008, 0x8802},
257 {0x0041, 0x8801},
258 {0x000c, 0x8800},
259 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
260 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
261 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
262 {0x0008, 0x8802},
263 {0x0042, 0x8801},
264 {0x000c, 0x8800},
265 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
266 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
267 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
268 {0x0008, 0x8802},
269 {0x0043, 0x8801},
270 {0x0028, 0x8800},
271 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
272 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
273 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
274 {0x0008, 0x8802},
275 {0x0044, 0x8801},
276 {0x0080, 0x8800},
277 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
278 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
279 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
280 {0x0008, 0x8802},
281 {0x0045, 0x8801},
282 {0x0020, 0x8800},
283 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
284 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
285 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
286 {0x0008, 0x8802},
287 {0x0046, 0x8801},
288 {0x0020, 0x8800},
289 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
290 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
291 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
292 {0x0008, 0x8802},
293 {0x0047, 0x8801},
294 {0x0080, 0x8800},
295 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
296 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
297 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
298 {0x0008, 0x8802},
299 {0x0048, 0x8801},
300 {0x004c, 0x8800},
301 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
302 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
303 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
304 {0x0008, 0x8802},
305 {0x0049, 0x8801},
306 {0x0084, 0x8800},
307 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
308 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
309 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
310 {0x0008, 0x8802},
311 {0x004a, 0x8801},
312 {0x0084, 0x8800},
313 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
314 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
315 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
316 {0x0008, 0x8802},
317 {0x004b, 0x8801},
318 {0x0084, 0x8800},
319 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
320 /* --------------------------------------- */
321 {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
322 {0x0000, 0x8701}, /* CKx1 clock delay adj */
323 {0x0000, 0x8701}, /* CKx1 clock delay adj */
324 {0x0001, 0x870c}, /* CKOx2 output */
325 /* --------------------------------------- */
326 {0x0080, 0x8600}, /* Line memory read counter (L) */
327 {0x0001, 0x8606}, /* reserved */
328 {0x0064, 0x8607}, /* Line memory read counter (H) 0x6480=25,728 */
329 {0x002a, 0x8601}, /* CDSP sharp interpolation mode,
330 * line sel for color sep, edge enhance enab */
331 {0x0000, 0x8602}, /* optical black level for user settng = 0 */
332 {0x0080, 0x8600}, /* Line memory read counter (L) */
333 {0x000a, 0x8603}, /* optical black level calc mode:
334 * auto; optical black offset = 10 */
335 {0x00df, 0x865b}, /* Horiz offset for valid pixels (L)=0xdf */
336 {0x0012, 0x865c}, /* Vert offset for valid lines (L)=0x12 */
337
338/* The following two lines seem to be the "wrong" resolution. */
339/* But perhaps these indicate the actual size of the sensor */
340/* rather than the size of the current video mode. */
341 {0x0058, 0x865d}, /* Horiz valid pixels (*4) (L) = 352 */
342 {0x0048, 0x865e}, /* Vert valid lines (*4) (L) = 288 */
343
344 {0x0015, 0x8608}, /* A11 Coef ... */
345 {0x0030, 0x8609},
346 {0x00fb, 0x860a},
347 {0x003e, 0x860b},
348 {0x00ce, 0x860c},
349 {0x00f4, 0x860d},
350 {0x00eb, 0x860e},
351 {0x00dc, 0x860f},
352 {0x0039, 0x8610},
353 {0x0001, 0x8611}, /* R offset for white balance ... */
354 {0x0000, 0x8612},
355 {0x0001, 0x8613},
356 {0x0000, 0x8614},
357 {0x005b, 0x8651}, /* R gain for white balance ... */
358 {0x0040, 0x8652},
359 {0x0060, 0x8653},
360 {0x0040, 0x8654},
361 {0x0000, 0x8655},
362 {0x0001, 0x863f}, /* Fixed gamma correction enable, USB control,
363 * lum filter disable, lum noise clip disable */
364 {0x00a1, 0x8656}, /* Window1 size 256x256, Windows2 size 64x64,
365 * gamma look-up disable,
366 * new edge enhancement enable */
367 {0x0018, 0x8657}, /* Edge gain high thresh */
368 {0x0020, 0x8658}, /* Edge gain low thresh */
369 {0x000a, 0x8659}, /* Edge bandwidth high threshold */
370 {0x0005, 0x865a}, /* Edge bandwidth low threshold */
371 /* -------------------------------- */
372 {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */
373 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
374 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
375 {0xa908, 0x8802},
376 {0x0034, 0x8801}, /* SSI reg addr */
377 {0x00ca, 0x8800},
378 /* SSI data to write */
379 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
380 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
381 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
382 {0x1f08, 0x8802},
383 {0x0006, 0x8801},
384 {0x0080, 0x8800},
385 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
386
387/* ----- Read back coefs we wrote earlier. */
388 /* READ { 0x0000, 0x8608 } -> 0000: 15 */
389 /* READ { 0x0000, 0x8609 } -> 0000: 30 */
390 /* READ { 0x0000, 0x860a } -> 0000: fb */
391 /* READ { 0x0000, 0x860b } -> 0000: 3e */
392 /* READ { 0x0000, 0x860c } -> 0000: ce */
393 /* READ { 0x0000, 0x860d } -> 0000: f4 */
394 /* READ { 0x0000, 0x860e } -> 0000: eb */
395 /* READ { 0x0000, 0x860f } -> 0000: dc */
396 /* READ { 0x0000, 0x8610 } -> 0000: 39 */
397 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
398 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
399 {0xb008, 0x8802},
400 {0x0006, 0x8801},
401 {0x007d, 0x8800},
402 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
403
404
405 /* This chunk is seemingly redundant with */
406 /* earlier commands (A11 Coef...), but if I disable it, */
407 /* the image appears too dark. Maybe there was some kind of */
408 /* reset since the earlier commands, so this is necessary again. */
409 {0x0015, 0x8608},
410 {0x0030, 0x8609},
411 {0xfffb, 0x860a},
412 {0x003e, 0x860b},
413 {0xffce, 0x860c},
414 {0xfff4, 0x860d},
415 {0xffeb, 0x860e},
416 {0xffdc, 0x860f},
417 {0x0039, 0x8610},
418 {0x0018, 0x8657},
419
420 {0x0000, 0x8508}, /* Disable compression. */
421 /* Previous line was:
422 {0x0021, 0x8508}, * Enable compression. */
423 {0x0032, 0x850b}, /* compression stuff */
424 {0x0003, 0x8509}, /* compression stuff */
425 {0x0011, 0x850a}, /* compression stuff */
426 {0x0021, 0x850d}, /* compression stuff */
427 {0x0010, 0x850c}, /* compression stuff */
428 {0x0003, 0x8500}, /* *** Video mode: 160x120 */
429 {0x0001, 0x8501}, /* Hardware-dominated snap control */
430 {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128,
431 * gamma look-up disable,
432 * new edge enhancement enable */
433 {0x0018, 0x8617}, /* Window1 start X (*2) */
434 {0x0008, 0x8618}, /* Window1 start Y (*2) */
435 {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128,
436 * gamma look-up disable,
437 * new edge enhancement enable */
438 {0x0058, 0x8619}, /* Window2 start X (*2) */
439 {0x0008, 0x861a}, /* Window2 start Y (*2) */
440 {0x00ff, 0x8615}, /* High lum thresh for white balance */
441 {0x0000, 0x8616}, /* Low lum thresh for white balance */
442 {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
443 {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
444 /* READ { 0x0000, 0x8656 } -> 0000: 61 */
445 {0x0028, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
446 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
447 /* READ { 0x0001, 0x8802 } -> 0000: 28 */
448 {0x1f28, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
449 {0x0010, 0x8801}, /* SSI reg addr */
450 {0x003e, 0x8800}, /* SSI data to write */
451 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
452 {0x0028, 0x8802},
453 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
454 /* READ { 0x0001, 0x8802 } -> 0000: 28 */
455 {0x1f28, 0x8802},
456 {0x0000, 0x8801},
457 {0x001f, 0x8800},
458 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
459 {0x0001, 0x8602}, /* optical black level for user settning = 1 */
460
461 /* Original: */
462 {0x0023, 0x8700}, /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
463 {0x000f, 0x8602}, /* optical black level for user settning = 15 */
464
465 {0x0028, 0x8802},
466 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
467 /* READ { 0x0001, 0x8802 } -> 0000: 28 */
468 {0x1f28, 0x8802},
469 {0x0010, 0x8801},
470 {0x007b, 0x8800},
471 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
472 {0x002f, 0x8651}, /* R gain for white balance ... */
473 {0x0080, 0x8653},
474 /* READ { 0x0000, 0x8655 } -> 0000: 00 */
475 {0x0000, 0x8655},
476
477 {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */
478 {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */
479 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
480 {}
481};
482
483/*
484 * Initialization data for Intel EasyPC Camera CS110
485 */
486static const u16 spca508cs110_init_data[][2] = {
487 {0x0000, 0x870b}, /* Reset CTL3 */
488 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
489 {0x0000, 0x8111}, /* Normal operation on reset */
490 {0x0090, 0x8110},
491 /* External Clock 2x & Synchronous Serial Interface Output */
492 {0x0020, 0x8112}, /* Video Drop packet enable */
493 {0x0000, 0x8114}, /* Software GPIO output data */
494 {0x0001, 0x8114},
495 {0x0001, 0x8114},
496 {0x0001, 0x8114},
497 {0x0003, 0x8114},
498
499 /* Initial sequence Synchronous Serial Interface */
500 {0x000f, 0x8402}, /* Memory bank Address */
501 {0x0000, 0x8403}, /* Memory bank Address */
502 {0x00ba, 0x8804}, /* SSI Slave address */
503 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
504 {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */
505
506 {0x0001, 0x8801},
507 {0x000a, 0x8805}, /* a - NWG: Dunno what this is about */
508 {0x0000, 0x8800},
509 {0x0010, 0x8802},
510
511 {0x0002, 0x8801},
512 {0x0000, 0x8805},
513 {0x0000, 0x8800},
514 {0x0010, 0x8802},
515
516 {0x0003, 0x8801},
517 {0x0027, 0x8805},
518 {0x0001, 0x8800},
519 {0x0010, 0x8802},
520
521 {0x0004, 0x8801},
522 {0x0065, 0x8805},
523 {0x0001, 0x8800},
524 {0x0010, 0x8802},
525
526 {0x0005, 0x8801},
527 {0x0003, 0x8805},
528 {0x0000, 0x8800},
529 {0x0010, 0x8802},
530
531 {0x0006, 0x8801},
532 {0x001c, 0x8805},
533 {0x0000, 0x8800},
534 {0x0010, 0x8802},
535
536 {0x0007, 0x8801},
537 {0x002a, 0x8805},
538 {0x0000, 0x8800},
539 {0x0010, 0x8802},
540
541 {0x0002, 0x8704}, /* External input CKIx1 */
542 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
543 {0x009a, 0x8600}, /* Line memory Read Counter (L) */
544 {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
545 {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */
546 {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */
547
548 {0x0006, 0x8660}, /* Nibble data + input order */
549
550 {0x000a, 0x8602}, /* Optical black level set to 0x0a */
551 {0x0000, 0x8603}, /* Optical black level Offset */
552
553/* {0x0000, 0x8611}, * 0 R Offset for white Balance */
554/* {0x0000, 0x8612}, * 1 Gr Offset for white Balance */
555/* {0x0000, 0x8613}, * 1f B Offset for white Balance */
556/* {0x0000, 0x8614}, * f0 Gb Offset for white Balance */
557
558 {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */
559 {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */
560 {0x0035, 0x8653}, /* 26 RED gain for white balance */
561 {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */
562 {0x0041, 0x863f},
563 /* Fixed Gamma correction enabled (makes colours look better) */
564
565 {0x0000, 0x8655},
566 /* High bits for white balance*****brightness control*** */
567 {}
568};
569
570static const u16 spca508_sightcam_init_data[][2] = {
571/* This line seems to setup the frame/canvas */
572 {0x000f, 0x8402},
573
574/* These 6 lines are needed to startup the webcam */
575 {0x0090, 0x8110},
576 {0x0001, 0x8114},
577 {0x0001, 0x8114},
578 {0x0001, 0x8114},
579 {0x0003, 0x8114},
580 {0x0080, 0x8804},
581
582/* This part seems to make the pictures darker? (autobrightness?) */
583 {0x0001, 0x8801},
584 {0x0004, 0x8800},
585 {0x0003, 0x8801},
586 {0x00e0, 0x8800},
587 {0x0004, 0x8801},
588 {0x00b4, 0x8800},
589 {0x0005, 0x8801},
590 {0x0000, 0x8800},
591
592 {0x0006, 0x8801},
593 {0x00e0, 0x8800},
594 {0x0007, 0x8801},
595 {0x000c, 0x8800},
596
597/* This section is just needed, it probably
598 * does something like the previous section,
599 * but the cam won't start if it's not included.
600 */
601 {0x0014, 0x8801},
602 {0x0008, 0x8800},
603 {0x0015, 0x8801},
604 {0x0067, 0x8800},
605 {0x0016, 0x8801},
606 {0x0000, 0x8800},
607 {0x0017, 0x8801},
608 {0x0020, 0x8800},
609 {0x0018, 0x8801},
610 {0x0044, 0x8800},
611
612/* Makes the picture darker - and the
613 * cam won't start if not included
614 */
615 {0x001e, 0x8801},
616 {0x00ea, 0x8800},
617 {0x001f, 0x8801},
618 {0x0001, 0x8800},
619 {0x0003, 0x8801},
620 {0x00e0, 0x8800},
621
622/* seems to place the colors ontop of each other #1 */
623 {0x0006, 0x8704},
624 {0x0001, 0x870c},
625 {0x0016, 0x8600},
626 {0x0002, 0x8606},
627
628/* if not included the pictures becomes _very_ dark */
629 {0x0064, 0x8607},
630 {0x003a, 0x8601},
631 {0x0000, 0x8602},
632
633/* seems to place the colors ontop of each other #2 */
634 {0x0016, 0x8600},
635 {0x0018, 0x8617},
636 {0x0008, 0x8618},
637 {0x00a1, 0x8656},
638
639/* webcam won't start if not included */
640 {0x0007, 0x865b},
641 {0x0001, 0x865c},
642 {0x0058, 0x865d},
643 {0x0048, 0x865e},
644
645/* adjusts the colors */
646 {0x0049, 0x8651},
647 {0x0040, 0x8652},
648 {0x004c, 0x8653},
649 {0x0040, 0x8654},
650 {}
651};
652
653static const u16 spca508_sightcam2_init_data[][2] = {
654 {0x0020, 0x8112},
655
656 {0x000f, 0x8402},
657 {0x0000, 0x8403},
658
659 {0x0008, 0x8201},
660 {0x0008, 0x8200},
661 {0x0001, 0x8200},
662 {0x0009, 0x8201},
663 {0x0008, 0x8200},
664 {0x0001, 0x8200},
665 {0x000a, 0x8201},
666 {0x0008, 0x8200},
667 {0x0001, 0x8200},
668 {0x000b, 0x8201},
669 {0x0008, 0x8200},
670 {0x0001, 0x8200},
671 {0x000c, 0x8201},
672 {0x0008, 0x8200},
673 {0x0001, 0x8200},
674 {0x000d, 0x8201},
675 {0x0008, 0x8200},
676 {0x0001, 0x8200},
677 {0x000e, 0x8201},
678 {0x0008, 0x8200},
679 {0x0001, 0x8200},
680 {0x0007, 0x8201},
681 {0x0008, 0x8200},
682 {0x0001, 0x8200},
683 {0x000f, 0x8201},
684 {0x0008, 0x8200},
685 {0x0001, 0x8200},
686
687 {0x0018, 0x8660},
688 {0x0010, 0x8201},
689
690 {0x0008, 0x8200},
691 {0x0001, 0x8200},
692 {0x0011, 0x8201},
693 {0x0008, 0x8200},
694 {0x0001, 0x8200},
695
696 {0x0000, 0x86b0},
697 {0x0034, 0x86b1},
698 {0x0000, 0x86b2},
699 {0x0049, 0x86b3},
700 {0x0000, 0x86b4},
701 {0x0000, 0x86b4},
702
703 {0x0012, 0x8201},
704 {0x0008, 0x8200},
705 {0x0001, 0x8200},
706 {0x0013, 0x8201},
707 {0x0008, 0x8200},
708 {0x0001, 0x8200},
709
710 {0x0001, 0x86b0},
711 {0x00aa, 0x86b1},
712 {0x0000, 0x86b2},
713 {0x00e4, 0x86b3},
714 {0x0000, 0x86b4},
715 {0x0000, 0x86b4},
716
717 {0x0018, 0x8660},
718
719 {0x0090, 0x8110},
720 {0x0001, 0x8114},
721 {0x0001, 0x8114},
722 {0x0001, 0x8114},
723 {0x0003, 0x8114},
724
725 {0x0080, 0x8804},
726 {0x0003, 0x8801},
727 {0x0012, 0x8800},
728 {0x0004, 0x8801},
729 {0x0005, 0x8800},
730 {0x0005, 0x8801},
731 {0x0000, 0x8800},
732 {0x0006, 0x8801},
733 {0x0000, 0x8800},
734 {0x0007, 0x8801},
735 {0x0000, 0x8800},
736 {0x0008, 0x8801},
737 {0x0005, 0x8800},
738 {0x000a, 0x8700},
739 {0x000e, 0x8801},
740 {0x0004, 0x8800},
741 {0x0005, 0x8801},
742 {0x0047, 0x8800},
743 {0x0006, 0x8801},
744 {0x0000, 0x8800},
745 {0x0007, 0x8801},
746 {0x00c0, 0x8800},
747 {0x0008, 0x8801},
748 {0x0003, 0x8800},
749 {0x0013, 0x8801},
750 {0x0001, 0x8800},
751 {0x0009, 0x8801},
752 {0x0000, 0x8800},
753 {0x000a, 0x8801},
754 {0x0000, 0x8800},
755 {0x000b, 0x8801},
756 {0x0000, 0x8800},
757 {0x000c, 0x8801},
758 {0x0000, 0x8800},
759 {0x000e, 0x8801},
760 {0x0004, 0x8800},
761 {0x000f, 0x8801},
762 {0x0000, 0x8800},
763 {0x0010, 0x8801},
764 {0x0006, 0x8800},
765 {0x0011, 0x8801},
766 {0x0006, 0x8800},
767 {0x0012, 0x8801},
768 {0x0000, 0x8800},
769 {0x0013, 0x8801},
770 {0x0001, 0x8800},
771
772 {0x000a, 0x8700},
773 {0x0000, 0x8702},
774 {0x0000, 0x8703},
775 {0x00c2, 0x8704},
776 {0x0001, 0x870c},
777
778 {0x0044, 0x8600},
779 {0x0002, 0x8606},
780 {0x0064, 0x8607},
781 {0x003a, 0x8601},
782 {0x0008, 0x8602},
783 {0x0044, 0x8600},
784 {0x0018, 0x8617},
785 {0x0008, 0x8618},
786 {0x00a1, 0x8656},
787 {0x0004, 0x865b},
788 {0x0002, 0x865c},
789 {0x0058, 0x865d},
790 {0x0048, 0x865e},
791 {0x0012, 0x8608},
792 {0x002c, 0x8609},
793 {0x0002, 0x860a},
794 {0x002c, 0x860b},
795 {0x00db, 0x860c},
796 {0x00f9, 0x860d},
797 {0x00f1, 0x860e},
798 {0x00e3, 0x860f},
799 {0x002c, 0x8610},
800 {0x006c, 0x8651},
801 {0x0041, 0x8652},
802 {0x0059, 0x8653},
803 {0x0040, 0x8654},
804 {0x00fa, 0x8611},
805 {0x00ff, 0x8612},
806 {0x00f8, 0x8613},
807 {0x0000, 0x8614},
808 {0x0001, 0x863f},
809 {0x0000, 0x8640},
810 {0x0026, 0x8641},
811 {0x0045, 0x8642},
812 {0x0060, 0x8643},
813 {0x0075, 0x8644},
814 {0x0088, 0x8645},
815 {0x009b, 0x8646},
816 {0x00b0, 0x8647},
817 {0x00c5, 0x8648},
818 {0x00d2, 0x8649},
819 {0x00dc, 0x864a},
820 {0x00e5, 0x864b},
821 {0x00eb, 0x864c},
822 {0x00f0, 0x864d},
823 {0x00f6, 0x864e},
824 {0x00fa, 0x864f},
825 {0x00ff, 0x8650},
826 {0x0060, 0x8657},
827 {0x0010, 0x8658},
828 {0x0018, 0x8659},
829 {0x0005, 0x865a},
830 {0x0018, 0x8660},
831 {0x0003, 0x8509},
832 {0x0011, 0x850a},
833 {0x0032, 0x850b},
834 {0x0010, 0x850c},
835 {0x0021, 0x850d},
836 {0x0001, 0x8500},
837 {0x0000, 0x8508},
838 {0x0012, 0x8608},
839 {0x002c, 0x8609},
840 {0x0002, 0x860a},
841 {0x0039, 0x860b},
842 {0x00d0, 0x860c},
843 {0x00f7, 0x860d},
844 {0x00ed, 0x860e},
845 {0x00db, 0x860f},
846 {0x0039, 0x8610},
847 {0x0012, 0x8657},
848 {0x000c, 0x8619},
849 {0x0004, 0x861a},
850 {0x00a1, 0x8656},
851 {0x00c8, 0x8615},
852 {0x0032, 0x8616},
853
854 {0x0030, 0x8112},
855 {0x0020, 0x8112},
856 {0x0020, 0x8112},
857 {0x000f, 0x8402},
858 {0x0000, 0x8403},
859
860 {0x0090, 0x8110},
861 {0x0001, 0x8114},
862 {0x0001, 0x8114},
863 {0x0001, 0x8114},
864 {0x0003, 0x8114},
865 {0x0080, 0x8804},
866
867 {0x0003, 0x8801},
868 {0x0012, 0x8800},
869 {0x0004, 0x8801},
870 {0x0005, 0x8800},
871 {0x0005, 0x8801},
872 {0x0047, 0x8800},
873 {0x0006, 0x8801},
874 {0x0000, 0x8800},
875 {0x0007, 0x8801},
876 {0x00c0, 0x8800},
877 {0x0008, 0x8801},
878 {0x0003, 0x8800},
879 {0x000a, 0x8700},
880 {0x000e, 0x8801},
881 {0x0004, 0x8800},
882 {0x0005, 0x8801},
883 {0x0047, 0x8800},
884 {0x0006, 0x8801},
885 {0x0000, 0x8800},
886 {0x0007, 0x8801},
887 {0x00c0, 0x8800},
888 {0x0008, 0x8801},
889 {0x0003, 0x8800},
890 {0x0013, 0x8801},
891 {0x0001, 0x8800},
892 {0x0009, 0x8801},
893 {0x0000, 0x8800},
894 {0x000a, 0x8801},
895 {0x0000, 0x8800},
896 {0x000b, 0x8801},
897 {0x0000, 0x8800},
898 {0x000c, 0x8801},
899 {0x0000, 0x8800},
900 {0x000e, 0x8801},
901 {0x0004, 0x8800},
902 {0x000f, 0x8801},
903 {0x0000, 0x8800},
904 {0x0010, 0x8801},
905 {0x0006, 0x8800},
906 {0x0011, 0x8801},
907 {0x0006, 0x8800},
908 {0x0012, 0x8801},
909 {0x0000, 0x8800},
910 {0x0013, 0x8801},
911 {0x0001, 0x8800},
912 {0x000a, 0x8700},
913 {0x0000, 0x8702},
914 {0x0000, 0x8703},
915 {0x00c2, 0x8704},
916 {0x0001, 0x870c},
917 {0x0044, 0x8600},
918 {0x0002, 0x8606},
919 {0x0064, 0x8607},
920 {0x003a, 0x8601},
921 {0x0008, 0x8602},
922 {0x0044, 0x8600},
923 {0x0018, 0x8617},
924 {0x0008, 0x8618},
925 {0x00a1, 0x8656},
926 {0x0004, 0x865b},
927 {0x0002, 0x865c},
928 {0x0058, 0x865d},
929 {0x0048, 0x865e},
930 {0x0012, 0x8608},
931 {0x002c, 0x8609},
932 {0x0002, 0x860a},
933 {0x002c, 0x860b},
934 {0x00db, 0x860c},
935 {0x00f9, 0x860d},
936 {0x00f1, 0x860e},
937 {0x00e3, 0x860f},
938 {0x002c, 0x8610},
939 {0x006c, 0x8651},
940 {0x0041, 0x8652},
941 {0x0059, 0x8653},
942 {0x0040, 0x8654},
943 {0x00fa, 0x8611},
944 {0x00ff, 0x8612},
945 {0x00f8, 0x8613},
946 {0x0000, 0x8614},
947 {0x0001, 0x863f},
948 {0x0000, 0x8640},
949 {0x0026, 0x8641},
950 {0x0045, 0x8642},
951 {0x0060, 0x8643},
952 {0x0075, 0x8644},
953 {0x0088, 0x8645},
954 {0x009b, 0x8646},
955 {0x00b0, 0x8647},
956 {0x00c5, 0x8648},
957 {0x00d2, 0x8649},
958 {0x00dc, 0x864a},
959 {0x00e5, 0x864b},
960 {0x00eb, 0x864c},
961 {0x00f0, 0x864d},
962 {0x00f6, 0x864e},
963 {0x00fa, 0x864f},
964 {0x00ff, 0x8650},
965 {0x0060, 0x8657},
966 {0x0010, 0x8658},
967 {0x0018, 0x8659},
968 {0x0005, 0x865a},
969 {0x0018, 0x8660},
970 {0x0003, 0x8509},
971 {0x0011, 0x850a},
972 {0x0032, 0x850b},
973 {0x0010, 0x850c},
974 {0x0021, 0x850d},
975 {0x0001, 0x8500},
976 {0x0000, 0x8508},
977
978 {0x0012, 0x8608},
979 {0x002c, 0x8609},
980 {0x0002, 0x860a},
981 {0x0039, 0x860b},
982 {0x00d0, 0x860c},
983 {0x00f7, 0x860d},
984 {0x00ed, 0x860e},
985 {0x00db, 0x860f},
986 {0x0039, 0x8610},
987 {0x0012, 0x8657},
988 {0x0064, 0x8619},
989
990/* This line starts it all, it is not needed here */
991/* since it has been build into the driver */
992/* jfm: don't start now */
993/* {0x0030, 0x8112}, */
994 {}
995};
996
997/*
998 * Initialization data for Creative Webcam Vista
999 */
1000static const u16 spca508_vista_init_data[][2] = {
1001 {0x0008, 0x8200}, /* Clear register */
1002 {0x0000, 0x870b}, /* Reset CTL3 */
1003 {0x0020, 0x8112}, /* Video Drop packet enable */
1004 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
1005 {0x0000, 0x8110}, /* Disable everything */
1006 {0x0000, 0x8114}, /* Software GPIO output data */
1007 {0x0000, 0x8114},
1008
1009 {0x0003, 0x8111},
1010 {0x0000, 0x8111},
1011 {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */
1012 {0x0020, 0x8112},
1013 {0x0000, 0x8114},
1014 {0x0001, 0x8114},
1015 {0x0001, 0x8114},
1016 {0x0001, 0x8114},
1017 {0x0003, 0x8114},
1018
1019 {0x000f, 0x8402}, /* Memory bank Address */
1020 {0x0000, 0x8403}, /* Memory bank Address */
1021 {0x00ba, 0x8804}, /* SSI Slave address */
1022 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
1023
1024 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1025 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1026 {0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */
1027 {0x0020, 0x8801}, /* Register address for SSI read/write */
1028 {0x0044, 0x8805}, /* DATA2 */
1029 {0x0004, 0x8800}, /* DATA1 -> write triggered */
1030 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1031
1032 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1033 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1034 {0x0010, 0x8802},
1035 {0x0009, 0x8801},
1036 {0x0042, 0x8805},
1037 {0x0001, 0x8800},
1038 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1039
1040 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1041 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1042 {0x0010, 0x8802},
1043 {0x003c, 0x8801},
1044 {0x0001, 0x8805},
1045 {0x0000, 0x8800},
1046 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1047
1048 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1049 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1050 {0x0010, 0x8802},
1051 {0x0001, 0x8801},
1052 {0x000a, 0x8805},
1053 {0x0000, 0x8800},
1054 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1055
1056 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1057 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1058 {0x0010, 0x8802},
1059 {0x0002, 0x8801},
1060 {0x0000, 0x8805},
1061 {0x0000, 0x8800},
1062 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1063
1064 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1065 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1066 {0x0010, 0x8802},
1067 {0x0003, 0x8801},
1068 {0x0027, 0x8805},
1069 {0x0001, 0x8800},
1070 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1071
1072 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1073 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1074 {0x0010, 0x8802},
1075 {0x0004, 0x8801},
1076 {0x0065, 0x8805},
1077 {0x0001, 0x8800},
1078 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1079
1080 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1081 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1082 {0x0010, 0x8802},
1083 {0x0005, 0x8801},
1084 {0x0003, 0x8805},
1085 {0x0000, 0x8800},
1086 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1087
1088 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1089 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1090 {0x0010, 0x8802},
1091 {0x0006, 0x8801},
1092 {0x001c, 0x8805},
1093 {0x0000, 0x8800},
1094 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1095
1096 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1097 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1098 {0x0010, 0x8802},
1099 {0x0007, 0x8801},
1100 {0x002a, 0x8805},
1101 {0x0000, 0x8800},
1102 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1103
1104 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1105 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1106 {0x0010, 0x8802},
1107 {0x000e, 0x8801},
1108 {0x0000, 0x8805},
1109 {0x0000, 0x8800},
1110 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1111
1112 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1113 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1114 {0x0010, 0x8802},
1115 {0x0028, 0x8801},
1116 {0x002e, 0x8805},
1117 {0x0000, 0x8800},
1118 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1119
1120 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1121 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1122 {0x0010, 0x8802},
1123 {0x0039, 0x8801},
1124 {0x0013, 0x8805},
1125 {0x0000, 0x8800},
1126 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1127
1128 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1129 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1130 {0x0010, 0x8802},
1131 {0x003b, 0x8801},
1132 {0x000c, 0x8805},
1133 {0x0000, 0x8800},
1134 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1135
1136 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1137 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1138 {0x0010, 0x8802},
1139 {0x0035, 0x8801},
1140 {0x0028, 0x8805},
1141 {0x0000, 0x8800},
1142 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1143
1144 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1145 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1146 {0x0010, 0x8802},
1147 {0x0009, 0x8801},
1148 {0x0042, 0x8805},
1149 {0x0001, 0x8800},
1150 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1151
1152 {0x0050, 0x8703},
1153 {0x0002, 0x8704}, /* External input CKIx1 */
1154 {0x0001, 0x870c}, /* Select CKOx2 output */
1155 {0x009a, 0x8600}, /* Line memory Read Counter (L) */
1156 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
1157 {0x0023, 0x8601},
1158 {0x0010, 0x8602},
1159 {0x000a, 0x8603},
1160 {0x009a, 0x8600},
1161 {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
1162 {0x0003, 0x865c}, /* Vertical offset for valid lines (L) */
1163 {0x0058, 0x865d}, /* Horizontal valid pixels window (L) */
1164 {0x0048, 0x865e}, /* Vertical valid lines window (L) */
1165 {0x0000, 0x865f},
1166
1167 {0x0006, 0x8660},
1168 /* Enable nibble data input, select nibble input order */
1169
1170 {0x0013, 0x8608}, /* A11 Coeficients for color correction */
1171 {0x0028, 0x8609},
1172 /* Note: these values are confirmed at the end of array */
1173 {0x0005, 0x860a}, /* ... */
1174 {0x0025, 0x860b},
1175 {0x00e1, 0x860c},
1176 {0x00fa, 0x860d},
1177 {0x00f4, 0x860e},
1178 {0x00e8, 0x860f},
1179 {0x0025, 0x8610}, /* A33 Coef. */
1180 {0x00fc, 0x8611}, /* White balance offset: R */
1181 {0x0001, 0x8612}, /* White balance offset: Gr */
1182 {0x00fe, 0x8613}, /* White balance offset: B */
1183 {0x0000, 0x8614}, /* White balance offset: Gb */
1184
1185 {0x0064, 0x8651}, /* R gain for white balance (L) */
1186 {0x0040, 0x8652}, /* Gr gain for white balance (L) */
1187 {0x0066, 0x8653}, /* B gain for white balance (L) */
1188 {0x0040, 0x8654}, /* Gb gain for white balance (L) */
1189 {0x0001, 0x863f}, /* Enable fixed gamma correction */
1190
1191 {0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128,
1192 * UV division: UV no change,
1193 * Enable New edge enhancement */
1194 {0x0018, 0x8657}, /* Edge gain high threshold */
1195 {0x0020, 0x8658}, /* Edge gain low threshold */
1196 {0x000a, 0x8659}, /* Edge bandwidth high threshold */
1197 {0x0005, 0x865a}, /* Edge bandwidth low threshold */
1198 {0x0064, 0x8607}, /* UV filter enable */
1199
1200 {0x0016, 0x8660},
1201 {0x0000, 0x86b0}, /* Bad pixels compensation address */
1202 {0x00dc, 0x86b1}, /* X coord for bad pixels compensation (L) */
1203 {0x0000, 0x86b2},
1204 {0x0009, 0x86b3}, /* Y coord for bad pixels compensation (L) */
1205 {0x0000, 0x86b4},
1206
1207 {0x0001, 0x86b0},
1208 {0x00f5, 0x86b1},
1209 {0x0000, 0x86b2},
1210 {0x00c6, 0x86b3},
1211 {0x0000, 0x86b4},
1212
1213 {0x0002, 0x86b0},
1214 {0x001c, 0x86b1},
1215 {0x0001, 0x86b2},
1216 {0x00d7, 0x86b3},
1217 {0x0000, 0x86b4},
1218
1219 {0x0003, 0x86b0},
1220 {0x001c, 0x86b1},
1221 {0x0001, 0x86b2},
1222 {0x00d8, 0x86b3},
1223 {0x0000, 0x86b4},
1224
1225 {0x0004, 0x86b0},
1226 {0x001d, 0x86b1},
1227 {0x0001, 0x86b2},
1228 {0x00d8, 0x86b3},
1229 {0x0000, 0x86b4},
1230 {0x001e, 0x8660},
1231
1232 /* READ { 0x0000, 0x8608 } -> 0000: 13 */
1233 /* READ { 0x0000, 0x8609 } -> 0000: 28 */
1234 /* READ { 0x0000, 0x8610 } -> 0000: 05 */
1235 /* READ { 0x0000, 0x8611 } -> 0000: 25 */
1236 /* READ { 0x0000, 0x8612 } -> 0000: e1 */
1237 /* READ { 0x0000, 0x8613 } -> 0000: fa */
1238 /* READ { 0x0000, 0x8614 } -> 0000: f4 */
1239 /* READ { 0x0000, 0x8615 } -> 0000: e8 */
1240 /* READ { 0x0000, 0x8616 } -> 0000: 25 */
1241 {}
1242};
1243
1244static int reg_write(struct usb_device *dev,
1245 u16 index, u16 value)
1246{
1247 int ret;
1248
1249 ret = usb_control_msg(dev,
1250 usb_sndctrlpipe(dev, 0),
1251 0, /* request */
1252 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1253 value, index, NULL, 0, 500);
1254 PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
1255 index, value);
1256 if (ret < 0)
1257 pr_err("reg write: error %d\n", ret);
1258 return ret;
1259}
1260
1261/* read 1 byte */
1262/* returns: negative is error, pos or zero is data */
1263static int reg_read(struct gspca_dev *gspca_dev,
1264 u16 index) /* wIndex */
1265{
1266 int ret;
1267
1268 ret = usb_control_msg(gspca_dev->dev,
1269 usb_rcvctrlpipe(gspca_dev->dev, 0),
1270 0, /* register */
1271 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1272 0, /* value */
1273 index,
1274 gspca_dev->usb_buf, 1,
1275 500); /* timeout */
1276 PDEBUG(D_USBI, "reg read i:%04x --> %02x",
1277 index, gspca_dev->usb_buf[0]);
1278 if (ret < 0) {
1279 pr_err("reg_read err %d\n", ret);
1280 return ret;
1281 }
1282 return gspca_dev->usb_buf[0];
1283}
1284
1285/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
1286static int ssi_w(struct gspca_dev *gspca_dev,
1287 u16 reg, u16 val)
1288{
1289 struct usb_device *dev = gspca_dev->dev;
1290 int ret, retry;
1291
1292 ret = reg_write(dev, 0x8802, reg >> 8);
1293 if (ret < 0)
1294 goto out;
1295 ret = reg_write(dev, 0x8801, reg & 0x00ff);
1296 if (ret < 0)
1297 goto out;
1298 if ((reg & 0xff00) == 0x1000) { /* if 2 bytes */
1299 ret = reg_write(dev, 0x8805, val & 0x00ff);
1300 if (ret < 0)
1301 goto out;
1302 val >>= 8;
1303 }
1304 ret = reg_write(dev, 0x8800, val);
1305 if (ret < 0)
1306 goto out;
1307
1308 /* poll until not busy */
1309 retry = 10;
1310 for (;;) {
1311 ret = reg_read(gspca_dev, 0x8803);
1312 if (ret < 0)
1313 break;
1314 if (gspca_dev->usb_buf[0] == 0)
1315 break;
1316 if (--retry <= 0) {
1317 PDEBUG(D_ERR, "ssi_w busy %02x",
1318 gspca_dev->usb_buf[0]);
1319 ret = -1;
1320 break;
1321 }
1322 msleep(8);
1323 }
1324
1325out:
1326 return ret;
1327}
1328
1329static int write_vector(struct gspca_dev *gspca_dev,
1330 const u16 (*data)[2])
1331{
1332 struct usb_device *dev = gspca_dev->dev;
1333 int ret = 0;
1334
1335 while ((*data)[1] != 0) {
1336 if ((*data)[1] & 0x8000) {
1337 if ((*data)[1] == 0xdd00) /* delay */
1338 msleep((*data)[0]);
1339 else
1340 ret = reg_write(dev, (*data)[1], (*data)[0]);
1341 } else {
1342 ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
1343 }
1344 if (ret < 0)
1345 break;
1346 data++;
1347 }
1348 return ret;
1349}
1350
1351/* this function is called at probe time */
1352static int sd_config(struct gspca_dev *gspca_dev,
1353 const struct usb_device_id *id)
1354{
1355 struct sd *sd = (struct sd *) gspca_dev;
1356 struct cam *cam;
1357 const u16 (*init_data)[2];
1358 static const u16 (*(init_data_tb[]))[2] = {
1359 spca508_vista_init_data, /* CreativeVista 0 */
1360 spca508_sightcam_init_data, /* HamaUSBSightcam 1 */
1361 spca508_sightcam2_init_data, /* HamaUSBSightcam2 2 */
1362 spca508cs110_init_data, /* IntelEasyPCCamera 3 */
1363 spca508cs110_init_data, /* MicroInnovationIC200 4 */
1364 spca508_init_data, /* ViewQuestVQ110 5 */
1365 };
1366
1367#ifdef GSPCA_DEBUG
1368 int data1, data2;
1369
1370 /* Read from global register the USB product and vendor IDs, just to
1371 * prove that we can communicate with the device. This works, which
1372 * confirms at we are communicating properly and that the device
1373 * is a 508. */
1374 data1 = reg_read(gspca_dev, 0x8104);
1375 data2 = reg_read(gspca_dev, 0x8105);
1376 PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1377
1378 data1 = reg_read(gspca_dev, 0x8106);
1379 data2 = reg_read(gspca_dev, 0x8107);
1380 PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1381
1382 data1 = reg_read(gspca_dev, 0x8621);
1383 PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1384#endif
1385
1386 cam = &gspca_dev->cam;
1387 cam->cam_mode = sif_mode;
1388 cam->nmodes = ARRAY_SIZE(sif_mode);
1389
1390 sd->subtype = id->driver_info;
1391
1392 init_data = init_data_tb[sd->subtype];
1393 return write_vector(gspca_dev, init_data);
1394}
1395
1396/* this function is called at probe and resume time */
1397static int sd_init(struct gspca_dev *gspca_dev)
1398{
1399 return 0;
1400}
1401
1402static int sd_start(struct gspca_dev *gspca_dev)
1403{
1404 int mode;
1405
1406 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1407 reg_write(gspca_dev->dev, 0x8500, mode);
1408 switch (mode) {
1409 case 0:
1410 case 1:
1411 reg_write(gspca_dev->dev, 0x8700, 0x28); /* clock */
1412 break;
1413 default:
1414/* case 2: */
1415/* case 3: */
1416 reg_write(gspca_dev->dev, 0x8700, 0x23); /* clock */
1417 break;
1418 }
1419 reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
1420 return 0;
1421}
1422
1423static void sd_stopN(struct gspca_dev *gspca_dev)
1424{
1425 /* Video ISO disable, Video Drop Packet enable: */
1426 reg_write(gspca_dev->dev, 0x8112, 0x20);
1427}
1428
1429static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1430 u8 *data, /* isoc packet */
1431 int len) /* iso packet length */
1432{
1433 switch (data[0]) {
1434 case 0: /* start of frame */
1435 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1436 data += SPCA508_OFFSET_DATA;
1437 len -= SPCA508_OFFSET_DATA;
1438 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1439 break;
1440 case 0xff: /* drop */
1441 break;
1442 default:
1443 data += 1;
1444 len -= 1;
1445 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1446 break;
1447 }
1448}
1449
1450static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
1451{
1452 /* MX seem contrast */
1453 reg_write(gspca_dev->dev, 0x8651, brightness);
1454 reg_write(gspca_dev->dev, 0x8652, brightness);
1455 reg_write(gspca_dev->dev, 0x8653, brightness);
1456 reg_write(gspca_dev->dev, 0x8654, brightness);
1457}
1458
1459static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1460{
1461 struct gspca_dev *gspca_dev =
1462 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1463
1464 gspca_dev->usb_err = 0;
1465
1466 if (!gspca_dev->streaming)
1467 return 0;
1468
1469 switch (ctrl->id) {
1470 case V4L2_CID_BRIGHTNESS:
1471 setbrightness(gspca_dev, ctrl->val);
1472 break;
1473 }
1474 return gspca_dev->usb_err;
1475}
1476
1477static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1478 .s_ctrl = sd_s_ctrl,
1479};
1480
1481static int sd_init_controls(struct gspca_dev *gspca_dev)
1482{
1483 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1484
1485 gspca_dev->vdev.ctrl_handler = hdl;
1486 v4l2_ctrl_handler_init(hdl, 5);
1487 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1488 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1489
1490 if (hdl->error) {
1491 pr_err("Could not initialize controls\n");
1492 return hdl->error;
1493 }
1494 return 0;
1495}
1496
1497/* sub-driver description */
1498static const struct sd_desc sd_desc = {
1499 .name = MODULE_NAME,
1500 .config = sd_config,
1501 .init = sd_init,
1502 .init_controls = sd_init_controls,
1503 .start = sd_start,
1504 .stopN = sd_stopN,
1505 .pkt_scan = sd_pkt_scan,
1506};
1507
1508/* -- module initialisation -- */
1509static const struct usb_device_id device_table[] = {
1510 {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
1511 {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
1512 {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
1513 {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
1514 {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
1515 {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
1516 {}
1517};
1518MODULE_DEVICE_TABLE(usb, device_table);
1519
1520/* -- device connect -- */
1521static int sd_probe(struct usb_interface *intf,
1522 const struct usb_device_id *id)
1523{
1524 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1525 THIS_MODULE);
1526}
1527
1528static struct usb_driver sd_driver = {
1529 .name = MODULE_NAME,
1530 .id_table = device_table,
1531 .probe = sd_probe,
1532 .disconnect = gspca_disconnect,
1533#ifdef CONFIG_PM
1534 .suspend = gspca_suspend,
1535 .resume = gspca_resume,
1536 .reset_resume = gspca_resume,
1537#endif
1538};
1539
1540module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca561.c b/drivers/media/usb/gspca/spca561.c
new file mode 100644
index 00000000000..cfe71dd6747
--- /dev/null
+++ b/drivers/media/usb/gspca/spca561.c
@@ -0,0 +1,936 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#define MODULE_NAME "spca561"
26
27#include <linux/input.h>
28#include "gspca.h"
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34#define EXPOSURE_MAX (2047 + 325)
35
36/* specific webcam descriptor */
37struct sd {
38 struct gspca_dev gspca_dev; /* !! must be the first item */
39
40 struct { /* hue/contrast control cluster */
41 struct v4l2_ctrl *contrast;
42 struct v4l2_ctrl *hue;
43 };
44 struct v4l2_ctrl *autogain;
45
46#define EXPO12A_DEF 3
47 __u8 expo12a; /* expo/gain? for rev 12a */
48
49 __u8 chip_revision;
50#define Rev012A 0
51#define Rev072A 1
52
53 signed char ag_cnt;
54#define AG_CNT_START 13
55};
56
57static const struct v4l2_pix_format sif_012a_mode[] = {
58 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
59 .bytesperline = 160,
60 .sizeimage = 160 * 120,
61 .colorspace = V4L2_COLORSPACE_SRGB,
62 .priv = 3},
63 {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
64 .bytesperline = 176,
65 .sizeimage = 176 * 144,
66 .colorspace = V4L2_COLORSPACE_SRGB,
67 .priv = 2},
68 {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
69 .bytesperline = 320,
70 .sizeimage = 320 * 240 * 4 / 8,
71 .colorspace = V4L2_COLORSPACE_SRGB,
72 .priv = 1},
73 {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
74 .bytesperline = 352,
75 .sizeimage = 352 * 288 * 4 / 8,
76 .colorspace = V4L2_COLORSPACE_SRGB,
77 .priv = 0},
78};
79
80static const struct v4l2_pix_format sif_072a_mode[] = {
81 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
82 .bytesperline = 160,
83 .sizeimage = 160 * 120,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 3},
86 {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
87 .bytesperline = 176,
88 .sizeimage = 176 * 144,
89 .colorspace = V4L2_COLORSPACE_SRGB,
90 .priv = 2},
91 {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
92 .bytesperline = 320,
93 .sizeimage = 320 * 240,
94 .colorspace = V4L2_COLORSPACE_SRGB,
95 .priv = 1},
96 {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
97 .bytesperline = 352,
98 .sizeimage = 352 * 288,
99 .colorspace = V4L2_COLORSPACE_SRGB,
100 .priv = 0},
101};
102
103/*
104 * Initialization data
105 * I'm not very sure how to split initialization from open data
106 * chunks. For now, we'll consider everything as initialization
107 */
108/* Frame packet header offsets for the spca561 */
109#define SPCA561_OFFSET_SNAP 1
110#define SPCA561_OFFSET_TYPE 2
111#define SPCA561_OFFSET_COMPRESS 3
112#define SPCA561_OFFSET_FRAMSEQ 4
113#define SPCA561_OFFSET_GPIO 5
114#define SPCA561_OFFSET_USBBUFF 6
115#define SPCA561_OFFSET_WIN2GRAVE 7
116#define SPCA561_OFFSET_WIN2RAVE 8
117#define SPCA561_OFFSET_WIN2BAVE 9
118#define SPCA561_OFFSET_WIN2GBAVE 10
119#define SPCA561_OFFSET_WIN1GRAVE 11
120#define SPCA561_OFFSET_WIN1RAVE 12
121#define SPCA561_OFFSET_WIN1BAVE 13
122#define SPCA561_OFFSET_WIN1GBAVE 14
123#define SPCA561_OFFSET_FREQ 15
124#define SPCA561_OFFSET_VSYNC 16
125#define SPCA561_INDEX_I2C_BASE 0x8800
126#define SPCA561_SNAPBIT 0x20
127#define SPCA561_SNAPCTRL 0x40
128
129static const u16 rev72a_reset[][2] = {
130 {0x0000, 0x8114}, /* Software GPIO output data */
131 {0x0001, 0x8114}, /* Software GPIO output data */
132 {0x0000, 0x8112}, /* Some kind of reset */
133 {}
134};
135static const __u16 rev72a_init_data1[][2] = {
136 {0x0003, 0x8701}, /* PCLK clock delay adjustment */
137 {0x0001, 0x8703}, /* HSYNC from cmos inverted */
138 {0x0011, 0x8118}, /* Enable and conf sensor */
139 {0x0001, 0x8118}, /* Conf sensor */
140 {0x0092, 0x8804}, /* I know nothing about these */
141 {0x0010, 0x8802}, /* 0x88xx registers, so I won't */
142 {}
143};
144static const u16 rev72a_init_sensor1[][2] = {
145 {0x0001, 0x000d},
146 {0x0002, 0x0018},
147 {0x0004, 0x0165},
148 {0x0005, 0x0021},
149 {0x0007, 0x00aa},
150 {0x0020, 0x1504},
151 {0x0039, 0x0002},
152 {0x0035, 0x0010},
153 {0x0009, 0x1049},
154 {0x0028, 0x000b},
155 {0x003b, 0x000f},
156 {0x003c, 0x0000},
157 {}
158};
159static const __u16 rev72a_init_data2[][2] = {
160 {0x0018, 0x8601}, /* Pixel/line selection for color separation */
161 {0x0000, 0x8602}, /* Optical black level for user setting */
162 {0x0060, 0x8604}, /* Optical black horizontal offset */
163 {0x0002, 0x8605}, /* Optical black vertical offset */
164 {0x0000, 0x8603}, /* Non-automatic optical black level */
165 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
166 {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */
167 {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */
168 {0x0090, 0x865e}, /* Vertical valid lines window (x2) */
169 {0x00e0, 0x8406}, /* Memory buffer threshold */
170 {0x0000, 0x8660}, /* Compensation memory stuff */
171 {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */
172 {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
173 {0x0001, 0x8200}, /* OprMode to be executed by hardware */
174/* from ms-win */
175 {0x0000, 0x8611}, /* R offset for white balance */
176 {0x00fd, 0x8612}, /* Gr offset for white balance */
177 {0x0003, 0x8613}, /* B offset for white balance */
178 {0x0000, 0x8614}, /* Gb offset for white balance */
179/* from ms-win */
180 {0x0035, 0x8651}, /* R gain for white balance */
181 {0x0040, 0x8652}, /* Gr gain for white balance */
182 {0x005f, 0x8653}, /* B gain for white balance */
183 {0x0040, 0x8654}, /* Gb gain for white balance */
184 {0x0002, 0x8502}, /* Maximum average bit rate stuff */
185 {0x0011, 0x8802},
186
187 {0x0087, 0x8700}, /* Set master clock (96Mhz????) */
188 {0x0081, 0x8702}, /* Master clock output enable */
189
190 {0x0000, 0x8500}, /* Set image type (352x288 no compression) */
191 /* Originally was 0x0010 (352x288 compression) */
192
193 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
194 {0x0003, 0x865c}, /* Vertical offset for valid lines */
195 {}
196};
197static const u16 rev72a_init_sensor2[][2] = {
198 {0x0003, 0x0121},
199 {0x0004, 0x0165},
200 {0x0005, 0x002f}, /* blanking control column */
201 {0x0006, 0x0000}, /* blanking mode row*/
202 {0x000a, 0x0002},
203 {0x0009, 0x1061}, /* setexposure times && pixel clock
204 * 0001 0 | 000 0110 0001 */
205 {0x0035, 0x0014},
206 {}
207};
208
209/******************** QC Express etch2 stuff ********************/
210static const __u16 Pb100_1map8300[][2] = {
211 /* reg, value */
212 {0x8320, 0x3304},
213
214 {0x8303, 0x0125}, /* image area */
215 {0x8304, 0x0169},
216 {0x8328, 0x000b},
217 {0x833c, 0x0001}, /*fixme: win:07*/
218
219 {0x832f, 0x1904}, /*fixme: was 0419*/
220 {0x8307, 0x00aa},
221 {0x8301, 0x0003},
222 {0x8302, 0x000e},
223 {}
224};
225static const __u16 Pb100_2map8300[][2] = {
226 /* reg, value */
227 {0x8339, 0x0000},
228 {0x8307, 0x00aa},
229 {}
230};
231
232static const __u16 spca561_161rev12A_data1[][2] = {
233 {0x29, 0x8118}, /* Control register (various enable bits) */
234 {0x08, 0x8114}, /* GPIO: Led off */
235 {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */
236 {0x00, 0x8102}, /* white balance - new */
237 {0x92, 0x8804},
238 {0x04, 0x8802}, /* windows uses 08 */
239 {}
240};
241static const __u16 spca561_161rev12A_data2[][2] = {
242 {0x21, 0x8118},
243 {0x10, 0x8500},
244 {0x07, 0x8601},
245 {0x07, 0x8602},
246 {0x04, 0x8501},
247
248 {0x07, 0x8201}, /* windows uses 02 */
249 {0x08, 0x8200},
250 {0x01, 0x8200},
251
252 {0x90, 0x8604},
253 {0x00, 0x8605},
254 {0xb0, 0x8603},
255
256 /* sensor gains */
257 {0x07, 0x8601}, /* white balance - new */
258 {0x07, 0x8602}, /* white balance - new */
259 {0x00, 0x8610}, /* *red */
260 {0x00, 0x8611}, /* 3f *green */
261 {0x00, 0x8612}, /* green *blue */
262 {0x00, 0x8613}, /* blue *green */
263 {0x43, 0x8614}, /* green *red - white balance - was 0x35 */
264 {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */
265 {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */
266 {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */
267
268 {0x0c, 0x8620}, /* 0c */
269 {0xc8, 0x8631}, /* c8 */
270 {0xc8, 0x8634}, /* c8 */
271 {0x23, 0x8635}, /* 23 */
272 {0x1f, 0x8636}, /* 1f */
273 {0xdd, 0x8637}, /* dd */
274 {0xe1, 0x8638}, /* e1 */
275 {0x1d, 0x8639}, /* 1d */
276 {0x21, 0x863a}, /* 21 */
277 {0xe3, 0x863b}, /* e3 */
278 {0xdf, 0x863c}, /* df */
279 {0xf0, 0x8505},
280 {0x32, 0x850a},
281/* {0x99, 0x8700}, * - white balance - new (removed) */
282 /* HDG we used to do this in stop0, making the init state and the state
283 after a start / stop different, so do this here instead. */
284 {0x29, 0x8118},
285 {}
286};
287
288static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
289{
290 int ret;
291
292 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
293 0, /* request */
294 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
295 value, index, NULL, 0, 500);
296 PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
297 if (ret < 0)
298 pr_err("reg write: error %d\n", ret);
299}
300
301static void write_vector(struct gspca_dev *gspca_dev,
302 const __u16 data[][2])
303{
304 struct usb_device *dev = gspca_dev->dev;
305 int i;
306
307 i = 0;
308 while (data[i][1] != 0) {
309 reg_w_val(dev, data[i][1], data[i][0]);
310 i++;
311 }
312}
313
314/* read 'len' bytes to gspca_dev->usb_buf */
315static void reg_r(struct gspca_dev *gspca_dev,
316 __u16 index, __u16 length)
317{
318 usb_control_msg(gspca_dev->dev,
319 usb_rcvctrlpipe(gspca_dev->dev, 0),
320 0, /* request */
321 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
322 0, /* value */
323 index, gspca_dev->usb_buf, length, 500);
324}
325
326/* write 'len' bytes from gspca_dev->usb_buf */
327static void reg_w_buf(struct gspca_dev *gspca_dev,
328 __u16 index, __u16 len)
329{
330 usb_control_msg(gspca_dev->dev,
331 usb_sndctrlpipe(gspca_dev->dev, 0),
332 0, /* request */
333 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
334 0, /* value */
335 index, gspca_dev->usb_buf, len, 500);
336}
337
338static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
339{
340 int retry = 60;
341
342 reg_w_val(gspca_dev->dev, 0x8801, reg);
343 reg_w_val(gspca_dev->dev, 0x8805, value);
344 reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
345 do {
346 reg_r(gspca_dev, 0x8803, 1);
347 if (!gspca_dev->usb_buf[0])
348 return;
349 msleep(10);
350 } while (--retry);
351}
352
353static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
354{
355 int retry = 60;
356 __u8 value;
357
358 reg_w_val(gspca_dev->dev, 0x8804, 0x92);
359 reg_w_val(gspca_dev->dev, 0x8801, reg);
360 reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
361 do {
362 reg_r(gspca_dev, 0x8803, 1);
363 if (!gspca_dev->usb_buf[0]) {
364 reg_r(gspca_dev, 0x8800, 1);
365 value = gspca_dev->usb_buf[0];
366 reg_r(gspca_dev, 0x8805, 1);
367 return ((int) value << 8) | gspca_dev->usb_buf[0];
368 }
369 msleep(10);
370 } while (--retry);
371 return -1;
372}
373
374static void sensor_mapwrite(struct gspca_dev *gspca_dev,
375 const __u16 (*sensormap)[2])
376{
377 while ((*sensormap)[0]) {
378 gspca_dev->usb_buf[0] = (*sensormap)[1];
379 gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
380 reg_w_buf(gspca_dev, (*sensormap)[0], 2);
381 sensormap++;
382 }
383}
384
385static void write_sensor_72a(struct gspca_dev *gspca_dev,
386 const __u16 (*sensor)[2])
387{
388 while ((*sensor)[0]) {
389 i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
390 sensor++;
391 }
392}
393
394static void init_161rev12A(struct gspca_dev *gspca_dev)
395{
396 write_vector(gspca_dev, spca561_161rev12A_data1);
397 sensor_mapwrite(gspca_dev, Pb100_1map8300);
398/*fixme: should be in sd_start*/
399 write_vector(gspca_dev, spca561_161rev12A_data2);
400 sensor_mapwrite(gspca_dev, Pb100_2map8300);
401}
402
403/* this function is called at probe time */
404static int sd_config(struct gspca_dev *gspca_dev,
405 const struct usb_device_id *id)
406{
407 struct sd *sd = (struct sd *) gspca_dev;
408 struct cam *cam;
409 __u16 vendor, product;
410 __u8 data1, data2;
411
412 /* Read frm global register the USB product and vendor IDs, just to
413 * prove that we can communicate with the device. This works, which
414 * confirms at we are communicating properly and that the device
415 * is a 561. */
416 reg_r(gspca_dev, 0x8104, 1);
417 data1 = gspca_dev->usb_buf[0];
418 reg_r(gspca_dev, 0x8105, 1);
419 data2 = gspca_dev->usb_buf[0];
420 vendor = (data2 << 8) | data1;
421 reg_r(gspca_dev, 0x8106, 1);
422 data1 = gspca_dev->usb_buf[0];
423 reg_r(gspca_dev, 0x8107, 1);
424 data2 = gspca_dev->usb_buf[0];
425 product = (data2 << 8) | data1;
426 if (vendor != id->idVendor || product != id->idProduct) {
427 PDEBUG(D_PROBE, "Bad vendor / product from device");
428 return -EINVAL;
429 }
430
431 cam = &gspca_dev->cam;
432 cam->needs_full_bandwidth = 1;
433
434 sd->chip_revision = id->driver_info;
435 if (sd->chip_revision == Rev012A) {
436 cam->cam_mode = sif_012a_mode;
437 cam->nmodes = ARRAY_SIZE(sif_012a_mode);
438 } else {
439 cam->cam_mode = sif_072a_mode;
440 cam->nmodes = ARRAY_SIZE(sif_072a_mode);
441 }
442 sd->expo12a = EXPO12A_DEF;
443 return 0;
444}
445
446/* this function is called at probe and resume time */
447static int sd_init_12a(struct gspca_dev *gspca_dev)
448{
449 PDEBUG(D_STREAM, "Chip revision: 012a");
450 init_161rev12A(gspca_dev);
451 return 0;
452}
453static int sd_init_72a(struct gspca_dev *gspca_dev)
454{
455 PDEBUG(D_STREAM, "Chip revision: 072a");
456 write_vector(gspca_dev, rev72a_reset);
457 msleep(200);
458 write_vector(gspca_dev, rev72a_init_data1);
459 write_sensor_72a(gspca_dev, rev72a_init_sensor1);
460 write_vector(gspca_dev, rev72a_init_data2);
461 write_sensor_72a(gspca_dev, rev72a_init_sensor2);
462 reg_w_val(gspca_dev->dev, 0x8112, 0x30);
463 return 0;
464}
465
466static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
467{
468 struct sd *sd = (struct sd *) gspca_dev;
469 struct usb_device *dev = gspca_dev->dev;
470 __u16 reg;
471
472 if (sd->chip_revision == Rev012A)
473 reg = 0x8610;
474 else
475 reg = 0x8611;
476
477 reg_w_val(dev, reg + 0, val); /* R */
478 reg_w_val(dev, reg + 1, val); /* Gr */
479 reg_w_val(dev, reg + 2, val); /* B */
480 reg_w_val(dev, reg + 3, val); /* Gb */
481}
482
483static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
484{
485 struct sd *sd = (struct sd *) gspca_dev;
486 struct usb_device *dev = gspca_dev->dev;
487 __u8 blue, red;
488 __u16 reg;
489
490 /* try to emulate MS-win as possible */
491 red = 0x20 + white * 3 / 8;
492 blue = 0x90 - white * 5 / 8;
493 if (sd->chip_revision == Rev012A) {
494 reg = 0x8614;
495 } else {
496 reg = 0x8651;
497 red += contrast - 0x20;
498 blue += contrast - 0x20;
499 reg_w_val(dev, 0x8652, contrast + 0x20); /* Gr */
500 reg_w_val(dev, 0x8654, contrast + 0x20); /* Gb */
501 }
502 reg_w_val(dev, reg, red);
503 reg_w_val(dev, reg + 2, blue);
504}
505
506/* rev 12a only */
507static void setexposure(struct gspca_dev *gspca_dev, s32 val)
508{
509 int i, expo = 0;
510
511 /* Register 0x8309 controls exposure for the spca561,
512 the basic exposure setting goes from 1-2047, where 1 is completely
513 dark and 2047 is very bright. It not only influences exposure but
514 also the framerate (to allow for longer exposure) from 1 - 300 it
515 only raises the exposure time then from 300 - 600 it halves the
516 framerate to be able to further raise the exposure time and for every
517 300 more it halves the framerate again. This allows for a maximum
518 exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
519 Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
520 configure a divider for the base framerate which us used at the
521 exposure setting of 1-300. These bits configure the base framerate
522 according to the following formula: fps = 60 / (value + 2) */
523
524 /* We choose to use the high bits setting the fixed framerate divisor
525 asap, as setting high basic exposure setting without the fixed
526 divider in combination with high gains makes the cam stop */
527 int table[] = { 0, 450, 550, 625, EXPOSURE_MAX };
528
529 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
530 if (val <= table[i + 1]) {
531 expo = val - table[i];
532 if (i)
533 expo += 300;
534 expo |= i << 11;
535 break;
536 }
537 }
538
539 gspca_dev->usb_buf[0] = expo;
540 gspca_dev->usb_buf[1] = expo >> 8;
541 reg_w_buf(gspca_dev, 0x8309, 2);
542}
543
544/* rev 12a only */
545static void setgain(struct gspca_dev *gspca_dev, s32 val)
546{
547 /* gain reg low 6 bits 0-63 gain, bit 6 and 7, both double the
548 sensitivity when set, so 31 + one of them set == 63, and 15
549 with both of them set == 63 */
550 if (val < 64)
551 gspca_dev->usb_buf[0] = val;
552 else if (val < 128)
553 gspca_dev->usb_buf[0] = (val / 2) | 0x40;
554 else
555 gspca_dev->usb_buf[0] = (val / 4) | 0xc0;
556
557 gspca_dev->usb_buf[1] = 0;
558 reg_w_buf(gspca_dev, 0x8335, 2);
559}
560
561static void setautogain(struct gspca_dev *gspca_dev, s32 val)
562{
563 struct sd *sd = (struct sd *) gspca_dev;
564
565 if (val)
566 sd->ag_cnt = AG_CNT_START;
567 else
568 sd->ag_cnt = -1;
569}
570
571static int sd_start_12a(struct gspca_dev *gspca_dev)
572{
573 struct usb_device *dev = gspca_dev->dev;
574 int mode;
575 static const __u8 Reg8391[8] =
576 {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
577
578 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
579 if (mode <= 1) {
580 /* Use compression on 320x240 and above */
581 reg_w_val(dev, 0x8500, 0x10 | mode);
582 } else {
583 /* I couldn't get the compression to work below 320x240
584 * Fortunately at these resolutions the bandwidth
585 * is sufficient to push raw frames at ~20fps */
586 reg_w_val(dev, 0x8500, mode);
587 } /* -- qq@kuku.eu.org */
588
589 gspca_dev->usb_buf[0] = 0xaa;
590 gspca_dev->usb_buf[1] = 0x00;
591 reg_w_buf(gspca_dev, 0x8307, 2);
592 /* clock - lower 0x8X values lead to fps > 30 */
593 reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
594 /* 0x8f 0x85 0x27 clock */
595 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
596 reg_w_val(gspca_dev->dev, 0x850b, 0x03);
597 memcpy(gspca_dev->usb_buf, Reg8391, 8);
598 reg_w_buf(gspca_dev, 0x8391, 8);
599 reg_w_buf(gspca_dev, 0x8390, 8);
600
601 /* Led ON (bit 3 -> 0 */
602 reg_w_val(gspca_dev->dev, 0x8114, 0x00);
603 return 0;
604}
605static int sd_start_72a(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608 struct usb_device *dev = gspca_dev->dev;
609 int Clck;
610 int mode;
611
612 write_vector(gspca_dev, rev72a_reset);
613 msleep(200);
614 write_vector(gspca_dev, rev72a_init_data1);
615 write_sensor_72a(gspca_dev, rev72a_init_sensor1);
616
617 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
618 switch (mode) {
619 default:
620 case 0:
621 Clck = 0x27; /* ms-win 0x87 */
622 break;
623 case 1:
624 Clck = 0x25;
625 break;
626 case 2:
627 Clck = 0x22;
628 break;
629 case 3:
630 Clck = 0x21;
631 break;
632 }
633 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
634 reg_w_val(dev, 0x8702, 0x81);
635 reg_w_val(dev, 0x8500, mode); /* mode */
636 write_sensor_72a(gspca_dev, rev72a_init_sensor2);
637 setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
638 v4l2_ctrl_g_ctrl(sd->contrast));
639/* setbrightness(gspca_dev); * fixme: bad values */
640 setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
641 reg_w_val(dev, 0x8112, 0x10 | 0x20);
642 return 0;
643}
644
645static void sd_stopN(struct gspca_dev *gspca_dev)
646{
647 struct sd *sd = (struct sd *) gspca_dev;
648
649 if (sd->chip_revision == Rev012A) {
650 reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
651 /* Led Off (bit 3 -> 1 */
652 reg_w_val(gspca_dev->dev, 0x8114, 0x08);
653 } else {
654 reg_w_val(gspca_dev->dev, 0x8112, 0x20);
655/* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
656 }
657}
658
659static void do_autogain(struct gspca_dev *gspca_dev)
660{
661 struct sd *sd = (struct sd *) gspca_dev;
662 int expotimes;
663 int pixelclk;
664 int gainG;
665 __u8 R, Gr, Gb, B;
666 int y;
667 __u8 luma_mean = 110;
668 __u8 luma_delta = 20;
669 __u8 spring = 4;
670
671 if (sd->ag_cnt < 0)
672 return;
673 if (--sd->ag_cnt >= 0)
674 return;
675 sd->ag_cnt = AG_CNT_START;
676
677 switch (sd->chip_revision) {
678 case Rev072A:
679 reg_r(gspca_dev, 0x8621, 1);
680 Gr = gspca_dev->usb_buf[0];
681 reg_r(gspca_dev, 0x8622, 1);
682 R = gspca_dev->usb_buf[0];
683 reg_r(gspca_dev, 0x8623, 1);
684 B = gspca_dev->usb_buf[0];
685 reg_r(gspca_dev, 0x8624, 1);
686 Gb = gspca_dev->usb_buf[0];
687 y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
688 /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
689 /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
690 /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
691
692 if (y < luma_mean - luma_delta ||
693 y > luma_mean + luma_delta) {
694 expotimes = i2c_read(gspca_dev, 0x09, 0x10);
695 pixelclk = 0x0800;
696 expotimes = expotimes & 0x07ff;
697 /* PDEBUG(D_PACK,
698 "Exposition Times 0x%03X Clock 0x%04X ",
699 expotimes,pixelclk); */
700 gainG = i2c_read(gspca_dev, 0x35, 0x10);
701 /* PDEBUG(D_PACK,
702 "reading Gain register %d", gainG); */
703
704 expotimes += (luma_mean - y) >> spring;
705 gainG += (luma_mean - y) / 50;
706 /* PDEBUG(D_PACK,
707 "compute expotimes %d gain %d",
708 expotimes,gainG); */
709
710 if (gainG > 0x3f)
711 gainG = 0x3f;
712 else if (gainG < 3)
713 gainG = 3;
714 i2c_write(gspca_dev, gainG, 0x35);
715
716 if (expotimes > 0x0256)
717 expotimes = 0x0256;
718 else if (expotimes < 3)
719 expotimes = 3;
720 i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
721 }
722 break;
723 }
724}
725
726static void sd_pkt_scan(struct gspca_dev *gspca_dev,
727 u8 *data, /* isoc packet */
728 int len) /* iso packet length */
729{
730 struct sd *sd = (struct sd *) gspca_dev;
731
732 len--;
733 switch (*data++) { /* sequence number */
734 case 0: /* start of frame */
735 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
736
737 /* This should never happen */
738 if (len < 2) {
739 PDEBUG(D_ERR, "Short SOF packet, ignoring");
740 gspca_dev->last_packet_type = DISCARD_PACKET;
741 return;
742 }
743
744#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
745 if (data[0] & 0x20) {
746 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
747 input_sync(gspca_dev->input_dev);
748 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
749 input_sync(gspca_dev->input_dev);
750 }
751#endif
752
753 if (data[1] & 0x10) {
754 /* compressed bayer */
755 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
756 } else {
757 /* raw bayer (with a header, which we skip) */
758 if (sd->chip_revision == Rev012A) {
759 data += 20;
760 len -= 20;
761 } else {
762 data += 16;
763 len -= 16;
764 }
765 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
766 }
767 return;
768 case 0xff: /* drop (empty mpackets) */
769 return;
770 }
771 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
772}
773
774static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
775{
776 struct gspca_dev *gspca_dev =
777 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
778 struct sd *sd = (struct sd *)gspca_dev;
779
780 gspca_dev->usb_err = 0;
781
782 if (!gspca_dev->streaming)
783 return 0;
784
785 switch (ctrl->id) {
786 case V4L2_CID_BRIGHTNESS:
787 setbrightness(gspca_dev, ctrl->val);
788 break;
789 case V4L2_CID_CONTRAST:
790 /* hue/contrast control cluster for 72a */
791 setwhite(gspca_dev, sd->hue->val, ctrl->val);
792 break;
793 case V4L2_CID_HUE:
794 /* just plain hue control for 12a */
795 setwhite(gspca_dev, ctrl->val, 0);
796 break;
797 case V4L2_CID_EXPOSURE:
798 setexposure(gspca_dev, ctrl->val);
799 break;
800 case V4L2_CID_GAIN:
801 setgain(gspca_dev, ctrl->val);
802 break;
803 case V4L2_CID_AUTOGAIN:
804 setautogain(gspca_dev, ctrl->val);
805 break;
806 }
807 return gspca_dev->usb_err;
808}
809
810static const struct v4l2_ctrl_ops sd_ctrl_ops = {
811 .s_ctrl = sd_s_ctrl,
812};
813
814static int sd_init_controls_12a(struct gspca_dev *gspca_dev)
815{
816 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
817
818 gspca_dev->vdev.ctrl_handler = hdl;
819 v4l2_ctrl_handler_init(hdl, 3);
820 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
821 V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
822 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
823 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
824 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
825 V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700);
826 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
827 V4L2_CID_GAIN, 0, 255, 1, 63);
828
829 if (hdl->error) {
830 pr_err("Could not initialize controls\n");
831 return hdl->error;
832 }
833 return 0;
834}
835
836static int sd_init_controls_72a(struct gspca_dev *gspca_dev)
837{
838 struct sd *sd = (struct sd *)gspca_dev;
839 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
840
841 gspca_dev->vdev.ctrl_handler = hdl;
842 v4l2_ctrl_handler_init(hdl, 4);
843 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
844 V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20);
845 sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
846 V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
847 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
848 V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20);
849 sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
850 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
851
852 if (hdl->error) {
853 pr_err("Could not initialize controls\n");
854 return hdl->error;
855 }
856 v4l2_ctrl_cluster(2, &sd->contrast);
857 return 0;
858}
859
860/* sub-driver description */
861static const struct sd_desc sd_desc_12a = {
862 .name = MODULE_NAME,
863 .init_controls = sd_init_controls_12a,
864 .config = sd_config,
865 .init = sd_init_12a,
866 .start = sd_start_12a,
867 .stopN = sd_stopN,
868 .pkt_scan = sd_pkt_scan,
869#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
870 .other_input = 1,
871#endif
872};
873static const struct sd_desc sd_desc_72a = {
874 .name = MODULE_NAME,
875 .init_controls = sd_init_controls_72a,
876 .config = sd_config,
877 .init = sd_init_72a,
878 .start = sd_start_72a,
879 .stopN = sd_stopN,
880 .pkt_scan = sd_pkt_scan,
881 .dq_callback = do_autogain,
882#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
883 .other_input = 1,
884#endif
885};
886static const struct sd_desc *sd_desc[2] = {
887 &sd_desc_12a,
888 &sd_desc_72a
889};
890
891/* -- module initialisation -- */
892static const struct usb_device_id device_table[] = {
893 {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
894 {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
895 {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
896 {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
897 {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
898 {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
899 {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
900 {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
901 {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
902 {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
903 {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
904 {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
905 {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
906 {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
907 {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
908 {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
909 {}
910};
911
912MODULE_DEVICE_TABLE(usb, device_table);
913
914/* -- device connect -- */
915static int sd_probe(struct usb_interface *intf,
916 const struct usb_device_id *id)
917{
918 return gspca_dev_probe(intf, id,
919 sd_desc[id->driver_info],
920 sizeof(struct sd),
921 THIS_MODULE);
922}
923
924static struct usb_driver sd_driver = {
925 .name = MODULE_NAME,
926 .id_table = device_table,
927 .probe = sd_probe,
928 .disconnect = gspca_disconnect,
929#ifdef CONFIG_PM
930 .suspend = gspca_suspend,
931 .resume = gspca_resume,
932 .reset_resume = gspca_resume,
933#endif
934};
935
936module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c
new file mode 100644
index 00000000000..a8ac97931ad
--- /dev/null
+++ b/drivers/media/usb/gspca/sq905.c
@@ -0,0 +1,440 @@
1/*
2 * SQ905 subdriver
3 *
4 * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore
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 * History and Acknowledgments
23 *
24 * The original Linux driver for SQ905 based cameras was written by
25 * Marcell Lengyel and furter developed by many other contributors
26 * and is available from http://sourceforge.net/projects/sqcam/
27 *
28 * This driver takes advantage of the reverse engineering work done for
29 * that driver and for libgphoto2 but shares no code with them.
30 *
31 * This driver has used as a base the finepix driver and other gspca
32 * based drivers and may still contain code fragments taken from those
33 * drivers.
34 */
35
36#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
37
38#define MODULE_NAME "sq905"
39
40#include <linux/workqueue.h>
41#include <linux/slab.h>
42#include "gspca.h"
43
44MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
45 "Theodore Kilgore <kilgota@auburn.edu>");
46MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
47MODULE_LICENSE("GPL");
48
49/* Default timeouts, in ms */
50#define SQ905_CMD_TIMEOUT 500
51#define SQ905_DATA_TIMEOUT 1000
52
53/* Maximum transfer size to use. */
54#define SQ905_MAX_TRANSFER 0x8000
55#define FRAME_HEADER_LEN 64
56
57/* The known modes, or registers. These go in the "value" slot. */
58
59/* 00 is "none" obviously */
60
61#define SQ905_BULK_READ 0x03 /* precedes any bulk read */
62#define SQ905_COMMAND 0x06 /* precedes the command codes below */
63#define SQ905_PING 0x07 /* when reading an "idling" command */
64#define SQ905_READ_DONE 0xc0 /* ack bulk read completed */
65
66/* Any non-zero value in the bottom 2 bits of the 2nd byte of
67 * the ID appears to indicate the camera can do 640*480. If the
68 * LSB of that byte is set the image is just upside down, otherwise
69 * it is rotated 180 degrees. */
70#define SQ905_HIRES_MASK 0x00000300
71#define SQ905_ORIENTATION_MASK 0x00000100
72
73/* Some command codes. These go in the "index" slot. */
74
75#define SQ905_ID 0xf0 /* asks for model string */
76#define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */
77#define SQ905_DATA 0x30 /* accesses photo data, not used here */
78#define SQ905_CLEAR 0xa0 /* clear everything */
79#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */
80#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */
81#define SQ905_CAPTURE_HIGH 0x62 /* Starts capture at 640x480 (some cams only) */
82/* note that the capture command also controls the output dimensions */
83
84/* Structure to hold all of our device specific stuff */
85struct sd {
86 struct gspca_dev gspca_dev; /* !! must be the first item */
87
88 /*
89 * Driver stuff
90 */
91 struct work_struct work_struct;
92 struct workqueue_struct *work_thread;
93};
94
95static struct v4l2_pix_format sq905_mode[] = {
96 { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
97 .bytesperline = 160,
98 .sizeimage = 160 * 120,
99 .colorspace = V4L2_COLORSPACE_SRGB,
100 .priv = 0},
101 { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
102 .bytesperline = 320,
103 .sizeimage = 320 * 240,
104 .colorspace = V4L2_COLORSPACE_SRGB,
105 .priv = 0},
106 { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
107 .bytesperline = 640,
108 .sizeimage = 640 * 480,
109 .colorspace = V4L2_COLORSPACE_SRGB,
110 .priv = 0}
111};
112
113/*
114 * Send a command to the camera.
115 */
116static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
117{
118 int ret;
119
120 gspca_dev->usb_buf[0] = '\0';
121 ret = usb_control_msg(gspca_dev->dev,
122 usb_sndctrlpipe(gspca_dev->dev, 0),
123 USB_REQ_SYNCH_FRAME, /* request */
124 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
125 SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
126 SQ905_CMD_TIMEOUT);
127 if (ret < 0) {
128 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
129 return ret;
130 }
131
132 ret = usb_control_msg(gspca_dev->dev,
133 usb_sndctrlpipe(gspca_dev->dev, 0),
134 USB_REQ_SYNCH_FRAME, /* request */
135 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
136 SQ905_PING, 0, gspca_dev->usb_buf, 1,
137 SQ905_CMD_TIMEOUT);
138 if (ret < 0) {
139 pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
140 return ret;
141 }
142
143 return 0;
144}
145
146/*
147 * Acknowledge the end of a frame - see warning on sq905_command.
148 */
149static int sq905_ack_frame(struct gspca_dev *gspca_dev)
150{
151 int ret;
152
153 gspca_dev->usb_buf[0] = '\0';
154 ret = usb_control_msg(gspca_dev->dev,
155 usb_sndctrlpipe(gspca_dev->dev, 0),
156 USB_REQ_SYNCH_FRAME, /* request */
157 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
158 SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
159 SQ905_CMD_TIMEOUT);
160 if (ret < 0) {
161 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
162 return ret;
163 }
164
165 return 0;
166}
167
168/*
169 * request and read a block of data - see warning on sq905_command.
170 */
171static int
172sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
173{
174 int ret;
175 int act_len;
176
177 gspca_dev->usb_buf[0] = '\0';
178 if (need_lock)
179 mutex_lock(&gspca_dev->usb_lock);
180 ret = usb_control_msg(gspca_dev->dev,
181 usb_sndctrlpipe(gspca_dev->dev, 0),
182 USB_REQ_SYNCH_FRAME, /* request */
183 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
184 SQ905_BULK_READ, size, gspca_dev->usb_buf,
185 1, SQ905_CMD_TIMEOUT);
186 if (need_lock)
187 mutex_unlock(&gspca_dev->usb_lock);
188 if (ret < 0) {
189 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
190 return ret;
191 }
192 ret = usb_bulk_msg(gspca_dev->dev,
193 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
194 data, size, &act_len, SQ905_DATA_TIMEOUT);
195
196 /* successful, it returns 0, otherwise negative */
197 if (ret < 0 || act_len != size) {
198 pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
199 return -EIO;
200 }
201 return 0;
202}
203
204/* This function is called as a workqueue function and runs whenever the camera
205 * is streaming data. Because it is a workqueue function it is allowed to sleep
206 * so we can use synchronous USB calls. To avoid possible collisions with other
207 * threads attempting to use the camera's USB interface we take the gspca
208 * usb_lock when performing USB operations. In practice the only thing we need
209 * to protect against is the usb_set_interface call that gspca makes during
210 * stream_off as the camera doesn't provide any controls that the user could try
211 * to change.
212 */
213static void sq905_dostream(struct work_struct *work)
214{
215 struct sd *dev = container_of(work, struct sd, work_struct);
216 struct gspca_dev *gspca_dev = &dev->gspca_dev;
217 int bytes_left; /* bytes remaining in current frame. */
218 int data_len; /* size to use for the next read. */
219 int header_read; /* true if we have already read the frame header. */
220 int packet_type;
221 int frame_sz;
222 int ret;
223 u8 *data;
224 u8 *buffer;
225
226 buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
227 if (!buffer) {
228 pr_err("Couldn't allocate USB buffer\n");
229 goto quit_stream;
230 }
231
232 frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
233 + FRAME_HEADER_LEN;
234
235 while (gspca_dev->dev && gspca_dev->streaming) {
236#ifdef CONFIG_PM
237 if (gspca_dev->frozen)
238 break;
239#endif
240 /* request some data and then read it until we have
241 * a complete frame. */
242 bytes_left = frame_sz;
243 header_read = 0;
244
245 /* Note we do not check for gspca_dev->streaming here, as
246 we must finish reading an entire frame, otherwise the
247 next time we stream we start reading in the middle of a
248 frame. */
249 while (bytes_left > 0 && gspca_dev->dev) {
250 data_len = bytes_left > SQ905_MAX_TRANSFER ?
251 SQ905_MAX_TRANSFER : bytes_left;
252 ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
253 if (ret < 0)
254 goto quit_stream;
255 PDEBUG(D_PACK,
256 "Got %d bytes out of %d for frame",
257 data_len, bytes_left);
258 bytes_left -= data_len;
259 data = buffer;
260 if (!header_read) {
261 packet_type = FIRST_PACKET;
262 /* The first 64 bytes of each frame are
263 * a header full of FF 00 bytes */
264 data += FRAME_HEADER_LEN;
265 data_len -= FRAME_HEADER_LEN;
266 header_read = 1;
267 } else if (bytes_left == 0) {
268 packet_type = LAST_PACKET;
269 } else {
270 packet_type = INTER_PACKET;
271 }
272 gspca_frame_add(gspca_dev, packet_type,
273 data, data_len);
274 /* If entire frame fits in one packet we still
275 need to add a LAST_PACKET */
276 if (packet_type == FIRST_PACKET &&
277 bytes_left == 0)
278 gspca_frame_add(gspca_dev, LAST_PACKET,
279 NULL, 0);
280 }
281 if (gspca_dev->dev) {
282 /* acknowledge the frame */
283 mutex_lock(&gspca_dev->usb_lock);
284 ret = sq905_ack_frame(gspca_dev);
285 mutex_unlock(&gspca_dev->usb_lock);
286 if (ret < 0)
287 goto quit_stream;
288 }
289 }
290quit_stream:
291 if (gspca_dev->dev) {
292 mutex_lock(&gspca_dev->usb_lock);
293 sq905_command(gspca_dev, SQ905_CLEAR);
294 mutex_unlock(&gspca_dev->usb_lock);
295 }
296 kfree(buffer);
297}
298
299/* This function is called at probe time just before sd_init */
300static int sd_config(struct gspca_dev *gspca_dev,
301 const struct usb_device_id *id)
302{
303 struct cam *cam = &gspca_dev->cam;
304 struct sd *dev = (struct sd *) gspca_dev;
305
306 /* We don't use the buffer gspca allocates so make it small. */
307 cam->bulk = 1;
308 cam->bulk_size = 64;
309
310 INIT_WORK(&dev->work_struct, sq905_dostream);
311
312 return 0;
313}
314
315/* called on streamoff with alt==0 and on disconnect */
316/* the usb_lock is held at entry - restore on exit */
317static void sd_stop0(struct gspca_dev *gspca_dev)
318{
319 struct sd *dev = (struct sd *) gspca_dev;
320
321 /* wait for the work queue to terminate */
322 mutex_unlock(&gspca_dev->usb_lock);
323 /* This waits for sq905_dostream to finish */
324 destroy_workqueue(dev->work_thread);
325 dev->work_thread = NULL;
326 mutex_lock(&gspca_dev->usb_lock);
327}
328
329/* this function is called at probe and resume time */
330static int sd_init(struct gspca_dev *gspca_dev)
331{
332 u32 ident;
333 int ret;
334
335 /* connect to the camera and read
336 * the model ID and process that and put it away.
337 */
338 ret = sq905_command(gspca_dev, SQ905_CLEAR);
339 if (ret < 0)
340 return ret;
341 ret = sq905_command(gspca_dev, SQ905_ID);
342 if (ret < 0)
343 return ret;
344 ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
345 if (ret < 0)
346 return ret;
347 /* usb_buf is allocated with kmalloc so is aligned.
348 * Camera model number is the right way round if we assume this
349 * reverse engineered ID is supposed to be big endian. */
350 ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf);
351 ret = sq905_command(gspca_dev, SQ905_CLEAR);
352 if (ret < 0)
353 return ret;
354 PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident);
355 gspca_dev->cam.cam_mode = sq905_mode;
356 gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode);
357 if (!(ident & SQ905_HIRES_MASK))
358 gspca_dev->cam.nmodes--;
359
360 if (ident & SQ905_ORIENTATION_MASK)
361 gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP;
362 else
363 gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP |
364 V4L2_IN_ST_HFLIP;
365 return 0;
366}
367
368/* Set up for getting frames. */
369static int sd_start(struct gspca_dev *gspca_dev)
370{
371 struct sd *dev = (struct sd *) gspca_dev;
372 int ret;
373
374 /* "Open the shutter" and set size, to start capture */
375 switch (gspca_dev->curr_mode) {
376 default:
377/* case 2: */
378 PDEBUG(D_STREAM, "Start streaming at high resolution");
379 ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH);
380 break;
381 case 1:
382 PDEBUG(D_STREAM, "Start streaming at medium resolution");
383 ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
384 break;
385 case 0:
386 PDEBUG(D_STREAM, "Start streaming at low resolution");
387 ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW);
388 }
389
390 if (ret < 0) {
391 PDEBUG(D_ERR, "Start streaming command failed");
392 return ret;
393 }
394 /* Start the workqueue function to do the streaming */
395 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
396 queue_work(dev->work_thread, &dev->work_struct);
397
398 return 0;
399}
400
401/* Table of supported USB devices */
402static const struct usb_device_id device_table[] = {
403 {USB_DEVICE(0x2770, 0x9120)},
404 {}
405};
406
407MODULE_DEVICE_TABLE(usb, device_table);
408
409/* sub-driver description */
410static const struct sd_desc sd_desc = {
411 .name = MODULE_NAME,
412 .config = sd_config,
413 .init = sd_init,
414 .start = sd_start,
415 .stop0 = sd_stop0,
416};
417
418/* -- device connect -- */
419static int sd_probe(struct usb_interface *intf,
420 const struct usb_device_id *id)
421{
422 return gspca_dev_probe(intf, id,
423 &sd_desc,
424 sizeof(struct sd),
425 THIS_MODULE);
426}
427
428static struct usb_driver sd_driver = {
429 .name = MODULE_NAME,
430 .id_table = device_table,
431 .probe = sd_probe,
432 .disconnect = gspca_disconnect,
433#ifdef CONFIG_PM
434 .suspend = gspca_suspend,
435 .resume = gspca_resume,
436 .reset_resume = gspca_resume,
437#endif
438};
439
440module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c
new file mode 100644
index 00000000000..70fae6982e9
--- /dev/null
+++ b/drivers/media/usb/gspca/sq905c.c
@@ -0,0 +1,344 @@
1/*
2 * SQ905C subdriver
3 *
4 * Copyright (C) 2009 Theodore Kilgore
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 *
23 * This driver uses work done in
24 * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore.
25 *
26 * This driver has also used as a base the sq905c driver
27 * and may contain code fragments from it.
28 */
29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#define MODULE_NAME "sq905c"
33
34#include <linux/workqueue.h>
35#include <linux/slab.h>
36#include "gspca.h"
37
38MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
39MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
40MODULE_LICENSE("GPL");
41
42/* Default timeouts, in ms */
43#define SQ905C_CMD_TIMEOUT 500
44#define SQ905C_DATA_TIMEOUT 1000
45
46/* Maximum transfer size to use. */
47#define SQ905C_MAX_TRANSFER 0x8000
48
49#define FRAME_HEADER_LEN 0x50
50
51/* Commands. These go in the "value" slot. */
52#define SQ905C_CLEAR 0xa0 /* clear everything */
53#define SQ905C_GET_ID 0x14f4 /* Read version number */
54#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */
55#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */
56#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */
57
58/* For capture, this must go in the "index" slot. */
59#define SQ905C_CAPTURE_INDEX 0x110f
60
61/* Structure to hold all of our device specific stuff */
62struct sd {
63 struct gspca_dev gspca_dev; /* !! must be the first item */
64 const struct v4l2_pix_format *cap_mode;
65 /* Driver stuff */
66 struct work_struct work_struct;
67 struct workqueue_struct *work_thread;
68};
69
70/*
71 * Most of these cameras will do 640x480 and 320x240. 160x120 works
72 * in theory but gives very poor output. Therefore, not supported.
73 * The 0x2770:0x9050 cameras have max resolution of 320x240.
74 */
75static struct v4l2_pix_format sq905c_mode[] = {
76 { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
77 .bytesperline = 320,
78 .sizeimage = 320 * 240,
79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .priv = 0},
81 { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
82 .bytesperline = 640,
83 .sizeimage = 640 * 480,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0}
86};
87
88/* Send a command to the camera. */
89static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
90{
91 int ret;
92
93 ret = usb_control_msg(gspca_dev->dev,
94 usb_sndctrlpipe(gspca_dev->dev, 0),
95 USB_REQ_SYNCH_FRAME, /* request */
96 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
97 command, index, NULL, 0,
98 SQ905C_CMD_TIMEOUT);
99 if (ret < 0) {
100 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
101 return ret;
102 }
103
104 return 0;
105}
106
107static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
108 int size)
109{
110 int ret;
111
112 ret = usb_control_msg(gspca_dev->dev,
113 usb_rcvctrlpipe(gspca_dev->dev, 0),
114 USB_REQ_SYNCH_FRAME, /* request */
115 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
116 command, index, gspca_dev->usb_buf, size,
117 SQ905C_CMD_TIMEOUT);
118 if (ret < 0) {
119 pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
120 return ret;
121 }
122
123 return 0;
124}
125
126/* This function is called as a workqueue function and runs whenever the camera
127 * is streaming data. Because it is a workqueue function it is allowed to sleep
128 * so we can use synchronous USB calls. To avoid possible collisions with other
129 * threads attempting to use the camera's USB interface the gspca usb_lock is
130 * used when performing the one USB control operation inside the workqueue,
131 * which tells the camera to close the stream. In practice the only thing
132 * which needs to be protected against is the usb_set_interface call that
133 * gspca makes during stream_off. Otherwise the camera doesn't provide any
134 * controls that the user could try to change.
135 */
136static void sq905c_dostream(struct work_struct *work)
137{
138 struct sd *dev = container_of(work, struct sd, work_struct);
139 struct gspca_dev *gspca_dev = &dev->gspca_dev;
140 int bytes_left; /* bytes remaining in current frame. */
141 int data_len; /* size to use for the next read. */
142 int act_len;
143 int packet_type;
144 int ret;
145 u8 *buffer;
146
147 buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
148 if (!buffer) {
149 pr_err("Couldn't allocate USB buffer\n");
150 goto quit_stream;
151 }
152
153 while (gspca_dev->dev && gspca_dev->streaming) {
154#ifdef CONFIG_PM
155 if (gspca_dev->frozen)
156 break;
157#endif
158 /* Request the header, which tells the size to download */
159 ret = usb_bulk_msg(gspca_dev->dev,
160 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
161 buffer, FRAME_HEADER_LEN, &act_len,
162 SQ905C_DATA_TIMEOUT);
163 PDEBUG(D_STREAM,
164 "Got %d bytes out of %d for header",
165 act_len, FRAME_HEADER_LEN);
166 if (ret < 0 || act_len < FRAME_HEADER_LEN)
167 goto quit_stream;
168 /* size is read from 4 bytes starting 0x40, little endian */
169 bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
170 |(buffer[0x43]<<24);
171 PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
172 /* We keep the header. It has other information, too. */
173 packet_type = FIRST_PACKET;
174 gspca_frame_add(gspca_dev, packet_type,
175 buffer, FRAME_HEADER_LEN);
176 while (bytes_left > 0 && gspca_dev->dev) {
177 data_len = bytes_left > SQ905C_MAX_TRANSFER ?
178 SQ905C_MAX_TRANSFER : bytes_left;
179 ret = usb_bulk_msg(gspca_dev->dev,
180 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
181 buffer, data_len, &act_len,
182 SQ905C_DATA_TIMEOUT);
183 if (ret < 0 || act_len < data_len)
184 goto quit_stream;
185 PDEBUG(D_STREAM,
186 "Got %d bytes out of %d for frame",
187 data_len, bytes_left);
188 bytes_left -= data_len;
189 if (bytes_left == 0)
190 packet_type = LAST_PACKET;
191 else
192 packet_type = INTER_PACKET;
193 gspca_frame_add(gspca_dev, packet_type,
194 buffer, data_len);
195 }
196 }
197quit_stream:
198 if (gspca_dev->dev) {
199 mutex_lock(&gspca_dev->usb_lock);
200 sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
201 mutex_unlock(&gspca_dev->usb_lock);
202 }
203 kfree(buffer);
204}
205
206/* This function is called at probe time just before sd_init */
207static int sd_config(struct gspca_dev *gspca_dev,
208 const struct usb_device_id *id)
209{
210 struct cam *cam = &gspca_dev->cam;
211 struct sd *dev = (struct sd *) gspca_dev;
212 int ret;
213
214 PDEBUG(D_PROBE,
215 "SQ9050 camera detected"
216 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
217
218 ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
219 if (ret < 0) {
220 PDEBUG(D_ERR, "Get version command failed");
221 return ret;
222 }
223
224 ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
225 if (ret < 0) {
226 PDEBUG(D_ERR, "Reading version command failed");
227 return ret;
228 }
229 /* Note we leave out the usb id and the manufacturing date */
230 PDEBUG(D_PROBE,
231 "SQ9050 ID string: %02x - %*ph",
232 gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14);
233
234 cam->cam_mode = sq905c_mode;
235 cam->nmodes = 2;
236 if (gspca_dev->usb_buf[15] == 0)
237 cam->nmodes = 1;
238 /* We don't use the buffer gspca allocates so make it small. */
239 cam->bulk_size = 32;
240 cam->bulk = 1;
241 INIT_WORK(&dev->work_struct, sq905c_dostream);
242 return 0;
243}
244
245/* called on streamoff with alt==0 and on disconnect */
246/* the usb_lock is held at entry - restore on exit */
247static void sd_stop0(struct gspca_dev *gspca_dev)
248{
249 struct sd *dev = (struct sd *) gspca_dev;
250
251 /* wait for the work queue to terminate */
252 mutex_unlock(&gspca_dev->usb_lock);
253 /* This waits for sq905c_dostream to finish */
254 destroy_workqueue(dev->work_thread);
255 dev->work_thread = NULL;
256 mutex_lock(&gspca_dev->usb_lock);
257}
258
259/* this function is called at probe and resume time */
260static int sd_init(struct gspca_dev *gspca_dev)
261{
262 int ret;
263
264 /* connect to the camera and reset it. */
265 ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
266 return ret;
267}
268
269/* Set up for getting frames. */
270static int sd_start(struct gspca_dev *gspca_dev)
271{
272 struct sd *dev = (struct sd *) gspca_dev;
273 int ret;
274
275 dev->cap_mode = gspca_dev->cam.cam_mode;
276 /* "Open the shutter" and set size, to start capture */
277 switch (gspca_dev->width) {
278 case 640:
279 PDEBUG(D_STREAM, "Start streaming at high resolution");
280 dev->cap_mode++;
281 ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
282 SQ905C_CAPTURE_INDEX);
283 break;
284 default: /* 320 */
285 PDEBUG(D_STREAM, "Start streaming at medium resolution");
286 ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
287 SQ905C_CAPTURE_INDEX);
288 }
289
290 if (ret < 0) {
291 PDEBUG(D_ERR, "Start streaming command failed");
292 return ret;
293 }
294 /* Start the workqueue function to do the streaming */
295 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
296 queue_work(dev->work_thread, &dev->work_struct);
297
298 return 0;
299}
300
301/* Table of supported USB devices */
302static const struct usb_device_id device_table[] = {
303 {USB_DEVICE(0x2770, 0x905c)},
304 {USB_DEVICE(0x2770, 0x9050)},
305 {USB_DEVICE(0x2770, 0x9051)},
306 {USB_DEVICE(0x2770, 0x9052)},
307 {USB_DEVICE(0x2770, 0x913d)},
308 {}
309};
310
311MODULE_DEVICE_TABLE(usb, device_table);
312
313/* sub-driver description */
314static const struct sd_desc sd_desc = {
315 .name = MODULE_NAME,
316 .config = sd_config,
317 .init = sd_init,
318 .start = sd_start,
319 .stop0 = sd_stop0,
320};
321
322/* -- device connect -- */
323static int sd_probe(struct usb_interface *intf,
324 const struct usb_device_id *id)
325{
326 return gspca_dev_probe(intf, id,
327 &sd_desc,
328 sizeof(struct sd),
329 THIS_MODULE);
330}
331
332static struct usb_driver sd_driver = {
333 .name = MODULE_NAME,
334 .id_table = device_table,
335 .probe = sd_probe,
336 .disconnect = gspca_disconnect,
337#ifdef CONFIG_PM
338 .suspend = gspca_suspend,
339 .resume = gspca_resume,
340 .reset_resume = gspca_resume,
341#endif
342};
343
344module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c
new file mode 100644
index 00000000000..7e8748b31e8
--- /dev/null
+++ b/drivers/media/usb/gspca/sq930x.c
@@ -0,0 +1,1164 @@
1/*
2 * SQ930x subdriver
3 *
4 * Copyright (C) 2010 Jean-François Moine <http://moinejf.free.fr>
5 * Copyright (C) 2006 -2008 Gerard Klaver <gerard at gkall dot hobby dot nl>
6 * Copyright (C) 2007 Sam Revitch <samr7@cs.washington.edu>
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#define MODULE_NAME "sq930x"
26
27#include "gspca.h"
28
29MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"
30 "Gerard Klaver <gerard at gkall dot hobby dot nl\n"
31 "Sam Revitch <samr7@cs.washington.edu>");
32MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver");
33MODULE_LICENSE("GPL");
34
35/* Structure to hold all of our device specific stuff */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 struct { /* exposure/gain control cluster */
40 struct v4l2_ctrl *exposure;
41 struct v4l2_ctrl *gain;
42 };
43
44 u8 do_ctrl;
45 u8 gpio[2];
46 u8 sensor;
47 u8 type;
48#define Generic 0
49#define Creative_live_motion 1
50};
51enum sensors {
52 SENSOR_ICX098BQ,
53 SENSOR_LZ24BP,
54 SENSOR_MI0360,
55 SENSOR_MT9V111, /* = MI360SOC */
56 SENSOR_OV7660,
57 SENSOR_OV9630,
58};
59
60static struct v4l2_pix_format vga_mode[] = {
61 {320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
62 .bytesperline = 320,
63 .sizeimage = 320 * 240,
64 .colorspace = V4L2_COLORSPACE_SRGB,
65 .priv = 0},
66 {640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
67 .bytesperline = 640,
68 .sizeimage = 640 * 480,
69 .colorspace = V4L2_COLORSPACE_SRGB,
70 .priv = 1},
71};
72
73/* sq930x registers */
74#define SQ930_CTRL_UCBUS_IO 0x0001
75#define SQ930_CTRL_I2C_IO 0x0002
76#define SQ930_CTRL_GPIO 0x0005
77#define SQ930_CTRL_CAP_START 0x0010
78#define SQ930_CTRL_CAP_STOP 0x0011
79#define SQ930_CTRL_SET_EXPOSURE 0x001d
80#define SQ930_CTRL_RESET 0x001e
81#define SQ930_CTRL_GET_DEV_INFO 0x001f
82
83/* gpio 1 (8..15) */
84#define SQ930_GPIO_DFL_I2C_SDA 0x0001
85#define SQ930_GPIO_DFL_I2C_SCL 0x0002
86#define SQ930_GPIO_RSTBAR 0x0004
87#define SQ930_GPIO_EXTRA1 0x0040
88#define SQ930_GPIO_EXTRA2 0x0080
89/* gpio 3 (24..31) */
90#define SQ930_GPIO_POWER 0x0200
91#define SQ930_GPIO_DFL_LED 0x1000
92
93struct ucbus_write_cmd {
94 u16 bw_addr;
95 u8 bw_data;
96};
97struct i2c_write_cmd {
98 u8 reg;
99 u16 val;
100};
101
102static const struct ucbus_write_cmd icx098bq_start_0[] = {
103 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce},
104 {0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e},
105 {0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02},
106 {0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02},
107 {0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00},
108 {0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04},
109 {0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00},
110 {0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48},
111 {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
112 {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
113 {0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff},
114 {0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
115 {0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00},
116 {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
117 {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
118 {0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c},
119 {0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30},
120 {0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30},
121 {0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc},
122 {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
123 {0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00},
124 {0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00},
125 {0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa},
126 {0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa},
127 {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
128 {0xf800, 0x03}
129};
130static const struct ucbus_write_cmd icx098bq_start_1[] = {
131 {0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
132 {0xf5f4, 0xc0},
133 {0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
134 {0xf5f4, 0xc0},
135 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
136 {0xf5f9, 0x00}
137};
138
139static const struct ucbus_write_cmd icx098bq_start_2[] = {
140 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00},
141 {0xf807, 0x7f}, {0xf800, 0x03},
142 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00},
143 {0xf807, 0x7f}, {0xf800, 0x03},
144 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0},
145 {0xf807, 0x7f}, {0xf800, 0x03},
146 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
147 {0xf807, 0x7f}, {0xf800, 0x03}
148};
149
150static const struct ucbus_write_cmd lz24bp_start_0[] = {
151 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe},
152 {0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06},
153 {0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02},
154 {0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00},
155 {0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00},
156 {0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03},
157 {0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00},
158 {0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48},
159 {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
160 {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
161 {0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0},
162 {0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
163 {0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00},
164 {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
165 {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
166 {0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30},
167 {0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c},
168 {0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c},
169 {0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d},
170 {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
171 {0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d},
172 {0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d},
173 {0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04},
174 {0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04},
175 {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
176 {0xf800, 0x03}
177};
178static const struct ucbus_write_cmd lz24bp_start_1_gen[] = {
179 {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
180 {0xf5f4, 0xb3},
181 {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
182 {0xf5f4, 0xb3},
183 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
184 {0xf5f9, 0x00}
185};
186
187static const struct ucbus_write_cmd lz24bp_start_1_clm[] = {
188 {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
189 {0xf5f4, 0xc0},
190 {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
191 {0xf5f4, 0xc0},
192 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
193 {0xf5f9, 0x00}
194};
195
196static const struct ucbus_write_cmd lz24bp_start_2[] = {
197 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00},
198 {0xf807, 0x7f}, {0xf800, 0x03},
199 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00},
200 {0xf807, 0x7f}, {0xf800, 0x03},
201 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48},
202 {0xf807, 0x7f}, {0xf800, 0x03},
203 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
204 {0xf807, 0x7f}, {0xf800, 0x03}
205};
206
207static const struct ucbus_write_cmd mi0360_start_0[] = {
208 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc},
209 {0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00}
210};
211static const struct i2c_write_cmd mi0360_init_23[] = {
212 {0x30, 0x0040}, /* reserved - def 0x0005 */
213 {0x31, 0x0000}, /* reserved - def 0x002a */
214 {0x34, 0x0100}, /* reserved - def 0x0100 */
215 {0x3d, 0x068f}, /* reserved - def 0x068f */
216};
217static const struct i2c_write_cmd mi0360_init_24[] = {
218 {0x03, 0x01e5}, /* window height */
219 {0x04, 0x0285}, /* window width */
220};
221static const struct i2c_write_cmd mi0360_init_25[] = {
222 {0x35, 0x0020}, /* global gain */
223 {0x2b, 0x0020}, /* green1 gain */
224 {0x2c, 0x002a}, /* blue gain */
225 {0x2d, 0x0028}, /* red gain */
226 {0x2e, 0x0020}, /* green2 gain */
227};
228static const struct ucbus_write_cmd mi0360_start_1[] = {
229 {0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
230 {0xf5f4, 0xa6},
231 {0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
232 {0xf5f4, 0xa6},
233 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
234 {0xf5f9, 0x00}
235};
236static const struct i2c_write_cmd mi0360_start_2[] = {
237 {0x62, 0x041d}, /* reserved - def 0x0418 */
238};
239static const struct i2c_write_cmd mi0360_start_3[] = {
240 {0x05, 0x007b}, /* horiz blanking */
241};
242static const struct i2c_write_cmd mi0360_start_4[] = {
243 {0x05, 0x03f5}, /* horiz blanking */
244};
245
246static const struct i2c_write_cmd mt9v111_init_0[] = {
247 {0x01, 0x0001}, /* select IFP/SOC registers */
248 {0x06, 0x300c}, /* operating mode control */
249 {0x08, 0xcc00}, /* output format control (RGB) */
250 {0x01, 0x0004}, /* select sensor core registers */
251};
252static const struct i2c_write_cmd mt9v111_init_1[] = {
253 {0x03, 0x01e5}, /* window height */
254 {0x04, 0x0285}, /* window width */
255};
256static const struct i2c_write_cmd mt9v111_init_2[] = {
257 {0x30, 0x7800},
258 {0x31, 0x0000},
259 {0x07, 0x3002}, /* output control */
260 {0x35, 0x0020}, /* global gain */
261 {0x2b, 0x0020}, /* green1 gain */
262 {0x2c, 0x0020}, /* blue gain */
263 {0x2d, 0x0020}, /* red gain */
264 {0x2e, 0x0020}, /* green2 gain */
265};
266static const struct ucbus_write_cmd mt9v111_start_1[] = {
267 {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
268 {0xf5f4, 0xaa},
269 {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
270 {0xf5f4, 0xaa},
271 {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a},
272 {0xf5f9, 0x0a}
273};
274static const struct i2c_write_cmd mt9v111_init_3[] = {
275 {0x62, 0x0405},
276};
277static const struct i2c_write_cmd mt9v111_init_4[] = {
278/* {0x05, 0x00ce}, */
279 {0x05, 0x005d}, /* horizontal blanking */
280};
281
282static const struct ucbus_write_cmd ov7660_start_0[] = {
283 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0},
284 {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03}
285};
286
287static const struct ucbus_write_cmd ov9630_start_0[] = {
288 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00},
289 {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03}
290};
291
292/* start parameters indexed by [sensor][mode] */
293static const struct cap_s {
294 u8 cc_sizeid;
295 u8 cc_bytes[32];
296} capconfig[4][2] = {
297 [SENSOR_ICX098BQ] = {
298 {2, /* Bayer 320x240 */
299 {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
300 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
303 {4, /* Bayer 640x480 */
304 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
305 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
308 },
309 [SENSOR_LZ24BP] = {
310 {2, /* Bayer 320x240 */
311 {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
312 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
315 {4, /* Bayer 640x480 */
316 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
317 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
320 },
321 [SENSOR_MI0360] = {
322 {2, /* Bayer 320x240 */
323 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
324 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
327 {4, /* Bayer 640x480 */
328 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
329 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
332 },
333 [SENSOR_MT9V111] = {
334 {2, /* Bayer 320x240 */
335 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
336 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
339 {4, /* Bayer 640x480 */
340 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
341 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
344 },
345};
346
347struct sensor_s {
348 const char *name;
349 u8 i2c_addr;
350 u8 i2c_dum;
351 u8 gpio[5];
352 u8 cmd_len;
353 const struct ucbus_write_cmd *cmd;
354};
355
356static const struct sensor_s sensor_tb[] = {
357 [SENSOR_ICX098BQ] = {
358 "icx098bp",
359 0x00, 0x00,
360 {0,
361 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
362 SQ930_GPIO_DFL_I2C_SDA,
363 0,
364 SQ930_GPIO_RSTBAR
365 },
366 8, icx098bq_start_0
367 },
368 [SENSOR_LZ24BP] = {
369 "lz24bp",
370 0x00, 0x00,
371 {0,
372 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
373 SQ930_GPIO_DFL_I2C_SDA,
374 0,
375 SQ930_GPIO_RSTBAR
376 },
377 8, lz24bp_start_0
378 },
379 [SENSOR_MI0360] = {
380 "mi0360",
381 0x5d, 0x80,
382 {SQ930_GPIO_RSTBAR,
383 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
384 SQ930_GPIO_DFL_I2C_SDA,
385 0,
386 0
387 },
388 7, mi0360_start_0
389 },
390 [SENSOR_MT9V111] = {
391 "mt9v111",
392 0x5c, 0x7f,
393 {SQ930_GPIO_RSTBAR,
394 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
395 SQ930_GPIO_DFL_I2C_SDA,
396 0,
397 0
398 },
399 7, mi0360_start_0
400 },
401 [SENSOR_OV7660] = {
402 "ov7660",
403 0x21, 0x00,
404 {0,
405 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
406 SQ930_GPIO_DFL_I2C_SDA,
407 0,
408 SQ930_GPIO_RSTBAR
409 },
410 7, ov7660_start_0
411 },
412 [SENSOR_OV9630] = {
413 "ov9630",
414 0x30, 0x00,
415 {0,
416 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
417 SQ930_GPIO_DFL_I2C_SDA,
418 0,
419 SQ930_GPIO_RSTBAR
420 },
421 7, ov9630_start_0
422 },
423};
424
425static void reg_r(struct gspca_dev *gspca_dev,
426 u16 value, int len)
427{
428 int ret;
429
430 if (gspca_dev->usb_err < 0)
431 return;
432 ret = usb_control_msg(gspca_dev->dev,
433 usb_rcvctrlpipe(gspca_dev->dev, 0),
434 0x0c,
435 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
436 value, 0, gspca_dev->usb_buf, len,
437 500);
438 if (ret < 0) {
439 pr_err("reg_r %04x failed %d\n", value, ret);
440 gspca_dev->usb_err = ret;
441 }
442}
443
444static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
445{
446 int ret;
447
448 if (gspca_dev->usb_err < 0)
449 return;
450 PDEBUG(D_USBO, "reg_w v: %04x i: %04x", value, index);
451 ret = usb_control_msg(gspca_dev->dev,
452 usb_sndctrlpipe(gspca_dev->dev, 0),
453 0x0c, /* request */
454 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
455 value, index, NULL, 0,
456 500);
457 msleep(30);
458 if (ret < 0) {
459 pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
460 gspca_dev->usb_err = ret;
461 }
462}
463
464static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,
465 const u8 *data, int len)
466{
467 int ret;
468
469 if (gspca_dev->usb_err < 0)
470 return;
471 PDEBUG(D_USBO, "reg_wb v: %04x i: %04x %02x...%02x",
472 value, index, *data, data[len - 1]);
473 memcpy(gspca_dev->usb_buf, data, len);
474 ret = usb_control_msg(gspca_dev->dev,
475 usb_sndctrlpipe(gspca_dev->dev, 0),
476 0x0c, /* request */
477 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
478 value, index, gspca_dev->usb_buf, len,
479 1000);
480 msleep(30);
481 if (ret < 0) {
482 pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
483 gspca_dev->usb_err = ret;
484 }
485}
486
487static void i2c_write(struct sd *sd,
488 const struct i2c_write_cmd *cmd,
489 int ncmds)
490{
491 struct gspca_dev *gspca_dev = &sd->gspca_dev;
492 const struct sensor_s *sensor;
493 u16 val, idx;
494 u8 *buf;
495 int ret;
496
497 if (gspca_dev->usb_err < 0)
498 return;
499
500 sensor = &sensor_tb[sd->sensor];
501
502 val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO;
503 idx = (cmd->val & 0xff00) | cmd->reg;
504
505 buf = gspca_dev->usb_buf;
506 *buf++ = sensor->i2c_dum;
507 *buf++ = cmd->val;
508
509 while (--ncmds > 0) {
510 cmd++;
511 *buf++ = cmd->reg;
512 *buf++ = cmd->val >> 8;
513 *buf++ = sensor->i2c_dum;
514 *buf++ = cmd->val;
515 }
516
517 PDEBUG(D_USBO, "i2c_w v: %04x i: %04x %02x...%02x",
518 val, idx, gspca_dev->usb_buf[0], buf[-1]);
519 ret = usb_control_msg(gspca_dev->dev,
520 usb_sndctrlpipe(gspca_dev->dev, 0),
521 0x0c, /* request */
522 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
523 val, idx,
524 gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
525 500);
526 if (ret < 0) {
527 pr_err("i2c_write failed %d\n", ret);
528 gspca_dev->usb_err = ret;
529 }
530}
531
532static void ucbus_write(struct gspca_dev *gspca_dev,
533 const struct ucbus_write_cmd *cmd,
534 int ncmds,
535 int batchsize)
536{
537 u8 *buf;
538 u16 val, idx;
539 int len, ret;
540
541 if (gspca_dev->usb_err < 0)
542 return;
543
544#ifdef GSPCA_DEBUG
545 if ((batchsize - 1) * 3 > USB_BUF_SZ) {
546 pr_err("Bug: usb_buf overflow\n");
547 gspca_dev->usb_err = -ENOMEM;
548 return;
549 }
550#endif
551
552 for (;;) {
553 len = ncmds;
554 if (len > batchsize)
555 len = batchsize;
556 ncmds -= len;
557
558 val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO;
559 idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8);
560
561 buf = gspca_dev->usb_buf;
562 while (--len > 0) {
563 cmd++;
564 *buf++ = cmd->bw_addr;
565 *buf++ = cmd->bw_addr >> 8;
566 *buf++ = cmd->bw_data;
567 }
568 if (buf != gspca_dev->usb_buf)
569 PDEBUG(D_USBO, "ucbus v: %04x i: %04x %02x...%02x",
570 val, idx,
571 gspca_dev->usb_buf[0], buf[-1]);
572 else
573 PDEBUG(D_USBO, "ucbus v: %04x i: %04x",
574 val, idx);
575 ret = usb_control_msg(gspca_dev->dev,
576 usb_sndctrlpipe(gspca_dev->dev, 0),
577 0x0c, /* request */
578 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
579 val, idx,
580 gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
581 500);
582 if (ret < 0) {
583 pr_err("ucbus_write failed %d\n", ret);
584 gspca_dev->usb_err = ret;
585 return;
586 }
587 msleep(30);
588 if (ncmds <= 0)
589 break;
590 cmd++;
591 }
592}
593
594static void gpio_set(struct sd *sd, u16 val, u16 mask)
595{
596 struct gspca_dev *gspca_dev = &sd->gspca_dev;
597
598 if (mask & 0x00ff) {
599 sd->gpio[0] &= ~mask;
600 sd->gpio[0] |= val;
601 reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO,
602 ~sd->gpio[0] << 8);
603 }
604 mask >>= 8;
605 val >>= 8;
606 if (mask) {
607 sd->gpio[1] &= ~mask;
608 sd->gpio[1] |= val;
609 reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO,
610 ~sd->gpio[1] << 8);
611 }
612}
613
614static void gpio_init(struct sd *sd,
615 const u8 *gpio)
616{
617 gpio_set(sd, *gpio++, 0x000f);
618 gpio_set(sd, *gpio++, 0x000f);
619 gpio_set(sd, *gpio++, 0x000f);
620 gpio_set(sd, *gpio++, 0x000f);
621 gpio_set(sd, *gpio, 0x000f);
622}
623
624static void bridge_init(struct sd *sd)
625{
626 static const struct ucbus_write_cmd clkfreq_cmd = {
627 0xf031, 0 /* SQ930_CLKFREQ_60MHZ */
628 };
629
630 ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1);
631
632 gpio_set(sd, SQ930_GPIO_POWER, 0xff00);
633}
634
635static void cmos_probe(struct gspca_dev *gspca_dev)
636{
637 struct sd *sd = (struct sd *) gspca_dev;
638 int i;
639 const struct sensor_s *sensor;
640 static const u8 probe_order[] = {
641/* SENSOR_LZ24BP, (tested as ccd) */
642 SENSOR_OV9630,
643 SENSOR_MI0360,
644 SENSOR_OV7660,
645 SENSOR_MT9V111,
646 };
647
648 for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
649 sensor = &sensor_tb[probe_order[i]];
650 ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8);
651 gpio_init(sd, sensor->gpio);
652 msleep(100);
653 reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1);
654 msleep(100);
655 if (gspca_dev->usb_buf[0] != 0)
656 break;
657 }
658 if (i >= ARRAY_SIZE(probe_order)) {
659 pr_err("Unknown sensor\n");
660 gspca_dev->usb_err = -EINVAL;
661 return;
662 }
663 sd->sensor = probe_order[i];
664 switch (sd->sensor) {
665 case SENSOR_OV7660:
666 case SENSOR_OV9630:
667 pr_err("Sensor %s not yet treated\n",
668 sensor_tb[sd->sensor].name);
669 gspca_dev->usb_err = -EINVAL;
670 break;
671 }
672}
673
674static void mt9v111_init(struct gspca_dev *gspca_dev)
675{
676 int i, nwait;
677 static const u8 cmd_001b[] = {
678 0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00,
679 0x00, 0x00, 0x00
680 };
681 static const u8 cmd_011b[][7] = {
682 {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00},
683 {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00},
684 {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00},
685 {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00},
686 };
687
688 reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b);
689 for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) {
690 reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i],
691 ARRAY_SIZE(cmd_011b[0]));
692 msleep(400);
693 nwait = 20;
694 for (;;) {
695 reg_r(gspca_dev, 0x031b, 1);
696 if (gspca_dev->usb_buf[0] == 0
697 || gspca_dev->usb_err != 0)
698 break;
699 if (--nwait < 0) {
700 PDEBUG(D_PROBE, "mt9v111_init timeout");
701 gspca_dev->usb_err = -ETIME;
702 return;
703 }
704 msleep(50);
705 }
706 }
707}
708
709static void global_init(struct sd *sd, int first_time)
710{
711 switch (sd->sensor) {
712 case SENSOR_ICX098BQ:
713 if (first_time)
714 ucbus_write(&sd->gspca_dev,
715 icx098bq_start_0,
716 8, 8);
717 gpio_init(sd, sensor_tb[sd->sensor].gpio);
718 break;
719 case SENSOR_LZ24BP:
720 if (sd->type != Creative_live_motion)
721 gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff);
722 else
723 gpio_set(sd, 0, 0x00ff);
724 msleep(50);
725 if (first_time)
726 ucbus_write(&sd->gspca_dev,
727 lz24bp_start_0,
728 8, 8);
729 gpio_init(sd, sensor_tb[sd->sensor].gpio);
730 break;
731 case SENSOR_MI0360:
732 if (first_time)
733 ucbus_write(&sd->gspca_dev,
734 mi0360_start_0,
735 ARRAY_SIZE(mi0360_start_0),
736 8);
737 gpio_init(sd, sensor_tb[sd->sensor].gpio);
738 gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2);
739 break;
740 default:
741/* case SENSOR_MT9V111: */
742 if (first_time)
743 mt9v111_init(&sd->gspca_dev);
744 else
745 gpio_init(sd, sensor_tb[sd->sensor].gpio);
746 break;
747 }
748}
749
750static void lz24bp_ppl(struct sd *sd, u16 ppl)
751{
752 struct ucbus_write_cmd cmds[2] = {
753 {0xf810, ppl >> 8},
754 {0xf811, ppl}
755 };
756
757 ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2);
758}
759
760static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain)
761{
762 struct sd *sd = (struct sd *) gspca_dev;
763 int i, integclks, intstartclk, frameclks, min_frclk;
764 const struct sensor_s *sensor;
765 u16 cmd;
766 u8 buf[15];
767
768 integclks = expo;
769 i = 0;
770 cmd = SQ930_CTRL_SET_EXPOSURE;
771
772 switch (sd->sensor) {
773 case SENSOR_ICX098BQ: /* ccd */
774 case SENSOR_LZ24BP:
775 min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f;
776 if (integclks >= min_frclk) {
777 intstartclk = 0;
778 frameclks = integclks;
779 } else {
780 intstartclk = min_frclk - integclks;
781 frameclks = min_frclk;
782 }
783 buf[i++] = intstartclk >> 8;
784 buf[i++] = intstartclk;
785 buf[i++] = frameclks >> 8;
786 buf[i++] = frameclks;
787 buf[i++] = gain;
788 break;
789 default: /* cmos */
790/* case SENSOR_MI0360: */
791/* case SENSOR_MT9V111: */
792 cmd |= 0x0100;
793 sensor = &sensor_tb[sd->sensor];
794 buf[i++] = sensor->i2c_addr; /* i2c_slave_addr */
795 buf[i++] = 0x08; /* 2 * ni2c */
796 buf[i++] = 0x09; /* reg = shutter width */
797 buf[i++] = integclks >> 8; /* val H */
798 buf[i++] = sensor->i2c_dum;
799 buf[i++] = integclks; /* val L */
800 buf[i++] = 0x35; /* reg = global gain */
801 buf[i++] = 0x00; /* val H */
802 buf[i++] = sensor->i2c_dum;
803 buf[i++] = 0x80 + gain / 2; /* val L */
804 buf[i++] = 0x00;
805 buf[i++] = 0x00;
806 buf[i++] = 0x00;
807 buf[i++] = 0x00;
808 buf[i++] = 0x83;
809 break;
810 }
811 reg_wb(gspca_dev, cmd, 0, buf, i);
812}
813
814/* This function is called at probe time just before sd_init */
815static int sd_config(struct gspca_dev *gspca_dev,
816 const struct usb_device_id *id)
817{
818 struct sd *sd = (struct sd *) gspca_dev;
819 struct cam *cam = &gspca_dev->cam;
820
821 sd->sensor = id->driver_info >> 8;
822 sd->type = id->driver_info;
823
824 cam->cam_mode = vga_mode;
825 cam->nmodes = ARRAY_SIZE(vga_mode);
826
827 cam->bulk = 1;
828
829 return 0;
830}
831
832/* this function is called at probe and resume time */
833static int sd_init(struct gspca_dev *gspca_dev)
834{
835 struct sd *sd = (struct sd *) gspca_dev;
836
837 sd->gpio[0] = sd->gpio[1] = 0xff; /* force gpio rewrite */
838
839/*fixme: is this needed for icx098bp and mi0360?
840 if (sd->sensor != SENSOR_LZ24BP)
841 reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000);
842 */
843
844 reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8);
845 if (gspca_dev->usb_err < 0)
846 return gspca_dev->usb_err;
847
848/* it returns:
849 * 03 00 12 93 0b f6 c9 00 live! ultra
850 * 03 00 07 93 0b f6 ca 00 live! ultra for notebook
851 * 03 00 12 93 0b fe c8 00 Trust WB-3500T
852 * 02 00 06 93 0b fe c8 00 Joy-IT 318S
853 * 03 00 12 93 0b f6 cf 00 icam tracer - sensor icx098bq
854 * 02 00 12 93 0b fe cf 00 ProQ Motion Webcam
855 *
856 * byte
857 * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit)
858 * 1: 00
859 * 2: 06 / 07 / 12 = mode webcam? firmware??
860 * 3: 93 chip = 930b (930b or 930c)
861 * 4: 0b
862 * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors)
863 * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam?
864 * 7: 00
865 */
866 PDEBUG(D_PROBE, "info: %*ph", 8, gspca_dev->usb_buf);
867
868 bridge_init(sd);
869
870 if (sd->sensor == SENSOR_MI0360) {
871
872 /* no sensor probe for icam tracer */
873 if (gspca_dev->usb_buf[5] == 0xf6) /* if ccd */
874 sd->sensor = SENSOR_ICX098BQ;
875 else
876 cmos_probe(gspca_dev);
877 }
878 if (gspca_dev->usb_err >= 0) {
879 PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
880 global_init(sd, 1);
881 }
882 return gspca_dev->usb_err;
883}
884
885/* send the start/stop commands to the webcam */
886static void send_start(struct gspca_dev *gspca_dev)
887{
888 struct sd *sd = (struct sd *) gspca_dev;
889 const struct cap_s *cap;
890 int mode;
891
892 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
893 cap = &capconfig[sd->sensor][mode];
894 reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START,
895 0x0a00 | cap->cc_sizeid,
896 cap->cc_bytes, 32);
897}
898
899static void send_stop(struct gspca_dev *gspca_dev)
900{
901 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0);
902}
903
904/* function called at start time before URB creation */
905static int sd_isoc_init(struct gspca_dev *gspca_dev)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */
910 sd->do_ctrl = 0;
911 gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8;
912 return 0;
913}
914
915/* start the capture */
916static int sd_start(struct gspca_dev *gspca_dev)
917{
918 struct sd *sd = (struct sd *) gspca_dev;
919 int mode;
920
921 bridge_init(sd);
922 global_init(sd, 0);
923 msleep(100);
924
925 switch (sd->sensor) {
926 case SENSOR_ICX098BQ:
927 ucbus_write(gspca_dev, icx098bq_start_0,
928 ARRAY_SIZE(icx098bq_start_0),
929 8);
930 ucbus_write(gspca_dev, icx098bq_start_1,
931 ARRAY_SIZE(icx098bq_start_1),
932 5);
933 ucbus_write(gspca_dev, icx098bq_start_2,
934 ARRAY_SIZE(icx098bq_start_2),
935 6);
936 msleep(50);
937
938 /* 1st start */
939 send_start(gspca_dev);
940 gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
941 msleep(70);
942 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000);
943 gpio_set(sd, 0x7f, 0x00ff);
944
945 /* 2nd start */
946 send_start(gspca_dev);
947 gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
948 goto out;
949 case SENSOR_LZ24BP:
950 ucbus_write(gspca_dev, lz24bp_start_0,
951 ARRAY_SIZE(lz24bp_start_0),
952 8);
953 if (sd->type != Creative_live_motion)
954 ucbus_write(gspca_dev, lz24bp_start_1_gen,
955 ARRAY_SIZE(lz24bp_start_1_gen),
956 5);
957 else
958 ucbus_write(gspca_dev, lz24bp_start_1_clm,
959 ARRAY_SIZE(lz24bp_start_1_clm),
960 5);
961 ucbus_write(gspca_dev, lz24bp_start_2,
962 ARRAY_SIZE(lz24bp_start_2),
963 6);
964 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
965 lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310);
966 msleep(10);
967 break;
968 case SENSOR_MI0360:
969 ucbus_write(gspca_dev, mi0360_start_0,
970 ARRAY_SIZE(mi0360_start_0),
971 8);
972 i2c_write(sd, mi0360_init_23,
973 ARRAY_SIZE(mi0360_init_23));
974 i2c_write(sd, mi0360_init_24,
975 ARRAY_SIZE(mi0360_init_24));
976 i2c_write(sd, mi0360_init_25,
977 ARRAY_SIZE(mi0360_init_25));
978 ucbus_write(gspca_dev, mi0360_start_1,
979 ARRAY_SIZE(mi0360_start_1),
980 5);
981 i2c_write(sd, mi0360_start_2,
982 ARRAY_SIZE(mi0360_start_2));
983 i2c_write(sd, mi0360_start_3,
984 ARRAY_SIZE(mi0360_start_3));
985
986 /* 1st start */
987 send_start(gspca_dev);
988 msleep(60);
989 send_stop(gspca_dev);
990
991 i2c_write(sd,
992 mi0360_start_4, ARRAY_SIZE(mi0360_start_4));
993 break;
994 default:
995/* case SENSOR_MT9V111: */
996 ucbus_write(gspca_dev, mi0360_start_0,
997 ARRAY_SIZE(mi0360_start_0),
998 8);
999 i2c_write(sd, mt9v111_init_0,
1000 ARRAY_SIZE(mt9v111_init_0));
1001 i2c_write(sd, mt9v111_init_1,
1002 ARRAY_SIZE(mt9v111_init_1));
1003 i2c_write(sd, mt9v111_init_2,
1004 ARRAY_SIZE(mt9v111_init_2));
1005 ucbus_write(gspca_dev, mt9v111_start_1,
1006 ARRAY_SIZE(mt9v111_start_1),
1007 5);
1008 i2c_write(sd, mt9v111_init_3,
1009 ARRAY_SIZE(mt9v111_init_3));
1010 i2c_write(sd, mt9v111_init_4,
1011 ARRAY_SIZE(mt9v111_init_4));
1012 break;
1013 }
1014
1015 send_start(gspca_dev);
1016out:
1017 msleep(1000);
1018
1019 if (sd->sensor == SENSOR_MT9V111)
1020 gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED);
1021
1022 sd->do_ctrl = 1; /* set the exposure */
1023
1024 return gspca_dev->usb_err;
1025}
1026
1027static void sd_stopN(struct gspca_dev *gspca_dev)
1028{
1029 struct sd *sd = (struct sd *) gspca_dev;
1030
1031 if (sd->sensor == SENSOR_MT9V111)
1032 gpio_set(sd, 0, SQ930_GPIO_DFL_LED);
1033 send_stop(gspca_dev);
1034}
1035
1036/* function called when the application gets a new frame */
1037/* It sets the exposure if required and restart the bulk transfer. */
1038static void sd_dq_callback(struct gspca_dev *gspca_dev)
1039{
1040 struct sd *sd = (struct sd *) gspca_dev;
1041 int ret;
1042
1043 if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0)
1044 return;
1045 sd->do_ctrl = 0;
1046
1047 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure),
1048 v4l2_ctrl_g_ctrl(sd->gain));
1049
1050 gspca_dev->cam.bulk_nurbs = 1;
1051 ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
1052 if (ret < 0)
1053 pr_err("sd_dq_callback() err %d\n", ret);
1054
1055 /* wait a little time, otherwise the webcam crashes */
1056 msleep(100);
1057}
1058
1059static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1060 u8 *data, /* isoc packet */
1061 int len) /* iso packet length */
1062{
1063 struct sd *sd = (struct sd *) gspca_dev;
1064
1065 if (sd->do_ctrl)
1066 gspca_dev->cam.bulk_nurbs = 0;
1067 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
1068 gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8);
1069 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1070}
1071
1072static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1073{
1074 struct gspca_dev *gspca_dev =
1075 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1076 struct sd *sd = (struct sd *) gspca_dev;
1077
1078 gspca_dev->usb_err = 0;
1079
1080 if (!gspca_dev->streaming)
1081 return 0;
1082
1083 switch (ctrl->id) {
1084 case V4L2_CID_EXPOSURE:
1085 setexposure(gspca_dev, ctrl->val, sd->gain->val);
1086 break;
1087 }
1088 return gspca_dev->usb_err;
1089}
1090
1091static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1092 .s_ctrl = sd_s_ctrl,
1093};
1094
1095static int sd_init_controls(struct gspca_dev *gspca_dev)
1096{
1097 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1098 struct sd *sd = (struct sd *) gspca_dev;
1099
1100 gspca_dev->vdev.ctrl_handler = hdl;
1101 v4l2_ctrl_handler_init(hdl, 2);
1102 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1103 V4L2_CID_EXPOSURE, 1, 0xfff, 1, 0x356);
1104 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1105 V4L2_CID_GAIN, 1, 255, 1, 0x8d);
1106
1107 if (hdl->error) {
1108 pr_err("Could not initialize controls\n");
1109 return hdl->error;
1110 }
1111 v4l2_ctrl_cluster(2, &sd->exposure);
1112 return 0;
1113}
1114
1115/* sub-driver description */
1116static const struct sd_desc sd_desc = {
1117 .name = MODULE_NAME,
1118 .config = sd_config,
1119 .init = sd_init,
1120 .init_controls = sd_init_controls,
1121 .isoc_init = sd_isoc_init,
1122 .start = sd_start,
1123 .stopN = sd_stopN,
1124 .pkt_scan = sd_pkt_scan,
1125 .dq_callback = sd_dq_callback,
1126};
1127
1128/* Table of supported USB devices */
1129#define ST(sensor, type) \
1130 .driver_info = (SENSOR_ ## sensor << 8) \
1131 | (type)
1132static const struct usb_device_id device_table[] = {
1133 {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)},
1134 {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)},
1135 {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)},
1136 {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)},
1137 {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)},
1138 {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)},
1139 {}
1140};
1141MODULE_DEVICE_TABLE(usb, device_table);
1142
1143
1144/* -- device connect -- */
1145static int sd_probe(struct usb_interface *intf,
1146 const struct usb_device_id *id)
1147{
1148 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1149 THIS_MODULE);
1150}
1151
1152static struct usb_driver sd_driver = {
1153 .name = MODULE_NAME,
1154 .id_table = device_table,
1155 .probe = sd_probe,
1156 .disconnect = gspca_disconnect,
1157#ifdef CONFIG_PM
1158 .suspend = gspca_suspend,
1159 .resume = gspca_resume,
1160 .reset_resume = gspca_resume,
1161#endif
1162};
1163
1164module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/stk014.c b/drivers/media/usb/gspca/stk014.c
new file mode 100644
index 00000000000..8c0982607f2
--- /dev/null
+++ b/drivers/media/usb/gspca/stk014.c
@@ -0,0 +1,446 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23#define MODULE_NAME "stk014"
24
25#include "gspca.h"
26#include "jpeg.h"
27
28MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
29MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32#define QUALITY 50
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37 u8 jpeg_hdr[JPEG_HDR_SZ];
38};
39
40static const struct v4l2_pix_format vga_mode[] = {
41 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
42 .bytesperline = 320,
43 .sizeimage = 320 * 240 * 3 / 8 + 590,
44 .colorspace = V4L2_COLORSPACE_JPEG,
45 .priv = 1},
46 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
47 .bytesperline = 640,
48 .sizeimage = 640 * 480 * 3 / 8 + 590,
49 .colorspace = V4L2_COLORSPACE_JPEG,
50 .priv = 0},
51};
52
53/* -- read a register -- */
54static u8 reg_r(struct gspca_dev *gspca_dev,
55 __u16 index)
56{
57 struct usb_device *dev = gspca_dev->dev;
58 int ret;
59
60 if (gspca_dev->usb_err < 0)
61 return 0;
62 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
63 0x00,
64 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
65 0x00,
66 index,
67 gspca_dev->usb_buf, 1,
68 500);
69 if (ret < 0) {
70 pr_err("reg_r err %d\n", ret);
71 gspca_dev->usb_err = ret;
72 return 0;
73 }
74 return gspca_dev->usb_buf[0];
75}
76
77/* -- write a register -- */
78static void reg_w(struct gspca_dev *gspca_dev,
79 __u16 index, __u16 value)
80{
81 struct usb_device *dev = gspca_dev->dev;
82 int ret;
83
84 if (gspca_dev->usb_err < 0)
85 return;
86 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
87 0x01,
88 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
89 value,
90 index,
91 NULL,
92 0,
93 500);
94 if (ret < 0) {
95 pr_err("reg_w err %d\n", ret);
96 gspca_dev->usb_err = ret;
97 }
98}
99
100/* -- get a bulk value (4 bytes) -- */
101static void rcv_val(struct gspca_dev *gspca_dev,
102 int ads)
103{
104 struct usb_device *dev = gspca_dev->dev;
105 int alen, ret;
106
107 reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
108 reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
109 reg_w(gspca_dev, 0x636, ads & 0xff);
110 reg_w(gspca_dev, 0x637, 0);
111 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */
112 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */
113 reg_w(gspca_dev, 0x63a, 0);
114 reg_w(gspca_dev, 0x63b, 0);
115 reg_w(gspca_dev, 0x630, 5);
116 if (gspca_dev->usb_err < 0)
117 return;
118 ret = usb_bulk_msg(dev,
119 usb_rcvbulkpipe(dev, 0x05),
120 gspca_dev->usb_buf,
121 4, /* length */
122 &alen,
123 500); /* timeout in milliseconds */
124 if (ret < 0) {
125 pr_err("rcv_val err %d\n", ret);
126 gspca_dev->usb_err = ret;
127 }
128}
129
130/* -- send a bulk value -- */
131static void snd_val(struct gspca_dev *gspca_dev,
132 int ads,
133 unsigned int val)
134{
135 struct usb_device *dev = gspca_dev->dev;
136 int alen, ret;
137 __u8 seq = 0;
138
139 if (ads == 0x003f08) {
140 reg_r(gspca_dev, 0x0704);
141 seq = reg_r(gspca_dev, 0x0705);
142 reg_r(gspca_dev, 0x0650);
143 reg_w(gspca_dev, 0x654, seq);
144 } else {
145 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
146 }
147 reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
148 reg_w(gspca_dev, 0x656, ads & 0xff);
149 reg_w(gspca_dev, 0x657, 0);
150 reg_w(gspca_dev, 0x658, 0x04); /* size */
151 reg_w(gspca_dev, 0x659, 0);
152 reg_w(gspca_dev, 0x65a, 0);
153 reg_w(gspca_dev, 0x65b, 0);
154 reg_w(gspca_dev, 0x650, 5);
155 if (gspca_dev->usb_err < 0)
156 return;
157 gspca_dev->usb_buf[0] = val >> 24;
158 gspca_dev->usb_buf[1] = val >> 16;
159 gspca_dev->usb_buf[2] = val >> 8;
160 gspca_dev->usb_buf[3] = val;
161 ret = usb_bulk_msg(dev,
162 usb_sndbulkpipe(dev, 6),
163 gspca_dev->usb_buf,
164 4,
165 &alen,
166 500); /* timeout in milliseconds */
167 if (ret < 0) {
168 pr_err("snd_val err %d\n", ret);
169 gspca_dev->usb_err = ret;
170 } else {
171 if (ads == 0x003f08) {
172 seq += 4;
173 seq &= 0x3f;
174 reg_w(gspca_dev, 0x705, seq);
175 }
176 }
177}
178
179/* set a camera parameter */
180static void set_par(struct gspca_dev *gspca_dev,
181 int parval)
182{
183 snd_val(gspca_dev, 0x003f08, parval);
184}
185
186static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
187{
188 int parval;
189
190 parval = 0x06000000 /* whiteness */
191 + (val << 16);
192 set_par(gspca_dev, parval);
193}
194
195static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
196{
197 int parval;
198
199 parval = 0x07000000 /* contrast */
200 + (val << 16);
201 set_par(gspca_dev, parval);
202}
203
204static void setcolors(struct gspca_dev *gspca_dev, s32 val)
205{
206 int parval;
207
208 parval = 0x08000000 /* saturation */
209 + (val << 16);
210 set_par(gspca_dev, parval);
211}
212
213static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
214{
215 set_par(gspca_dev, val == 1
216 ? 0x33640000 /* 50 Hz */
217 : 0x33780000); /* 60 Hz */
218}
219
220/* this function is called at probe time */
221static int sd_config(struct gspca_dev *gspca_dev,
222 const struct usb_device_id *id)
223{
224 gspca_dev->cam.cam_mode = vga_mode;
225 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
226 return 0;
227}
228
229/* this function is called at probe and resume time */
230static int sd_init(struct gspca_dev *gspca_dev)
231{
232 u8 ret;
233
234 /* check if the device responds */
235 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
236 ret = reg_r(gspca_dev, 0x0740);
237 if (gspca_dev->usb_err >= 0) {
238 if (ret != 0xff) {
239 pr_err("init reg: 0x%02x\n", ret);
240 gspca_dev->usb_err = -EIO;
241 }
242 }
243 return gspca_dev->usb_err;
244}
245
246/* -- start the camera -- */
247static int sd_start(struct gspca_dev *gspca_dev)
248{
249 struct sd *sd = (struct sd *) gspca_dev;
250 int ret, value;
251
252 /* create the JPEG header */
253 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
254 0x22); /* JPEG 411 */
255 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
256
257 /* work on alternate 1 */
258 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
259
260 set_par(gspca_dev, 0x10000000);
261 set_par(gspca_dev, 0x00000000);
262 set_par(gspca_dev, 0x8002e001);
263 set_par(gspca_dev, 0x14000000);
264 if (gspca_dev->width > 320)
265 value = 0x8002e001; /* 640x480 */
266 else
267 value = 0x4001f000; /* 320x240 */
268 set_par(gspca_dev, value);
269 ret = usb_set_interface(gspca_dev->dev,
270 gspca_dev->iface,
271 gspca_dev->alt);
272 if (ret < 0) {
273 pr_err("set intf %d %d failed\n",
274 gspca_dev->iface, gspca_dev->alt);
275 gspca_dev->usb_err = ret;
276 goto out;
277 }
278 reg_r(gspca_dev, 0x0630);
279 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
280 reg_r(gspca_dev, 0x0650);
281 snd_val(gspca_dev, 0x000020, 0xffffffff);
282 reg_w(gspca_dev, 0x0620, 0);
283 reg_w(gspca_dev, 0x0630, 0);
284 reg_w(gspca_dev, 0x0640, 0);
285 reg_w(gspca_dev, 0x0650, 0);
286 reg_w(gspca_dev, 0x0660, 0);
287 set_par(gspca_dev, 0x09800000); /* Red ? */
288 set_par(gspca_dev, 0x0a800000); /* Green ? */
289 set_par(gspca_dev, 0x0b800000); /* Blue ? */
290 set_par(gspca_dev, 0x0d030000); /* Gamma ? */
291
292 /* start the video flow */
293 set_par(gspca_dev, 0x01000000);
294 set_par(gspca_dev, 0x01000000);
295 if (gspca_dev->usb_err >= 0)
296 PDEBUG(D_STREAM, "camera started alt: 0x%02x",
297 gspca_dev->alt);
298out:
299 return gspca_dev->usb_err;
300}
301
302static void sd_stopN(struct gspca_dev *gspca_dev)
303{
304 struct usb_device *dev = gspca_dev->dev;
305
306 set_par(gspca_dev, 0x02000000);
307 set_par(gspca_dev, 0x02000000);
308 usb_set_interface(dev, gspca_dev->iface, 1);
309 reg_r(gspca_dev, 0x0630);
310 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
311 reg_r(gspca_dev, 0x0650);
312 snd_val(gspca_dev, 0x000020, 0xffffffff);
313 reg_w(gspca_dev, 0x0620, 0);
314 reg_w(gspca_dev, 0x0630, 0);
315 reg_w(gspca_dev, 0x0640, 0);
316 reg_w(gspca_dev, 0x0650, 0);
317 reg_w(gspca_dev, 0x0660, 0);
318 PDEBUG(D_STREAM, "camera stopped");
319}
320
321static void sd_pkt_scan(struct gspca_dev *gspca_dev,
322 u8 *data, /* isoc packet */
323 int len) /* iso packet length */
324{
325 struct sd *sd = (struct sd *) gspca_dev;
326 static unsigned char ffd9[] = {0xff, 0xd9};
327
328 /* a frame starts with:
329 * - 0xff 0xfe
330 * - 0x08 0x00 - length (little endian ?!)
331 * - 4 bytes = size of whole frame (BE - including header)
332 * - 0x00 0x0c
333 * - 0xff 0xd8
334 * - .. JPEG image with escape sequences (ff 00)
335 * (without ending - ff d9)
336 */
337 if (data[0] == 0xff && data[1] == 0xfe) {
338 gspca_frame_add(gspca_dev, LAST_PACKET,
339 ffd9, 2);
340
341 /* put the JPEG 411 header */
342 gspca_frame_add(gspca_dev, FIRST_PACKET,
343 sd->jpeg_hdr, JPEG_HDR_SZ);
344
345 /* beginning of the frame */
346#define STKHDRSZ 12
347 data += STKHDRSZ;
348 len -= STKHDRSZ;
349 }
350 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
351}
352
353static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
354{
355 struct gspca_dev *gspca_dev =
356 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
357
358 gspca_dev->usb_err = 0;
359
360 if (!gspca_dev->streaming)
361 return 0;
362
363 switch (ctrl->id) {
364 case V4L2_CID_BRIGHTNESS:
365 setbrightness(gspca_dev, ctrl->val);
366 break;
367 case V4L2_CID_CONTRAST:
368 setcontrast(gspca_dev, ctrl->val);
369 break;
370 case V4L2_CID_SATURATION:
371 setcolors(gspca_dev, ctrl->val);
372 break;
373 case V4L2_CID_POWER_LINE_FREQUENCY:
374 setlightfreq(gspca_dev, ctrl->val);
375 break;
376 }
377 return gspca_dev->usb_err;
378}
379
380static const struct v4l2_ctrl_ops sd_ctrl_ops = {
381 .s_ctrl = sd_s_ctrl,
382};
383
384static int sd_init_controls(struct gspca_dev *gspca_dev)
385{
386 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
387
388 gspca_dev->vdev.ctrl_handler = hdl;
389 v4l2_ctrl_handler_init(hdl, 4);
390 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
391 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
392 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
393 V4L2_CID_CONTRAST, 0, 255, 1, 127);
394 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
395 V4L2_CID_SATURATION, 0, 255, 1, 127);
396 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
397 V4L2_CID_POWER_LINE_FREQUENCY,
398 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
399 V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
400
401 if (hdl->error) {
402 pr_err("Could not initialize controls\n");
403 return hdl->error;
404 }
405 return 0;
406}
407
408/* sub-driver description */
409static const struct sd_desc sd_desc = {
410 .name = MODULE_NAME,
411 .config = sd_config,
412 .init = sd_init,
413 .init_controls = sd_init_controls,
414 .start = sd_start,
415 .stopN = sd_stopN,
416 .pkt_scan = sd_pkt_scan,
417};
418
419/* -- module initialisation -- */
420static const struct usb_device_id device_table[] = {
421 {USB_DEVICE(0x05e1, 0x0893)},
422 {}
423};
424MODULE_DEVICE_TABLE(usb, device_table);
425
426/* -- device connect -- */
427static int sd_probe(struct usb_interface *intf,
428 const struct usb_device_id *id)
429{
430 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
431 THIS_MODULE);
432}
433
434static struct usb_driver sd_driver = {
435 .name = MODULE_NAME,
436 .id_table = device_table,
437 .probe = sd_probe,
438 .disconnect = gspca_disconnect,
439#ifdef CONFIG_PM
440 .suspend = gspca_suspend,
441 .resume = gspca_resume,
442 .reset_resume = gspca_resume,
443#endif
444};
445
446module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c
new file mode 100644
index 00000000000..67605272aaa
--- /dev/null
+++ b/drivers/media/usb/gspca/stv0680.c
@@ -0,0 +1,353 @@
1/*
2 * STV0680 USB Camera Driver
3 *
4 * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
5 *
6 * This module is adapted from the in kernel v4l1 stv680 driver:
7 *
8 * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
9 *
10 * Thanks to STMicroelectronics for information on the usb commands, and
11 * to Steve Miller at STM for his help and encouragement while I was
12 * writing this driver.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#define MODULE_NAME "stv0680"
33
34#include "gspca.h"
35
36MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
37MODULE_DESCRIPTION("STV0680 USB Camera Driver");
38MODULE_LICENSE("GPL");
39
40/* specific webcam descriptor */
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43 struct v4l2_pix_format mode;
44 u8 orig_mode;
45 u8 video_mode;
46 u8 current_mode;
47};
48
49static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
50 int size)
51{
52 int ret = -1;
53 u8 req_type = 0;
54 unsigned int pipe = 0;
55
56 switch (set) {
57 case 0: /* 0xc1 */
58 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
59 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
60 break;
61 case 1: /* 0x41 */
62 req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
63 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
64 break;
65 case 2: /* 0x80 */
66 req_type = USB_DIR_IN | USB_RECIP_DEVICE;
67 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
68 break;
69 case 3: /* 0x40 */
70 req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
71 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
72 break;
73 }
74
75 ret = usb_control_msg(gspca_dev->dev, pipe,
76 req, req_type,
77 val, 0, gspca_dev->usb_buf, size, 500);
78
79 if ((ret < 0) && (req != 0x0a))
80 pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
81 set, req, ret);
82
83 return ret;
84}
85
86static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
87{
88 stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
89 PDEBUG(D_ERR, "last error: %i, command = 0x%x",
90 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
91 return ret;
92}
93
94static int stv0680_get_video_mode(struct gspca_dev *gspca_dev)
95{
96 /* Note not sure if this init of usb_buf is really necessary */
97 memset(gspca_dev->usb_buf, 0, 8);
98 gspca_dev->usb_buf[0] = 0x0f;
99
100 if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) {
101 PDEBUG(D_ERR, "Get_Camera_Mode failed");
102 return stv0680_handle_error(gspca_dev, -EIO);
103 }
104
105 return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */
106}
107
108static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode)
109{
110 struct sd *sd = (struct sd *) gspca_dev;
111
112 if (sd->current_mode == mode)
113 return 0;
114
115 memset(gspca_dev->usb_buf, 0, 8);
116 gspca_dev->usb_buf[0] = mode;
117
118 if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) {
119 PDEBUG(D_ERR, "Set_Camera_Mode failed");
120 return stv0680_handle_error(gspca_dev, -EIO);
121 }
122
123 /* Verify we got what we've asked for */
124 if (stv0680_get_video_mode(gspca_dev) != mode) {
125 PDEBUG(D_ERR, "Error setting camera video mode!");
126 return -EIO;
127 }
128
129 sd->current_mode = mode;
130
131 return 0;
132}
133
134/* this function is called at probe time */
135static int sd_config(struct gspca_dev *gspca_dev,
136 const struct usb_device_id *id)
137{
138 int ret;
139 struct sd *sd = (struct sd *) gspca_dev;
140 struct cam *cam = &gspca_dev->cam;
141
142 /* Give the camera some time to settle, otherwise initalization will
143 fail on hotplug, and yes it really needs a full second. */
144 msleep(1000);
145
146 /* ping camera to be sure STV0680 is present */
147 if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
148 gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
149 PDEBUG(D_ERR, "STV(e): camera ping failed!!");
150 return stv0680_handle_error(gspca_dev, -ENODEV);
151 }
152
153 /* get camera descriptor */
154 if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09)
155 return stv0680_handle_error(gspca_dev, -ENODEV);
156
157 if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
158 gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
159 PDEBUG(D_ERR, "Could not get descriptor 0200.");
160 return stv0680_handle_error(gspca_dev, -ENODEV);
161 }
162 if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02)
163 return stv0680_handle_error(gspca_dev, -ENODEV);
164 if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24)
165 return stv0680_handle_error(gspca_dev, -ENODEV);
166 if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
167 return stv0680_handle_error(gspca_dev, -ENODEV);
168
169 if (!(gspca_dev->usb_buf[7] & 0x09)) {
170 PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode");
171 return -ENODEV;
172 }
173 if (gspca_dev->usb_buf[7] & 0x01)
174 PDEBUG(D_PROBE, "Camera supports CIF mode");
175 if (gspca_dev->usb_buf[7] & 0x02)
176 PDEBUG(D_PROBE, "Camera supports VGA mode");
177 if (gspca_dev->usb_buf[7] & 0x04)
178 PDEBUG(D_PROBE, "Camera supports QCIF mode");
179 if (gspca_dev->usb_buf[7] & 0x08)
180 PDEBUG(D_PROBE, "Camera supports QVGA mode");
181
182 if (gspca_dev->usb_buf[7] & 0x01)
183 sd->video_mode = 0x00; /* CIF */
184 else
185 sd->video_mode = 0x03; /* QVGA */
186
187 /* FW rev, ASIC rev, sensor ID */
188 PDEBUG(D_PROBE, "Firmware rev is %i.%i",
189 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
190 PDEBUG(D_PROBE, "ASIC rev is %i.%i",
191 gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]);
192 PDEBUG(D_PROBE, "Sensor ID is %i",
193 (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4));
194
195
196 ret = stv0680_get_video_mode(gspca_dev);
197 if (ret < 0)
198 return ret;
199 sd->current_mode = sd->orig_mode = ret;
200
201 ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
202 if (ret < 0)
203 return ret;
204
205 /* Get mode details */
206 if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10)
207 return stv0680_handle_error(gspca_dev, -EIO);
208
209 cam->bulk = 1;
210 cam->bulk_nurbs = 1; /* The cam cannot handle more */
211 cam->bulk_size = (gspca_dev->usb_buf[0] << 24) |
212 (gspca_dev->usb_buf[1] << 16) |
213 (gspca_dev->usb_buf[2] << 8) |
214 (gspca_dev->usb_buf[3]);
215 sd->mode.width = (gspca_dev->usb_buf[4] << 8) |
216 (gspca_dev->usb_buf[5]); /* 322, 356, 644 */
217 sd->mode.height = (gspca_dev->usb_buf[6] << 8) |
218 (gspca_dev->usb_buf[7]); /* 242, 292, 484 */
219 sd->mode.pixelformat = V4L2_PIX_FMT_STV0680;
220 sd->mode.field = V4L2_FIELD_NONE;
221 sd->mode.bytesperline = sd->mode.width;
222 sd->mode.sizeimage = cam->bulk_size;
223 sd->mode.colorspace = V4L2_COLORSPACE_SRGB;
224
225 /* origGain = gspca_dev->usb_buf[12]; */
226
227 cam->cam_mode = &sd->mode;
228 cam->nmodes = 1;
229
230
231 ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode);
232 if (ret < 0)
233 return ret;
234
235 if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
236 gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
237 pr_err("Could not get descriptor 0100\n");
238 return stv0680_handle_error(gspca_dev, -EIO);
239 }
240
241 return 0;
242}
243
244/* this function is called at probe and resume time */
245static int sd_init(struct gspca_dev *gspca_dev)
246{
247 return 0;
248}
249
250/* -- start the camera -- */
251static int sd_start(struct gspca_dev *gspca_dev)
252{
253 int ret;
254 struct sd *sd = (struct sd *) gspca_dev;
255
256 ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
257 if (ret < 0)
258 return ret;
259
260 if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
261 return stv0680_handle_error(gspca_dev, -EIO);
262
263 /* Start stream at:
264 0x0000 = CIF (352x288)
265 0x0100 = VGA (640x480)
266 0x0300 = QVGA (320x240) */
267 if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0)
268 return stv0680_handle_error(gspca_dev, -EIO);
269
270 return 0;
271}
272
273static void sd_stopN(struct gspca_dev *gspca_dev)
274{
275 /* This is a high priority command; it stops all lower order cmds */
276 if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0)
277 stv0680_handle_error(gspca_dev, -EIO);
278}
279
280static void sd_stop0(struct gspca_dev *gspca_dev)
281{
282 struct sd *sd = (struct sd *) gspca_dev;
283
284 if (!sd->gspca_dev.present)
285 return;
286
287 stv0680_set_video_mode(gspca_dev, sd->orig_mode);
288}
289
290static void sd_pkt_scan(struct gspca_dev *gspca_dev,
291 u8 *data,
292 int len)
293{
294 struct sd *sd = (struct sd *) gspca_dev;
295
296 /* Every now and then the camera sends a 16 byte packet, no idea
297 what it contains, but it is not image data, when this
298 happens the frame received before this packet is corrupt,
299 so discard it. */
300 if (len != sd->mode.sizeimage) {
301 gspca_dev->last_packet_type = DISCARD_PACKET;
302 return;
303 }
304
305 /* Finish the previous frame, we do this upon reception of the next
306 packet, even though it is already complete so that the strange 16
307 byte packets send after a corrupt frame can discard it. */
308 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
309
310 /* Store the just received frame */
311 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
312}
313
314/* sub-driver description */
315static const struct sd_desc sd_desc = {
316 .name = MODULE_NAME,
317 .config = sd_config,
318 .init = sd_init,
319 .start = sd_start,
320 .stopN = sd_stopN,
321 .stop0 = sd_stop0,
322 .pkt_scan = sd_pkt_scan,
323};
324
325/* -- module initialisation -- */
326static const struct usb_device_id device_table[] = {
327 {USB_DEVICE(0x0553, 0x0202)},
328 {USB_DEVICE(0x041e, 0x4007)},
329 {}
330};
331MODULE_DEVICE_TABLE(usb, device_table);
332
333/* -- device connect -- */
334static int sd_probe(struct usb_interface *intf,
335 const struct usb_device_id *id)
336{
337 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
338 THIS_MODULE);
339}
340
341static struct usb_driver sd_driver = {
342 .name = MODULE_NAME,
343 .id_table = device_table,
344 .probe = sd_probe,
345 .disconnect = gspca_disconnect,
346#ifdef CONFIG_PM
347 .suspend = gspca_suspend,
348 .resume = gspca_resume,
349 .reset_resume = gspca_resume,
350#endif
351};
352
353module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/stv06xx/Kconfig b/drivers/media/usb/gspca/stv06xx/Kconfig
new file mode 100644
index 00000000000..634ad38d9fb
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/Kconfig
@@ -0,0 +1,9 @@
1config USB_STV06XX
2 tristate "STV06XX USB Camera Driver"
3 depends on USB_GSPCA
4 help
5 Say Y here if you want support for cameras based on
6 the ST STV06XX chip.
7
8 To compile this driver as a module, choose M here: the
9 module will be called gspca_stv06xx.
diff --git a/drivers/media/usb/gspca/stv06xx/Makefile b/drivers/media/usb/gspca/stv06xx/Makefile
new file mode 100644
index 00000000000..3a4b2f89904
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/Makefile
@@ -0,0 +1,10 @@
1obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o
2
3gspca_stv06xx-objs := stv06xx.o \
4 stv06xx_vv6410.o \
5 stv06xx_hdcs.o \
6 stv06xx_pb0100.o \
7 stv06xx_st6422.o
8
9ccflags-y += -I$(srctree)/drivers/media/usb/gspca
10
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
new file mode 100644
index 00000000000..999ec776444
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -0,0 +1,634 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#include <linux/input.h>
33#include "stv06xx_sensor.h"
34
35MODULE_AUTHOR("Erik Andrén");
36MODULE_DESCRIPTION("STV06XX USB Camera Driver");
37MODULE_LICENSE("GPL");
38
39static bool dump_bridge;
40static bool dump_sensor;
41
42int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
43{
44 int err;
45 struct usb_device *udev = sd->gspca_dev.dev;
46 __u8 *buf = sd->gspca_dev.usb_buf;
47 u8 len = (i2c_data > 0xff) ? 2 : 1;
48
49 buf[0] = i2c_data & 0xff;
50 buf[1] = (i2c_data >> 8) & 0xff;
51
52 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
53 0x04, 0x40, address, 0, buf, len,
54 STV06XX_URB_MSG_TIMEOUT);
55
56 PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d",
57 i2c_data, address, err);
58
59 return (err < 0) ? err : 0;
60}
61
62int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
63{
64 int err;
65 struct usb_device *udev = sd->gspca_dev.dev;
66 __u8 *buf = sd->gspca_dev.usb_buf;
67
68 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
69 0x04, 0xc0, address, 0, buf, 1,
70 STV06XX_URB_MSG_TIMEOUT);
71
72 *i2c_data = buf[0];
73
74 PDEBUG(D_CONF, "Reading 0x%x from address 0x%x, status %d",
75 *i2c_data, address, err);
76
77 return (err < 0) ? err : 0;
78}
79
80/* Wraps the normal write sensor bytes / words functions for writing a
81 single value */
82int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value)
83{
84 if (sd->sensor->i2c_len == 2) {
85 u16 data[2] = { address, value };
86 return stv06xx_write_sensor_words(sd, data, 1);
87 } else {
88 u8 data[2] = { address, value };
89 return stv06xx_write_sensor_bytes(sd, data, 1);
90 }
91}
92
93static int stv06xx_write_sensor_finish(struct sd *sd)
94{
95 int err = 0;
96
97 if (sd->bridge == BRIDGE_STV610) {
98 struct usb_device *udev = sd->gspca_dev.dev;
99 __u8 *buf = sd->gspca_dev.usb_buf;
100
101 buf[0] = 0;
102 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
103 0x04, 0x40, 0x1704, 0, buf, 1,
104 STV06XX_URB_MSG_TIMEOUT);
105 }
106
107 return (err < 0) ? err : 0;
108}
109
110int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
111{
112 int err, i, j;
113 struct usb_device *udev = sd->gspca_dev.dev;
114 __u8 *buf = sd->gspca_dev.usb_buf;
115
116 PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
117 for (i = 0; i < len;) {
118 /* Build the command buffer */
119 memset(buf, 0, I2C_BUFFER_LENGTH);
120 for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) {
121 buf[j] = data[2*i];
122 buf[0x10 + j] = data[2*i+1];
123 PDEBUG(D_CONF, "I2C: Writing 0x%02x to reg 0x%02x",
124 data[2*i+1], data[2*i]);
125 }
126 buf[0x20] = sd->sensor->i2c_addr;
127 buf[0x21] = j - 1; /* Number of commands to send - 1 */
128 buf[0x22] = I2C_WRITE_CMD;
129 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
130 0x04, 0x40, 0x0400, 0, buf,
131 I2C_BUFFER_LENGTH,
132 STV06XX_URB_MSG_TIMEOUT);
133 if (err < 0)
134 return err;
135 }
136 return stv06xx_write_sensor_finish(sd);
137}
138
139int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
140{
141 int err, i, j;
142 struct usb_device *udev = sd->gspca_dev.dev;
143 __u8 *buf = sd->gspca_dev.usb_buf;
144
145 PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
146
147 for (i = 0; i < len;) {
148 /* Build the command buffer */
149 memset(buf, 0, I2C_BUFFER_LENGTH);
150 for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) {
151 buf[j] = data[2*i];
152 buf[0x10 + j * 2] = data[2*i+1];
153 buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8;
154 PDEBUG(D_CONF, "I2C: Writing 0x%04x to reg 0x%02x",
155 data[2*i+1], data[2*i]);
156 }
157 buf[0x20] = sd->sensor->i2c_addr;
158 buf[0x21] = j - 1; /* Number of commands to send - 1 */
159 buf[0x22] = I2C_WRITE_CMD;
160 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
161 0x04, 0x40, 0x0400, 0, buf,
162 I2C_BUFFER_LENGTH,
163 STV06XX_URB_MSG_TIMEOUT);
164 if (err < 0)
165 return err;
166 }
167 return stv06xx_write_sensor_finish(sd);
168}
169
170int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
171{
172 int err;
173 struct usb_device *udev = sd->gspca_dev.dev;
174 __u8 *buf = sd->gspca_dev.usb_buf;
175
176 err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush);
177 if (err < 0)
178 return err;
179
180 /* Clear mem */
181 memset(buf, 0, I2C_BUFFER_LENGTH);
182
183 buf[0] = address;
184 buf[0x20] = sd->sensor->i2c_addr;
185 buf[0x21] = 0;
186
187 /* Read I2C register */
188 buf[0x22] = I2C_READ_CMD;
189
190 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
191 0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
192 STV06XX_URB_MSG_TIMEOUT);
193 if (err < 0) {
194 pr_err("I2C: Read error writing address: %d\n", err);
195 return err;
196 }
197
198 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
199 0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len,
200 STV06XX_URB_MSG_TIMEOUT);
201 if (sd->sensor->i2c_len == 2)
202 *value = buf[0] | (buf[1] << 8);
203 else
204 *value = buf[0];
205
206 PDEBUG(D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d",
207 *value, address, err);
208
209 return (err < 0) ? err : 0;
210}
211
212/* Dumps all bridge registers */
213static void stv06xx_dump_bridge(struct sd *sd)
214{
215 int i;
216 u8 data, buf;
217
218 pr_info("Dumping all stv06xx bridge registers\n");
219 for (i = 0x1400; i < 0x160f; i++) {
220 stv06xx_read_bridge(sd, i, &data);
221
222 pr_info("Read 0x%x from address 0x%x\n", data, i);
223 }
224
225 pr_info("Testing stv06xx bridge registers for writability\n");
226 for (i = 0x1400; i < 0x160f; i++) {
227 stv06xx_read_bridge(sd, i, &data);
228 buf = data;
229
230 stv06xx_write_bridge(sd, i, 0xff);
231 stv06xx_read_bridge(sd, i, &data);
232 if (data == 0xff)
233 pr_info("Register 0x%x is read/write\n", i);
234 else if (data != buf)
235 pr_info("Register 0x%x is read/write, but only partially\n",
236 i);
237 else
238 pr_info("Register 0x%x is read-only\n", i);
239
240 stv06xx_write_bridge(sd, i, buf);
241 }
242}
243
244/* this function is called at probe and resume time */
245static int stv06xx_init(struct gspca_dev *gspca_dev)
246{
247 struct sd *sd = (struct sd *) gspca_dev;
248 int err;
249
250 PDEBUG(D_PROBE, "Initializing camera");
251
252 /* Let the usb init settle for a bit
253 before performing the initialization */
254 msleep(250);
255
256 err = sd->sensor->init(sd);
257
258 if (dump_sensor && sd->sensor->dump)
259 sd->sensor->dump(sd);
260
261 return (err < 0) ? err : 0;
262}
263
264/* this function is called at probe time */
265static int stv06xx_init_controls(struct gspca_dev *gspca_dev)
266{
267 struct sd *sd = (struct sd *) gspca_dev;
268
269 PDEBUG(D_PROBE, "Initializing controls");
270
271 gspca_dev->vdev.ctrl_handler = &gspca_dev->ctrl_handler;
272 return sd->sensor->init_controls(sd);
273}
274
275/* Start the camera */
276static int stv06xx_start(struct gspca_dev *gspca_dev)
277{
278 struct sd *sd = (struct sd *) gspca_dev;
279 struct usb_host_interface *alt;
280 struct usb_interface *intf;
281 int err, packet_size;
282
283 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
284 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
285 if (!alt) {
286 PDEBUG(D_ERR, "Couldn't get altsetting");
287 return -EIO;
288 }
289
290 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
291 err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
292 if (err < 0)
293 return err;
294
295 /* Prepare the sensor for start */
296 err = sd->sensor->start(sd);
297 if (err < 0)
298 goto out;
299
300 /* Start isochronous streaming */
301 err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1);
302
303out:
304 if (err < 0)
305 PDEBUG(D_STREAM, "Starting stream failed");
306 else
307 PDEBUG(D_STREAM, "Started streaming");
308
309 return (err < 0) ? err : 0;
310}
311
312static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
313{
314 struct usb_host_interface *alt;
315 struct sd *sd = (struct sd *) gspca_dev;
316
317 /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
318 alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
319 alt->endpoint[0].desc.wMaxPacketSize =
320 cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
321
322 return 0;
323}
324
325static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
326{
327 int ret, packet_size, min_packet_size;
328 struct usb_host_interface *alt;
329 struct sd *sd = (struct sd *) gspca_dev;
330
331 alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
332 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
333 min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
334 if (packet_size <= min_packet_size)
335 return -EIO;
336
337 packet_size -= 100;
338 if (packet_size < min_packet_size)
339 packet_size = min_packet_size;
340 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
341
342 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
343 if (ret < 0)
344 PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
345
346 return ret;
347}
348
349static void stv06xx_stopN(struct gspca_dev *gspca_dev)
350{
351 int err;
352 struct sd *sd = (struct sd *) gspca_dev;
353
354 /* stop ISO-streaming */
355 err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
356 if (err < 0)
357 goto out;
358
359 err = sd->sensor->stop(sd);
360
361out:
362 if (err < 0)
363 PDEBUG(D_STREAM, "Failed to stop stream");
364 else
365 PDEBUG(D_STREAM, "Stopped streaming");
366}
367
368/*
369 * Analyse an USB packet of the data stream and store it appropriately.
370 * Each packet contains an integral number of chunks. Each chunk has
371 * 2-bytes identification, followed by 2-bytes that describe the chunk
372 * length. Known/guessed chunk identifications are:
373 * 8001/8005/C001/C005 - Begin new frame
374 * 8002/8006/C002/C006 - End frame
375 * 0200/4200 - Contains actual image data, bayer or compressed
376 * 0005 - 11 bytes of unknown data
377 * 0100 - 2 bytes of unknown data
378 * The 0005 and 0100 chunks seem to appear only in compressed stream.
379 */
380static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
381 u8 *data, /* isoc packet */
382 int len) /* iso packet length */
383{
384 struct sd *sd = (struct sd *) gspca_dev;
385
386 PDEBUG(D_PACK, "Packet of length %d arrived", len);
387
388 /* A packet may contain several frames
389 loop until the whole packet is reached */
390 while (len) {
391 int id, chunk_len;
392
393 if (len < 4) {
394 PDEBUG(D_PACK, "Packet is smaller than 4 bytes");
395 return;
396 }
397
398 /* Capture the id */
399 id = (data[0] << 8) | data[1];
400
401 /* Capture the chunk length */
402 chunk_len = (data[2] << 8) | data[3];
403 PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len);
404
405 data += 4;
406 len -= 4;
407
408 if (len < chunk_len) {
409 PDEBUG(D_ERR, "URB packet length is smaller"
410 " than the specified chunk length");
411 gspca_dev->last_packet_type = DISCARD_PACKET;
412 return;
413 }
414
415 /* First byte seem to be 02=data 2nd byte is unknown??? */
416 if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200)
417 goto frame_data;
418
419 switch (id) {
420 case 0x0200:
421 case 0x4200:
422frame_data:
423 PDEBUG(D_PACK, "Frame data packet detected");
424
425 if (sd->to_skip) {
426 int skip = (sd->to_skip < chunk_len) ?
427 sd->to_skip : chunk_len;
428 data += skip;
429 len -= skip;
430 chunk_len -= skip;
431 sd->to_skip -= skip;
432 }
433
434 gspca_frame_add(gspca_dev, INTER_PACKET,
435 data, chunk_len);
436 break;
437
438 case 0x8001:
439 case 0x8005:
440 case 0xc001:
441 case 0xc005:
442 PDEBUG(D_PACK, "Starting new frame");
443
444 /* Create a new frame, chunk length should be zero */
445 gspca_frame_add(gspca_dev, FIRST_PACKET,
446 NULL, 0);
447
448 if (sd->bridge == BRIDGE_ST6422)
449 sd->to_skip = gspca_dev->width * 4;
450
451 if (chunk_len)
452 PDEBUG(D_ERR, "Chunk length is "
453 "non-zero on a SOF");
454 break;
455
456 case 0x8002:
457 case 0x8006:
458 case 0xc002:
459 PDEBUG(D_PACK, "End of frame detected");
460
461 /* Complete the last frame (if any) */
462 gspca_frame_add(gspca_dev, LAST_PACKET,
463 NULL, 0);
464
465 if (chunk_len)
466 PDEBUG(D_ERR, "Chunk length is "
467 "non-zero on a EOF");
468 break;
469
470 case 0x0005:
471 PDEBUG(D_PACK, "Chunk 0x005 detected");
472 /* Unknown chunk with 11 bytes of data,
473 occurs just before end of each frame
474 in compressed mode */
475 break;
476
477 case 0x0100:
478 PDEBUG(D_PACK, "Chunk 0x0100 detected");
479 /* Unknown chunk with 2 bytes of data,
480 occurs 2-3 times per USB interrupt */
481 break;
482 case 0x42ff:
483 PDEBUG(D_PACK, "Chunk 0x42ff detected");
484 /* Special chunk seen sometimes on the ST6422 */
485 break;
486 default:
487 PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
488 /* Unknown chunk */
489 }
490 data += chunk_len;
491 len -= chunk_len;
492 }
493}
494
495#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
496static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
497 u8 *data, /* interrupt packet data */
498 int len) /* interrupt packet length */
499{
500 int ret = -EINVAL;
501
502 if (len == 1 && data[0] == 0x80) {
503 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
504 input_sync(gspca_dev->input_dev);
505 ret = 0;
506 }
507
508 if (len == 1 && data[0] == 0x88) {
509 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
510 input_sync(gspca_dev->input_dev);
511 ret = 0;
512 }
513
514 return ret;
515}
516#endif
517
518static int stv06xx_config(struct gspca_dev *gspca_dev,
519 const struct usb_device_id *id);
520
521/* sub-driver description */
522static const struct sd_desc sd_desc = {
523 .name = MODULE_NAME,
524 .config = stv06xx_config,
525 .init = stv06xx_init,
526 .init_controls = stv06xx_init_controls,
527 .start = stv06xx_start,
528 .stopN = stv06xx_stopN,
529 .pkt_scan = stv06xx_pkt_scan,
530 .isoc_init = stv06xx_isoc_init,
531 .isoc_nego = stv06xx_isoc_nego,
532#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
533 .int_pkt_scan = sd_int_pkt_scan,
534#endif
535};
536
537/* This function is called at probe time */
538static int stv06xx_config(struct gspca_dev *gspca_dev,
539 const struct usb_device_id *id)
540{
541 struct sd *sd = (struct sd *) gspca_dev;
542
543 PDEBUG(D_PROBE, "Configuring camera");
544
545 sd->bridge = id->driver_info;
546 gspca_dev->sd_desc = &sd_desc;
547
548 if (dump_bridge)
549 stv06xx_dump_bridge(sd);
550
551 sd->sensor = &stv06xx_sensor_st6422;
552 if (!sd->sensor->probe(sd))
553 return 0;
554
555 sd->sensor = &stv06xx_sensor_vv6410;
556 if (!sd->sensor->probe(sd))
557 return 0;
558
559 sd->sensor = &stv06xx_sensor_hdcs1x00;
560 if (!sd->sensor->probe(sd))
561 return 0;
562
563 sd->sensor = &stv06xx_sensor_hdcs1020;
564 if (!sd->sensor->probe(sd))
565 return 0;
566
567 sd->sensor = &stv06xx_sensor_pb0100;
568 if (!sd->sensor->probe(sd))
569 return 0;
570
571 sd->sensor = NULL;
572 return -ENODEV;
573}
574
575
576
577/* -- module initialisation -- */
578static const struct usb_device_id device_table[] = {
579 /* QuickCam Express */
580 {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
581 /* LEGO cam / QuickCam Web */
582 {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
583 /* Dexxa WebCam USB */
584 {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
585 /* QuickCam Messenger */
586 {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
587 /* QuickCam Communicate */
588 {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
589 /* QuickCam Messenger (new) */
590 {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
591 {}
592};
593MODULE_DEVICE_TABLE(usb, device_table);
594
595/* -- device connect -- */
596static int sd_probe(struct usb_interface *intf,
597 const struct usb_device_id *id)
598{
599 PDEBUG(D_PROBE, "Probing for a stv06xx device");
600 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
601 THIS_MODULE);
602}
603
604static void sd_disconnect(struct usb_interface *intf)
605{
606 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
607 struct sd *sd = (struct sd *) gspca_dev;
608 void *priv = sd->sensor_priv;
609 PDEBUG(D_PROBE, "Disconnecting the stv06xx device");
610
611 sd->sensor = NULL;
612 gspca_disconnect(intf);
613 kfree(priv);
614}
615
616static struct usb_driver sd_driver = {
617 .name = MODULE_NAME,
618 .id_table = device_table,
619 .probe = sd_probe,
620 .disconnect = sd_disconnect,
621#ifdef CONFIG_PM
622 .suspend = gspca_suspend,
623 .resume = gspca_resume,
624 .reset_resume = gspca_resume,
625#endif
626};
627
628module_usb_driver(sd_driver);
629
630module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
631MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
632
633module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
634MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup");
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.h b/drivers/media/usb/gspca/stv06xx/stv06xx.h
new file mode 100644
index 00000000000..34957a4ec15
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.h
@@ -0,0 +1,116 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_H_
31#define STV06XX_H_
32
33#include <linux/slab.h>
34#include "gspca.h"
35
36#define MODULE_NAME "STV06xx"
37
38#define STV_ISOC_ENDPOINT_ADDR 0x81
39
40#define STV_R 0x0509
41
42#define STV_REG23 0x0423
43
44/* Control registers of the STV0600 ASIC */
45#define STV_I2C_PARTNER 0x1420
46#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421
47#define STV_I2C_READ_WRITE_TOGGLE 0x1422
48#define STV_I2C_FLUSH 0x1423
49#define STV_I2C_SUCC_READ_REG_VALS 0x1424
50
51#define STV_ISO_ENABLE 0x1440
52#define STV_SCAN_RATE 0x1443
53#define STV_LED_CTRL 0x1445
54#define STV_STV0600_EMULATION 0x1446
55#define STV_REG00 0x1500
56#define STV_REG01 0x1501
57#define STV_REG02 0x1502
58#define STV_REG03 0x1503
59#define STV_REG04 0x1504
60
61#define STV_ISO_SIZE_L 0x15c1
62#define STV_ISO_SIZE_H 0x15c2
63
64/* Refers to the CIF 352x288 and QCIF 176x144 */
65/* 1: 288 lines, 2: 144 lines */
66#define STV_Y_CTRL 0x15c3
67
68#define STV_RESET 0x1620
69
70/* 0xa: 352 columns, 0x6: 176 columns */
71#define STV_X_CTRL 0x1680
72
73#define STV06XX_URB_MSG_TIMEOUT 5000
74
75#define I2C_MAX_BYTES 16
76#define I2C_MAX_WORDS 8
77
78#define I2C_BUFFER_LENGTH 0x23
79#define I2C_READ_CMD 3
80#define I2C_WRITE_CMD 1
81
82#define LED_ON 1
83#define LED_OFF 0
84
85/* STV06xx device descriptor */
86struct sd {
87 struct gspca_dev gspca_dev;
88
89 /* A pointer to the currently connected sensor */
90 const struct stv06xx_sensor *sensor;
91
92 /* Sensor private data */
93 void *sensor_priv;
94
95 /* The first 4 lines produced by the stv6422 are no good, this keeps
96 track of how many bytes we still need to skip during a frame */
97 int to_skip;
98
99 /* Bridge / Camera type */
100 u8 bridge;
101 #define BRIDGE_STV600 0
102 #define BRIDGE_STV602 1
103 #define BRIDGE_STV610 2
104 #define BRIDGE_ST6422 3 /* With integrated sensor */
105};
106
107int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
108int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data);
109
110int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len);
111int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len);
112
113int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value);
114int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value);
115
116#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
new file mode 100644
index 00000000000..06fa54c5efb
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
@@ -0,0 +1,540 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 * Copyright (c) 2008 Chia-I Wu
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * P/N 861037: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
24 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
25 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
26 * P/N 861075-0040: Sensor HDCS1000 ASIC
27 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
28 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
29 */
30
31#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32
33#include "stv06xx_hdcs.h"
34
35static struct v4l2_pix_format hdcs1x00_mode[] = {
36 {
37 HDCS_1X00_DEF_WIDTH,
38 HDCS_1X00_DEF_HEIGHT,
39 V4L2_PIX_FMT_SGRBG8,
40 V4L2_FIELD_NONE,
41 .sizeimage =
42 HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
43 .bytesperline = HDCS_1X00_DEF_WIDTH,
44 .colorspace = V4L2_COLORSPACE_SRGB,
45 .priv = 1
46 }
47};
48
49static struct v4l2_pix_format hdcs1020_mode[] = {
50 {
51 HDCS_1020_DEF_WIDTH,
52 HDCS_1020_DEF_HEIGHT,
53 V4L2_PIX_FMT_SGRBG8,
54 V4L2_FIELD_NONE,
55 .sizeimage =
56 HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
57 .bytesperline = HDCS_1020_DEF_WIDTH,
58 .colorspace = V4L2_COLORSPACE_SRGB,
59 .priv = 1
60 }
61};
62
63enum hdcs_power_state {
64 HDCS_STATE_SLEEP,
65 HDCS_STATE_IDLE,
66 HDCS_STATE_RUN
67};
68
69/* no lock? */
70struct hdcs {
71 enum hdcs_power_state state;
72 int w, h;
73
74 /* visible area of the sensor array */
75 struct {
76 int left, top;
77 int width, height;
78 int border;
79 } array;
80
81 struct {
82 /* Column timing overhead */
83 u8 cto;
84 /* Column processing overhead */
85 u8 cpo;
86 /* Row sample period constant */
87 u16 rs;
88 /* Exposure reset duration */
89 u16 er;
90 } exp;
91
92 int psmp;
93};
94
95static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
96{
97 u8 regs[I2C_MAX_BYTES * 2];
98 int i;
99
100 if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
101 (reg + len > 0xff)))
102 return -EINVAL;
103
104 for (i = 0; i < len; i++) {
105 regs[2 * i] = reg;
106 regs[2 * i + 1] = vals[i];
107 /* All addresses are shifted left one bit
108 * as bit 0 toggles r/w */
109 reg += 2;
110 }
111
112 return stv06xx_write_sensor_bytes(sd, regs, len);
113}
114
115static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
116{
117 struct hdcs *hdcs = sd->sensor_priv;
118 u8 val;
119 int ret;
120
121 if (hdcs->state == state)
122 return 0;
123
124 /* we need to go idle before running or sleeping */
125 if (hdcs->state != HDCS_STATE_IDLE) {
126 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
127 if (ret)
128 return ret;
129 }
130
131 hdcs->state = HDCS_STATE_IDLE;
132
133 if (state == HDCS_STATE_IDLE)
134 return 0;
135
136 switch (state) {
137 case HDCS_STATE_SLEEP:
138 val = HDCS_SLEEP_MODE;
139 break;
140
141 case HDCS_STATE_RUN:
142 val = HDCS_RUN_ENABLE;
143 break;
144
145 default:
146 return -EINVAL;
147 }
148
149 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
150
151 /* Update the state if the write succeeded */
152 if (!ret)
153 hdcs->state = state;
154
155 return ret;
156}
157
158static int hdcs_reset(struct sd *sd)
159{
160 struct hdcs *hdcs = sd->sensor_priv;
161 int err;
162
163 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
164 if (err < 0)
165 return err;
166
167 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
168 if (err < 0)
169 hdcs->state = HDCS_STATE_IDLE;
170
171 return err;
172}
173
174static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
175{
176 struct sd *sd = (struct sd *) gspca_dev;
177 struct hdcs *hdcs = sd->sensor_priv;
178 int rowexp, srowexp;
179 int max_srowexp;
180 /* Column time period */
181 int ct;
182 /* Column processing period */
183 int cp;
184 /* Row processing period */
185 int rp;
186 /* Minimum number of column timing periods
187 within the column processing period */
188 int mnct;
189 int cycles, err;
190 u8 exp[14];
191
192 cycles = val * HDCS_CLK_FREQ_MHZ * 257;
193
194 ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
195 cp = hdcs->exp.cto + (hdcs->w * ct / 2);
196
197 /* the cycles one row takes */
198 rp = hdcs->exp.rs + cp;
199
200 rowexp = cycles / rp;
201
202 /* the remaining cycles */
203 cycles -= rowexp * rp;
204
205 /* calculate sub-row exposure */
206 if (IS_1020(sd)) {
207 /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
208 srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
209
210 mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
211 max_srowexp = hdcs->w - mnct;
212 } else {
213 /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
214 srowexp = cp - hdcs->exp.er - 6 - cycles;
215
216 mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
217 max_srowexp = cp - mnct * ct - 1;
218 }
219
220 if (srowexp < 0)
221 srowexp = 0;
222 else if (srowexp > max_srowexp)
223 srowexp = max_srowexp;
224
225 if (IS_1020(sd)) {
226 exp[0] = HDCS20_CONTROL;
227 exp[1] = 0x00; /* Stop streaming */
228 exp[2] = HDCS_ROWEXPL;
229 exp[3] = rowexp & 0xff;
230 exp[4] = HDCS_ROWEXPH;
231 exp[5] = rowexp >> 8;
232 exp[6] = HDCS20_SROWEXP;
233 exp[7] = (srowexp >> 2) & 0xff;
234 exp[8] = HDCS20_ERROR;
235 exp[9] = 0x10; /* Clear exposure error flag*/
236 exp[10] = HDCS20_CONTROL;
237 exp[11] = 0x04; /* Restart streaming */
238 err = stv06xx_write_sensor_bytes(sd, exp, 6);
239 } else {
240 exp[0] = HDCS00_CONTROL;
241 exp[1] = 0x00; /* Stop streaming */
242 exp[2] = HDCS_ROWEXPL;
243 exp[3] = rowexp & 0xff;
244 exp[4] = HDCS_ROWEXPH;
245 exp[5] = rowexp >> 8;
246 exp[6] = HDCS00_SROWEXPL;
247 exp[7] = srowexp & 0xff;
248 exp[8] = HDCS00_SROWEXPH;
249 exp[9] = srowexp >> 8;
250 exp[10] = HDCS_STATUS;
251 exp[11] = 0x10; /* Clear exposure error flag*/
252 exp[12] = HDCS00_CONTROL;
253 exp[13] = 0x04; /* Restart streaming */
254 err = stv06xx_write_sensor_bytes(sd, exp, 7);
255 if (err < 0)
256 return err;
257 }
258 PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
259 val, rowexp, srowexp);
260 return err;
261}
262
263static int hdcs_set_gains(struct sd *sd, u8 g)
264{
265 int err;
266 u8 gains[4];
267
268 /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
269 if (g > 127)
270 g = 0x80 | (g / 2);
271
272 gains[0] = g;
273 gains[1] = g;
274 gains[2] = g;
275 gains[3] = g;
276
277 err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
278 return err;
279}
280
281static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
282{
283 PDEBUG(D_V4L2, "Writing gain %d", val);
284 return hdcs_set_gains((struct sd *) gspca_dev,
285 val & 0xff);
286}
287
288static int hdcs_set_size(struct sd *sd,
289 unsigned int width, unsigned int height)
290{
291 struct hdcs *hdcs = sd->sensor_priv;
292 u8 win[4];
293 unsigned int x, y;
294 int err;
295
296 /* must be multiple of 4 */
297 width = (width + 3) & ~0x3;
298 height = (height + 3) & ~0x3;
299
300 if (width > hdcs->array.width)
301 width = hdcs->array.width;
302
303 if (IS_1020(sd)) {
304 /* the borders are also invalid */
305 if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
306 > hdcs->array.height)
307 height = hdcs->array.height - 2 * hdcs->array.border -
308 HDCS_1020_BOTTOM_Y_SKIP;
309
310 y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
311 + hdcs->array.top;
312 } else {
313 if (height > hdcs->array.height)
314 height = hdcs->array.height;
315
316 y = hdcs->array.top + (hdcs->array.height - height) / 2;
317 }
318
319 x = hdcs->array.left + (hdcs->array.width - width) / 2;
320
321 win[0] = y / 4;
322 win[1] = x / 4;
323 win[2] = (y + height) / 4 - 1;
324 win[3] = (x + width) / 4 - 1;
325
326 err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
327 if (err < 0)
328 return err;
329
330 /* Update the current width and height */
331 hdcs->w = width;
332 hdcs->h = height;
333 return err;
334}
335
336static int hdcs_s_ctrl(struct v4l2_ctrl *ctrl)
337{
338 struct gspca_dev *gspca_dev =
339 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
340 int err = -EINVAL;
341
342 switch (ctrl->id) {
343 case V4L2_CID_GAIN:
344 err = hdcs_set_gain(gspca_dev, ctrl->val);
345 break;
346 case V4L2_CID_EXPOSURE:
347 err = hdcs_set_exposure(gspca_dev, ctrl->val);
348 break;
349 }
350 return err;
351}
352
353static const struct v4l2_ctrl_ops hdcs_ctrl_ops = {
354 .s_ctrl = hdcs_s_ctrl,
355};
356
357static int hdcs_init_controls(struct sd *sd)
358{
359 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
360
361 v4l2_ctrl_handler_init(hdl, 2);
362 v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
363 V4L2_CID_EXPOSURE, 0, 0xff, 1, HDCS_DEFAULT_EXPOSURE);
364 v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
365 V4L2_CID_GAIN, 0, 0xff, 1, HDCS_DEFAULT_GAIN);
366 return hdl->error;
367}
368
369static int hdcs_probe_1x00(struct sd *sd)
370{
371 struct hdcs *hdcs;
372 u16 sensor;
373 int ret;
374
375 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
376 if (ret < 0 || sensor != 0x08)
377 return -ENODEV;
378
379 pr_info("HDCS-1000/1100 sensor detected\n");
380
381 sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
382 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
383
384 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
385 if (!hdcs)
386 return -ENOMEM;
387
388 hdcs->array.left = 8;
389 hdcs->array.top = 8;
390 hdcs->array.width = HDCS_1X00_DEF_WIDTH;
391 hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
392 hdcs->array.border = 4;
393
394 hdcs->exp.cto = 4;
395 hdcs->exp.cpo = 2;
396 hdcs->exp.rs = 186;
397 hdcs->exp.er = 100;
398
399 /*
400 * Frame rate on HDCS-1000 with STV600 depends on PSMP:
401 * 4 = doesn't work at all
402 * 5 = 7.8 fps,
403 * 6 = 6.9 fps,
404 * 8 = 6.3 fps,
405 * 10 = 5.5 fps,
406 * 15 = 4.4 fps,
407 * 31 = 2.8 fps
408 *
409 * Frame rate on HDCS-1000 with STV602 depends on PSMP:
410 * 15 = doesn't work at all
411 * 18 = doesn't work at all
412 * 19 = 7.3 fps
413 * 20 = 7.4 fps
414 * 21 = 7.4 fps
415 * 22 = 7.4 fps
416 * 24 = 6.3 fps
417 * 30 = 5.4 fps
418 */
419 hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
420
421 sd->sensor_priv = hdcs;
422
423 return 0;
424}
425
426static int hdcs_probe_1020(struct sd *sd)
427{
428 struct hdcs *hdcs;
429 u16 sensor;
430 int ret;
431
432 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
433 if (ret < 0 || sensor != 0x10)
434 return -ENODEV;
435
436 pr_info("HDCS-1020 sensor detected\n");
437
438 sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
439 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
440
441 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
442 if (!hdcs)
443 return -ENOMEM;
444
445 /*
446 * From Andrey's test image: looks like HDCS-1020 upper-left
447 * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
448 * visible pixel at 375,299 (x maybe even larger?)
449 */
450 hdcs->array.left = 24;
451 hdcs->array.top = 4;
452 hdcs->array.width = HDCS_1020_DEF_WIDTH;
453 hdcs->array.height = 304;
454 hdcs->array.border = 4;
455
456 hdcs->psmp = 6;
457
458 hdcs->exp.cto = 3;
459 hdcs->exp.cpo = 3;
460 hdcs->exp.rs = 155;
461 hdcs->exp.er = 96;
462
463 sd->sensor_priv = hdcs;
464
465 return 0;
466}
467
468static int hdcs_start(struct sd *sd)
469{
470 PDEBUG(D_STREAM, "Starting stream");
471
472 return hdcs_set_state(sd, HDCS_STATE_RUN);
473}
474
475static int hdcs_stop(struct sd *sd)
476{
477 PDEBUG(D_STREAM, "Halting stream");
478
479 return hdcs_set_state(sd, HDCS_STATE_SLEEP);
480}
481
482static int hdcs_init(struct sd *sd)
483{
484 struct hdcs *hdcs = sd->sensor_priv;
485 int i, err = 0;
486
487 /* Set the STV0602AA in STV0600 emulation mode */
488 if (sd->bridge == BRIDGE_STV602)
489 stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
490
491 /* Execute the bridge init */
492 for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
493 err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
494 stv_bridge_init[i][1]);
495 }
496 if (err < 0)
497 return err;
498
499 /* sensor soft reset */
500 hdcs_reset(sd);
501
502 /* Execute the sensor init */
503 for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
504 err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
505 stv_sensor_init[i][1]);
506 }
507 if (err < 0)
508 return err;
509
510 /* Enable continuous frame capture, bit 2: stop when frame complete */
511 err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
512 if (err < 0)
513 return err;
514
515 /* Set PGA sample duration
516 (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
517 if (IS_1020(sd))
518 err = stv06xx_write_sensor(sd, HDCS_TCTRL,
519 (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
520 else
521 err = stv06xx_write_sensor(sd, HDCS_TCTRL,
522 (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
523 if (err < 0)
524 return err;
525
526 return hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
527}
528
529static int hdcs_dump(struct sd *sd)
530{
531 u16 reg, val;
532
533 pr_info("Dumping sensor registers:\n");
534
535 for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
536 stv06xx_read_sensor(sd, reg, &val);
537 pr_info("reg 0x%02x = 0x%02x\n", reg, val);
538 }
539 return 0;
540}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h
new file mode 100644
index 00000000000..1ba9158d010
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h
@@ -0,0 +1,206 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
6 * Copyright (c) 2008 Chia-I Wu
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * P/N 861037: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
24 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
25 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
26 * P/N 861075-0040: Sensor HDCS1000 ASIC
27 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
28 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
29 */
30
31#ifndef STV06XX_HDCS_H_
32#define STV06XX_HDCS_H_
33
34#include "stv06xx_sensor.h"
35
36#define HDCS_REG_CONFIG(sd) (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG)
37#define HDCS_REG_CONTROL(sd) (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL)
38
39#define HDCS_1X00_DEF_WIDTH 360
40#define HDCS_1X00_DEF_HEIGHT 296
41
42#define HDCS_1020_DEF_WIDTH 352
43#define HDCS_1020_DEF_HEIGHT 292
44
45#define HDCS_1020_BOTTOM_Y_SKIP 4
46
47#define HDCS_CLK_FREQ_MHZ 25
48
49#define HDCS_ADC_START_SIG_DUR 3
50
51/* LSB bit of I2C or register address signifies write (0) or read (1) */
52/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */
53/* Identifications Register */
54#define HDCS_IDENT (0x00 << 1)
55/* Status Register */
56#define HDCS_STATUS (0x01 << 1)
57/* Interrupt Mask Register */
58#define HDCS_IMASK (0x02 << 1)
59/* Pad Control Register */
60#define HDCS_PCTRL (0x03 << 1)
61/* Pad Drive Control Register */
62#define HDCS_PDRV (0x04 << 1)
63/* Interface Control Register */
64#define HDCS_ICTRL (0x05 << 1)
65/* Interface Timing Register */
66#define HDCS_ITMG (0x06 << 1)
67/* Baud Fraction Register */
68#define HDCS_BFRAC (0x07 << 1)
69/* Baud Rate Register */
70#define HDCS_BRATE (0x08 << 1)
71/* ADC Control Register */
72#define HDCS_ADCCTRL (0x09 << 1)
73/* First Window Row Register */
74#define HDCS_FWROW (0x0a << 1)
75/* First Window Column Register */
76#define HDCS_FWCOL (0x0b << 1)
77/* Last Window Row Register */
78#define HDCS_LWROW (0x0c << 1)
79/* Last Window Column Register */
80#define HDCS_LWCOL (0x0d << 1)
81/* Timing Control Register */
82#define HDCS_TCTRL (0x0e << 1)
83/* PGA Gain Register: Even Row, Even Column */
84#define HDCS_ERECPGA (0x0f << 1)
85/* PGA Gain Register: Even Row, Odd Column */
86#define HDCS_EROCPGA (0x10 << 1)
87/* PGA Gain Register: Odd Row, Even Column */
88#define HDCS_ORECPGA (0x11 << 1)
89/* PGA Gain Register: Odd Row, Odd Column */
90#define HDCS_OROCPGA (0x12 << 1)
91/* Row Exposure Low Register */
92#define HDCS_ROWEXPL (0x13 << 1)
93/* Row Exposure High Register */
94#define HDCS_ROWEXPH (0x14 << 1)
95
96/* I2C Registers only for HDCS-1000/1100 */
97/* Sub-Row Exposure Low Register */
98#define HDCS00_SROWEXPL (0x15 << 1)
99/* Sub-Row Exposure High Register */
100#define HDCS00_SROWEXPH (0x16 << 1)
101/* Configuration Register */
102#define HDCS00_CONFIG (0x17 << 1)
103/* Control Register */
104#define HDCS00_CONTROL (0x18 << 1)
105
106/* I2C Registers only for HDCS-1020 */
107/* Sub-Row Exposure Register */
108#define HDCS20_SROWEXP (0x15 << 1)
109/* Error Control Register */
110#define HDCS20_ERROR (0x16 << 1)
111/* Interface Timing 2 Register */
112#define HDCS20_ITMG2 (0x17 << 1)
113/* Interface Control 2 Register */
114#define HDCS20_ICTRL2 (0x18 << 1)
115/* Horizontal Blank Register */
116#define HDCS20_HBLANK (0x19 << 1)
117/* Vertical Blank Register */
118#define HDCS20_VBLANK (0x1a << 1)
119/* Configuration Register */
120#define HDCS20_CONFIG (0x1b << 1)
121/* Control Register */
122#define HDCS20_CONTROL (0x1c << 1)
123
124#define HDCS_RUN_ENABLE (1 << 2)
125#define HDCS_SLEEP_MODE (1 << 1)
126
127#define HDCS_DEFAULT_EXPOSURE 48
128#define HDCS_DEFAULT_GAIN 50
129
130static int hdcs_probe_1x00(struct sd *sd);
131static int hdcs_probe_1020(struct sd *sd);
132static int hdcs_start(struct sd *sd);
133static int hdcs_init(struct sd *sd);
134static int hdcs_init_controls(struct sd *sd);
135static int hdcs_stop(struct sd *sd);
136static int hdcs_dump(struct sd *sd);
137
138static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
139static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val);
140
141const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
142 .name = "HP HDCS-1000/1100",
143 .i2c_flush = 0,
144 .i2c_addr = (0x55 << 1),
145 .i2c_len = 1,
146
147 /* FIXME (see if we can lower min_packet_size, needs testing, and also
148 adjusting framerate when the bandwidth gets lower) */
149 .min_packet_size = { 847 },
150 .max_packet_size = { 847 },
151
152 .init = hdcs_init,
153 .init_controls = hdcs_init_controls,
154 .probe = hdcs_probe_1x00,
155 .start = hdcs_start,
156 .stop = hdcs_stop,
157 .dump = hdcs_dump,
158};
159
160const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
161 .name = "HDCS-1020",
162 .i2c_flush = 0,
163 .i2c_addr = (0x55 << 1),
164 .i2c_len = 1,
165
166 /* FIXME (see if we can lower min_packet_size, needs testing, and also
167 adjusting framerate when the bandwidthm gets lower) */
168 .min_packet_size = { 847 },
169 .max_packet_size = { 847 },
170
171 .init = hdcs_init,
172 .init_controls = hdcs_init_controls,
173 .probe = hdcs_probe_1020,
174 .start = hdcs_start,
175 .stop = hdcs_stop,
176 .dump = hdcs_dump,
177};
178
179static const u16 stv_bridge_init[][2] = {
180 {STV_ISO_ENABLE, 0},
181 {STV_REG23, 0},
182 {STV_REG00, 0x1d},
183 {STV_REG01, 0xb5},
184 {STV_REG02, 0xa8},
185 {STV_REG03, 0x95},
186 {STV_REG04, 0x07},
187
188 {STV_SCAN_RATE, 0x20},
189 {STV_Y_CTRL, 0x01},
190 {STV_X_CTRL, 0x0a}
191};
192
193static const u8 stv_sensor_init[][2] = {
194 /* Clear status (writing 1 will clear the corresponding status bit) */
195 {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
196 /* Disable all interrupts */
197 {HDCS_IMASK, 0x00},
198 {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)},
199 {HDCS_PDRV, 0x00},
200 {HDCS_ICTRL, BIT(5)},
201 {HDCS_ITMG, BIT(4) | BIT(1)},
202 /* ADC output resolution to 10 bits */
203 {HDCS_ADCCTRL, 10}
204};
205
206#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
new file mode 100644
index 00000000000..cdfc3d05ab6
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
@@ -0,0 +1,434 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30/*
31 * The spec file for the PB-0100 suggests the following for best quality
32 * images after the sensor has been reset :
33 *
34 * PB_ADCGAINL = R60 = 0x03 (3 dec) : sets low reference of ADC
35 to produce good black level
36 * PB_PREADCTRL = R32 = 0x1400 (5120 dec) : Enables global gain changes
37 through R53
38 * PB_ADCMINGAIN = R52 = 0x10 (16 dec) : Sets the minimum gain for
39 auto-exposure
40 * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec) : Sets the global gain
41 * PB_EXPGAIN = R14 = 0x11 (17 dec) : Sets the auto-exposure value
42 * PB_UPDATEINT = R23 = 0x02 (2 dec) : Sets the speed on
43 auto-exposure routine
44 * PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate
45 */
46
47#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
48
49#include "stv06xx_pb0100.h"
50
51struct pb0100_ctrls {
52 struct { /* one big happy control cluster... */
53 struct v4l2_ctrl *autogain;
54 struct v4l2_ctrl *gain;
55 struct v4l2_ctrl *exposure;
56 struct v4l2_ctrl *red;
57 struct v4l2_ctrl *blue;
58 struct v4l2_ctrl *natural;
59 };
60 struct v4l2_ctrl *target;
61};
62
63static struct v4l2_pix_format pb0100_mode[] = {
64/* low res / subsample modes disabled as they are only half res horizontal,
65 halving the vertical resolution does not seem to work */
66 {
67 320,
68 240,
69 V4L2_PIX_FMT_SGRBG8,
70 V4L2_FIELD_NONE,
71 .sizeimage = 320 * 240,
72 .bytesperline = 320,
73 .colorspace = V4L2_COLORSPACE_SRGB,
74 .priv = PB0100_CROP_TO_VGA
75 },
76 {
77 352,
78 288,
79 V4L2_PIX_FMT_SGRBG8,
80 V4L2_FIELD_NONE,
81 .sizeimage = 352 * 288,
82 .bytesperline = 352,
83 .colorspace = V4L2_COLORSPACE_SRGB,
84 .priv = 0
85 }
86};
87
88static int pb0100_s_ctrl(struct v4l2_ctrl *ctrl)
89{
90 struct gspca_dev *gspca_dev =
91 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
92 struct sd *sd = (struct sd *)gspca_dev;
93 struct pb0100_ctrls *ctrls = sd->sensor_priv;
94 int err = -EINVAL;
95
96 switch (ctrl->id) {
97 case V4L2_CID_AUTOGAIN:
98 err = pb0100_set_autogain(gspca_dev, ctrl->val);
99 if (err)
100 break;
101 if (ctrl->val)
102 break;
103 err = pb0100_set_gain(gspca_dev, ctrls->gain->val);
104 if (err)
105 break;
106 err = pb0100_set_exposure(gspca_dev, ctrls->exposure->val);
107 break;
108 case V4L2_CTRL_CLASS_USER + 0x1001:
109 err = pb0100_set_autogain_target(gspca_dev, ctrl->val);
110 break;
111 }
112 return err;
113}
114
115static const struct v4l2_ctrl_ops pb0100_ctrl_ops = {
116 .s_ctrl = pb0100_s_ctrl,
117};
118
119static int pb0100_init_controls(struct sd *sd)
120{
121 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
122 struct pb0100_ctrls *ctrls;
123 static const struct v4l2_ctrl_config autogain_target = {
124 .ops = &pb0100_ctrl_ops,
125 .id = V4L2_CTRL_CLASS_USER + 0x1000,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Automatic Gain Target",
128 .max = 255,
129 .step = 1,
130 .def = 128,
131 };
132 static const struct v4l2_ctrl_config natural_light = {
133 .ops = &pb0100_ctrl_ops,
134 .id = V4L2_CTRL_CLASS_USER + 0x1001,
135 .type = V4L2_CTRL_TYPE_BOOLEAN,
136 .name = "Natural Light Source",
137 .max = 1,
138 .step = 1,
139 .def = 1,
140 };
141
142 ctrls = kzalloc(sizeof(*ctrls), GFP_KERNEL);
143 if (!ctrls)
144 return -ENOMEM;
145
146 v4l2_ctrl_handler_init(hdl, 6);
147 ctrls->autogain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
148 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
149 ctrls->exposure = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
150 V4L2_CID_EXPOSURE, 0, 511, 1, 12);
151 ctrls->gain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
152 V4L2_CID_GAIN, 0, 255, 1, 128);
153 ctrls->red = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
154 V4L2_CID_RED_BALANCE, -255, 255, 1, 0);
155 ctrls->blue = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
156 V4L2_CID_BLUE_BALANCE, -255, 255, 1, 0);
157 ctrls->natural = v4l2_ctrl_new_custom(hdl, &natural_light, NULL);
158 ctrls->target = v4l2_ctrl_new_custom(hdl, &autogain_target, NULL);
159 if (hdl->error) {
160 kfree(ctrls);
161 return hdl->error;
162 }
163 sd->sensor_priv = ctrls;
164 v4l2_ctrl_auto_cluster(5, &ctrls->autogain, 0, false);
165 return 0;
166}
167
168static int pb0100_probe(struct sd *sd)
169{
170 u16 sensor;
171 int err;
172
173 err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
174
175 if (err < 0)
176 return -ENODEV;
177 if ((sensor >> 8) != 0x64)
178 return -ENODEV;
179
180 pr_info("Photobit pb0100 sensor detected\n");
181
182 sd->gspca_dev.cam.cam_mode = pb0100_mode;
183 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
184
185 return 0;
186}
187
188static int pb0100_start(struct sd *sd)
189{
190 int err, packet_size, max_packet_size;
191 struct usb_host_interface *alt;
192 struct usb_interface *intf;
193 struct cam *cam = &sd->gspca_dev.cam;
194 u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
195
196 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
197 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
198 if (!alt)
199 return -ENODEV;
200 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
201
202 /* If we don't have enough bandwidth use a lower framerate */
203 max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
204 if (packet_size < max_packet_size)
205 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
206 else
207 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
208
209 /* Setup sensor window */
210 if (mode & PB0100_CROP_TO_VGA) {
211 stv06xx_write_sensor(sd, PB_RSTART, 30);
212 stv06xx_write_sensor(sd, PB_CSTART, 20);
213 stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
214 stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
215 } else {
216 stv06xx_write_sensor(sd, PB_RSTART, 8);
217 stv06xx_write_sensor(sd, PB_CSTART, 4);
218 stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
219 stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
220 }
221
222 if (mode & PB0100_SUBSAMPLE) {
223 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */
224 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
225
226 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
227 } else {
228 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
229 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
230 /* larger -> slower */
231 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
232 }
233
234 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
235 PDEBUG(D_STREAM, "Started stream, status: %d", err);
236
237 return (err < 0) ? err : 0;
238}
239
240static int pb0100_stop(struct sd *sd)
241{
242 int err;
243
244 err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
245
246 if (err < 0)
247 goto out;
248
249 /* Set bit 1 to zero */
250 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
251
252 PDEBUG(D_STREAM, "Halting stream");
253out:
254 return (err < 0) ? err : 0;
255}
256
257/* FIXME: Sort the init commands out and put them into tables,
258 this is only for getting the camera to work */
259/* FIXME: No error handling for now,
260 add this once the init has been converted to proper tables */
261static int pb0100_init(struct sd *sd)
262{
263 stv06xx_write_bridge(sd, STV_REG00, 1);
264 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
265
266 /* Reset sensor */
267 stv06xx_write_sensor(sd, PB_RESET, 1);
268 stv06xx_write_sensor(sd, PB_RESET, 0);
269
270 /* Disable chip */
271 stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
272
273 /* Gain stuff...*/
274 stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
275 stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
276
277 /* Set up auto-exposure */
278 /* ADC VREF_HI new setting for a transition
279 from the Expose1 to the Expose2 setting */
280 stv06xx_write_sensor(sd, PB_R28, 12);
281 /* gain max for autoexposure */
282 stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
283 /* gain min for autoexposure */
284 stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
285 /* Maximum frame integration time (programmed into R8)
286 allowed for auto-exposure routine */
287 stv06xx_write_sensor(sd, PB_R54, 3);
288 /* Minimum frame integration time (programmed into R8)
289 allowed for auto-exposure routine */
290 stv06xx_write_sensor(sd, PB_R55, 0);
291 stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
292 /* R15 Expose0 (maximum that auto-exposure may use) */
293 stv06xx_write_sensor(sd, PB_R15, 800);
294 /* R17 Expose2 (minimum that auto-exposure may use) */
295 stv06xx_write_sensor(sd, PB_R17, 10);
296
297 stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
298
299 /* 0x14 */
300 stv06xx_write_sensor(sd, PB_VOFFSET, 0);
301 /* 0x0D */
302 stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
303 /* Set black level (important!) */
304 stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
305
306 /* ??? */
307 stv06xx_write_bridge(sd, STV_REG00, 0x11);
308 stv06xx_write_bridge(sd, STV_REG03, 0x45);
309 stv06xx_write_bridge(sd, STV_REG04, 0x07);
310
311 /* Scan/timing for the sensor */
312 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
313 stv06xx_write_sensor(sd, PB_CFILLIN, 14);
314 stv06xx_write_sensor(sd, PB_VBL, 0);
315 stv06xx_write_sensor(sd, PB_FINTTIME, 0);
316 stv06xx_write_sensor(sd, PB_RINTTIME, 123);
317
318 stv06xx_write_bridge(sd, STV_REG01, 0xc2);
319 stv06xx_write_bridge(sd, STV_REG02, 0xb0);
320 return 0;
321}
322
323static int pb0100_dump(struct sd *sd)
324{
325 return 0;
326}
327
328static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
329{
330 int err;
331 struct sd *sd = (struct sd *) gspca_dev;
332 struct pb0100_ctrls *ctrls = sd->sensor_priv;
333
334 err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
335 if (!err)
336 err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
337 PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
338
339 if (!err)
340 err = pb0100_set_red_balance(gspca_dev, ctrls->red->val);
341 if (!err)
342 err = pb0100_set_blue_balance(gspca_dev, ctrls->blue->val);
343
344 return err;
345}
346
347static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
348{
349 int err;
350 struct sd *sd = (struct sd *) gspca_dev;
351 struct pb0100_ctrls *ctrls = sd->sensor_priv;
352
353 val += ctrls->gain->val;
354 if (val < 0)
355 val = 0;
356 else if (val > 255)
357 val = 255;
358
359 err = stv06xx_write_sensor(sd, PB_RGAIN, val);
360 PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
361
362 return err;
363}
364
365static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
366{
367 int err;
368 struct sd *sd = (struct sd *) gspca_dev;
369 struct pb0100_ctrls *ctrls = sd->sensor_priv;
370
371 val += ctrls->gain->val;
372 if (val < 0)
373 val = 0;
374 else if (val > 255)
375 val = 255;
376
377 err = stv06xx_write_sensor(sd, PB_BGAIN, val);
378 PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
379
380 return err;
381}
382
383static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
384{
385 struct sd *sd = (struct sd *) gspca_dev;
386 int err;
387
388 err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
389 PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
390
391 return err;
392}
393
394static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
395{
396 int err;
397 struct sd *sd = (struct sd *) gspca_dev;
398 struct pb0100_ctrls *ctrls = sd->sensor_priv;
399
400 if (val) {
401 if (ctrls->natural->val)
402 val = BIT(6)|BIT(4)|BIT(0);
403 else
404 val = BIT(4)|BIT(0);
405 } else
406 val = 0;
407
408 err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
409 PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
410 val, ctrls->natural->val, err);
411
412 return err;
413}
414
415static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
416{
417 int err, totalpixels, brightpixels, darkpixels;
418 struct sd *sd = (struct sd *) gspca_dev;
419
420 /* Number of pixels counted by the sensor when subsampling the pixels.
421 * Slightly larger than the real value to avoid oscillation */
422 totalpixels = gspca_dev->width * gspca_dev->height;
423 totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
424
425 brightpixels = (totalpixels * val) >> 8;
426 darkpixels = totalpixels - brightpixels;
427 err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
428 if (!err)
429 err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
430
431 PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
432
433 return err;
434}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h
new file mode 100644
index 00000000000..5071e5353fd
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h
@@ -0,0 +1,144 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_PB0100_H_
31#define STV06XX_PB0100_H_
32
33#include "stv06xx_sensor.h"
34
35/* mode priv field flags */
36#define PB0100_CROP_TO_VGA 0x01
37#define PB0100_SUBSAMPLE 0x02
38
39/* I2C Registers */
40#define PB_IDENT 0x00 /* Chip Version */
41#define PB_RSTART 0x01 /* Row Window Start */
42#define PB_CSTART 0x02 /* Column Window Start */
43#define PB_RWSIZE 0x03 /* Row Window Size */
44#define PB_CWSIZE 0x04 /* Column Window Size */
45#define PB_CFILLIN 0x05 /* Column Fill-In */
46#define PB_VBL 0x06 /* Vertical Blank Count */
47#define PB_CONTROL 0x07 /* Control Mode */
48#define PB_FINTTIME 0x08 /* Integration Time/Frame Unit Count */
49#define PB_RINTTIME 0x09 /* Integration Time/Row Unit Count */
50#define PB_ROWSPEED 0x0a /* Row Speed Control */
51#define PB_ABORTFRAME 0x0b /* Abort Frame */
52#define PB_R12 0x0c /* Reserved */
53#define PB_RESET 0x0d /* Reset */
54#define PB_EXPGAIN 0x0e /* Exposure Gain Command */
55#define PB_R15 0x0f /* Expose0 */
56#define PB_R16 0x10 /* Expose1 */
57#define PB_R17 0x11 /* Expose2 */
58#define PB_R18 0x12 /* Low0_DAC */
59#define PB_R19 0x13 /* Low1_DAC */
60#define PB_R20 0x14 /* Low2_DAC */
61#define PB_R21 0x15 /* Threshold11 */
62#define PB_R22 0x16 /* Threshold0x */
63#define PB_UPDATEINT 0x17 /* Update Interval */
64#define PB_R24 0x18 /* High_DAC */
65#define PB_R25 0x19 /* Trans0H */
66#define PB_R26 0x1a /* Trans1L */
67#define PB_R27 0x1b /* Trans1H */
68#define PB_R28 0x1c /* Trans2L */
69#define PB_R29 0x1d /* Reserved */
70#define PB_R30 0x1e /* Reserved */
71#define PB_R31 0x1f /* Wait to Read */
72#define PB_PREADCTRL 0x20 /* Pixel Read Control Mode */
73#define PB_R33 0x21 /* IREF_VLN */
74#define PB_R34 0x22 /* IREF_VLP */
75#define PB_R35 0x23 /* IREF_VLN_INTEG */
76#define PB_R36 0x24 /* IREF_MASTER */
77#define PB_R37 0x25 /* IDACP */
78#define PB_R38 0x26 /* IDACN */
79#define PB_R39 0x27 /* DAC_Control_Reg */
80#define PB_R40 0x28 /* VCL */
81#define PB_R41 0x29 /* IREF_VLN_ADCIN */
82#define PB_R42 0x2a /* Reserved */
83#define PB_G1GAIN 0x2b /* Green 1 Gain */
84#define PB_BGAIN 0x2c /* Blue Gain */
85#define PB_RGAIN 0x2d /* Red Gain */
86#define PB_G2GAIN 0x2e /* Green 2 Gain */
87#define PB_R47 0x2f /* Dark Row Address */
88#define PB_R48 0x30 /* Dark Row Options */
89#define PB_R49 0x31 /* Reserved */
90#define PB_R50 0x32 /* Image Test Data */
91#define PB_ADCMAXGAIN 0x33 /* Maximum Gain */
92#define PB_ADCMINGAIN 0x34 /* Minimum Gain */
93#define PB_ADCGLOBALGAIN 0x35 /* Global Gain */
94#define PB_R54 0x36 /* Maximum Frame */
95#define PB_R55 0x37 /* Minimum Frame */
96#define PB_R56 0x38 /* Reserved */
97#define PB_VOFFSET 0x39 /* VOFFSET */
98#define PB_R58 0x3a /* Snap-Shot Sequence Trigger */
99#define PB_ADCGAINH 0x3b /* VREF_HI */
100#define PB_ADCGAINL 0x3c /* VREF_LO */
101#define PB_R61 0x3d /* Reserved */
102#define PB_R62 0x3e /* Reserved */
103#define PB_R63 0x3f /* Reserved */
104#define PB_R64 0x40 /* Red/Blue Gain */
105#define PB_R65 0x41 /* Green 2/Green 1 Gain */
106#define PB_R66 0x42 /* VREF_HI/LO */
107#define PB_R67 0x43 /* Integration Time/Row Unit Count */
108#define PB_R240 0xf0 /* ADC Test */
109#define PB_R241 0xf1 /* Chip Enable */
110#define PB_R242 0xf2 /* Reserved */
111
112static int pb0100_probe(struct sd *sd);
113static int pb0100_start(struct sd *sd);
114static int pb0100_init(struct sd *sd);
115static int pb0100_init_controls(struct sd *sd);
116static int pb0100_stop(struct sd *sd);
117static int pb0100_dump(struct sd *sd);
118
119/* V4L2 controls supported by the driver */
120static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val);
121static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
122static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
123static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
124static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val);
125static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val);
126
127const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
128 .name = "PB-0100",
129 .i2c_flush = 1,
130 .i2c_addr = 0xba,
131 .i2c_len = 2,
132
133 .min_packet_size = { 635, 847 },
134 .max_packet_size = { 847, 923 },
135
136 .init = pb0100_init,
137 .init_controls = pb0100_init_controls,
138 .probe = pb0100_probe,
139 .start = pb0100_start,
140 .stop = pb0100_stop,
141 .dump = pb0100_dump,
142};
143
144#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h
new file mode 100644
index 00000000000..3a498c2495c
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_SENSOR_H_
31#define STV06XX_SENSOR_H_
32
33#include "stv06xx.h"
34
35#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020)
36
37extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
38extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
39extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
40extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
41extern const struct stv06xx_sensor stv06xx_sensor_st6422;
42
43struct stv06xx_sensor {
44 /* Defines the name of a sensor */
45 char name[32];
46
47 /* Sensor i2c address */
48 u8 i2c_addr;
49
50 /* Flush value*/
51 u8 i2c_flush;
52
53 /* length of an i2c word */
54 u8 i2c_len;
55
56 /* Isoc packet size (per mode) */
57 int min_packet_size[4];
58 int max_packet_size[4];
59
60 /* Probes if the sensor is connected */
61 int (*probe)(struct sd *sd);
62
63 /* Performs a initialization sequence */
64 int (*init)(struct sd *sd);
65
66 /* Initializes the controls */
67 int (*init_controls)(struct sd *sd);
68
69 /* Reads a sensor register */
70 int (*read_sensor)(struct sd *sd, const u8 address,
71 u8 *i2c_data, const u8 len);
72
73 /* Writes to a sensor register */
74 int (*write_sensor)(struct sd *sd, const u8 address,
75 u8 *i2c_data, const u8 len);
76
77 /* Instructs the sensor to start streaming */
78 int (*start)(struct sd *sd);
79
80 /* Instructs the sensor to stop streaming */
81 int (*stop)(struct sd *sd);
82
83 /* Instructs the sensor to dump all its contents */
84 int (*dump)(struct sd *sd);
85};
86
87#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
new file mode 100644
index 00000000000..8a57990dfe0
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
@@ -0,0 +1,285 @@
1/*
2 * Support for the sensor part which is integrated (I think) into the
3 * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
4 * but instead direct bridge writes.
5 *
6 * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
7 *
8 * Strongly based on qc-usb-messenger, which is:
9 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
10 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
11 * Copyright (c) 2002, 2003 Tuukka Toivonen
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include "stv06xx_st6422.h"
32
33static struct v4l2_pix_format st6422_mode[] = {
34 /* Note we actually get 124 lines of data, of which we skip the 4st
35 4 as they are garbage */
36 {
37 162,
38 120,
39 V4L2_PIX_FMT_SGRBG8,
40 V4L2_FIELD_NONE,
41 .sizeimage = 162 * 120,
42 .bytesperline = 162,
43 .colorspace = V4L2_COLORSPACE_SRGB,
44 .priv = 1
45 },
46 /* Note we actually get 248 lines of data, of which we skip the 4st
47 4 as they are garbage, and we tell the app it only gets the
48 first 240 of the 244 lines it actually gets, so that it ignores
49 the last 4. */
50 {
51 324,
52 240,
53 V4L2_PIX_FMT_SGRBG8,
54 V4L2_FIELD_NONE,
55 .sizeimage = 324 * 244,
56 .bytesperline = 324,
57 .colorspace = V4L2_COLORSPACE_SRGB,
58 .priv = 0
59 },
60};
61
62/* V4L2 controls supported by the driver */
63static int setbrightness(struct sd *sd, s32 val);
64static int setcontrast(struct sd *sd, s32 val);
65static int setgain(struct sd *sd, u8 gain);
66static int setexposure(struct sd *sd, s16 expo);
67
68static int st6422_s_ctrl(struct v4l2_ctrl *ctrl)
69{
70 struct gspca_dev *gspca_dev =
71 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
72 struct sd *sd = (struct sd *)gspca_dev;
73 int err = -EINVAL;
74
75 switch (ctrl->id) {
76 case V4L2_CID_BRIGHTNESS:
77 err = setbrightness(sd, ctrl->val);
78 break;
79 case V4L2_CID_CONTRAST:
80 err = setcontrast(sd, ctrl->val);
81 break;
82 case V4L2_CID_GAIN:
83 err = setgain(sd, ctrl->val);
84 break;
85 case V4L2_CID_EXPOSURE:
86 err = setexposure(sd, ctrl->val);
87 break;
88 }
89
90 /* commit settings */
91 if (err >= 0)
92 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
93 sd->gspca_dev.usb_err = err;
94 return err;
95}
96
97static const struct v4l2_ctrl_ops st6422_ctrl_ops = {
98 .s_ctrl = st6422_s_ctrl,
99};
100
101static int st6422_init_controls(struct sd *sd)
102{
103 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
104
105 v4l2_ctrl_handler_init(hdl, 4);
106 v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
107 V4L2_CID_BRIGHTNESS, 0, 31, 1, 3);
108 v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
109 V4L2_CID_CONTRAST, 0, 15, 1, 11);
110 v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
111 V4L2_CID_EXPOSURE, 0, 1023, 1, 256);
112 v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
113 V4L2_CID_GAIN, 0, 255, 1, 64);
114
115 return hdl->error;
116}
117
118static int st6422_probe(struct sd *sd)
119{
120 if (sd->bridge != BRIDGE_ST6422)
121 return -ENODEV;
122
123 pr_info("st6422 sensor detected\n");
124
125 sd->gspca_dev.cam.cam_mode = st6422_mode;
126 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
127 return 0;
128}
129
130static int st6422_init(struct sd *sd)
131{
132 int err = 0, i;
133
134 const u16 st6422_bridge_init[][2] = {
135 { STV_ISO_ENABLE, 0x00 }, /* disable capture */
136 { 0x1436, 0x00 },
137 { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
138 { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
139 { 0x0509, 0x38 }, /* R */
140 { 0x050a, 0x38 }, /* G */
141 { 0x050b, 0x38 }, /* B */
142 { 0x050c, 0x2a },
143 { 0x050d, 0x01 },
144
145
146 { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
147 { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
148 { 0x1438, 0x18 }, /* 640x480 */
149/* 18 bayes */
150/* 10 compressed? */
151
152 { 0x1439, 0x00 },
153/* anti-noise? 0xa2 gives a perfect image */
154
155 { 0x143b, 0x05 },
156 { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
157
158
159/* shutter time 0x0000-0x03FF */
160/* low value give good picures on moving objects (but requires much light) */
161/* high value gives good picures in darkness (but tends to be overexposed) */
162 { 0x143e, 0x01 },
163 { 0x143d, 0x00 },
164
165 { 0x1442, 0xe2 },
166/* write: 1x1x xxxx */
167/* read: 1x1x xxxx */
168/* bit 5 == button pressed and hold if 0 */
169/* write 0xe2,0xea */
170
171/* 0x144a */
172/* 0x00 init */
173/* bit 7 == button has been pressed, but not handled */
174
175/* interrupt */
176/* if(urb->iso_frame_desc[i].status == 0x80) { */
177/* if(urb->iso_frame_desc[i].status == 0x88) { */
178
179 { 0x1500, 0xd0 },
180 { 0x1500, 0xd0 },
181 { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
182
183 { 0x1501, 0xaf },
184/* high val-> light area gets darker */
185/* low val -> light area gets lighter */
186 { 0x1502, 0xc2 },
187/* high val-> light area gets darker */
188/* low val -> light area gets lighter */
189 { 0x1503, 0x45 },
190/* high val-> light area gets darker */
191/* low val -> light area gets lighter */
192 { 0x1505, 0x02 },
193/* 2 : 324x248 80352 bytes */
194/* 7 : 248x162 40176 bytes */
195/* c+f: 162*124 20088 bytes */
196
197 { 0x150e, 0x8e },
198 { 0x150f, 0x37 },
199 { 0x15c0, 0x00 },
200 { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
201
202
203 { 0x143f, 0x01 }, /* commit settings */
204
205 };
206
207 for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
208 err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
209 st6422_bridge_init[i][1]);
210 }
211
212 return err;
213}
214
215static int setbrightness(struct sd *sd, s32 val)
216{
217 /* val goes from 0 -> 31 */
218 return stv06xx_write_bridge(sd, 0x1432, val);
219}
220
221static int setcontrast(struct sd *sd, s32 val)
222{
223 /* Val goes from 0 -> 15 */
224 return stv06xx_write_bridge(sd, 0x143a, val | 0xf0);
225}
226
227static int setgain(struct sd *sd, u8 gain)
228{
229 int err;
230
231 /* Set red, green, blue, gain */
232 err = stv06xx_write_bridge(sd, 0x0509, gain);
233 if (err < 0)
234 return err;
235
236 err = stv06xx_write_bridge(sd, 0x050a, gain);
237 if (err < 0)
238 return err;
239
240 err = stv06xx_write_bridge(sd, 0x050b, gain);
241 if (err < 0)
242 return err;
243
244 /* 2 mystery writes */
245 err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
246 if (err < 0)
247 return err;
248
249 return stv06xx_write_bridge(sd, 0x050d, 0x01);
250}
251
252static int setexposure(struct sd *sd, s16 expo)
253{
254 int err;
255
256 err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
257 if (err < 0)
258 return err;
259
260 return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
261}
262
263static int st6422_start(struct sd *sd)
264{
265 int err;
266 struct cam *cam = &sd->gspca_dev.cam;
267
268 if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
269 err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
270 else
271 err = stv06xx_write_bridge(sd, 0x1505, 0x02);
272 if (err < 0)
273 return err;
274
275 /* commit settings */
276 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
277 return (err < 0) ? err : 0;
278}
279
280static int st6422_stop(struct sd *sd)
281{
282 PDEBUG(D_STREAM, "Halting stream");
283
284 return 0;
285}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h
new file mode 100644
index 00000000000..8f20fbf30f3
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h
@@ -0,0 +1,52 @@
1/*
2 * Support for the sensor part which is integrated (I think) into the
3 * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
4 * but instead direct bridge writes.
5 *
6 * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
7 *
8 * Strongly based on qc-usb-messenger, which is:
9 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
10 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
11 * Copyright (c) 2002, 2003 Tuukka Toivonen
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29#ifndef STV06XX_ST6422_H_
30#define STV06XX_ST6422_H_
31
32#include "stv06xx_sensor.h"
33
34static int st6422_probe(struct sd *sd);
35static int st6422_start(struct sd *sd);
36static int st6422_init(struct sd *sd);
37static int st6422_init_controls(struct sd *sd);
38static int st6422_stop(struct sd *sd);
39
40const struct stv06xx_sensor stv06xx_sensor_st6422 = {
41 .name = "ST6422",
42 /* No known way to lower framerate in case of less bandwidth */
43 .min_packet_size = { 300, 847 },
44 .max_packet_size = { 300, 847 },
45 .init = st6422_init,
46 .init_controls = st6422_init_controls,
47 .probe = st6422_probe,
48 .start = st6422_start,
49 .stop = st6422_stop,
50};
51
52#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
new file mode 100644
index 00000000000..748e1421d6d
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
@@ -0,0 +1,272 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#include "stv06xx_vv6410.h"
33
34static struct v4l2_pix_format vv6410_mode[] = {
35 {
36 356,
37 292,
38 V4L2_PIX_FMT_SGRBG8,
39 V4L2_FIELD_NONE,
40 .sizeimage = 356 * 292,
41 .bytesperline = 356,
42 .colorspace = V4L2_COLORSPACE_SRGB,
43 .priv = 0
44 }
45};
46
47static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl)
48{
49 struct gspca_dev *gspca_dev =
50 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
51 int err = -EINVAL;
52
53 switch (ctrl->id) {
54 case V4L2_CID_HFLIP:
55 err = vv6410_set_hflip(gspca_dev, ctrl->val);
56 break;
57 case V4L2_CID_VFLIP:
58 err = vv6410_set_vflip(gspca_dev, ctrl->val);
59 break;
60 case V4L2_CID_GAIN:
61 err = vv6410_set_analog_gain(gspca_dev, ctrl->val);
62 break;
63 case V4L2_CID_EXPOSURE:
64 err = vv6410_set_exposure(gspca_dev, ctrl->val);
65 break;
66 }
67 return err;
68}
69
70static const struct v4l2_ctrl_ops vv6410_ctrl_ops = {
71 .s_ctrl = vv6410_s_ctrl,
72};
73
74static int vv6410_probe(struct sd *sd)
75{
76 u16 data;
77 int err;
78
79 err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
80 if (err < 0)
81 return -ENODEV;
82
83 if (data != 0x19)
84 return -ENODEV;
85
86 pr_info("vv6410 sensor detected\n");
87
88 sd->gspca_dev.cam.cam_mode = vv6410_mode;
89 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
90 return 0;
91}
92
93static int vv6410_init_controls(struct sd *sd)
94{
95 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
96
97 v4l2_ctrl_handler_init(hdl, 4);
98 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
99 V4L2_CID_HFLIP, 0, 1, 1, 0);
100 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
101 V4L2_CID_VFLIP, 0, 1, 1, 0);
102 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
103 V4L2_CID_EXPOSURE, 0, 32768, 1, 20000);
104 v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
105 V4L2_CID_GAIN, 0, 15, 1, 10);
106 return hdl->error;
107}
108
109static int vv6410_init(struct sd *sd)
110{
111 int err = 0, i;
112
113 for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++)
114 stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
115
116 if (err < 0)
117 return err;
118
119 err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
120 ARRAY_SIZE(vv6410_sensor_init));
121 return (err < 0) ? err : 0;
122}
123
124static int vv6410_start(struct sd *sd)
125{
126 int err;
127 struct cam *cam = &sd->gspca_dev.cam;
128 u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
129
130 if (priv & VV6410_SUBSAMPLE) {
131 PDEBUG(D_CONF, "Enabling subsampling");
132 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
133 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
134
135 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
136 } else {
137 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
138 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
139 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
140
141 }
142
143 /* Turn on LED */
144 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
145 if (err < 0)
146 return err;
147
148 err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
149 if (err < 0)
150 return err;
151
152 PDEBUG(D_STREAM, "Starting stream");
153
154 return 0;
155}
156
157static int vv6410_stop(struct sd *sd)
158{
159 int err;
160
161 /* Turn off LED */
162 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
163 if (err < 0)
164 return err;
165
166 err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
167 if (err < 0)
168 return err;
169
170 PDEBUG(D_STREAM, "Halting stream");
171
172 return (err < 0) ? err : 0;
173}
174
175static int vv6410_dump(struct sd *sd)
176{
177 u8 i;
178 int err = 0;
179
180 pr_info("Dumping all vv6410 sensor registers\n");
181 for (i = 0; i < 0xff && !err; i++) {
182 u16 data;
183 err = stv06xx_read_sensor(sd, i, &data);
184 pr_info("Register 0x%x contained 0x%x\n", i, data);
185 }
186 return (err < 0) ? err : 0;
187}
188
189static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
190{
191 int err;
192 u16 i2c_data;
193 struct sd *sd = (struct sd *) gspca_dev;
194
195 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
196 if (err < 0)
197 return err;
198
199 if (val)
200 i2c_data |= VV6410_HFLIP;
201 else
202 i2c_data &= ~VV6410_HFLIP;
203
204 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
205 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
206
207 return (err < 0) ? err : 0;
208}
209
210static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
211{
212 int err;
213 u16 i2c_data;
214 struct sd *sd = (struct sd *) gspca_dev;
215
216 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
217 if (err < 0)
218 return err;
219
220 if (val)
221 i2c_data |= VV6410_VFLIP;
222 else
223 i2c_data &= ~VV6410_VFLIP;
224
225 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
226 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
227
228 return (err < 0) ? err : 0;
229}
230
231static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
232{
233 int err;
234 struct sd *sd = (struct sd *) gspca_dev;
235
236 PDEBUG(D_V4L2, "Set analog gain to %d", val);
237 err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
238
239 return (err < 0) ? err : 0;
240}
241
242static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
243{
244 int err;
245 struct sd *sd = (struct sd *) gspca_dev;
246 unsigned int fine, coarse;
247
248 val = (val * val >> 14) + val / 4;
249
250 fine = val % VV6410_CIF_LINELENGTH;
251 coarse = min(512, val / VV6410_CIF_LINELENGTH);
252
253 PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
254 coarse, fine);
255
256 err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
257 if (err < 0)
258 goto out;
259
260 err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
261 if (err < 0)
262 goto out;
263
264 err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
265 if (err < 0)
266 goto out;
267
268 err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
269
270out:
271 return err;
272}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h
new file mode 100644
index 00000000000..53e67b40ca0
--- /dev/null
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h
@@ -0,0 +1,255 @@
1/*
2 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4 * Copyright (c) 2002, 2003 Tuukka Toivonen
5 * Copyright (c) 2008 Erik Andrén
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 * (at your option) 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 * P/N 861037: Sensor HDCS1000 ASIC STV0600
22 * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600
23 * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express
24 * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam
25 * P/N 861075-0040: Sensor HDCS1000 ASIC
26 * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB
27 * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web
28 */
29
30#ifndef STV06XX_VV6410_H_
31#define STV06XX_VV6410_H_
32
33#include "stv06xx_sensor.h"
34
35#define VV6410_COLS 416
36#define VV6410_ROWS 320
37
38/* Status registers */
39/* Chip identification number including revision indicator */
40#define VV6410_DEVICEH 0x00
41#define VV6410_DEVICEL 0x01
42
43/* User can determine whether timed I2C data
44 has been consumed by interrogating flag states */
45#define VV6410_STATUS0 0x02
46
47/* Current line counter value */
48#define VV6410_LINECOUNTH 0x03
49#define VV6410_LINECOUNTL 0x04
50
51/* End x coordinate of image size */
52#define VV6410_XENDH 0x05
53#define VV6410_XENDL 0x06
54
55/* End y coordinate of image size */
56#define VV6410_YENDH 0x07
57#define VV6410_YENDL 0x08
58
59/* This is the average pixel value returned from the
60 dark line offset cancellation algorithm */
61#define VV6410_DARKAVGH 0x09
62#define VV6410_DARKAVGL 0x0a
63
64/* This is the average pixel value returned from the
65 black line offset cancellation algorithm */
66#define VV6410_BLACKAVGH 0x0b
67#define VV6410_BLACKAVGL 0x0c
68
69/* Flags to indicate whether the x or y image coordinates have been clipped */
70#define VV6410_STATUS1 0x0d
71
72/* Setup registers */
73
74/* Low-power/sleep modes & video timing */
75#define VV6410_SETUP0 0x10
76
77/* Various parameters */
78#define VV6410_SETUP1 0x11
79
80/* Contains pixel counter reset value used by external sync */
81#define VV6410_SYNCVALUE 0x12
82
83/* Frame grabbing modes (FST, LST and QCK) */
84#define VV6410_FGMODES 0x14
85
86/* FST and QCK mapping modes. */
87#define VV6410_PINMAPPING 0x15
88
89/* Data resolution */
90#define VV6410_DATAFORMAT 0x16
91
92/* Output coding formats */
93#define VV6410_OPFORMAT 0x17
94
95/* Various mode select bits */
96#define VV6410_MODESELECT 0x18
97
98/* Exposure registers */
99/* Fine exposure. */
100#define VV6410_FINEH 0x20
101#define VV6410_FINEL 0x21
102
103/* Coarse exposure */
104#define VV6410_COARSEH 0x22
105#define VV6410_COARSEL 0x23
106
107/* Analog gain setting */
108#define VV6410_ANALOGGAIN 0x24
109
110/* Clock division */
111#define VV6410_CLKDIV 0x25
112
113/* Dark line offset cancellation value */
114#define VV6410_DARKOFFSETH 0x2c
115#define VV6410_DARKOFFSETL 0x2d
116
117/* Dark line offset cancellation enable */
118#define VV6410_DARKOFFSETSETUP 0x2e
119
120/* Video timing registers */
121/* Line Length (Pixel Clocks) */
122#define VV6410_LINELENGTHH 0x52
123#define VV6410_LINELENGTHL 0x53
124
125/* X-co-ordinate of top left corner of region of interest (x-offset) */
126#define VV6410_XOFFSETH 0x57
127#define VV6410_XOFFSETL 0x58
128
129/* Y-coordinate of top left corner of region of interest (y-offset) */
130#define VV6410_YOFFSETH 0x59
131#define VV6410_YOFFSETL 0x5a
132
133/* Field length (Lines) */
134#define VV6410_FIELDLENGTHH 0x61
135#define VV6410_FIELDLENGTHL 0x62
136
137/* System registers */
138/* Black offset cancellation default value */
139#define VV6410_BLACKOFFSETH 0x70
140#define VV6410_BLACKOFFSETL 0x71
141
142/* Black offset cancellation setup */
143#define VV6410_BLACKOFFSETSETUP 0x72
144
145/* Analog Control Register 0 */
146#define VV6410_CR0 0x75
147
148/* Analog Control Register 1 */
149#define VV6410_CR1 0x76
150
151/* ADC Setup Register */
152#define VV6410_AS0 0x77
153
154/* Analog Test Register */
155#define VV6410_AT0 0x78
156
157/* Audio Amplifier Setup Register */
158#define VV6410_AT1 0x79
159
160#define VV6410_HFLIP (1 << 3)
161#define VV6410_VFLIP (1 << 4)
162
163#define VV6410_LOW_POWER_MODE (1 << 0)
164#define VV6410_SOFT_RESET (1 << 2)
165#define VV6410_PAL_25_FPS (0 << 3)
166
167#define VV6410_CLK_DIV_2 (1 << 1)
168
169#define VV6410_FINE_EXPOSURE 320
170#define VV6410_COARSE_EXPOSURE 192
171#define VV6410_DEFAULT_GAIN 5
172
173#define VV6410_SUBSAMPLE 0x01
174#define VV6410_CROP_TO_QVGA 0x02
175
176#define VV6410_CIF_LINELENGTH 415
177
178static int vv6410_probe(struct sd *sd);
179static int vv6410_start(struct sd *sd);
180static int vv6410_init(struct sd *sd);
181static int vv6410_init_controls(struct sd *sd);
182static int vv6410_stop(struct sd *sd);
183static int vv6410_dump(struct sd *sd);
184
185/* V4L2 controls supported by the driver */
186static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
187static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
188static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
189static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
190
191const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
192 .name = "ST VV6410",
193 .i2c_flush = 5,
194 .i2c_addr = 0x20,
195 .i2c_len = 1,
196 /* FIXME (see if we can lower packet_size-s, needs testing, and also
197 adjusting framerate when the bandwidth gets lower) */
198 .min_packet_size = { 1023 },
199 .max_packet_size = { 1023 },
200 .init = vv6410_init,
201 .init_controls = vv6410_init_controls,
202 .probe = vv6410_probe,
203 .start = vv6410_start,
204 .stop = vv6410_stop,
205 .dump = vv6410_dump,
206};
207
208/* If NULL, only single value to write, stored in len */
209struct stv_init {
210 u16 addr;
211 u8 data;
212};
213
214static const struct stv_init stv_bridge_init[] = {
215 /* This reg is written twice. Some kind of reset? */
216 {STV_RESET, 0x80},
217 {STV_RESET, 0x00},
218 {STV_SCAN_RATE, 0x00},
219 {STV_I2C_FLUSH, 0x04},
220 {STV_REG00, 0x0b},
221 {STV_REG01, 0xa7},
222 {STV_REG02, 0xb7},
223 {STV_REG03, 0x00},
224 {STV_REG04, 0x00},
225 {0x1536, 0x02},
226 {0x1537, 0x00},
227 {0x1538, 0x60},
228 {0x1539, 0x01},
229 {0x153a, 0x20},
230 {0x153b, 0x01},
231};
232
233static const u8 vv6410_sensor_init[][2] = {
234 /* Setup registers */
235 {VV6410_SETUP0, VV6410_SOFT_RESET},
236 {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
237 /* Use shuffled read-out mode */
238 {VV6410_SETUP1, BIT(6)},
239 /* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
240 {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
241 {VV6410_PINMAPPING, 0x00},
242 /* Pre-clock generator divide off */
243 {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
244
245 {VV6410_CLKDIV, VV6410_CLK_DIV_2},
246
247 /* System registers */
248 /* Enable voltage doubler */
249 {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
250 {VV6410_AT0, 0x00},
251 /* Power up audio, differential */
252 {VV6410_AT1, BIT(4) | BIT(0)},
253};
254
255#endif
diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c
new file mode 100644
index 00000000000..9ccfcb1c647
--- /dev/null
+++ b/drivers/media/usb/gspca/sunplus.c
@@ -0,0 +1,1085 @@
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "sunplus"
25
26#include "gspca.h"
27#include "jpeg.h"
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33#define QUALITY 85
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 bool autogain;
40
41 u8 bridge;
42#define BRIDGE_SPCA504 0
43#define BRIDGE_SPCA504B 1
44#define BRIDGE_SPCA504C 2
45#define BRIDGE_SPCA533 3
46#define BRIDGE_SPCA536 4
47 u8 subtype;
48#define AiptekMiniPenCam13 1
49#define LogitechClickSmart420 2
50#define LogitechClickSmart820 3
51#define MegapixV4 4
52#define MegaImageVI 5
53
54 u8 jpeg_hdr[JPEG_HDR_SZ];
55};
56
57static const struct v4l2_pix_format vga_mode[] = {
58 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
59 .bytesperline = 320,
60 .sizeimage = 320 * 240 * 3 / 8 + 590,
61 .colorspace = V4L2_COLORSPACE_JPEG,
62 .priv = 2},
63 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
64 .bytesperline = 640,
65 .sizeimage = 640 * 480 * 3 / 8 + 590,
66 .colorspace = V4L2_COLORSPACE_JPEG,
67 .priv = 1},
68};
69
70static const struct v4l2_pix_format custom_mode[] = {
71 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
72 .bytesperline = 320,
73 .sizeimage = 320 * 240 * 3 / 8 + 590,
74 .colorspace = V4L2_COLORSPACE_JPEG,
75 .priv = 2},
76 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
77 .bytesperline = 464,
78 .sizeimage = 464 * 480 * 3 / 8 + 590,
79 .colorspace = V4L2_COLORSPACE_JPEG,
80 .priv = 1},
81};
82
83static const struct v4l2_pix_format vga_mode2[] = {
84 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
85 .bytesperline = 176,
86 .sizeimage = 176 * 144 * 3 / 8 + 590,
87 .colorspace = V4L2_COLORSPACE_JPEG,
88 .priv = 4},
89 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
90 .bytesperline = 320,
91 .sizeimage = 320 * 240 * 3 / 8 + 590,
92 .colorspace = V4L2_COLORSPACE_JPEG,
93 .priv = 3},
94 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
95 .bytesperline = 352,
96 .sizeimage = 352 * 288 * 3 / 8 + 590,
97 .colorspace = V4L2_COLORSPACE_JPEG,
98 .priv = 2},
99 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
100 .bytesperline = 640,
101 .sizeimage = 640 * 480 * 3 / 8 + 590,
102 .colorspace = V4L2_COLORSPACE_JPEG,
103 .priv = 1},
104};
105
106#define SPCA50X_OFFSET_DATA 10
107#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
108#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
109#define SPCA504_PCCAM600_OFFSET_MODE 5
110#define SPCA504_PCCAM600_OFFSET_DATA 14
111 /* Frame packet header offsets for the spca533 */
112#define SPCA533_OFFSET_DATA 16
113#define SPCA533_OFFSET_FRAMSEQ 15
114/* Frame packet header offsets for the spca536 */
115#define SPCA536_OFFSET_DATA 4
116#define SPCA536_OFFSET_FRAMSEQ 1
117
118struct cmd {
119 u8 req;
120 u16 val;
121 u16 idx;
122};
123
124/* Initialisation data for the Creative PC-CAM 600 */
125static const struct cmd spca504_pccam600_init_data[] = {
126/* {0xa0, 0x0000, 0x0503}, * capture mode */
127 {0x00, 0x0000, 0x2000},
128 {0x00, 0x0013, 0x2301},
129 {0x00, 0x0003, 0x2000},
130 {0x00, 0x0001, 0x21ac},
131 {0x00, 0x0001, 0x21a6},
132 {0x00, 0x0000, 0x21a7}, /* brightness */
133 {0x00, 0x0020, 0x21a8}, /* contrast */
134 {0x00, 0x0001, 0x21ac}, /* sat/hue */
135 {0x00, 0x0000, 0x21ad}, /* hue */
136 {0x00, 0x001a, 0x21ae}, /* saturation */
137 {0x00, 0x0002, 0x21a3}, /* gamma */
138 {0x30, 0x0154, 0x0008},
139 {0x30, 0x0004, 0x0006},
140 {0x30, 0x0258, 0x0009},
141 {0x30, 0x0004, 0x0000},
142 {0x30, 0x0093, 0x0004},
143 {0x30, 0x0066, 0x0005},
144 {0x00, 0x0000, 0x2000},
145 {0x00, 0x0013, 0x2301},
146 {0x00, 0x0003, 0x2000},
147 {0x00, 0x0013, 0x2301},
148 {0x00, 0x0003, 0x2000},
149};
150
151/* Creative PC-CAM 600 specific open data, sent before using the
152 * generic initialisation data from spca504_open_data.
153 */
154static const struct cmd spca504_pccam600_open_data[] = {
155 {0x00, 0x0001, 0x2501},
156 {0x20, 0x0500, 0x0001}, /* snapshot mode */
157 {0x00, 0x0003, 0x2880},
158 {0x00, 0x0001, 0x2881},
159};
160
161/* Initialisation data for the logitech clicksmart 420 */
162static const struct cmd spca504A_clicksmart420_init_data[] = {
163/* {0xa0, 0x0000, 0x0503}, * capture mode */
164 {0x00, 0x0000, 0x2000},
165 {0x00, 0x0013, 0x2301},
166 {0x00, 0x0003, 0x2000},
167 {0x00, 0x0001, 0x21ac},
168 {0x00, 0x0001, 0x21a6},
169 {0x00, 0x0000, 0x21a7}, /* brightness */
170 {0x00, 0x0020, 0x21a8}, /* contrast */
171 {0x00, 0x0001, 0x21ac}, /* sat/hue */
172 {0x00, 0x0000, 0x21ad}, /* hue */
173 {0x00, 0x001a, 0x21ae}, /* saturation */
174 {0x00, 0x0002, 0x21a3}, /* gamma */
175 {0x30, 0x0004, 0x000a},
176 {0xb0, 0x0001, 0x0000},
177
178 {0xa1, 0x0080, 0x0001},
179 {0x30, 0x0049, 0x0000},
180 {0x30, 0x0060, 0x0005},
181 {0x0c, 0x0004, 0x0000},
182 {0x00, 0x0000, 0x0000},
183 {0x00, 0x0000, 0x2000},
184 {0x00, 0x0013, 0x2301},
185 {0x00, 0x0003, 0x2000},
186};
187
188/* clicksmart 420 open data ? */
189static const struct cmd spca504A_clicksmart420_open_data[] = {
190 {0x00, 0x0001, 0x2501},
191 {0x20, 0x0502, 0x0000},
192 {0x06, 0x0000, 0x0000},
193 {0x00, 0x0004, 0x2880},
194 {0x00, 0x0001, 0x2881},
195
196 {0xa0, 0x0000, 0x0503},
197};
198
199static const u8 qtable_creative_pccam[2][64] = {
200 { /* Q-table Y-components */
201 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
202 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
203 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
204 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
205 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
206 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
207 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
208 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
209 { /* Q-table C-components */
210 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
211 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
212 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
213 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
214 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
215 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
216 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
217 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
218};
219
220/* FIXME: This Q-table is identical to the Creative PC-CAM one,
221 * except for one byte. Possibly a typo?
222 * NWG: 18/05/2003.
223 */
224static const u8 qtable_spca504_default[2][64] = {
225 { /* Q-table Y-components */
226 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
227 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
228 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
229 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
230 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
231 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
232 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
233 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
234 },
235 { /* Q-table C-components */
236 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
237 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
238 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
239 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
240 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
241 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
242 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
243 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
244};
245
246/* read <len> bytes to gspca_dev->usb_buf */
247static void reg_r(struct gspca_dev *gspca_dev,
248 u8 req,
249 u16 index,
250 u16 len)
251{
252 int ret;
253
254#ifdef GSPCA_DEBUG
255 if (len > USB_BUF_SZ) {
256 pr_err("reg_r: buffer overflow\n");
257 return;
258 }
259#endif
260 if (gspca_dev->usb_err < 0)
261 return;
262 ret = usb_control_msg(gspca_dev->dev,
263 usb_rcvctrlpipe(gspca_dev->dev, 0),
264 req,
265 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
266 0, /* value */
267 index,
268 len ? gspca_dev->usb_buf : NULL, len,
269 500);
270 if (ret < 0) {
271 pr_err("reg_r err %d\n", ret);
272 gspca_dev->usb_err = ret;
273 }
274}
275
276/* write one byte */
277static void reg_w_1(struct gspca_dev *gspca_dev,
278 u8 req,
279 u16 value,
280 u16 index,
281 u16 byte)
282{
283 int ret;
284
285 if (gspca_dev->usb_err < 0)
286 return;
287 gspca_dev->usb_buf[0] = byte;
288 ret = usb_control_msg(gspca_dev->dev,
289 usb_sndctrlpipe(gspca_dev->dev, 0),
290 req,
291 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
292 value, index,
293 gspca_dev->usb_buf, 1,
294 500);
295 if (ret < 0) {
296 pr_err("reg_w_1 err %d\n", ret);
297 gspca_dev->usb_err = ret;
298 }
299}
300
301/* write req / index / value */
302static void reg_w_riv(struct gspca_dev *gspca_dev,
303 u8 req, u16 index, u16 value)
304{
305 struct usb_device *dev = gspca_dev->dev;
306 int ret;
307
308 if (gspca_dev->usb_err < 0)
309 return;
310 ret = usb_control_msg(dev,
311 usb_sndctrlpipe(dev, 0),
312 req,
313 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
314 value, index, NULL, 0, 500);
315 if (ret < 0) {
316 pr_err("reg_w_riv err %d\n", ret);
317 gspca_dev->usb_err = ret;
318 return;
319 }
320 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
321 req, index, value);
322}
323
324static void write_vector(struct gspca_dev *gspca_dev,
325 const struct cmd *data, int ncmds)
326{
327 while (--ncmds >= 0) {
328 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
329 data++;
330 }
331}
332
333static void setup_qtable(struct gspca_dev *gspca_dev,
334 const u8 qtable[2][64])
335{
336 int i;
337
338 /* loop over y components */
339 for (i = 0; i < 64; i++)
340 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
341
342 /* loop over c components */
343 for (i = 0; i < 64; i++)
344 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
345}
346
347static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
348 u8 req, u16 idx, u16 val)
349{
350 reg_w_riv(gspca_dev, req, idx, val);
351 reg_r(gspca_dev, 0x01, 0x0001, 1);
352 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
353 reg_w_riv(gspca_dev, req, idx, val);
354
355 msleep(200);
356 reg_r(gspca_dev, 0x01, 0x0001, 1);
357 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
358}
359
360#ifdef GSPCA_DEBUG
361static void spca504_read_info(struct gspca_dev *gspca_dev)
362{
363 int i;
364 u8 info[6];
365
366 for (i = 0; i < 6; i++) {
367 reg_r(gspca_dev, 0, i, 1);
368 info[i] = gspca_dev->usb_buf[0];
369 }
370 PDEBUG(D_STREAM,
371 "Read info: %d %d %d %d %d %d."
372 " Should be 1,0,2,2,0,0",
373 info[0], info[1], info[2],
374 info[3], info[4], info[5]);
375}
376#endif
377
378static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
379 u8 req,
380 u16 idx, u16 val, u8 endcode, u8 count)
381{
382 u16 status;
383
384 reg_w_riv(gspca_dev, req, idx, val);
385 reg_r(gspca_dev, 0x01, 0x0001, 1);
386 if (gspca_dev->usb_err < 0)
387 return;
388 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
389 gspca_dev->usb_buf[0], endcode);
390 if (!count)
391 return;
392 count = 200;
393 while (--count > 0) {
394 msleep(10);
395 /* gsmart mini2 write a each wait setting 1 ms is enough */
396/* reg_w_riv(gspca_dev, req, idx, val); */
397 reg_r(gspca_dev, 0x01, 0x0001, 1);
398 status = gspca_dev->usb_buf[0];
399 if (status == endcode) {
400 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
401 status, 200 - count);
402 break;
403 }
404 }
405}
406
407static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
408{
409 int count = 10;
410
411 while (--count > 0) {
412 reg_r(gspca_dev, 0x21, 0, 1);
413 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
414 break;
415 msleep(10);
416 }
417}
418
419static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
420{
421 int count = 50;
422
423 while (--count > 0) {
424 reg_r(gspca_dev, 0x21, 1, 1);
425 if (gspca_dev->usb_buf[0] != 0) {
426 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
427 reg_r(gspca_dev, 0x21, 1, 1);
428 spca504B_PollingDataReady(gspca_dev);
429 break;
430 }
431 msleep(10);
432 }
433}
434
435#ifdef GSPCA_DEBUG
436static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
437{
438 u8 *data;
439
440 data = gspca_dev->usb_buf;
441 reg_r(gspca_dev, 0x20, 0, 5);
442 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
443 data[0], data[1], data[2], data[3], data[4]);
444 reg_r(gspca_dev, 0x23, 0, 64);
445 reg_r(gspca_dev, 0x23, 1, 64);
446}
447#endif
448
449static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
450{
451 struct sd *sd = (struct sd *) gspca_dev;
452 u8 Size;
453
454 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
455 switch (sd->bridge) {
456 case BRIDGE_SPCA533:
457 reg_w_riv(gspca_dev, 0x31, 0, 0);
458 spca504B_WaitCmdStatus(gspca_dev);
459 spca504B_PollingDataReady(gspca_dev);
460#ifdef GSPCA_DEBUG
461 spca50x_GetFirmware(gspca_dev);
462#endif
463 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
464 reg_r(gspca_dev, 0x24, 8, 1);
465
466 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
467 reg_r(gspca_dev, 0x25, 4, 1); /* size */
468 spca504B_PollingDataReady(gspca_dev);
469
470 /* Init the cam width height with some values get on init ? */
471 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
472 spca504B_WaitCmdStatus(gspca_dev);
473 spca504B_PollingDataReady(gspca_dev);
474 break;
475 default:
476/* case BRIDGE_SPCA504B: */
477/* case BRIDGE_SPCA536: */
478 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
479 reg_r(gspca_dev, 0x25, 4, 1); /* size */
480 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
481 reg_r(gspca_dev, 0x27, 0, 1); /* type */
482 spca504B_PollingDataReady(gspca_dev);
483 break;
484 case BRIDGE_SPCA504:
485 Size += 3;
486 if (sd->subtype == AiptekMiniPenCam13) {
487 /* spca504a aiptek */
488 spca504A_acknowledged_command(gspca_dev,
489 0x08, Size, 0,
490 0x80 | (Size & 0x0f), 1);
491 spca504A_acknowledged_command(gspca_dev,
492 1, 3, 0, 0x9f, 0);
493 } else {
494 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
495 }
496 break;
497 case BRIDGE_SPCA504C:
498 /* capture mode */
499 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
500 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
501 break;
502 }
503}
504
505static void spca504_wait_status(struct gspca_dev *gspca_dev)
506{
507 int cnt;
508
509 cnt = 256;
510 while (--cnt > 0) {
511 /* With this we get the status, when return 0 it's all ok */
512 reg_r(gspca_dev, 0x06, 0x00, 1);
513 if (gspca_dev->usb_buf[0] == 0)
514 return;
515 msleep(10);
516 }
517}
518
519static void spca504B_setQtable(struct gspca_dev *gspca_dev)
520{
521 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
522 reg_r(gspca_dev, 0x26, 0, 1);
523 spca504B_PollingDataReady(gspca_dev);
524}
525
526static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
527{
528 struct sd *sd = (struct sd *) gspca_dev;
529 u16 reg;
530
531 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
532 reg_w_riv(gspca_dev, 0x00, reg, val);
533}
534
535static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
536{
537 struct sd *sd = (struct sd *) gspca_dev;
538 u16 reg;
539
540 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
541 reg_w_riv(gspca_dev, 0x00, reg, val);
542}
543
544static void setcolors(struct gspca_dev *gspca_dev, s32 val)
545{
546 struct sd *sd = (struct sd *) gspca_dev;
547 u16 reg;
548
549 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
550 reg_w_riv(gspca_dev, 0x00, reg, val);
551}
552
553static void init_ctl_reg(struct gspca_dev *gspca_dev)
554{
555 struct sd *sd = (struct sd *) gspca_dev;
556 int pollreg = 1;
557
558 switch (sd->bridge) {
559 case BRIDGE_SPCA504:
560 case BRIDGE_SPCA504C:
561 pollreg = 0;
562 /* fall thru */
563 default:
564/* case BRIDGE_SPCA533: */
565/* case BRIDGE_SPCA504B: */
566 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
567 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
568 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
569 break;
570 case BRIDGE_SPCA536:
571 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
572 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
573 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
574 break;
575 }
576 if (pollreg)
577 spca504B_PollingDataReady(gspca_dev);
578}
579
580/* this function is called at probe time */
581static int sd_config(struct gspca_dev *gspca_dev,
582 const struct usb_device_id *id)
583{
584 struct sd *sd = (struct sd *) gspca_dev;
585 struct cam *cam;
586
587 cam = &gspca_dev->cam;
588
589 sd->bridge = id->driver_info >> 8;
590 sd->subtype = id->driver_info;
591
592 if (sd->subtype == AiptekMiniPenCam13) {
593
594 /* try to get the firmware as some cam answer 2.0.1.2.2
595 * and should be a spca504b then overwrite that setting */
596 reg_r(gspca_dev, 0x20, 0, 1);
597 switch (gspca_dev->usb_buf[0]) {
598 case 1:
599 break; /* (right bridge/subtype) */
600 case 2:
601 sd->bridge = BRIDGE_SPCA504B;
602 sd->subtype = 0;
603 break;
604 default:
605 return -ENODEV;
606 }
607 }
608
609 switch (sd->bridge) {
610 default:
611/* case BRIDGE_SPCA504B: */
612/* case BRIDGE_SPCA504: */
613/* case BRIDGE_SPCA536: */
614 cam->cam_mode = vga_mode;
615 cam->nmodes = ARRAY_SIZE(vga_mode);
616 break;
617 case BRIDGE_SPCA533:
618 cam->cam_mode = custom_mode;
619 if (sd->subtype == MegaImageVI) /* 320x240 only */
620 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
621 else
622 cam->nmodes = ARRAY_SIZE(custom_mode);
623 break;
624 case BRIDGE_SPCA504C:
625 cam->cam_mode = vga_mode2;
626 cam->nmodes = ARRAY_SIZE(vga_mode2);
627 break;
628 }
629 return 0;
630}
631
632/* this function is called at probe and resume time */
633static int sd_init(struct gspca_dev *gspca_dev)
634{
635 struct sd *sd = (struct sd *) gspca_dev;
636
637 switch (sd->bridge) {
638 case BRIDGE_SPCA504B:
639 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
640 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
641 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
642 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
643 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
644 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
645 /* fall thru */
646 case BRIDGE_SPCA533:
647 spca504B_PollingDataReady(gspca_dev);
648#ifdef GSPCA_DEBUG
649 spca50x_GetFirmware(gspca_dev);
650#endif
651 break;
652 case BRIDGE_SPCA536:
653#ifdef GSPCA_DEBUG
654 spca50x_GetFirmware(gspca_dev);
655#endif
656 reg_r(gspca_dev, 0x00, 0x5002, 1);
657 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
658 reg_r(gspca_dev, 0x24, 0, 1);
659 spca504B_PollingDataReady(gspca_dev);
660 reg_w_riv(gspca_dev, 0x34, 0, 0);
661 spca504B_WaitCmdStatus(gspca_dev);
662 break;
663 case BRIDGE_SPCA504C: /* pccam600 */
664 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
665 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
666 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
667 spca504_wait_status(gspca_dev);
668 if (sd->subtype == LogitechClickSmart420)
669 write_vector(gspca_dev,
670 spca504A_clicksmart420_open_data,
671 ARRAY_SIZE(spca504A_clicksmart420_open_data));
672 else
673 write_vector(gspca_dev, spca504_pccam600_open_data,
674 ARRAY_SIZE(spca504_pccam600_open_data));
675 setup_qtable(gspca_dev, qtable_creative_pccam);
676 break;
677 default:
678/* case BRIDGE_SPCA504: */
679 PDEBUG(D_STREAM, "Opening SPCA504");
680 if (sd->subtype == AiptekMiniPenCam13) {
681#ifdef GSPCA_DEBUG
682 spca504_read_info(gspca_dev);
683#endif
684
685 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
686 spca504A_acknowledged_command(gspca_dev, 0x24,
687 8, 3, 0x9e, 1);
688 /* Twice sequential need status 0xff->0x9e->0x9d */
689 spca504A_acknowledged_command(gspca_dev, 0x24,
690 8, 3, 0x9e, 0);
691
692 spca504A_acknowledged_command(gspca_dev, 0x24,
693 0, 0, 0x9d, 1);
694 /******************************/
695 /* spca504a aiptek */
696 spca504A_acknowledged_command(gspca_dev, 0x08,
697 6, 0, 0x86, 1);
698/* reg_write (dev, 0, 0x2000, 0); */
699/* reg_write (dev, 0, 0x2883, 1); */
700/* spca504A_acknowledged_command (gspca_dev, 0x08,
701 6, 0, 0x86, 1); */
702/* spca504A_acknowledged_command (gspca_dev, 0x24,
703 0, 0, 0x9D, 1); */
704 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
705 /* L92 sno1t.txt */
706 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
707 spca504A_acknowledged_command(gspca_dev, 0x01,
708 0x0f, 0, 0xff, 0);
709 }
710 /* setup qtable */
711 reg_w_riv(gspca_dev, 0, 0x2000, 0);
712 reg_w_riv(gspca_dev, 0, 0x2883, 1);
713 setup_qtable(gspca_dev, qtable_spca504_default);
714 break;
715 }
716 return gspca_dev->usb_err;
717}
718
719static int sd_start(struct gspca_dev *gspca_dev)
720{
721 struct sd *sd = (struct sd *) gspca_dev;
722 int enable;
723
724 /* create the JPEG header */
725 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
726 0x22); /* JPEG 411 */
727 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
728
729 if (sd->bridge == BRIDGE_SPCA504B)
730 spca504B_setQtable(gspca_dev);
731 spca504B_SetSizeType(gspca_dev);
732 switch (sd->bridge) {
733 default:
734/* case BRIDGE_SPCA504B: */
735/* case BRIDGE_SPCA533: */
736/* case BRIDGE_SPCA536: */
737 switch (sd->subtype) {
738 case MegapixV4:
739 case LogitechClickSmart820:
740 case MegaImageVI:
741 reg_w_riv(gspca_dev, 0xf0, 0, 0);
742 spca504B_WaitCmdStatus(gspca_dev);
743 reg_r(gspca_dev, 0xf0, 4, 0);
744 spca504B_WaitCmdStatus(gspca_dev);
745 break;
746 default:
747 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
748 spca504B_WaitCmdStatus(gspca_dev);
749 spca504B_PollingDataReady(gspca_dev);
750 break;
751 }
752 break;
753 case BRIDGE_SPCA504:
754 if (sd->subtype == AiptekMiniPenCam13) {
755#ifdef GSPCA_DEBUG
756 spca504_read_info(gspca_dev);
757#endif
758
759 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
760 spca504A_acknowledged_command(gspca_dev, 0x24,
761 8, 3, 0x9e, 1);
762 /* Twice sequential need status 0xff->0x9e->0x9d */
763 spca504A_acknowledged_command(gspca_dev, 0x24,
764 8, 3, 0x9e, 0);
765 spca504A_acknowledged_command(gspca_dev, 0x24,
766 0, 0, 0x9d, 1);
767 } else {
768 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
769#ifdef GSPCA_DEBUG
770 spca504_read_info(gspca_dev);
771#endif
772 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
773 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
774 }
775 spca504B_SetSizeType(gspca_dev);
776 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
777 /* L92 sno1t.txt */
778 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
779 break;
780 case BRIDGE_SPCA504C:
781 if (sd->subtype == LogitechClickSmart420) {
782 write_vector(gspca_dev,
783 spca504A_clicksmart420_init_data,
784 ARRAY_SIZE(spca504A_clicksmart420_init_data));
785 } else {
786 write_vector(gspca_dev, spca504_pccam600_init_data,
787 ARRAY_SIZE(spca504_pccam600_init_data));
788 }
789 enable = (sd->autogain ? 0x04 : 0x01);
790 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
791 /* auto exposure */
792 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
793 /* auto whiteness */
794
795 /* set default exposure compensation and whiteness balance */
796 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
797 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
798 spca504B_SetSizeType(gspca_dev);
799 break;
800 }
801 init_ctl_reg(gspca_dev);
802 return gspca_dev->usb_err;
803}
804
805static void sd_stopN(struct gspca_dev *gspca_dev)
806{
807 struct sd *sd = (struct sd *) gspca_dev;
808
809 switch (sd->bridge) {
810 default:
811/* case BRIDGE_SPCA533: */
812/* case BRIDGE_SPCA536: */
813/* case BRIDGE_SPCA504B: */
814 reg_w_riv(gspca_dev, 0x31, 0, 0);
815 spca504B_WaitCmdStatus(gspca_dev);
816 spca504B_PollingDataReady(gspca_dev);
817 break;
818 case BRIDGE_SPCA504:
819 case BRIDGE_SPCA504C:
820 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
821
822 if (sd->subtype == AiptekMiniPenCam13) {
823 /* spca504a aiptek */
824/* spca504A_acknowledged_command(gspca_dev, 0x08,
825 6, 0, 0x86, 1); */
826 spca504A_acknowledged_command(gspca_dev, 0x24,
827 0x00, 0x00, 0x9d, 1);
828 spca504A_acknowledged_command(gspca_dev, 0x01,
829 0x0f, 0x00, 0xff, 1);
830 } else {
831 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
832 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
833 }
834 break;
835 }
836}
837
838static void sd_pkt_scan(struct gspca_dev *gspca_dev,
839 u8 *data, /* isoc packet */
840 int len) /* iso packet length */
841{
842 struct sd *sd = (struct sd *) gspca_dev;
843 int i, sof = 0;
844 static u8 ffd9[] = {0xff, 0xd9};
845
846/* frames are jpeg 4.1.1 without 0xff escape */
847 switch (sd->bridge) {
848 case BRIDGE_SPCA533:
849 if (data[0] == 0xff) {
850 if (data[1] != 0x01) { /* drop packet */
851/* gspca_dev->last_packet_type = DISCARD_PACKET; */
852 return;
853 }
854 sof = 1;
855 data += SPCA533_OFFSET_DATA;
856 len -= SPCA533_OFFSET_DATA;
857 } else {
858 data += 1;
859 len -= 1;
860 }
861 break;
862 case BRIDGE_SPCA536:
863 if (data[0] == 0xff) {
864 sof = 1;
865 data += SPCA536_OFFSET_DATA;
866 len -= SPCA536_OFFSET_DATA;
867 } else {
868 data += 2;
869 len -= 2;
870 }
871 break;
872 default:
873/* case BRIDGE_SPCA504: */
874/* case BRIDGE_SPCA504B: */
875 switch (data[0]) {
876 case 0xfe: /* start of frame */
877 sof = 1;
878 data += SPCA50X_OFFSET_DATA;
879 len -= SPCA50X_OFFSET_DATA;
880 break;
881 case 0xff: /* drop packet */
882/* gspca_dev->last_packet_type = DISCARD_PACKET; */
883 return;
884 default:
885 data += 1;
886 len -= 1;
887 break;
888 }
889 break;
890 case BRIDGE_SPCA504C:
891 switch (data[0]) {
892 case 0xfe: /* start of frame */
893 sof = 1;
894 data += SPCA504_PCCAM600_OFFSET_DATA;
895 len -= SPCA504_PCCAM600_OFFSET_DATA;
896 break;
897 case 0xff: /* drop packet */
898/* gspca_dev->last_packet_type = DISCARD_PACKET; */
899 return;
900 default:
901 data += 1;
902 len -= 1;
903 break;
904 }
905 break;
906 }
907 if (sof) { /* start of frame */
908 gspca_frame_add(gspca_dev, LAST_PACKET,
909 ffd9, 2);
910
911 /* put the JPEG header in the new frame */
912 gspca_frame_add(gspca_dev, FIRST_PACKET,
913 sd->jpeg_hdr, JPEG_HDR_SZ);
914 }
915
916 /* add 0x00 after 0xff */
917 i = 0;
918 do {
919 if (data[i] == 0xff) {
920 gspca_frame_add(gspca_dev, INTER_PACKET,
921 data, i + 1);
922 len -= i;
923 data += i;
924 *data = 0x00;
925 i = 0;
926 }
927 i++;
928 } while (i < len);
929 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
930}
931
932static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
933{
934 struct gspca_dev *gspca_dev =
935 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
936 struct sd *sd = (struct sd *)gspca_dev;
937
938 gspca_dev->usb_err = 0;
939
940 if (!gspca_dev->streaming)
941 return 0;
942
943 switch (ctrl->id) {
944 case V4L2_CID_BRIGHTNESS:
945 setbrightness(gspca_dev, ctrl->val);
946 break;
947 case V4L2_CID_CONTRAST:
948 setcontrast(gspca_dev, ctrl->val);
949 break;
950 case V4L2_CID_SATURATION:
951 setcolors(gspca_dev, ctrl->val);
952 break;
953 case V4L2_CID_AUTOGAIN:
954 sd->autogain = ctrl->val;
955 break;
956 }
957 return gspca_dev->usb_err;
958}
959
960static const struct v4l2_ctrl_ops sd_ctrl_ops = {
961 .s_ctrl = sd_s_ctrl,
962};
963
964static int sd_init_controls(struct gspca_dev *gspca_dev)
965{
966 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
967
968 gspca_dev->vdev.ctrl_handler = hdl;
969 v4l2_ctrl_handler_init(hdl, 4);
970 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
971 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
972 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
973 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
974 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
975 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
976 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
977 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
978
979 if (hdl->error) {
980 pr_err("Could not initialize controls\n");
981 return hdl->error;
982 }
983 return 0;
984}
985
986/* sub-driver description */
987static const struct sd_desc sd_desc = {
988 .name = MODULE_NAME,
989 .config = sd_config,
990 .init = sd_init,
991 .init_controls = sd_init_controls,
992 .start = sd_start,
993 .stopN = sd_stopN,
994 .pkt_scan = sd_pkt_scan,
995};
996
997/* -- module initialisation -- */
998#define BS(bridge, subtype) \
999 .driver_info = (BRIDGE_ ## bridge << 8) \
1000 | (subtype)
1001static const struct usb_device_id device_table[] = {
1002 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1003 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1004 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1005 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1006 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1007 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1008 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1009 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1010 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1011 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1012 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1013 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1014 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1015 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1016 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1017 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1018 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1019 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1020 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1021 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1022 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1023 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1024 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1025 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1026 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1027 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1028 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1029 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1030 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1031 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1032 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1033 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1034 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1035 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1036 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1037 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1038 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1039 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1040 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1041 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1042 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1043 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1044 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1045 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1046 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1047 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1048 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1049 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1050 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1051 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1052 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1053 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1054 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1055 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1056 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1057 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1058 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1059 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1060 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1061 {}
1062};
1063MODULE_DEVICE_TABLE(usb, device_table);
1064
1065/* -- device connect -- */
1066static int sd_probe(struct usb_interface *intf,
1067 const struct usb_device_id *id)
1068{
1069 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1070 THIS_MODULE);
1071}
1072
1073static struct usb_driver sd_driver = {
1074 .name = MODULE_NAME,
1075 .id_table = device_table,
1076 .probe = sd_probe,
1077 .disconnect = gspca_disconnect,
1078#ifdef CONFIG_PM
1079 .suspend = gspca_suspend,
1080 .resume = gspca_resume,
1081 .reset_resume = gspca_resume,
1082#endif
1083};
1084
1085module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/t613.c b/drivers/media/usb/gspca/t613.c
new file mode 100644
index 00000000000..8bc6c3ceec2
--- /dev/null
+++ b/drivers/media/usb/gspca/t613.c
@@ -0,0 +1,1054 @@
1/*
2 * T613 subdriver
3 *
4 * Copyright (C) 2010 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 *Notes: * t613 + tas5130A
21 * * Focus to light do not balance well as in win.
22 * Quality in win is not good, but its kinda better.
23 * * Fix some "extraneous bytes", most of apps will show the image anyway
24 * * Gamma table, is there, but its really doing something?
25 * * 7~8 Fps, its ok, max on win its 10.
26 * Costantino Leandro
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#define MODULE_NAME "t613"
32
33#include <linux/input.h>
34#include <linux/slab.h>
35#include "gspca.h"
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 struct v4l2_ctrl *freq;
44 struct { /* awb / color gains control cluster */
45 struct v4l2_ctrl *awb;
46 struct v4l2_ctrl *gain;
47 struct v4l2_ctrl *red_balance;
48 struct v4l2_ctrl *blue_balance;
49 };
50
51 u8 sensor;
52 u8 button_pressed;
53};
54enum sensors {
55 SENSOR_OM6802,
56 SENSOR_OTHER,
57 SENSOR_TAS5130A,
58 SENSOR_LT168G, /* must verify if this is the actual model */
59};
60
61static const struct v4l2_pix_format vga_mode_t16[] = {
62 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
63 .bytesperline = 160,
64 .sizeimage = 160 * 120 * 4 / 8 + 590,
65 .colorspace = V4L2_COLORSPACE_JPEG,
66 .priv = 4},
67#if 0 /* HDG: broken with my test cam, so lets disable it */
68 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
69 .bytesperline = 176,
70 .sizeimage = 176 * 144 * 3 / 8 + 590,
71 .colorspace = V4L2_COLORSPACE_JPEG,
72 .priv = 3},
73#endif
74 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
75 .bytesperline = 320,
76 .sizeimage = 320 * 240 * 3 / 8 + 590,
77 .colorspace = V4L2_COLORSPACE_JPEG,
78 .priv = 2},
79#if 0 /* HDG: broken with my test cam, so lets disable it */
80 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
81 .bytesperline = 352,
82 .sizeimage = 352 * 288 * 3 / 8 + 590,
83 .colorspace = V4L2_COLORSPACE_JPEG,
84 .priv = 1},
85#endif
86 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
87 .bytesperline = 640,
88 .sizeimage = 640 * 480 * 3 / 8 + 590,
89 .colorspace = V4L2_COLORSPACE_JPEG,
90 .priv = 0},
91};
92
93/* sensor specific data */
94struct additional_sensor_data {
95 const u8 n3[6];
96 const u8 *n4, n4sz;
97 const u8 reg80, reg8e;
98 const u8 nset8[6];
99 const u8 data1[10];
100 const u8 data2[9];
101 const u8 data3[9];
102 const u8 data5[6];
103 const u8 stream[4];
104};
105
106static const u8 n4_om6802[] = {
107 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
108 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
109 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
110 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
111 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
112 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
113 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
114 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
115 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
116};
117static const u8 n4_other[] = {
118 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
119 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
120 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
121 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
122 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
123 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
124 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
125 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
126};
127static const u8 n4_tas5130a[] = {
128 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
129 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
130 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
131 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
132 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
133 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
134 0xc6, 0xda
135};
136static const u8 n4_lt168g[] = {
137 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
138 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
139 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
140 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
141 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
142 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
143 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
144 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
145 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
146};
147
148static const struct additional_sensor_data sensor_data[] = {
149[SENSOR_OM6802] = {
150 .n3 =
151 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
152 .n4 = n4_om6802,
153 .n4sz = sizeof n4_om6802,
154 .reg80 = 0x3c,
155 .reg8e = 0x33,
156 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
157 .data1 =
158 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
159 0xb3, 0xfc},
160 .data2 =
161 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
162 0xff},
163 .data3 =
164 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
165 0xff},
166 .data5 = /* this could be removed later */
167 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
168 .stream =
169 {0x0b, 0x04, 0x0a, 0x78},
170 },
171[SENSOR_OTHER] = {
172 .n3 =
173 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
174 .n4 = n4_other,
175 .n4sz = sizeof n4_other,
176 .reg80 = 0xac,
177 .reg8e = 0xb8,
178 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
179 .data1 =
180 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
181 0xe8, 0xfc},
182 .data2 =
183 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
184 0xd9},
185 .data3 =
186 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
187 0xd9},
188 .data5 =
189 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
190 .stream =
191 {0x0b, 0x04, 0x0a, 0x00},
192 },
193[SENSOR_TAS5130A] = {
194 .n3 =
195 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
196 .n4 = n4_tas5130a,
197 .n4sz = sizeof n4_tas5130a,
198 .reg80 = 0x3c,
199 .reg8e = 0xb4,
200 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
201 .data1 =
202 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
203 0xc8, 0xfc},
204 .data2 =
205 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
206 0xe0},
207 .data3 =
208 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
209 0xe0},
210 .data5 =
211 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
212 .stream =
213 {0x0b, 0x04, 0x0a, 0x40},
214 },
215[SENSOR_LT168G] = {
216 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
217 .n4 = n4_lt168g,
218 .n4sz = sizeof n4_lt168g,
219 .reg80 = 0x7c,
220 .reg8e = 0xb3,
221 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
222 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
223 0xb0, 0xf4},
224 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
225 0xff},
226 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
227 0xff},
228 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
229 .stream = {0x0b, 0x04, 0x0a, 0x28},
230 },
231};
232
233#define MAX_EFFECTS 7
234static const u8 effects_table[MAX_EFFECTS][6] = {
235 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
236 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
237 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
238 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
239 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
240 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
241 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
242};
243
244#define GAMMA_MAX (15)
245static const u8 gamma_table[GAMMA_MAX+1][17] = {
246/* gamma table from cam1690.ini */
247 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
248 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
249 0xff},
250 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
251 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
252 0xff},
253 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
254 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
255 0xff},
256 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
257 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
258 0xff},
259 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
260 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
261 0xff},
262 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
263 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
264 0xff},
265 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
266 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
267 0xff},
268 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
269 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
270 0xff},
271 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
272 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
273 0xff},
274 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
275 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
276 0xff},
277 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
278 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
279 0xff},
280 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
281 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
282 0xff},
283 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
284 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
285 0xff},
286 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
287 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
288 0xff},
289 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
290 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
291 0xff},
292 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
293 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
294 0xff}
295};
296
297static const u8 tas5130a_sensor_init[][8] = {
298 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
299 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
300 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
301};
302
303static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
304
305/* read 1 byte */
306static u8 reg_r(struct gspca_dev *gspca_dev,
307 u16 index)
308{
309 usb_control_msg(gspca_dev->dev,
310 usb_rcvctrlpipe(gspca_dev->dev, 0),
311 0, /* request */
312 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
313 0, /* value */
314 index,
315 gspca_dev->usb_buf, 1, 500);
316 return gspca_dev->usb_buf[0];
317}
318
319static void reg_w(struct gspca_dev *gspca_dev,
320 u16 index)
321{
322 usb_control_msg(gspca_dev->dev,
323 usb_sndctrlpipe(gspca_dev->dev, 0),
324 0,
325 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
326 0, index,
327 NULL, 0, 500);
328}
329
330static void reg_w_buf(struct gspca_dev *gspca_dev,
331 const u8 *buffer, u16 len)
332{
333 if (len <= USB_BUF_SZ) {
334 memcpy(gspca_dev->usb_buf, buffer, len);
335 usb_control_msg(gspca_dev->dev,
336 usb_sndctrlpipe(gspca_dev->dev, 0),
337 0,
338 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
339 0x01, 0,
340 gspca_dev->usb_buf, len, 500);
341 } else {
342 u8 *tmpbuf;
343
344 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
345 if (!tmpbuf) {
346 pr_err("Out of memory\n");
347 return;
348 }
349 usb_control_msg(gspca_dev->dev,
350 usb_sndctrlpipe(gspca_dev->dev, 0),
351 0,
352 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
353 0x01, 0,
354 tmpbuf, len, 500);
355 kfree(tmpbuf);
356 }
357}
358
359/* write values to consecutive registers */
360static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
361 u8 reg,
362 const u8 *buffer, u16 len)
363{
364 int i;
365 u8 *p, *tmpbuf;
366
367 if (len * 2 <= USB_BUF_SZ) {
368 p = tmpbuf = gspca_dev->usb_buf;
369 } else {
370 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
371 if (!tmpbuf) {
372 pr_err("Out of memory\n");
373 return;
374 }
375 }
376 i = len;
377 while (--i >= 0) {
378 *p++ = reg++;
379 *p++ = *buffer++;
380 }
381 usb_control_msg(gspca_dev->dev,
382 usb_sndctrlpipe(gspca_dev->dev, 0),
383 0,
384 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
385 0x01, 0,
386 tmpbuf, len * 2, 500);
387 if (len * 2 > USB_BUF_SZ)
388 kfree(tmpbuf);
389}
390
391static void om6802_sensor_init(struct gspca_dev *gspca_dev)
392{
393 int i;
394 const u8 *p;
395 u8 byte;
396 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
397 static const u8 sensor_init[] = {
398 0xdf, 0x6d,
399 0xdd, 0x18,
400 0x5a, 0xe0,
401 0x5c, 0x07,
402 0x5d, 0xb0,
403 0x5e, 0x1e,
404 0x60, 0x71,
405 0xef, 0x00,
406 0xe9, 0x00,
407 0xea, 0x00,
408 0x90, 0x24,
409 0x91, 0xb2,
410 0x82, 0x32,
411 0xfd, 0x41,
412 0x00 /* table end */
413 };
414
415 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
416 msleep(100);
417 i = 4;
418 while (--i > 0) {
419 byte = reg_r(gspca_dev, 0x0060);
420 if (!(byte & 0x01))
421 break;
422 msleep(100);
423 }
424 byte = reg_r(gspca_dev, 0x0063);
425 if (byte != 0x17) {
426 pr_err("Bad sensor reset %02x\n", byte);
427 /* continue? */
428 }
429
430 p = sensor_init;
431 while (*p != 0) {
432 val[1] = *p++;
433 val[3] = *p++;
434 if (*p == 0)
435 reg_w(gspca_dev, 0x3c80);
436 reg_w_buf(gspca_dev, val, sizeof val);
437 i = 4;
438 while (--i >= 0) {
439 msleep(15);
440 byte = reg_r(gspca_dev, 0x60);
441 if (!(byte & 0x01))
442 break;
443 }
444 }
445 msleep(15);
446 reg_w(gspca_dev, 0x3c80);
447}
448
449/* this function is called at probe time */
450static int sd_config(struct gspca_dev *gspca_dev,
451 const struct usb_device_id *id)
452{
453 struct cam *cam = &gspca_dev->cam;
454
455 cam->cam_mode = vga_mode_t16;
456 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
457
458 return 0;
459}
460
461static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
462{
463 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
464
465 if (brightness < 7) {
466 set6[1] = 0x26;
467 set6[3] = 0x70 - brightness * 0x10;
468 } else {
469 set6[3] = 0x00 + ((brightness - 7) * 0x10);
470 }
471
472 reg_w_buf(gspca_dev, set6, sizeof set6);
473}
474
475static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
476{
477 u16 reg_to_write;
478
479 if (contrast < 7)
480 reg_to_write = 0x8ea9 - contrast * 0x200;
481 else
482 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
483
484 reg_w(gspca_dev, reg_to_write);
485}
486
487static void setcolors(struct gspca_dev *gspca_dev, s32 val)
488{
489 u16 reg_to_write;
490
491 reg_to_write = 0x80bb + val * 0x100; /* was 0xc0 */
492 reg_w(gspca_dev, reg_to_write);
493}
494
495static void setgamma(struct gspca_dev *gspca_dev, s32 val)
496{
497 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
498 reg_w_ixbuf(gspca_dev, 0x90,
499 gamma_table[val], sizeof gamma_table[0]);
500}
501
502static void setawb_n_RGB(struct gspca_dev *gspca_dev)
503{
504 struct sd *sd = (struct sd *) gspca_dev;
505 u8 all_gain_reg[8] = {
506 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 };
507 s32 red_gain, blue_gain, green_gain;
508
509 green_gain = sd->gain->val;
510
511 red_gain = green_gain + sd->red_balance->val;
512 if (red_gain > 0x40)
513 red_gain = 0x40;
514 else if (red_gain < 0x10)
515 red_gain = 0x10;
516
517 blue_gain = green_gain + sd->blue_balance->val;
518 if (blue_gain > 0x40)
519 blue_gain = 0x40;
520 else if (blue_gain < 0x10)
521 blue_gain = 0x10;
522
523 all_gain_reg[1] = red_gain;
524 all_gain_reg[3] = blue_gain;
525 all_gain_reg[5] = green_gain;
526 all_gain_reg[7] = sensor_data[sd->sensor].reg80;
527 if (!sd->awb->val)
528 all_gain_reg[7] &= ~0x04; /* AWB off */
529
530 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
531}
532
533static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
534{
535 u16 reg_to_write;
536
537 reg_to_write = 0x0aa6 + 0x1000 * val;
538
539 reg_w(gspca_dev, reg_to_write);
540}
541
542static void setfreq(struct gspca_dev *gspca_dev, s32 val)
543{
544 struct sd *sd = (struct sd *) gspca_dev;
545 u8 reg66;
546 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
547
548 switch (sd->sensor) {
549 case SENSOR_LT168G:
550 if (val != 0)
551 freq[3] = 0xa8;
552 reg66 = 0x41;
553 break;
554 case SENSOR_OM6802:
555 reg66 = 0xca;
556 break;
557 default:
558 reg66 = 0x40;
559 break;
560 }
561 switch (val) {
562 case 0: /* no flicker */
563 freq[3] = 0xf0;
564 break;
565 case 2: /* 60Hz */
566 reg66 &= ~0x40;
567 break;
568 }
569 freq[1] = reg66;
570
571 reg_w_buf(gspca_dev, freq, sizeof freq);
572}
573
574/* this function is called at probe and resume time */
575static int sd_init(struct gspca_dev *gspca_dev)
576{
577 /* some of this registers are not really neded, because
578 * they are overriden by setbrigthness, setcontrast, etc,
579 * but wont hurt anyway, and can help someone with similar webcam
580 * to see the initial parameters.*/
581 struct sd *sd = (struct sd *) gspca_dev;
582 const struct additional_sensor_data *sensor;
583 int i;
584 u16 sensor_id;
585 u8 test_byte = 0;
586
587 static const u8 read_indexs[] =
588 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
589 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
590 static const u8 n1[] =
591 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
592 static const u8 n2[] =
593 {0x08, 0x00};
594
595 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
596 | reg_r(gspca_dev, 0x07);
597 switch (sensor_id & 0xff0f) {
598 case 0x0801:
599 PDEBUG(D_PROBE, "sensor tas5130a");
600 sd->sensor = SENSOR_TAS5130A;
601 break;
602 case 0x0802:
603 PDEBUG(D_PROBE, "sensor lt168g");
604 sd->sensor = SENSOR_LT168G;
605 break;
606 case 0x0803:
607 PDEBUG(D_PROBE, "sensor 'other'");
608 sd->sensor = SENSOR_OTHER;
609 break;
610 case 0x0807:
611 PDEBUG(D_PROBE, "sensor om6802");
612 sd->sensor = SENSOR_OM6802;
613 break;
614 default:
615 pr_err("unknown sensor %04x\n", sensor_id);
616 return -EINVAL;
617 }
618
619 if (sd->sensor == SENSOR_OM6802) {
620 reg_w_buf(gspca_dev, n1, sizeof n1);
621 i = 5;
622 while (--i >= 0) {
623 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
624 test_byte = reg_r(gspca_dev, 0x0063);
625 msleep(100);
626 if (test_byte == 0x17)
627 break; /* OK */
628 }
629 if (i < 0) {
630 pr_err("Bad sensor reset %02x\n", test_byte);
631 return -EIO;
632 }
633 reg_w_buf(gspca_dev, n2, sizeof n2);
634 }
635
636 i = 0;
637 while (read_indexs[i] != 0x00) {
638 test_byte = reg_r(gspca_dev, read_indexs[i]);
639 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
640 test_byte);
641 i++;
642 }
643
644 sensor = &sensor_data[sd->sensor];
645 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
646 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
647
648 if (sd->sensor == SENSOR_LT168G) {
649 test_byte = reg_r(gspca_dev, 0x80);
650 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
651 test_byte);
652 reg_w(gspca_dev, 0x6c80);
653 }
654
655 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
656 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
657 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
658
659 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
660 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
661 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
662 reg_w(gspca_dev, (0x20 << 8) + 0x87);
663 reg_w(gspca_dev, (0x20 << 8) + 0x88);
664 reg_w(gspca_dev, (0x20 << 8) + 0x89);
665
666 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
667 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
668 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
669
670 if (sd->sensor == SENSOR_LT168G) {
671 test_byte = reg_r(gspca_dev, 0x80);
672 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
673 test_byte);
674 reg_w(gspca_dev, 0x6c80);
675 }
676
677 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
678 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
679 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
680
681 return 0;
682}
683
684static void setmirror(struct gspca_dev *gspca_dev, s32 val)
685{
686 u8 hflipcmd[8] =
687 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
688
689 if (val)
690 hflipcmd[3] = 0x01;
691
692 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
693}
694
695static void seteffect(struct gspca_dev *gspca_dev, s32 val)
696{
697 int idx = 0;
698
699 switch (val) {
700 case V4L2_COLORFX_NONE:
701 break;
702 case V4L2_COLORFX_BW:
703 idx = 2;
704 break;
705 case V4L2_COLORFX_SEPIA:
706 idx = 3;
707 break;
708 case V4L2_COLORFX_SKETCH:
709 idx = 4;
710 break;
711 case V4L2_COLORFX_NEGATIVE:
712 idx = 6;
713 break;
714 default:
715 break;
716 }
717
718 reg_w_buf(gspca_dev, effects_table[idx],
719 sizeof effects_table[0]);
720
721 if (val == V4L2_COLORFX_SKETCH)
722 reg_w(gspca_dev, 0x4aa6);
723 else
724 reg_w(gspca_dev, 0xfaa6);
725}
726
727/* Is this really needed?
728 * i added some module parameters for test with some users */
729static void poll_sensor(struct gspca_dev *gspca_dev)
730{
731 static const u8 poll1[] =
732 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
733 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
734 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
735 0x60, 0x14};
736 static const u8 poll2[] =
737 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
738 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
739 static const u8 noise03[] = /* (some differences / ms-drv) */
740 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
741 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
742 0xc2, 0x80, 0xc3, 0x10};
743
744 PDEBUG(D_STREAM, "[Sensor requires polling]");
745 reg_w_buf(gspca_dev, poll1, sizeof poll1);
746 reg_w_buf(gspca_dev, poll2, sizeof poll2);
747 reg_w_buf(gspca_dev, noise03, sizeof noise03);
748}
749
750static int sd_start(struct gspca_dev *gspca_dev)
751{
752 struct sd *sd = (struct sd *) gspca_dev;
753 const struct additional_sensor_data *sensor;
754 int i, mode;
755 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
756 static const u8 t3[] =
757 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
758
759 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
760 switch (mode) {
761 case 0: /* 640x480 (0x00) */
762 break;
763 case 1: /* 352x288 */
764 t2[1] = 0x40;
765 break;
766 case 2: /* 320x240 */
767 t2[1] = 0x10;
768 break;
769 case 3: /* 176x144 */
770 t2[1] = 0x50;
771 break;
772 default:
773/* case 4: * 160x120 */
774 t2[1] = 0x20;
775 break;
776 }
777
778 switch (sd->sensor) {
779 case SENSOR_OM6802:
780 om6802_sensor_init(gspca_dev);
781 break;
782 case SENSOR_TAS5130A:
783 i = 0;
784 for (;;) {
785 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
786 sizeof tas5130a_sensor_init[0]);
787 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
788 break;
789 i++;
790 }
791 reg_w(gspca_dev, 0x3c80);
792 /* just in case and to keep sync with logs (for mine) */
793 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
794 sizeof tas5130a_sensor_init[0]);
795 reg_w(gspca_dev, 0x3c80);
796 break;
797 }
798 sensor = &sensor_data[sd->sensor];
799 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
800 reg_r(gspca_dev, 0x0012);
801 reg_w_buf(gspca_dev, t2, sizeof t2);
802 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
803 reg_w(gspca_dev, 0x0013);
804 msleep(15);
805 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
806 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
807
808 if (sd->sensor == SENSOR_OM6802)
809 poll_sensor(gspca_dev);
810
811 return 0;
812}
813
814static void sd_stopN(struct gspca_dev *gspca_dev)
815{
816 struct sd *sd = (struct sd *) gspca_dev;
817
818 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
819 sizeof sensor_data[sd->sensor].stream);
820 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
821 sizeof sensor_data[sd->sensor].stream);
822 if (sd->sensor == SENSOR_OM6802) {
823 msleep(20);
824 reg_w(gspca_dev, 0x0309);
825 }
826#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
827 /* If the last button state is pressed, release it now! */
828 if (sd->button_pressed) {
829 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
830 input_sync(gspca_dev->input_dev);
831 sd->button_pressed = 0;
832 }
833#endif
834}
835
836static void sd_pkt_scan(struct gspca_dev *gspca_dev,
837 u8 *data, /* isoc packet */
838 int len) /* iso packet length */
839{
840 struct sd *sd = (struct sd *) gspca_dev;
841 int pkt_type;
842
843 if (data[0] == 0x5a) {
844#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
845 if (len > 20) {
846 u8 state = (data[20] & 0x80) ? 1 : 0;
847 if (sd->button_pressed != state) {
848 input_report_key(gspca_dev->input_dev,
849 KEY_CAMERA, state);
850 input_sync(gspca_dev->input_dev);
851 sd->button_pressed = state;
852 }
853 }
854#endif
855 /* Control Packet, after this came the header again,
856 * but extra bytes came in the packet before this,
857 * sometimes an EOF arrives, sometimes not... */
858 return;
859 }
860 data += 2;
861 len -= 2;
862 if (data[0] == 0xff && data[1] == 0xd8)
863 pkt_type = FIRST_PACKET;
864 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
865 pkt_type = LAST_PACKET;
866 else
867 pkt_type = INTER_PACKET;
868 gspca_frame_add(gspca_dev, pkt_type, data, len);
869}
870
871static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
872{
873 struct gspca_dev *gspca_dev =
874 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
875 struct sd *sd = (struct sd *)gspca_dev;
876 s32 red_gain, blue_gain, green_gain;
877
878 gspca_dev->usb_err = 0;
879
880 switch (ctrl->id) {
881 case V4L2_CID_AUTO_WHITE_BALANCE:
882 red_gain = reg_r(gspca_dev, 0x0087);
883 if (red_gain > 0x40)
884 red_gain = 0x40;
885 else if (red_gain < 0x10)
886 red_gain = 0x10;
887
888 blue_gain = reg_r(gspca_dev, 0x0088);
889 if (blue_gain > 0x40)
890 blue_gain = 0x40;
891 else if (blue_gain < 0x10)
892 blue_gain = 0x10;
893
894 green_gain = reg_r(gspca_dev, 0x0089);
895 if (green_gain > 0x40)
896 green_gain = 0x40;
897 else if (green_gain < 0x10)
898 green_gain = 0x10;
899
900 sd->gain->val = green_gain;
901 sd->red_balance->val = red_gain - green_gain;
902 sd->blue_balance->val = blue_gain - green_gain;
903 break;
904 }
905 return 0;
906}
907
908static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
909{
910 struct gspca_dev *gspca_dev =
911 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
912
913 gspca_dev->usb_err = 0;
914
915 if (!gspca_dev->streaming)
916 return 0;
917
918 switch (ctrl->id) {
919 case V4L2_CID_BRIGHTNESS:
920 setbrightness(gspca_dev, ctrl->val);
921 break;
922 case V4L2_CID_CONTRAST:
923 setcontrast(gspca_dev, ctrl->val);
924 break;
925 case V4L2_CID_SATURATION:
926 setcolors(gspca_dev, ctrl->val);
927 break;
928 case V4L2_CID_GAMMA:
929 setgamma(gspca_dev, ctrl->val);
930 break;
931 case V4L2_CID_HFLIP:
932 setmirror(gspca_dev, ctrl->val);
933 break;
934 case V4L2_CID_SHARPNESS:
935 setsharpness(gspca_dev, ctrl->val);
936 break;
937 case V4L2_CID_POWER_LINE_FREQUENCY:
938 setfreq(gspca_dev, ctrl->val);
939 break;
940 case V4L2_CID_BACKLIGHT_COMPENSATION:
941 reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e);
942 break;
943 case V4L2_CID_AUTO_WHITE_BALANCE:
944 setawb_n_RGB(gspca_dev);
945 break;
946 case V4L2_CID_COLORFX:
947 seteffect(gspca_dev, ctrl->val);
948 break;
949 }
950 return gspca_dev->usb_err;
951}
952
953static const struct v4l2_ctrl_ops sd_ctrl_ops = {
954 .g_volatile_ctrl = sd_g_volatile_ctrl,
955 .s_ctrl = sd_s_ctrl,
956};
957
958static int sd_init_controls(struct gspca_dev *gspca_dev)
959{
960 struct sd *sd = (struct sd *)gspca_dev;
961 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
962
963 gspca_dev->vdev.ctrl_handler = hdl;
964 v4l2_ctrl_handler_init(hdl, 12);
965 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
966 V4L2_CID_BRIGHTNESS, 0, 14, 1, 8);
967 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
968 V4L2_CID_CONTRAST, 0, 0x0d, 1, 7);
969 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
970 V4L2_CID_SATURATION, 0, 0xf, 1, 5);
971 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
972 V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10);
973 /* Activate lowlight, some apps dont bring up the
974 backlight_compensation control) */
975 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
976 V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1);
977 if (sd->sensor == SENSOR_TAS5130A)
978 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
979 V4L2_CID_HFLIP, 0, 1, 1, 0);
980 sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
981 V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
982 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
983 V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20);
984 sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
985 V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0);
986 sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
987 V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0);
988 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
989 V4L2_CID_SHARPNESS, 0, 15, 1, 6);
990 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
991 V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH,
992 ~((1 << V4L2_COLORFX_NONE) |
993 (1 << V4L2_COLORFX_BW) |
994 (1 << V4L2_COLORFX_SEPIA) |
995 (1 << V4L2_COLORFX_SKETCH) |
996 (1 << V4L2_COLORFX_NEGATIVE)),
997 V4L2_COLORFX_NONE);
998 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
999 V4L2_CID_POWER_LINE_FREQUENCY,
1000 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
1001 V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
1002
1003 if (hdl->error) {
1004 pr_err("Could not initialize controls\n");
1005 return hdl->error;
1006 }
1007
1008 v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
1009
1010 return 0;
1011}
1012
1013/* sub-driver description */
1014static const struct sd_desc sd_desc = {
1015 .name = MODULE_NAME,
1016 .config = sd_config,
1017 .init = sd_init,
1018 .init_controls = sd_init_controls,
1019 .start = sd_start,
1020 .stopN = sd_stopN,
1021 .pkt_scan = sd_pkt_scan,
1022#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1023 .other_input = 1,
1024#endif
1025};
1026
1027/* -- module initialisation -- */
1028static const struct usb_device_id device_table[] = {
1029 {USB_DEVICE(0x17a1, 0x0128)},
1030 {}
1031};
1032MODULE_DEVICE_TABLE(usb, device_table);
1033
1034/* -- device connect -- */
1035static int sd_probe(struct usb_interface *intf,
1036 const struct usb_device_id *id)
1037{
1038 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1039 THIS_MODULE);
1040}
1041
1042static struct usb_driver sd_driver = {
1043 .name = MODULE_NAME,
1044 .id_table = device_table,
1045 .probe = sd_probe,
1046 .disconnect = gspca_disconnect,
1047#ifdef CONFIG_PM
1048 .suspend = gspca_suspend,
1049 .resume = gspca_resume,
1050 .reset_resume = gspca_resume,
1051#endif
1052};
1053
1054module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c
new file mode 100644
index 00000000000..a6055246cb9
--- /dev/null
+++ b/drivers/media/usb/gspca/topro.c
@@ -0,0 +1,4969 @@
1/*
2 * Topro TP6800/6810 webcam driver.
3 *
4 * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
5 * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se)
6 * Copyright (C) 2008 Thomas Champagne (lafeuil@gmail.com)
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, see <http://www.gnu.org/licenses/>.
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include "gspca.h"
25
26MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver");
27MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
28 "Anders Blomdell <anders.blomdell@control.lth.se>");
29MODULE_LICENSE("GPL");
30
31static int force_sensor = -1;
32
33/* JPEG header */
34static const u8 jpeg_head[] = {
35 0xff, 0xd8, /* jpeg */
36
37/* quantization table quality 50% */
38 0xff, 0xdb, 0x00, 0x84, /* DQT */
390,
40#define JPEG_QT0_OFFSET 7
41 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
42 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
43 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
44 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
45 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
46 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
47 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
48 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
491,
50#define JPEG_QT1_OFFSET 72
51 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
52 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
53 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
54 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
55 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
56 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
57 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
58 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
59
60 /* Define Huffman table (thanks to Thomas Kaiser) */
61 0xff, 0xc4, 0x01, 0x5e,
62 0x00, 0x00, 0x02, 0x03,
63 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
65 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
66 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
67 0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57,
68 0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21,
69 0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32,
70 0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52,
71 0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1,
72 0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2,
73 0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25,
74 0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44,
75 0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57,
76 0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73,
77 0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85,
78 0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97,
79 0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2,
80 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3,
81 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4,
82 0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5,
83 0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
84 0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
85 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
87 0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02,
88 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
89 0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01,
90 0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13,
91 0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14,
92 0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1,
93 0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43,
94 0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82,
95 0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28,
96 0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47,
97 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64,
98 0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76,
99 0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
100 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3,
101 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4,
102 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5,
103 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
104 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
105 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
106 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */
107 0x08, /* data precision */
108#define JPEG_HEIGHT_OFFSET 493
109 0x01, 0xe0, /* height */
110 0x02, 0x80, /* width */
111 0x03, /* component number */
112 0x01,
113 0x21, /* samples Y = jpeg 422 */
114 0x00, /* quant Y */
115 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */
116 0x03, 0x11, 0x01,
117
118 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */
119 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
120#define JPEG_HDR_SZ 521
121};
122
123struct sd {
124 struct gspca_dev gspca_dev; /* !! must be the first item */
125 struct v4l2_ctrl *jpegqual;
126 struct v4l2_ctrl *sharpness;
127 struct v4l2_ctrl *gamma;
128 struct v4l2_ctrl *blue;
129 struct v4l2_ctrl *red;
130
131 u8 framerate;
132 u8 quality; /* webcam current JPEG quality (0..16) */
133 s8 ag_cnt; /* autogain / start counter for tp6810 */
134#define AG_CNT_START 13 /* check gain every N frames */
135
136 u8 bridge;
137 u8 sensor;
138
139 u8 jpeg_hdr[JPEG_HDR_SZ];
140};
141
142enum bridges {
143 BRIDGE_TP6800,
144 BRIDGE_TP6810,
145};
146
147enum sensors {
148 SENSOR_CX0342,
149 SENSOR_SOI763A, /* ~= ov7630 / ov7648 */
150 NSENSORS
151};
152
153static const struct v4l2_pix_format vga_mode[] = {
154 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
155 .bytesperline = 320,
156 .sizeimage = 320 * 240 * 4 / 8 + 590,
157 .colorspace = V4L2_COLORSPACE_JPEG},
158 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
159 .bytesperline = 640,
160 .sizeimage = 640 * 480 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG}
162};
163
164/*
165 * JPEG quality
166 * index: webcam compression
167 * value: JPEG quality in %
168 */
169static const u8 jpeg_q[17] = {
170 88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94
171};
172
173#define BULK_OUT_SIZE 0x20
174#if BULK_OUT_SIZE > USB_BUF_SZ
175#error "USB buffer too small"
176#endif
177
178static const u8 rates[] = {30, 20, 15, 10, 7, 5};
179static const struct framerates framerates[] = {
180 {
181 .rates = rates,
182 .nrates = ARRAY_SIZE(rates)
183 },
184 {
185 .rates = rates,
186 .nrates = ARRAY_SIZE(rates)
187 }
188};
189static const u8 rates_6810[] = {30, 15, 10, 7, 5};
190static const struct framerates framerates_6810[] = {
191 {
192 .rates = rates_6810,
193 .nrates = ARRAY_SIZE(rates_6810)
194 },
195 {
196 .rates = rates_6810,
197 .nrates = ARRAY_SIZE(rates_6810)
198 }
199};
200
201/*
202 * webcam quality in %
203 * the last value is the ultra fine quality
204 */
205
206/* TP6800 register offsets */
207#define TP6800_R10_SIF_TYPE 0x10
208#define TP6800_R11_SIF_CONTROL 0x11
209#define TP6800_R12_SIF_ADDR_S 0x12
210#define TP6800_R13_SIF_TX_DATA 0x13
211#define TP6800_R14_SIF_RX_DATA 0x14
212#define TP6800_R15_GPIO_PU 0x15
213#define TP6800_R16_GPIO_PD 0x16
214#define TP6800_R17_GPIO_IO 0x17
215#define TP6800_R18_GPIO_DATA 0x18
216#define TP6800_R19_SIF_ADDR_S2 0x19
217#define TP6800_R1A_SIF_TX_DATA2 0x1a
218#define TP6800_R1B_SIF_RX_DATA2 0x1b
219#define TP6800_R21_ENDP_1_CTL 0x21
220#define TP6800_R2F_TIMING_CFG 0x2f
221#define TP6800_R30_SENSOR_CFG 0x30
222#define TP6800_R31_PIXEL_START 0x31
223#define TP6800_R32_PIXEL_END_L 0x32
224#define TP6800_R33_PIXEL_END_H 0x33
225#define TP6800_R34_LINE_START 0x34
226#define TP6800_R35_LINE_END_L 0x35
227#define TP6800_R36_LINE_END_H 0x36
228#define TP6800_R37_FRONT_DARK_ST 0x37
229#define TP6800_R38_FRONT_DARK_END 0x38
230#define TP6800_R39_REAR_DARK_ST_L 0x39
231#define TP6800_R3A_REAR_DARK_ST_H 0x3a
232#define TP6800_R3B_REAR_DARK_END_L 0x3b
233#define TP6800_R3C_REAR_DARK_END_H 0x3c
234#define TP6800_R3D_HORIZ_DARK_LINE_L 0x3d
235#define TP6800_R3E_HORIZ_DARK_LINE_H 0x3e
236#define TP6800_R3F_FRAME_RATE 0x3f
237#define TP6800_R50 0x50
238#define TP6800_R51 0x51
239#define TP6800_R52 0x52
240#define TP6800_R53 0x53
241#define TP6800_R54_DARK_CFG 0x54
242#define TP6800_R55_GAMMA_R 0x55
243#define TP6800_R56_GAMMA_G 0x56
244#define TP6800_R57_GAMMA_B 0x57
245#define TP6800_R5C_EDGE_THRLD 0x5c
246#define TP6800_R5D_DEMOSAIC_CFG 0x5d
247#define TP6800_R78_FORMAT 0x78
248#define TP6800_R79_QUALITY 0x79
249#define TP6800_R7A_BLK_THRLD 0x7a
250
251/* CX0342 register offsets */
252
253#define CX0342_SENSOR_ID 0x00
254#define CX0342_VERSION_NO 0x01
255#define CX0342_ORG_X_L 0x02
256#define CX0342_ORG_X_H 0x03
257#define CX0342_ORG_Y_L 0x04
258#define CX0342_ORG_Y_H 0x05
259#define CX0342_STOP_X_L 0x06
260#define CX0342_STOP_X_H 0x07
261#define CX0342_STOP_Y_L 0x08
262#define CX0342_STOP_Y_H 0x09
263#define CX0342_FRAME_WIDTH_L 0x0a
264#define CX0342_FRAME_WIDTH_H 0x0b
265#define CX0342_FRAME_HEIGH_L 0x0c
266#define CX0342_FRAME_HEIGH_H 0x0d
267#define CX0342_EXPO_LINE_L 0x10
268#define CX0342_EXPO_LINE_H 0x11
269#define CX0342_EXPO_CLK_L 0x12
270#define CX0342_EXPO_CLK_H 0x13
271#define CX0342_RAW_GRGAIN_L 0x14
272#define CX0342_RAW_GRGAIN_H 0x15
273#define CX0342_RAW_GBGAIN_L 0x16
274#define CX0342_RAW_GBGAIN_H 0x17
275#define CX0342_RAW_RGAIN_L 0x18
276#define CX0342_RAW_RGAIN_H 0x19
277#define CX0342_RAW_BGAIN_L 0x1a
278#define CX0342_RAW_BGAIN_H 0x1b
279#define CX0342_GLOBAL_GAIN 0x1c
280#define CX0342_SYS_CTRL_0 0x20
281#define CX0342_SYS_CTRL_1 0x21
282#define CX0342_SYS_CTRL_2 0x22
283#define CX0342_BYPASS_MODE 0x23
284#define CX0342_SYS_CTRL_3 0x24
285#define CX0342_TIMING_EN 0x25
286#define CX0342_OUTPUT_CTRL 0x26
287#define CX0342_AUTO_ADC_CALIB 0x27
288#define CX0342_SYS_CTRL_4 0x28
289#define CX0342_ADCGN 0x30
290#define CX0342_SLPCR 0x31
291#define CX0342_SLPFN_LO 0x32
292#define CX0342_ADC_CTL 0x33
293#define CX0342_LVRST_BLBIAS 0x34
294#define CX0342_VTHSEL 0x35
295#define CX0342_RAMP_RIV 0x36
296#define CX0342_LDOSEL 0x37
297#define CX0342_CLOCK_GEN 0x40
298#define CX0342_SOFT_RESET 0x41
299#define CX0342_PLL 0x42
300#define CX0342_DR_ENH_PULSE_OFFSET_L 0x43
301#define CX0342_DR_ENH_PULSE_OFFSET_H 0x44
302#define CX0342_DR_ENH_PULSE_POS_L 0x45
303#define CX0342_DR_ENH_PULSE_POS_H 0x46
304#define CX0342_DR_ENH_PULSE_WIDTH 0x47
305#define CX0342_AS_CURRENT_CNT_L 0x48
306#define CX0342_AS_CURRENT_CNT_H 0x49
307#define CX0342_AS_PREVIOUS_CNT_L 0x4a
308#define CX0342_AS_PREVIOUS_CNT_H 0x4b
309#define CX0342_SPV_VALUE_L 0x4c
310#define CX0342_SPV_VALUE_H 0x4d
311#define CX0342_GPXLTHD_L 0x50
312#define CX0342_GPXLTHD_H 0x51
313#define CX0342_RBPXLTHD_L 0x52
314#define CX0342_RBPXLTHD_H 0x53
315#define CX0342_PLANETHD_L 0x54
316#define CX0342_PLANETHD_H 0x55
317#define CX0342_ROWDARK_TH 0x56
318#define CX0342_ROWDARK_TOL 0x57
319#define CX0342_RB_GAP_L 0x58
320#define CX0342_RB_GAP_H 0x59
321#define CX0342_G_GAP_L 0x5a
322#define CX0342_G_GAP_H 0x5b
323#define CX0342_AUTO_ROW_DARK 0x60
324#define CX0342_MANUAL_DARK_VALUE 0x61
325#define CX0342_GB_DARK_OFFSET 0x62
326#define CX0342_GR_DARK_OFFSET 0x63
327#define CX0342_RED_DARK_OFFSET 0x64
328#define CX0342_BLUE_DARK_OFFSET 0x65
329#define CX0342_DATA_SCALING_MULTI 0x66
330#define CX0342_AUTOD_Q_FRAME 0x67
331#define CX0342_AUTOD_ALLOW_VARI 0x68
332#define CX0342_AUTO_DARK_VALUE_L 0x69
333#define CX0342_AUTO_DARK_VALUE_H 0x6a
334#define CX0342_IO_CTRL_0 0x70
335#define CX0342_IO_CTRL_1 0x71
336#define CX0342_IO_CTRL_2 0x72
337#define CX0342_IDLE_CTRL 0x73
338#define CX0342_TEST_MODE 0x74
339#define CX0342_FRAME_FIX_DATA_TEST 0x75
340#define CX0342_FRAME_CNT_TEST 0x76
341#define CX0342_RST_OVERFLOW_L 0x80
342#define CX0342_RST_OVERFLOW_H 0x81
343#define CX0342_RST_UNDERFLOW_L 0x82
344#define CX0342_RST_UNDERFLOW_H 0x83
345#define CX0342_DATA_OVERFLOW_L 0x84
346#define CX0342_DATA_OVERFLOW_H 0x85
347#define CX0342_DATA_UNDERFLOW_L 0x86
348#define CX0342_DATA_UNDERFLOW_H 0x87
349#define CX0342_CHANNEL_0_0_L_irst 0x90
350#define CX0342_CHANNEL_0_0_H_irst 0x91
351#define CX0342_CHANNEL_0_1_L_irst 0x92
352#define CX0342_CHANNEL_0_1_H_irst 0x93
353#define CX0342_CHANNEL_0_2_L_irst 0x94
354#define CX0342_CHANNEL_0_2_H_irst 0x95
355#define CX0342_CHANNEL_0_3_L_irst 0x96
356#define CX0342_CHANNEL_0_3_H_irst 0x97
357#define CX0342_CHANNEL_0_4_L_irst 0x98
358#define CX0342_CHANNEL_0_4_H_irst 0x99
359#define CX0342_CHANNEL_0_5_L_irst 0x9a
360#define CX0342_CHANNEL_0_5_H_irst 0x9b
361#define CX0342_CHANNEL_0_6_L_irst 0x9c
362#define CX0342_CHANNEL_0_6_H_irst 0x9d
363#define CX0342_CHANNEL_0_7_L_irst 0x9e
364#define CX0342_CHANNEL_0_7_H_irst 0x9f
365#define CX0342_CHANNEL_1_0_L_itx 0xa0
366#define CX0342_CHANNEL_1_0_H_itx 0xa1
367#define CX0342_CHANNEL_1_1_L_itx 0xa2
368#define CX0342_CHANNEL_1_1_H_itx 0xa3
369#define CX0342_CHANNEL_1_2_L_itx 0xa4
370#define CX0342_CHANNEL_1_2_H_itx 0xa5
371#define CX0342_CHANNEL_1_3_L_itx 0xa6
372#define CX0342_CHANNEL_1_3_H_itx 0xa7
373#define CX0342_CHANNEL_1_4_L_itx 0xa8
374#define CX0342_CHANNEL_1_4_H_itx 0xa9
375#define CX0342_CHANNEL_1_5_L_itx 0xaa
376#define CX0342_CHANNEL_1_5_H_itx 0xab
377#define CX0342_CHANNEL_1_6_L_itx 0xac
378#define CX0342_CHANNEL_1_6_H_itx 0xad
379#define CX0342_CHANNEL_1_7_L_itx 0xae
380#define CX0342_CHANNEL_1_7_H_itx 0xaf
381#define CX0342_CHANNEL_2_0_L_iwl 0xb0
382#define CX0342_CHANNEL_2_0_H_iwl 0xb1
383#define CX0342_CHANNEL_2_1_L_iwl 0xb2
384#define CX0342_CHANNEL_2_1_H_iwl 0xb3
385#define CX0342_CHANNEL_2_2_L_iwl 0xb4
386#define CX0342_CHANNEL_2_2_H_iwl 0xb5
387#define CX0342_CHANNEL_2_3_L_iwl 0xb6
388#define CX0342_CHANNEL_2_3_H_iwl 0xb7
389#define CX0342_CHANNEL_2_4_L_iwl 0xb8
390#define CX0342_CHANNEL_2_4_H_iwl 0xb9
391#define CX0342_CHANNEL_2_5_L_iwl 0xba
392#define CX0342_CHANNEL_2_5_H_iwl 0xbb
393#define CX0342_CHANNEL_2_6_L_iwl 0xbc
394#define CX0342_CHANNEL_2_6_H_iwl 0xbd
395#define CX0342_CHANNEL_2_7_L_iwl 0xbe
396#define CX0342_CHANNEL_2_7_H_iwl 0xbf
397#define CX0342_CHANNEL_3_0_L_ensp 0xc0
398#define CX0342_CHANNEL_3_0_H_ensp 0xc1
399#define CX0342_CHANNEL_3_1_L_ensp 0xc2
400#define CX0342_CHANNEL_3_1_H_ensp 0xc3
401#define CX0342_CHANNEL_3_2_L_ensp 0xc4
402#define CX0342_CHANNEL_3_2_H_ensp 0xc5
403#define CX0342_CHANNEL_3_3_L_ensp 0xc6
404#define CX0342_CHANNEL_3_3_H_ensp 0xc7
405#define CX0342_CHANNEL_3_4_L_ensp 0xc8
406#define CX0342_CHANNEL_3_4_H_ensp 0xc9
407#define CX0342_CHANNEL_3_5_L_ensp 0xca
408#define CX0342_CHANNEL_3_5_H_ensp 0xcb
409#define CX0342_CHANNEL_3_6_L_ensp 0xcc
410#define CX0342_CHANNEL_3_6_H_ensp 0xcd
411#define CX0342_CHANNEL_3_7_L_ensp 0xce
412#define CX0342_CHANNEL_3_7_H_ensp 0xcf
413#define CX0342_CHANNEL_4_0_L_sela 0xd0
414#define CX0342_CHANNEL_4_0_H_sela 0xd1
415#define CX0342_CHANNEL_4_1_L_sela 0xd2
416#define CX0342_CHANNEL_4_1_H_sela 0xd3
417#define CX0342_CHANNEL_5_0_L_intla 0xe0
418#define CX0342_CHANNEL_5_0_H_intla 0xe1
419#define CX0342_CHANNEL_5_1_L_intla 0xe2
420#define CX0342_CHANNEL_5_1_H_intla 0xe3
421#define CX0342_CHANNEL_5_2_L_intla 0xe4
422#define CX0342_CHANNEL_5_2_H_intla 0xe5
423#define CX0342_CHANNEL_5_3_L_intla 0xe6
424#define CX0342_CHANNEL_5_3_H_intla 0xe7
425#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0
426#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1
427#define CX0342_CHANNEL_7_1_L_cds_pos 0xf2
428#define CX0342_CHANNEL_7_1_H_cds_pos 0xf3
429#define CX0342_SENSOR_HEIGHT_L 0xfb
430#define CX0342_SENSOR_HEIGHT_H 0xfc
431#define CX0342_SENSOR_WIDTH_L 0xfd
432#define CX0342_SENSOR_WIDTH_H 0xfe
433#define CX0342_VSYNC_HSYNC_READ 0xff
434
435struct cmd {
436 u8 reg;
437 u8 val;
438};
439
440static const u8 DQT[17][130] = {
441 /* Define quantization table (thanks to Thomas Kaiser) */
442 { /* Quality 0 */
443 0x00,
444 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
445 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
446 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
447 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
448 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
449 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
450 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
451 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
452 0x01,
453 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06,
454 0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18,
455 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
456 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
457 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
458 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
459 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
460 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
461 },
462 { /* Quality 1 */
463 0x00,
464 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
465 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
466 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
467 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
468 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
469 0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09,
470 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
471 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
472 0x01,
473 0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d,
474 0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31,
475 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
476 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
477 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
478 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
479 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
480 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
481 },
482 { /* Quality 2 */
483 0x00,
484 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
485 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04,
486 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
487 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
488 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
489 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
490 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
491 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
492 0x01,
493 0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13,
494 0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a,
495 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
496 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
497 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
498 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
499 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
500 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
501 },
502 { /* Quality 3 */
503 0x00,
504 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
505 0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
506 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
507 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
508 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
509 0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13,
510 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
511 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
512 0x01,
513 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
514 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
515 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
516 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
517 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
518 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
519 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
520 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
521 },
522 { /* Quality 4 */
523 0x00,
524 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
525 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05,
526 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
527 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
528 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
529 0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17,
530 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
531 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
532 0x01,
533 0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20,
534 0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b,
535 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
536 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
537 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
538 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
539 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
540 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
541 },
542 { /* Quality 5 */
543 0x00,
544 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
545 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06,
546 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
547 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
548 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
549 0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
550 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
551 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
552 0x01,
553 0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27,
554 0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94,
555 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
556 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
557 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
558 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
559 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
560 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
561 },
562 { /* Quality 6 */
563 0x00,
564 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
565 0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07,
566 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
567 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
568 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
569 0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21,
570 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
571 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
572 0x01,
573 0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d,
574 0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad,
575 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
576 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
577 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
578 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
579 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
580 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
581 },
582 { /* Quality 7 */
583 0x00,
584 0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
585 0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08,
586 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
587 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
588 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
589 0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26,
590 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
591 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
592 0x01,
593 0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
594 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
595 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
596 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
597 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
598 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
599 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
600 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
601 },
602 { /* Quality 8 */
603 0x00,
604 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
605 0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a,
606 0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
607 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
608 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
609 0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
610 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
611 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
612 0x01,
613 0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41,
614 0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7,
615 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
616 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
617 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
618 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
619 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
620 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
621 },
622 { /* Quality 9 */
623 0x00,
624 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
625 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
626 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
627 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
628 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
629 0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39,
630 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
631 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
632 0x01,
633 0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
634 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
635 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
636 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
637 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
638 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
639 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
640 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
641 },
642 { /* Quality 10 */
643 0x00,
644 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
645 0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e,
646 0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
647 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
648 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
649 0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42,
650 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
651 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
652 0x01,
653 0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b,
654 0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff,
655 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
656 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
657 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
658 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
659 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
660 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
661 },
662 { /* Quality 11 */
663 0x00,
664 0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
665 0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10,
666 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
667 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
668 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
669 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
670 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
671 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
672 0x01,
673 0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68,
674 0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
675 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
676 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
677 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
678 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
679 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
680 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
681 },
682 { /* Quality 12 */
683 0x00,
684 0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
685 0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14,
686 0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
687 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
688 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
689 0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
690 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
691 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
692 0x01,
693 0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82,
694 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
695 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
696 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
697 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
698 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
699 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
700 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
701 },
702 { /* Quality 13 */
703 0x00,
704 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
705 0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18,
706 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
707 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
708 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
709 0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72,
710 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
711 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
712 0x01,
713 0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c,
714 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
715 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
716 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
717 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
718 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
719 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
720 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
721 },
722 { /* Quality 14 */
723 0x00,
724 0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
725 0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c,
726 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
727 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
728 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
729 0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85,
730 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
731 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
732 0x01,
733 0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6,
734 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
735 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
736 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
737 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
738 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
739 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
740 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
741 },
742 { /* Quality 15 */
743 0x00,
744 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
745 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20,
746 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
747 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
748 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
749 0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98,
750 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
751 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
752 0x01,
753 0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0,
754 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
755 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
756 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
757 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
758 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
759 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
760 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
761 },
762 { /* Quality 16-31 */
763 0x00,
764 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
765 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
766 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
767 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
768 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
769 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
770 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
771 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
772 0x01,
773 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
774 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
775 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
776 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
777 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
778 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
779 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
780 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
781 }
782};
783
784static const struct cmd tp6810_cx_init_common[] = {
785 {0x1c, 0x00},
786 {TP6800_R10_SIF_TYPE, 0x00},
787 {0x4e, 0x00},
788 {0x4f, 0x00},
789 {TP6800_R50, 0xff},
790 {TP6800_R51, 0x03},
791 {0x00, 0x07},
792 {TP6800_R79_QUALITY, 0x03},
793 {TP6800_R2F_TIMING_CFG, 0x37},
794 {TP6800_R30_SENSOR_CFG, 0x10},
795 {TP6800_R21_ENDP_1_CTL, 0x00},
796 {TP6800_R52, 0x40},
797 {TP6800_R53, 0x40},
798 {TP6800_R54_DARK_CFG, 0x40},
799 {TP6800_R30_SENSOR_CFG, 0x18},
800 {0x4b, 0x00},
801 {TP6800_R3F_FRAME_RATE, 0x83},
802 {TP6800_R79_QUALITY, 0x05},
803 {TP6800_R21_ENDP_1_CTL, 0x00},
804 {0x7c, 0x04},
805 {0x25, 0x14},
806 {0x26, 0x0f},
807 {0x7b, 0x10},
808};
809
810static const struct cmd tp6810_ov_init_common[] = {
811 {0x1c, 0x00},
812 {TP6800_R10_SIF_TYPE, 0x00},
813 {0x4e, 0x00},
814 {0x4f, 0x00},
815 {TP6800_R50, 0xff},
816 {TP6800_R51, 0x03},
817 {0x00, 0x07},
818 {TP6800_R52, 0x40},
819 {TP6800_R53, 0x40},
820 {TP6800_R54_DARK_CFG, 0x40},
821 {TP6800_R79_QUALITY, 0x03},
822 {TP6800_R2F_TIMING_CFG, 0x17},
823 {TP6800_R30_SENSOR_CFG, 0x18},
824 {TP6800_R21_ENDP_1_CTL, 0x00},
825 {TP6800_R3F_FRAME_RATE, 0x86},
826 {0x25, 0x18},
827 {0x26, 0x0f},
828 {0x7b, 0x90},
829};
830
831static const struct cmd tp6810_bridge_start[] = {
832 {0x59, 0x88},
833 {0x5a, 0x0f},
834 {0x5b, 0x4e},
835 {TP6800_R5C_EDGE_THRLD, 0x63},
836 {TP6800_R5D_DEMOSAIC_CFG, 0x00},
837 {0x03, 0x7f},
838 {0x04, 0x80},
839 {0x06, 0x00},
840 {0x00, 0x00},
841};
842
843static const struct cmd tp6810_late_start[] = {
844 {0x7d, 0x01},
845 {0xb0, 0x04},
846 {0xb1, 0x04},
847 {0xb2, 0x04},
848 {0xb3, 0x04},
849 {0xb4, 0x04},
850 {0xb5, 0x04},
851 {0xb6, 0x08},
852 {0xb7, 0x08},
853 {0xb8, 0x04},
854 {0xb9, 0x04},
855 {0xba, 0x04},
856 {0xbb, 0x04},
857 {0xbc, 0x04},
858 {0xbd, 0x08},
859 {0xbe, 0x08},
860 {0xbf, 0x08},
861 {0xc0, 0x04},
862 {0xc1, 0x04},
863 {0xc2, 0x08},
864 {0xc3, 0x08},
865 {0xc4, 0x08},
866 {0xc5, 0x08},
867 {0xc6, 0x08},
868 {0xc7, 0x13},
869 {0xc8, 0x04},
870 {0xc9, 0x08},
871 {0xca, 0x08},
872 {0xcb, 0x08},
873 {0xcc, 0x08},
874 {0xcd, 0x08},
875 {0xce, 0x13},
876 {0xcf, 0x13},
877 {0xd0, 0x08},
878 {0xd1, 0x08},
879 {0xd2, 0x08},
880 {0xd3, 0x08},
881 {0xd4, 0x08},
882 {0xd5, 0x13},
883 {0xd6, 0x13},
884 {0xd7, 0x13},
885 {0xd8, 0x08},
886 {0xd9, 0x08},
887 {0xda, 0x08},
888 {0xdb, 0x08},
889 {0xdc, 0x13},
890 {0xdd, 0x13},
891 {0xde, 0x13},
892 {0xdf, 0x13},
893 {0xe0, 0x08},
894 {0xe1, 0x08},
895 {0xe2, 0x08},
896 {0xe3, 0x13},
897 {0xe4, 0x13},
898 {0xe5, 0x13},
899 {0xe6, 0x13},
900 {0xe7, 0x13},
901 {0xe8, 0x08},
902 {0xe9, 0x08},
903 {0xea, 0x13},
904 {0xeb, 0x13},
905 {0xec, 0x13},
906 {0xed, 0x13},
907 {0xee, 0x13},
908 {0xef, 0x13},
909 {0x7d, 0x02},
910
911 /* later after isoc start */
912 {0x7d, 0x08},
913 {0x7d, 0x00},
914};
915
916static const struct cmd cx0342_timing_seq[] = {
917 {CX0342_CHANNEL_0_1_L_irst, 0x20},
918 {CX0342_CHANNEL_0_2_L_irst, 0x24},
919 {CX0342_CHANNEL_0_2_H_irst, 0x00},
920 {CX0342_CHANNEL_0_3_L_irst, 0x2f},
921 {CX0342_CHANNEL_0_3_H_irst, 0x00},
922 {CX0342_CHANNEL_1_0_L_itx, 0x02},
923 {CX0342_CHANNEL_1_0_H_itx, 0x00},
924 {CX0342_CHANNEL_1_1_L_itx, 0x20},
925 {CX0342_CHANNEL_1_1_H_itx, 0x00},
926 {CX0342_CHANNEL_1_2_L_itx, 0xe4},
927 {CX0342_CHANNEL_1_2_H_itx, 0x00},
928 {CX0342_CHANNEL_1_3_L_itx, 0xee},
929 {CX0342_CHANNEL_1_3_H_itx, 0x00},
930 {CX0342_CHANNEL_2_0_L_iwl, 0x30},
931 {CX0342_CHANNEL_2_0_H_iwl, 0x00},
932 {CX0342_CHANNEL_3_0_L_ensp, 0x34},
933 {CX0342_CHANNEL_3_1_L_ensp, 0xe2},
934 {CX0342_CHANNEL_3_1_H_ensp, 0x00},
935 {CX0342_CHANNEL_3_2_L_ensp, 0xf6},
936 {CX0342_CHANNEL_3_2_H_ensp, 0x00},
937 {CX0342_CHANNEL_3_3_L_ensp, 0xf4},
938 {CX0342_CHANNEL_3_3_H_ensp, 0x02},
939 {CX0342_CHANNEL_4_0_L_sela, 0x26},
940 {CX0342_CHANNEL_4_0_H_sela, 0x00},
941 {CX0342_CHANNEL_4_1_L_sela, 0xe2},
942 {CX0342_CHANNEL_4_1_H_sela, 0x00},
943 {CX0342_CHANNEL_5_0_L_intla, 0x26},
944 {CX0342_CHANNEL_5_1_L_intla, 0x29},
945 {CX0342_CHANNEL_5_2_L_intla, 0xf0},
946 {CX0342_CHANNEL_5_2_H_intla, 0x00},
947 {CX0342_CHANNEL_5_3_L_intla, 0xf3},
948 {CX0342_CHANNEL_5_3_H_intla, 0x00},
949 {CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24},
950 {CX0342_CHANNEL_7_1_L_cds_pos, 0x02},
951 {CX0342_TIMING_EN, 0x01},
952};
953
954/* define the JPEG header */
955static void jpeg_define(u8 *jpeg_hdr,
956 int height,
957 int width)
958{
959 memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
960 jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
961 jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
962 jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
963 jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
964}
965
966/* set the JPEG quality for sensor soi763a */
967static void jpeg_set_qual(u8 *jpeg_hdr,
968 int quality)
969{
970 int i, sc;
971
972 if (quality < 50)
973 sc = 5000 / quality;
974 else
975 sc = 200 - quality * 2;
976 for (i = 0; i < 64; i++) {
977 jpeg_hdr[JPEG_QT0_OFFSET + i] =
978 (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
979 jpeg_hdr[JPEG_QT1_OFFSET + i] =
980 (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
981 }
982}
983
984static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
985{
986 struct usb_device *dev = gspca_dev->dev;
987 int ret;
988
989 if (gspca_dev->usb_err < 0)
990 return;
991 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
992 0x0e,
993 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
994 value, index, NULL, 0, 500);
995 if (ret < 0) {
996 pr_err("reg_w err %d\n", ret);
997 gspca_dev->usb_err = ret;
998 }
999}
1000
1001/* the returned value is in gspca_dev->usb_buf */
1002static void reg_r(struct gspca_dev *gspca_dev, u8 index)
1003{
1004 struct usb_device *dev = gspca_dev->dev;
1005 int ret;
1006
1007 if (gspca_dev->usb_err < 0)
1008 return;
1009 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1010 0x0d,
1011 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1012 0, index, gspca_dev->usb_buf, 1, 500);
1013 if (ret < 0) {
1014 pr_err("reg_r err %d\n", ret);
1015 gspca_dev->usb_err = ret;
1016 }
1017}
1018
1019static void reg_w_buf(struct gspca_dev *gspca_dev,
1020 const struct cmd *p, int l)
1021{
1022 do {
1023 reg_w(gspca_dev, p->reg, p->val);
1024 p++;
1025 } while (--l > 0);
1026}
1027
1028static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
1029{
1030 struct sd *sd = (struct sd *) gspca_dev;
1031
1032 reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
1033 reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
1034 reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value);
1035 reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01);
1036 if (sd->bridge == BRIDGE_TP6800)
1037 return 0;
1038 msleep(5);
1039 reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
1040 if (gspca_dev->usb_buf[0] == 0)
1041 return 0;
1042 reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
1043 return -1; /* error */
1044}
1045
1046static void i2c_w_buf(struct gspca_dev *gspca_dev,
1047 const struct cmd *p, int l)
1048{
1049 do {
1050 i2c_w(gspca_dev, p->reg, p->val);
1051 p++;
1052 } while (--l > 0);
1053}
1054
1055static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len)
1056{
1057 struct sd *sd = (struct sd *) gspca_dev;
1058 int v;
1059
1060 reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
1061 reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02);
1062 msleep(5);
1063 reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA);
1064 v = gspca_dev->usb_buf[0];
1065 if (sd->bridge == BRIDGE_TP6800)
1066 return v;
1067 if (len > 1) {
1068 reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2);
1069 v |= (gspca_dev->usb_buf[0] << 8);
1070 }
1071 reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
1072 if (gspca_dev->usb_buf[0] == 0)
1073 return v;
1074 reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
1075 return -1;
1076}
1077
1078static void bulk_w(struct gspca_dev *gspca_dev,
1079 u8 tag,
1080 const u8 *data,
1081 int length)
1082{
1083 struct usb_device *dev = gspca_dev->dev;
1084 int count, actual_count, ret;
1085
1086 if (gspca_dev->usb_err < 0)
1087 return;
1088 for (;;) {
1089 count = length > BULK_OUT_SIZE - 1
1090 ? BULK_OUT_SIZE - 1 : length;
1091 gspca_dev->usb_buf[0] = tag;
1092 memcpy(&gspca_dev->usb_buf[1], data, count);
1093 ret = usb_bulk_msg(dev,
1094 usb_sndbulkpipe(dev, 3),
1095 gspca_dev->usb_buf, count + 1,
1096 &actual_count, 500);
1097 if (ret < 0) {
1098 pr_err("bulk write error %d tag=%02x\n",
1099 ret, tag);
1100 gspca_dev->usb_err = ret;
1101 return;
1102 }
1103 length -= count;
1104 if (length <= 0)
1105 break;
1106 data += count;
1107 }
1108}
1109
1110static int probe_6810(struct gspca_dev *gspca_dev)
1111{
1112 u8 gpio;
1113 int ret;
1114
1115 reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
1116 gpio = gspca_dev->usb_buf[0];
1117 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1118 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1119 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1120 reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04); /* i2c 16 bits */
1121 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21); /* ov??? */
1122 reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00);
1123 if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
1124 return SENSOR_SOI763A;
1125
1126 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1127 reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */
1128 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f); /* (unknown i2c) */
1129 if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
1130 return -2;
1131
1132 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1133 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1134 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1135 reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */
1136 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11); /* tas??? / hv??? */
1137 ret = i2c_r(gspca_dev, 0x00, 1);
1138 if (ret > 0)
1139 return -3;
1140
1141 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1142 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1143 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1144 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e); /* po??? */
1145 ret = i2c_r(gspca_dev, 0x00, 1);
1146 if (ret > 0)
1147 return -4;
1148
1149 ret = i2c_r(gspca_dev, 0x01, 1);
1150 if (ret > 0)
1151 return -5;
1152
1153 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1154 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1155 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1156 reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04); /* i2c 16 bits */
1157 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d); /* mi/mt??? */
1158 ret = i2c_r(gspca_dev, 0x00, 2);
1159 if (ret > 0)
1160 return -6;
1161
1162 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1163 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1164 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1165 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c); /* mi/mt??? */
1166 ret = i2c_r(gspca_dev, 0x36, 2);
1167 if (ret > 0)
1168 return -7;
1169
1170 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1171 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1172 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1173 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61); /* (unknown i2c) */
1174 reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10);
1175 if (i2c_w(gspca_dev, 0xff, 0x00) >= 0)
1176 return -8;
1177
1178 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1179 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
1180 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
1181 reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */
1182 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); /* cx0342 */
1183 ret = i2c_r(gspca_dev, 0x00, 1);
1184 if (ret > 0)
1185 return SENSOR_CX0342;
1186 return -9;
1187}
1188
1189static void cx0342_6810_init(struct gspca_dev *gspca_dev)
1190{
1191 static const struct cmd reg_init_1[] = {
1192 {TP6800_R2F_TIMING_CFG, 0x2f},
1193 {0x25, 0x02},
1194 {TP6800_R21_ENDP_1_CTL, 0x00},
1195 {TP6800_R3F_FRAME_RATE, 0x80},
1196 {TP6800_R2F_TIMING_CFG, 0x2f},
1197 {TP6800_R18_GPIO_DATA, 0xe1},
1198 {TP6800_R18_GPIO_DATA, 0xc1},
1199 {TP6800_R18_GPIO_DATA, 0xe1},
1200 {TP6800_R11_SIF_CONTROL, 0x00},
1201 };
1202 static const struct cmd reg_init_2[] = {
1203 {TP6800_R78_FORMAT, 0x48},
1204 {TP6800_R11_SIF_CONTROL, 0x00},
1205 };
1206 static const struct cmd sensor_init[] = {
1207 {CX0342_OUTPUT_CTRL, 0x07},
1208 {CX0342_BYPASS_MODE, 0x58},
1209 {CX0342_GPXLTHD_L, 0x28},
1210 {CX0342_RBPXLTHD_L, 0x28},
1211 {CX0342_PLANETHD_L, 0x50},
1212 {CX0342_PLANETHD_H, 0x03},
1213 {CX0342_RB_GAP_L, 0xff},
1214 {CX0342_RB_GAP_H, 0x07},
1215 {CX0342_G_GAP_L, 0xff},
1216 {CX0342_G_GAP_H, 0x07},
1217 {CX0342_RST_OVERFLOW_L, 0x5c},
1218 {CX0342_RST_OVERFLOW_H, 0x01},
1219 {CX0342_DATA_OVERFLOW_L, 0xfc},
1220 {CX0342_DATA_OVERFLOW_H, 0x03},
1221 {CX0342_DATA_UNDERFLOW_L, 0x00},
1222 {CX0342_DATA_UNDERFLOW_H, 0x00},
1223 {CX0342_SYS_CTRL_0, 0x40},
1224 {CX0342_GLOBAL_GAIN, 0x01},
1225 {CX0342_CLOCK_GEN, 0x00},
1226 {CX0342_SYS_CTRL_0, 0x02},
1227 {CX0342_IDLE_CTRL, 0x05},
1228 {CX0342_ADCGN, 0x00},
1229 {CX0342_ADC_CTL, 0x00},
1230 {CX0342_LVRST_BLBIAS, 0x01},
1231 {CX0342_VTHSEL, 0x0b},
1232 {CX0342_RAMP_RIV, 0x0b},
1233 {CX0342_LDOSEL, 0x07},
1234 {CX0342_SPV_VALUE_L, 0x40},
1235 {CX0342_SPV_VALUE_H, 0x02},
1236
1237 {CX0342_AUTO_ADC_CALIB, 0x81},
1238 {CX0342_TIMING_EN, 0x01},
1239 };
1240
1241 reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
1242 reg_w_buf(gspca_dev, tp6810_cx_init_common,
1243 ARRAY_SIZE(tp6810_cx_init_common));
1244 reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
1245
1246 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); /* cx0342 I2C addr */
1247 i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
1248 i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
1249}
1250
1251static void soi763a_6810_init(struct gspca_dev *gspca_dev)
1252{
1253 static const struct cmd reg_init_1[] = {
1254 {TP6800_R2F_TIMING_CFG, 0x2f},
1255 {TP6800_R18_GPIO_DATA, 0xe1},
1256 {0x25, 0x02},
1257 {TP6800_R21_ENDP_1_CTL, 0x00},
1258 {TP6800_R3F_FRAME_RATE, 0x80},
1259 {TP6800_R2F_TIMING_CFG, 0x2f},
1260 {TP6800_R18_GPIO_DATA, 0xc1},
1261 };
1262 static const struct cmd reg_init_2[] = {
1263 {TP6800_R78_FORMAT, 0x54},
1264 };
1265 static const struct cmd sensor_init[] = {
1266 {0x00, 0x00},
1267 {0x01, 0x80},
1268 {0x02, 0x80},
1269 {0x03, 0x90},
1270 {0x04, 0x20},
1271 {0x05, 0x20},
1272 {0x06, 0x80},
1273 {0x07, 0x00},
1274 {0x08, 0xff},
1275 {0x09, 0xff},
1276 {0x0a, 0x76}, /* 7630 = soi673a */
1277 {0x0b, 0x30},
1278 {0x0c, 0x20},
1279 {0x0d, 0x20},
1280 {0x0e, 0xff},
1281 {0x0f, 0xff},
1282 {0x10, 0x41},
1283 {0x15, 0x14},
1284 {0x11, 0x40},
1285 {0x12, 0x48},
1286 {0x13, 0x80},
1287 {0x14, 0x80},
1288 {0x16, 0x03},
1289 {0x28, 0xb0},
1290 {0x71, 0x20},
1291 {0x75, 0x8e},
1292 {0x17, 0x1b},
1293 {0x18, 0xbd},
1294 {0x19, 0x05},
1295 {0x1a, 0xf6},
1296 {0x1b, 0x04},
1297 {0x1c, 0x7f}, /* omnivision */
1298 {0x1d, 0xa2},
1299 {0x1e, 0x00},
1300 {0x1f, 0x00},
1301 {0x20, 0x45},
1302 {0x21, 0x80},
1303 {0x22, 0x80},
1304 {0x23, 0xee},
1305 {0x24, 0x50},
1306 {0x25, 0x7a},
1307 {0x26, 0xa0},
1308 {0x27, 0x9a},
1309 {0x29, 0x30},
1310 {0x2a, 0x80},
1311 {0x2b, 0x00},
1312 {0x2c, 0xac},
1313 {0x2d, 0x05},
1314 {0x2e, 0x80},
1315 {0x2f, 0x3c},
1316 {0x30, 0x22},
1317 {0x31, 0x00},
1318 {0x32, 0x86},
1319 {0x33, 0x08},
1320 {0x34, 0xff},
1321 {0x35, 0xff},
1322 {0x36, 0xff},
1323 {0x37, 0xff},
1324 {0x38, 0xff},
1325 {0x39, 0xff},
1326 {0x3a, 0xfe},
1327 {0x3b, 0xfe},
1328 {0x3c, 0xfe},
1329 {0x3d, 0xfe},
1330 {0x3e, 0xfe},
1331 {0x3f, 0x71},
1332 {0x40, 0xff},
1333 {0x41, 0xff},
1334 {0x42, 0xff},
1335 {0x43, 0xff},
1336 {0x44, 0xff},
1337 {0x45, 0xff},
1338 {0x46, 0xff},
1339 {0x47, 0xff},
1340 {0x48, 0xff},
1341 {0x49, 0xff},
1342 {0x4a, 0xfe},
1343 {0x4b, 0xff},
1344 {0x4c, 0x00},
1345 {0x4d, 0x00},
1346 {0x4e, 0xff},
1347 {0x4f, 0xff},
1348 {0x50, 0xff},
1349 {0x51, 0xff},
1350 {0x52, 0xff},
1351 {0x53, 0xff},
1352 {0x54, 0xff},
1353 {0x55, 0xff},
1354 {0x56, 0xff},
1355 {0x57, 0xff},
1356 {0x58, 0xff},
1357 {0x59, 0xff},
1358 {0x5a, 0xff},
1359 {0x5b, 0xfe},
1360 {0x5c, 0xff},
1361 {0x5d, 0x8f},
1362 {0x5e, 0xff},
1363 {0x5f, 0x8f},
1364 {0x60, 0xa2},
1365 {0x61, 0x4a},
1366 {0x62, 0xf3},
1367 {0x63, 0x75},
1368 {0x64, 0xf0},
1369 {0x65, 0x00},
1370 {0x66, 0x55},
1371 {0x67, 0x92},
1372 {0x68, 0xa0},
1373 {0x69, 0x4a},
1374 {0x6a, 0x22},
1375 {0x6b, 0x00},
1376 {0x6c, 0x33},
1377 {0x6d, 0x44},
1378 {0x6e, 0x22},
1379 {0x6f, 0x84},
1380 {0x70, 0x0b},
1381 {0x72, 0x10},
1382 {0x73, 0x50},
1383 {0x74, 0x21},
1384 {0x76, 0x00},
1385 {0x77, 0xa5},
1386 {0x78, 0x80},
1387 {0x79, 0x80},
1388 {0x7a, 0x80},
1389 {0x7b, 0xe2},
1390 {0x7c, 0x00},
1391 {0x7d, 0xf7},
1392 {0x7e, 0x00},
1393 {0x7f, 0x00},
1394 };
1395
1396 reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
1397 reg_w_buf(gspca_dev, tp6810_ov_init_common,
1398 ARRAY_SIZE(tp6810_ov_init_common));
1399 reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
1400
1401 i2c_w(gspca_dev, 0x12, 0x80); /* sensor reset */
1402 msleep(10);
1403 i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
1404}
1405
1406/* set the gain and exposure */
1407static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain,
1408 s32 blue, s32 red)
1409{
1410 struct sd *sd = (struct sd *) gspca_dev;
1411
1412 if (sd->sensor == SENSOR_CX0342) {
1413 expo = (expo << 2) - 1;
1414 i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
1415 i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
1416 if (sd->bridge == BRIDGE_TP6800)
1417 i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
1418 gain >> 8);
1419 i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, gain);
1420 if (sd->bridge == BRIDGE_TP6800)
1421 i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
1422 gain >> 8);
1423 i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, gain);
1424 if (sd->sensor == SENSOR_CX0342) {
1425 if (sd->bridge == BRIDGE_TP6800)
1426 i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
1427 blue >> 8);
1428 i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue);
1429 if (sd->bridge == BRIDGE_TP6800)
1430 i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
1431 red >> 8);
1432 i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, red);
1433 }
1434 i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
1435 sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
1436 return;
1437 }
1438
1439 /* soi763a */
1440 i2c_w(gspca_dev, 0x10, /* AEC_H (exposure time) */
1441 expo);
1442/* i2c_w(gspca_dev, 0x76, 0x02); * AEC_L ([1:0] */
1443 i2c_w(gspca_dev, 0x00, /* gain */
1444 gain);
1445}
1446
1447/* set the JPEG quantization tables */
1448static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
1449{
1450 struct sd *sd = (struct sd *) gspca_dev;
1451
1452 /* update the jpeg quantization tables */
1453 PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q);
1454 sd->quality = q;
1455 if (q > 16)
1456 q = 16;
1457 if (sd->sensor == SENSOR_SOI763A)
1458 jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]);
1459 else
1460 memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1],
1461 DQT[q], sizeof DQT[0]);
1462}
1463
1464/* set the JPEG compression quality factor */
1465static void setquality(struct gspca_dev *gspca_dev, s32 q)
1466{
1467 struct sd *sd = (struct sd *) gspca_dev;
1468
1469 if (q != 16)
1470 q = 15 - q;
1471
1472 reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00);
1473 reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04);
1474 reg_w(gspca_dev, TP6800_R79_QUALITY, q);
1475
1476 /* auto quality */
1477 if (q == 15 && sd->bridge == BRIDGE_TP6810) {
1478 msleep(4);
1479 reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19);
1480 }
1481}
1482
1483static const u8 color_null[18] = {
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1487};
1488static const u8 color_gain[NSENSORS][18] = {
1489[SENSOR_CX0342] =
1490 {0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00, /* Y R/G/B (LE values) */
1491 0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00, /* U R/G/B */
1492 0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */
1493[SENSOR_SOI763A] =
1494 {0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00, /* Y R/G/B (LE values) */
1495 0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00, /* U R/G/B */
1496 0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */
1497};
1498
1499static void setgamma(struct gspca_dev *gspca_dev, s32 gamma)
1500{
1501 struct sd *sd = (struct sd *) gspca_dev;
1502#define NGAMMA 6
1503 static const u8 gamma_tb[NGAMMA][3][1024] = {
1504 { /* gamma 0 - from tp6800 + soi763a */
1505 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1512 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
1513 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
1514 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
1515 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
1516 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
1517 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
1518 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
1519 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
1520 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
1521 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
1522 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
1523 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
1524 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
1525 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
1526 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
1527 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
1528 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
1529 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
1530 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
1531 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
1532 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
1533 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
1534 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
1535 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
1536 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
1537 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
1538 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
1539 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
1540 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
1541 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
1542 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
1543 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
1544 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
1545 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
1546 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
1547 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
1548 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
1549 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
1550 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
1551 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
1552 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
1553 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
1554 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
1555 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
1556 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
1557 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
1558 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
1559 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
1560 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
1561 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
1562 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
1563 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
1564 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
1565 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
1566 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
1567 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
1568 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
1569 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
1570 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
1571 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
1572 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
1573 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
1574 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
1575 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
1576 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
1577 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
1578 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
1579 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
1580 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
1581 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
1582 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
1583 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
1584 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
1585 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
1586 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
1587 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
1588 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
1589 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
1590 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
1591 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
1592 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
1593 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
1594 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
1595 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
1596 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
1597 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
1598 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
1599 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
1600 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
1601 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
1602 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
1603 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
1604 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
1605 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
1606 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1607 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1608 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1609 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1610 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1611 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1612 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1613 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1614 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1615 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1616 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1617 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1618 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1619 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1620 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1621 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1622 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1623 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1624 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1625 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1626 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1627 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1628 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1629 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1630 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1631 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1632 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
1633 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1634 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
1641 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
1642 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
1643 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
1644 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
1645 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
1646 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
1647 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
1648 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
1649 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
1650 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
1651 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
1652 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
1653 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
1654 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
1655 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
1656 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
1657 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
1658 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
1659 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
1660 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
1661 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
1662 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
1663 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
1664 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
1665 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
1666 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
1667 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
1668 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
1669 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
1670 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
1671 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
1672 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
1673 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
1674 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
1675 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
1676 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
1677 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
1678 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
1679 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
1680 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
1681 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
1682 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
1683 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
1684 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
1685 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
1686 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
1687 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
1688 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
1689 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
1690 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
1691 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
1692 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
1693 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
1694 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
1695 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
1696 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
1697 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
1698 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
1699 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
1700 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
1701 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
1702 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
1703 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
1704 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
1705 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
1706 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
1707 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
1708 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
1709 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
1710 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
1711 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
1712 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
1713 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
1714 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
1715 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
1716 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
1717 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
1718 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
1719 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
1720 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
1721 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
1722 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
1723 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
1724 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
1725 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
1726 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
1727 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
1728 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
1729 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
1730 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
1731 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
1732 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
1733 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
1734 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1735 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1736 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1737 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1738 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1739 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1740 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1741 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1742 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1743 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1744 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1745 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1746 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1747 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1748 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1749 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1750 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1751 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1752 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1753 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1754 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1755 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1756 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1757 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1758 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1759 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1760 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
1761 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1764 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
1765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1768 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
1769 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
1770 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
1771 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
1772 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
1773 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
1774 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
1775 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
1776 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
1777 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
1778 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
1779 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
1780 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
1781 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
1782 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
1783 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
1784 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
1785 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
1786 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
1787 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
1788 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
1789 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
1790 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
1791 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
1792 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
1793 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
1794 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
1795 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76,
1796 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
1797 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
1798 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
1799 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
1800 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
1801 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
1802 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
1803 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
1804 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
1805 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
1806 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
1807 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
1808 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
1809 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
1810 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
1811 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
1812 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
1813 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
1814 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
1815 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
1816 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
1817 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
1818 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
1819 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
1820 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
1821 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
1822 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
1823 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
1824 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
1825 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
1826 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
1827 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
1828 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
1829 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
1830 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
1831 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
1832 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
1833 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
1834 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
1835 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
1836 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
1837 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
1838 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
1839 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
1840 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
1841 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
1842 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
1843 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
1844 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
1845 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
1846 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
1847 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
1848 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
1849 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
1850 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
1851 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
1852 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
1853 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
1854 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
1855 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
1856 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
1857 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
1858 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
1859 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
1860 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
1861 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
1862 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1863 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1864 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1865 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1866 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1867 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1868 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1869 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1870 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1871 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1872 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1873 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1874 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1875 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1876 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1877 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1878 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1879 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1880 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1881 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1882 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1883 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1884 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1885 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1886 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1887 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1888 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
1889 },
1890 { /* gamma 1 - from tp6810 + soi763a */
1891 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1892 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1894 0x01, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a,
1895 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
1896 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
1897 0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27,
1898 0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
1899 0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35,
1900 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c,
1901 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
1902 0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49,
1903 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d,
1904 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
1905 0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59,
1906 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e,
1907 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61,
1908 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66,
1909 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69,
1910 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
1911 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
1912 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
1913 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
1914 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
1915 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80,
1916 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84,
1917 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
1918 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
1919 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
1920 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91,
1921 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93,
1922 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97,
1923 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
1924 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
1925 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e,
1926 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
1927 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
1928 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
1929 0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
1930 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab,
1931 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae,
1932 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
1933 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
1934 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
1935 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
1936 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
1937 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
1938 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
1939 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
1940 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
1941 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4,
1942 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
1943 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
1944 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
1945 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
1946 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
1947 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
1948 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
1949 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
1950 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
1951 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
1952 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
1953 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
1954 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
1955 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
1956 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
1957 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
1958 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
1959 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
1960 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8,
1961 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
1962 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
1963 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed,
1964 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
1965 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
1966 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
1967 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
1968 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
1969 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
1970 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
1971 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
1972 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
1973 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
1974 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe,
1975 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
1976 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1977 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1978 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1979 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1980 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1981 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1982 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1983 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1984 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1985 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1986 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1987 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1988 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1989 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1990 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1991 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1992 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1993 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1994 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1995 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1996 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1997 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1998 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1999 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2000 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2001 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2002 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2003 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2004 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2005 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2006 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2007 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2008 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2009 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2010 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2011 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2012 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2013 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2014 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2015 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2016 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2017 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2018 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
2019 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2020 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2022 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
2023 0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d,
2024 0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15,
2025 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
2026 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25,
2027 0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c,
2028 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31,
2029 0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38,
2030 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d,
2031 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43,
2032 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48,
2033 0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c,
2034 0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50,
2035 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
2036 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59,
2037 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
2038 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60,
2039 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65,
2040 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
2041 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a,
2042 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
2043 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
2044 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
2045 0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78,
2046 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a,
2047 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d,
2048 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
2049 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
2050 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
2051 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89,
2052 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
2053 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
2054 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
2055 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
2056 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
2057 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
2058 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
2059 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
2060 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
2061 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
2062 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
2063 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
2064 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
2065 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
2066 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
2067 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
2068 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
2069 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
2070 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
2071 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
2072 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
2073 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
2074 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
2075 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
2076 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
2077 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
2078 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
2079 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
2080 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
2081 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
2082 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9,
2083 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
2084 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
2085 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
2086 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf,
2087 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
2088 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
2089 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4,
2090 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
2091 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
2092 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
2093 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
2094 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
2095 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
2096 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
2097 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2,
2098 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
2099 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
2100 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
2101 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
2102 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
2103 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
2104 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
2105 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
2106 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
2107 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
2108 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
2109 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
2110 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
2111 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
2112 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
2113 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2114 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
2115 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
2116 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
2117 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
2118 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2119 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2125 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2126 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
2147 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2151 0x00, 0x00, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07,
2152 0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e,
2153 0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16,
2154 0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
2155 0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23,
2156 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29,
2157 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30,
2158 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35,
2159 0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a,
2160 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d,
2161 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43,
2162 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47,
2163 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b,
2164 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f,
2165 0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53,
2166 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56,
2167 0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a,
2168 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
2169 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60,
2170 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
2171 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
2172 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69,
2173 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
2174 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e,
2175 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
2176 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74,
2177 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77,
2178 0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79,
2179 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
2180 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
2181 0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
2182 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82,
2183 0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
2184 0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88,
2185 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a,
2186 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
2187 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
2188 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
2189 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
2190 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94,
2191 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96,
2192 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
2193 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
2194 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
2195 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
2196 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0,
2197 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
2198 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
2199 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
2200 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6,
2201 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
2202 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
2203 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac,
2204 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae,
2205 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
2206 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
2207 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2,
2208 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
2209 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6,
2210 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
2211 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
2212 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
2213 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
2214 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
2215 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
2216 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
2217 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
2218 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
2219 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
2220 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
2221 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
2222 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
2223 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2224 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
2225 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
2226 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
2227 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
2228 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
2229 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7,
2230 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
2231 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
2232 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
2233 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
2234 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
2235 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0,
2236 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
2237 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3,
2238 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4,
2239 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
2240 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
2241 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
2242 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
2243 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
2244 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
2245 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef,
2246 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1,
2247 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
2248 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
2249 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
2250 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
2251 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
2252 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2253 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc,
2254 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
2255 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
2256 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2257 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2258 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2259 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2260 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2261 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2262 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2263 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2264 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2265 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2266 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2267 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2268 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2269 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2270 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2271 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2272 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2273 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2274 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
2275 },
2276 { /* gamma 2 */
2277 {0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c,
2278 0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17,
2279 0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22,
2280 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
2281 0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34,
2282 0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b,
2283 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
2284 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49,
2285 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f,
2286 0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55,
2287 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a,
2288 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
2289 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
2290 0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
2291 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
2292 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70,
2293 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74,
2294 0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78,
2295 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
2296 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
2297 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
2298 0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
2299 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89,
2300 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d,
2301 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
2302 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
2303 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
2304 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
2305 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
2306 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
2307 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
2308 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
2309 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3,
2310 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5,
2311 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8,
2312 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
2313 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad,
2314 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
2315 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
2316 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
2317 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4,
2318 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
2319 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
2320 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba,
2321 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
2322 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
2323 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0,
2324 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
2325 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4,
2326 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
2327 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
2328 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
2329 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
2330 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
2331 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce,
2332 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
2333 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
2334 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4,
2335 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
2336 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
2337 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
2338 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
2339 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
2340 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
2341 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
2342 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
2343 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
2344 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
2345 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
2346 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
2347 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
2348 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
2349 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
2350 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
2351 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
2352 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
2353 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1,
2354 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
2355 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
2356 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
2357 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
2358 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9,
2359 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
2360 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2361 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2362 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2363 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2364 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2365 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2366 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2367 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2368 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2369 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2370 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2371 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2372 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2373 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2374 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2375 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2376 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2377 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2378 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2379 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2380 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2381 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2382 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2383 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2384 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2385 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2386 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2387 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2388 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2389 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2390 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2391 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2392 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2393 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2394 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2395 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2396 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2397 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2398 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2399 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2400 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2401 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2402 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2403 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2404 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
2405 {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05,
2406 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11,
2407 0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a,
2408 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23,
2409 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b,
2410 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33,
2411 0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39,
2412 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f,
2413 0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
2414 0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a,
2415 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d,
2416 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
2417 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58,
2418 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
2419 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
2420 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63,
2421 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67,
2422 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
2423 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d,
2424 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
2425 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73,
2426 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77,
2427 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
2428 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c,
2429 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f,
2430 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
2431 0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84,
2432 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
2433 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a,
2434 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
2435 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f,
2436 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91,
2437 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
2438 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
2439 0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
2440 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99,
2441 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b,
2442 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
2443 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e,
2444 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
2445 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
2446 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
2447 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
2448 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
2449 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
2450 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
2451 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae,
2452 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf,
2453 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
2454 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
2455 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
2456 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
2457 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
2458 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
2459 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
2460 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
2461 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
2462 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
2463 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
2464 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
2465 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
2466 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
2467 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
2468 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
2469 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
2470 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
2471 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
2472 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
2473 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
2474 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
2475 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
2476 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
2477 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
2478 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
2479 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
2480 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
2481 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
2482 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
2483 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
2484 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
2485 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
2486 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
2487 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
2488 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
2489 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
2490 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
2491 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
2492 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
2493 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
2494 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
2495 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef,
2496 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
2497 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
2498 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
2499 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
2500 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
2501 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
2502 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
2503 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
2504 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb,
2505 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2506 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2507 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2508 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2509 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2510 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2511 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2512 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2513 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2514 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2515 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2516 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2517 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2518 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2519 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2520 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2521 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2522 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2523 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2524 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2525 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2526 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2527 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2528 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2529 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2530 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2531 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2532 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
2533 {0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08,
2534 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14,
2535 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e,
2536 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27,
2537 0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f,
2538 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37,
2539 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c,
2540 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43,
2541 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49,
2542 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d,
2543 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
2544 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58,
2545 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
2546 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
2547 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65,
2548 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68,
2549 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
2550 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f,
2551 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73,
2552 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
2553 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a,
2554 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
2555 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80,
2556 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
2557 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
2558 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
2559 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b,
2560 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
2561 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90,
2562 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
2563 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
2564 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
2565 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
2566 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
2567 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
2568 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
2569 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
2570 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
2571 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
2572 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
2573 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
2574 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
2575 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
2576 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
2577 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
2578 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
2579 0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4,
2580 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
2581 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
2582 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
2583 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
2584 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
2585 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
2586 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
2587 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
2588 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
2589 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
2590 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
2591 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
2592 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
2593 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
2594 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
2595 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
2596 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
2597 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
2598 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
2599 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
2600 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
2601 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
2602 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
2603 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
2604 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
2605 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
2606 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
2607 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
2608 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
2609 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
2610 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6,
2611 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
2612 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
2613 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
2614 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
2615 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
2616 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
2617 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
2618 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1,
2619 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
2620 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
2621 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
2622 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7,
2623 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
2624 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
2625 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2626 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2627 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2628 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2629 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2630 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2631 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2632 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2633 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2634 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2635 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2636 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2637 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2638 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2639 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2640 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2641 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2642 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2643 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2644 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2645 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2646 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2647 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2648 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2649 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2650 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2651 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2652 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2653 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2654 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2655 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2656 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2657 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2658 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2659 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
2660 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
2661 },
2662 { /* gamma 3 - from tp6810 + cx0342 */
2663 {0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15,
2664 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23,
2665 0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f,
2666 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39,
2667 0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43,
2668 0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
2669 0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53,
2670 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a,
2671 0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
2672 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67,
2673 0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d,
2674 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73,
2675 0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78,
2676 0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c,
2677 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81,
2678 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
2679 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
2680 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
2681 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93,
2682 0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97,
2683 0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
2684 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
2685 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
2686 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
2687 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
2688 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
2689 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
2690 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
2691 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
2692 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
2693 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
2694 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
2695 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
2696 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
2697 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5,
2698 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
2699 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
2700 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
2701 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce,
2702 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
2703 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3,
2704 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
2705 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
2706 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda,
2707 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
2708 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
2709 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
2710 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
2711 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4,
2712 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
2713 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
2714 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
2715 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
2716 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
2717 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
2718 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
2719 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
2720 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
2721 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
2722 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
2723 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2724 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
2725 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
2726 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
2727 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
2728 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2729 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2730 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2731 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2732 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2733 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2734 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2735 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2736 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2737 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2738 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2739 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2740 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2741 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2742 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2743 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2744 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2745 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2746 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2747 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2748 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2749 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2750 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2751 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2752 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2753 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2754 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2755 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2756 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2757 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2758 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2759 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2760 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2761 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2762 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2763 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2764 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2765 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2766 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2767 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2768 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2769 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2770 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2771 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2772 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2773 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2774 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2775 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2776 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2777 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2778 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2779 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2780 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2781 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2782 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2783 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2784 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2785 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2786 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2787 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2788 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2789 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2790 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
2791 {0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10,
2792 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b,
2793 0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26,
2794 0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f,
2795 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38,
2796 0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f,
2797 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
2798 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b,
2799 0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52,
2800 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58,
2801 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c,
2802 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
2803 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66,
2804 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69,
2805 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
2806 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
2807 0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
2808 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
2809 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
2810 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80,
2811 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84,
2812 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86,
2813 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a,
2814 0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e,
2815 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90,
2816 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
2817 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96,
2818 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98,
2819 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a,
2820 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
2821 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
2822 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
2823 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
2824 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
2825 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
2826 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
2827 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad,
2828 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
2829 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
2830 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
2831 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4,
2832 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
2833 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
2834 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
2835 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
2836 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
2837 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
2838 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
2839 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
2840 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
2841 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
2842 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
2843 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
2844 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
2845 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
2846 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0,
2847 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
2848 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
2849 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
2850 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
2851 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
2852 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
2853 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
2854 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
2855 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
2856 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
2857 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2,
2858 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
2859 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
2860 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
2861 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
2862 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
2863 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
2864 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec,
2865 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
2866 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
2867 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
2868 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
2869 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
2870 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
2871 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
2872 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
2873 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
2874 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2875 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
2876 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
2877 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
2878 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
2879 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
2880 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2881 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2882 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2883 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2884 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2885 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2886 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2887 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2888 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2889 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2890 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2891 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2892 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2893 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2894 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2895 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2896 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2897 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2898 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2899 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2900 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2901 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2902 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2903 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2904 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2905 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2906 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2907 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2908 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2909 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2910 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2911 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2912 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2913 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2914 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2915 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2916 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2917 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2918 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
2919 {0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
2920 0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
2921 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d,
2922 0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38,
2923 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40,
2924 0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49,
2925 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50,
2926 0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58,
2927 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e,
2928 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63,
2929 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
2930 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e,
2931 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74,
2932 0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79,
2933 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d,
2934 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
2935 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
2936 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
2937 0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f,
2938 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
2939 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96,
2940 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
2941 0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
2942 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
2943 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
2944 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
2945 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9,
2946 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac,
2947 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf,
2948 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1,
2949 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
2950 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
2951 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
2952 0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc,
2953 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
2954 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
2955 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4,
2956 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
2957 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9,
2958 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb,
2959 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
2960 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf,
2961 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
2962 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3,
2963 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
2964 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
2965 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
2966 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
2967 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
2968 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
2969 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
2970 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
2971 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
2972 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
2973 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
2974 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb,
2975 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
2976 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
2977 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
2978 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
2979 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
2980 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
2981 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
2982 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
2983 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
2984 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
2985 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
2986 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
2987 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff,
2988 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2989 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2990 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2991 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2992 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2993 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2994 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2995 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2996 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2997 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2998 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2999 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3000 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3001 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3002 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3003 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3004 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3005 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3006 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3007 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3008 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3009 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3010 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3011 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3012 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3013 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3014 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3015 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3016 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3017 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3018 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3019 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3020 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3021 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3022 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3023 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3024 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3025 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3026 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3027 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3028 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3029 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3030 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3031 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3032 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3033 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3034 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3035 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3036 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3040 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3041 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3042 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3043 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3044 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3045 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3046 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
3047 },
3048 { /* gamma 4 - from tp6800 + soi763a */
3049 {0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f,
3050 0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d,
3051 0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a,
3052 0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45,
3053 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f,
3054 0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58,
3055 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60,
3056 0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67,
3057 0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e,
3058 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74,
3059 0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a,
3060 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
3061 0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86,
3062 0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
3063 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91,
3064 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96,
3065 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
3066 0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
3067 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2,
3068 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5,
3069 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab,
3070 0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
3071 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1,
3072 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4,
3073 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8,
3074 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc,
3075 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
3076 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
3077 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
3078 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9,
3079 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
3080 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce,
3081 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
3082 0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
3083 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
3084 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
3085 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
3086 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf,
3087 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
3088 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
3089 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
3090 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
3091 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
3092 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
3093 0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
3094 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
3095 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
3096 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
3097 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
3098 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
3099 0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
3100 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3101 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3102 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3103 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3104 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3105 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3106 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3107 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3108 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3109 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3110 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3111 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3112 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3113 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3114 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3115 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3116 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3117 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3118 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3119 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3120 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3121 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3122 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3123 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3124 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3125 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3126 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3127 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3128 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3129 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3130 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3131 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3132 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3133 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3134 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3135 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3136 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3137 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3138 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3139 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3140 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3141 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3142 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3143 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3144 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3145 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3146 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3147 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3148 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3149 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3150 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3151 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3152 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3153 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3154 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3155 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3156 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3157 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3158 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3159 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3160 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3161 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3162 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3163 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3164 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3165 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3166 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3167 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3168 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3169 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3170 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3171 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3172 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3173 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3174 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3175 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3176 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
3177 {0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15,
3178 0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
3179 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
3180 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35,
3181 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d,
3182 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
3183 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c,
3184 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54,
3185 0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a,
3186 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
3187 0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65,
3188 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
3189 0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
3190 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73,
3191 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77,
3192 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
3193 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
3194 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82,
3195 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86,
3196 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
3197 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
3198 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91,
3199 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94,
3200 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
3201 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a,
3202 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
3203 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
3204 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
3205 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4,
3206 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6,
3207 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
3208 0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad,
3209 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
3210 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
3211 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
3212 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
3213 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8,
3214 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
3215 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
3216 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
3217 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0,
3218 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
3219 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
3220 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
3221 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9,
3222 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
3223 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd,
3224 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
3225 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
3226 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3,
3227 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
3228 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
3229 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
3230 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
3231 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
3232 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
3233 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
3234 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
3235 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
3236 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
3237 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
3238 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
3239 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
3240 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
3241 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
3242 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
3243 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
3244 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
3245 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
3246 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
3247 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
3248 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
3249 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
3250 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
3251 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
3252 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3253 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3254 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3255 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3256 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3257 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3258 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3259 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3260 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3261 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3262 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3263 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3264 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3265 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3266 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3267 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3268 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3269 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3270 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3271 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3272 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3273 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3274 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3275 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3276 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3277 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3278 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3279 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3280 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3281 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3282 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3283 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3284 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3285 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3286 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3287 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3288 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3289 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3290 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3291 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3292 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3293 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3294 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3295 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3296 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3297 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3298 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3299 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3300 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3301 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3302 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3303 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3304 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
3305 {0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b,
3306 0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28,
3307 0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34,
3308 0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
3309 0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48,
3310 0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50,
3311 0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58,
3312 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f,
3313 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65,
3314 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c,
3315 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
3316 0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77,
3317 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
3318 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
3319 0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85,
3320 0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a,
3321 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f,
3322 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92,
3323 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97,
3324 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
3325 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
3326 0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
3327 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
3328 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
3329 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
3330 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
3331 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
3332 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
3333 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
3334 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba,
3335 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
3336 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
3337 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3,
3338 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
3339 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
3340 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
3341 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc,
3342 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
3343 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0,
3344 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
3345 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
3346 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8,
3347 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
3348 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
3349 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
3350 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
3351 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
3352 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
3353 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
3354 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8,
3355 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
3356 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
3357 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
3358 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
3359 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
3360 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
3361 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
3362 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8,
3363 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
3364 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
3365 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3366 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3367 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3368 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3369 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3370 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3371 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3372 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3373 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3374 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3375 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3376 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3377 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3378 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3379 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3380 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3381 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3382 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3383 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3384 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3385 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3386 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3387 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3388 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3389 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3390 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3391 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3392 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3393 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3394 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3395 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3396 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3397 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3398 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3399 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3400 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3401 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3402 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3403 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3404 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3405 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3406 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3407 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3408 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3409 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3410 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3411 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3412 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3413 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3414 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3415 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3416 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3417 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3418 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3419 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3420 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3421 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3422 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3423 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3424 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3425 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3426 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3427 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3428 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3429 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3430 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3431 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
3432 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
3433 },
3434 { /* gamma 5 */
3435 {0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21,
3436 0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c,
3437 0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36,
3438 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
3439 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
3440 0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
3441 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55,
3442 0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b,
3443 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
3444 0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66,
3445 0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b,
3446 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
3447 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75,
3448 0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79,
3449 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e,
3450 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82,
3451 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
3452 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
3453 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d,
3454 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90,
3455 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94,
3456 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97,
3457 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
3458 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
3459 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0,
3460 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
3461 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6,
3462 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8,
3463 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
3464 0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
3465 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
3466 0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3,
3467 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5,
3468 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
3469 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
3470 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc,
3471 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
3472 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
3473 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
3474 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
3475 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
3476 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9,
3477 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
3478 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
3479 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
3480 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
3481 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
3482 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5,
3483 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
3484 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
3485 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
3486 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd,
3487 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde,
3488 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
3489 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
3490 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
3491 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
3492 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7,
3493 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
3494 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
3495 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
3496 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
3497 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
3498 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
3499 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
3500 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
3501 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
3502 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
3503 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
3504 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
3505 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
3506 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
3507 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3508 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3509 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3510 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3511 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3512 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3513 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3514 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3515 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3516 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3517 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3518 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3519 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3520 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3521 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3522 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3523 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3524 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3525 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3526 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3527 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3528 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3529 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3530 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3531 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3532 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3533 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3534 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3535 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3536 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3537 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3538 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3539 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3540 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3541 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3542 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3543 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3544 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3545 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3546 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3547 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3548 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3549 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3550 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3551 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3552 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3553 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3554 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3555 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3556 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3557 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3558 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3559 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3560 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3561 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3562 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
3563 {0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19,
3564 0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
3565 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
3566 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32,
3567 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39,
3568 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f,
3569 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45,
3570 0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b,
3571 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50,
3572 0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54,
3573 0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59,
3574 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d,
3575 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
3576 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65,
3577 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68,
3578 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c,
3579 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f,
3580 0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72,
3581 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75,
3582 0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78,
3583 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
3584 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e,
3585 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81,
3586 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
3587 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
3588 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88,
3589 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b,
3590 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d,
3591 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
3592 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
3593 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
3594 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96,
3595 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98,
3596 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
3597 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
3598 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e,
3599 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0,
3600 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
3601 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
3602 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
3603 0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7,
3604 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9,
3605 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
3606 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
3607 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
3608 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
3609 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
3610 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
3611 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5,
3612 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
3613 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
3614 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
3615 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
3616 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
3617 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
3618 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
3619 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
3620 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
3621 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
3622 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
3623 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
3624 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9,
3625 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca,
3626 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
3627 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd,
3628 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce,
3629 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
3630 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
3631 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
3632 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
3633 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
3634 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
3635 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
3636 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
3637 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
3638 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
3639 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde,
3640 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf,
3641 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
3642 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
3643 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
3644 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
3645 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
3646 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
3647 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
3648 0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea,
3649 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
3650 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
3651 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
3652 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
3653 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
3654 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
3655 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
3656 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
3657 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
3658 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
3659 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
3660 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
3661 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
3662 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
3663 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3664 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3665 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3666 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3667 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3668 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3669 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3670 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3671 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3672 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3673 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3674 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3675 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3676 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3677 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3678 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3679 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3680 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3681 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3682 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3683 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3684 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3685 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3686 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3687 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3688 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3689 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3690 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
3691 {0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e,
3692 0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
3693 0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
3694 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
3695 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
3696 0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48,
3697 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e,
3698 0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54,
3699 0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59,
3700 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f,
3701 0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63,
3702 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
3703 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c,
3704 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
3705 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74,
3706 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78,
3707 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c,
3708 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f,
3709 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83,
3710 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
3711 0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89,
3712 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
3713 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
3714 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
3715 0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95,
3716 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
3717 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
3718 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d,
3719 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
3720 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2,
3721 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
3722 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6,
3723 0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9,
3724 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
3725 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad,
3726 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
3727 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
3728 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
3729 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5,
3730 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
3731 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
3732 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb,
3733 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
3734 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
3735 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
3736 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
3737 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
3738 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
3739 0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8,
3740 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
3741 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
3742 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
3743 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
3744 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
3745 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
3746 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
3747 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6,
3748 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
3749 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
3750 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
3751 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
3752 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
3753 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
3754 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
3755 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
3756 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
3757 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6,
3758 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
3759 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
3760 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea,
3761 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
3762 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
3763 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
3764 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
3765 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
3766 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
3767 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
3768 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
3769 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
3770 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
3771 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
3772 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
3773 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
3774 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3775 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3776 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3777 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3778 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3779 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3780 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3781 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3782 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3783 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3784 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3785 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3786 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3787 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3788 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3789 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3790 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3791 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3792 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3793 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3794 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3795 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3796 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3797 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3798 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3799 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3800 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3801 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3802 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3803 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3804 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3805 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3806 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3807 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3808 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3809 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3810 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3811 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3812 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3813 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3814 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3815 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3816 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3817 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3818 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
3819 },
3820 };
3821
3822 reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
3823 if (sd->bridge == BRIDGE_TP6810)
3824 reg_w(gspca_dev, 0x02, 0x28);
3825/* msleep(50); */
3826 bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
3827 bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
3828 bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
3829 if (sd->bridge == BRIDGE_TP6810) {
3830 int i;
3831
3832 reg_w(gspca_dev, 0x02, 0x2b);
3833 reg_w(gspca_dev, 0x02, 0x28);
3834 for (i = 0; i < 6; i++)
3835 reg_w(gspca_dev, TP6800_R55_GAMMA_R,
3836 gamma_tb[gamma][0][i]);
3837 reg_w(gspca_dev, 0x02, 0x2b);
3838 reg_w(gspca_dev, 0x02, 0x28);
3839 for (i = 0; i < 6; i++)
3840 reg_w(gspca_dev, TP6800_R56_GAMMA_G,
3841 gamma_tb[gamma][1][i]);
3842 reg_w(gspca_dev, 0x02, 0x2b);
3843 reg_w(gspca_dev, 0x02, 0x28);
3844 for (i = 0; i < 6; i++)
3845 reg_w(gspca_dev, TP6800_R57_GAMMA_B,
3846 gamma_tb[gamma][2][i]);
3847 reg_w(gspca_dev, 0x02, 0x28);
3848 }
3849 reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
3850/* msleep(50); */
3851}
3852
3853static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
3854{
3855 struct sd *sd = (struct sd *) gspca_dev;
3856
3857 if (sd->bridge == BRIDGE_TP6800) {
3858 val |= 0x08; /* grid compensation enable */
3859 if (gspca_dev->width == 640)
3860 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
3861 else
3862 val |= 0x04; /* scaling down enable */
3863 reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
3864 } else {
3865 val = (val << 5) | 0x08;
3866 reg_w(gspca_dev, 0x59, val);
3867 }
3868}
3869
3870static void setautogain(struct gspca_dev *gspca_dev, s32 val)
3871{
3872 struct sd *sd = (struct sd *) gspca_dev;
3873
3874 sd->ag_cnt = val ? AG_CNT_START : -1;
3875}
3876
3877/* set the resolution for sensor cx0342 */
3878static void set_resolution(struct gspca_dev *gspca_dev)
3879{
3880 struct sd *sd = (struct sd *) gspca_dev;
3881
3882 reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
3883 if (gspca_dev->width == 320) {
3884 reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
3885 msleep(100);
3886 i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
3887 msleep(100);
3888 reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
3889 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
3890 reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d);
3891 i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37);
3892 i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01);
3893 } else {
3894 reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05);
3895 msleep(100);
3896 i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
3897 msleep(100);
3898 reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
3899 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
3900 reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09);
3901 i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf);
3902 i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
3903 }
3904 i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
3905 bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
3906 ARRAY_SIZE(color_gain[0]));
3907 setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
3908 if (sd->sensor == SENSOR_SOI763A)
3909 setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
3910}
3911
3912/* convert the frame rate to a tp68x0 value */
3913static int get_fr_idx(struct gspca_dev *gspca_dev)
3914{
3915 struct sd *sd = (struct sd *) gspca_dev;
3916 int i;
3917
3918 if (sd->bridge == BRIDGE_TP6800) {
3919 for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) {
3920 if (sd->framerate >= rates[i])
3921 break;
3922 }
3923 i = 6 - i; /* 1 = 5fps .. 6 = 30fps */
3924
3925 /* 640x480 * 30 fps does not work */
3926 if (i == 6 /* if 30 fps */
3927 && gspca_dev->width == 640)
3928 i = 0x05; /* 15 fps */
3929 } else {
3930 for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
3931 if (sd->framerate >= rates_6810[i])
3932 break;
3933 }
3934 i = 7 - i; /* 3 = 5fps .. 7 = 30fps */
3935
3936 /* 640x480 * 30 fps does not work */
3937 if (i == 7 /* if 30 fps */
3938 && gspca_dev->width == 640)
3939 i = 6; /* 15 fps */
3940 i |= 0x80; /* clock * 1 */
3941 }
3942 return i;
3943}
3944
3945static void setframerate(struct gspca_dev *gspca_dev, s32 val)
3946{
3947 struct sd *sd = (struct sd *) gspca_dev;
3948 u8 fr_idx;
3949
3950 fr_idx = get_fr_idx(gspca_dev);
3951
3952 if (sd->bridge == BRIDGE_TP6810) {
3953 reg_r(gspca_dev, 0x7b);
3954 reg_w(gspca_dev, 0x7b,
3955 sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
3956 if (val >= 128)
3957 fr_idx = 0xf0; /* lower frame rate */
3958 }
3959
3960 reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx);
3961
3962 if (sd->sensor == SENSOR_CX0342)
3963 i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
3964}
3965
3966static void setrgain(struct gspca_dev *gspca_dev, s32 rgain)
3967{
3968 i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
3969 i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
3970 i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
3971}
3972
3973static int sd_setgain(struct gspca_dev *gspca_dev)
3974{
3975 struct sd *sd = (struct sd *) gspca_dev;
3976 s32 val = gspca_dev->gain->val;
3977
3978 if (sd->sensor == SENSOR_CX0342) {
3979 s32 old = gspca_dev->gain->cur.val ?
3980 gspca_dev->gain->cur.val : 1;
3981
3982 sd->blue->val = sd->blue->val * val / old;
3983 if (sd->blue->val > 4095)
3984 sd->blue->val = 4095;
3985 sd->red->val = sd->red->val * val / old;
3986 if (sd->red->val > 4095)
3987 sd->red->val = 4095;
3988 }
3989 if (gspca_dev->streaming) {
3990 if (sd->sensor == SENSOR_CX0342)
3991 setexposure(gspca_dev, gspca_dev->exposure->val,
3992 gspca_dev->gain->val,
3993 sd->blue->val, sd->red->val);
3994 else
3995 setexposure(gspca_dev, gspca_dev->exposure->val,
3996 gspca_dev->gain->val, 0, 0);
3997 }
3998 return gspca_dev->usb_err;
3999}
4000
4001static void setbgain(struct gspca_dev *gspca_dev, s32 bgain)
4002{
4003 i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
4004 i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
4005 i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
4006}
4007
4008/* this function is called at probe time */
4009static int sd_config(struct gspca_dev *gspca_dev,
4010 const struct usb_device_id *id)
4011{
4012 struct sd *sd = (struct sd *) gspca_dev;
4013
4014 sd->bridge = id->driver_info;
4015
4016 gspca_dev->cam.cam_mode = vga_mode;
4017 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
4018 gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ?
4019 framerates : framerates_6810;
4020
4021 sd->framerate = 30; /* default: 30 fps */
4022 return 0;
4023}
4024
4025/* this function is called at probe and resume time */
4026static int sd_init(struct gspca_dev *gspca_dev)
4027{
4028 struct sd *sd = (struct sd *) gspca_dev;
4029 static const struct cmd tp6800_preinit[] = {
4030 {TP6800_R10_SIF_TYPE, 0x01}, /* sif */
4031 {TP6800_R11_SIF_CONTROL, 0x01},
4032 {TP6800_R15_GPIO_PU, 0x9f},
4033 {TP6800_R16_GPIO_PD, 0x9f},
4034 {TP6800_R17_GPIO_IO, 0x80},
4035 {TP6800_R18_GPIO_DATA, 0x40}, /* LED off */
4036 };
4037 static const struct cmd tp6810_preinit[] = {
4038 {TP6800_R2F_TIMING_CFG, 0x2f},
4039 {TP6800_R15_GPIO_PU, 0x6f},
4040 {TP6800_R16_GPIO_PD, 0x40},
4041 {TP6800_R17_GPIO_IO, 0x9f},
4042 {TP6800_R18_GPIO_DATA, 0xc1}, /* LED off */
4043 };
4044
4045 if (sd->bridge == BRIDGE_TP6800)
4046 reg_w_buf(gspca_dev, tp6800_preinit,
4047 ARRAY_SIZE(tp6800_preinit));
4048 else
4049 reg_w_buf(gspca_dev, tp6810_preinit,
4050 ARRAY_SIZE(tp6810_preinit));
4051 msleep(15);
4052 reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
4053 PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]);
4054/* values:
4055 * 0x80: snapshot button
4056 * 0x40: LED
4057 * 0x20: (bridge / sensor) reset for tp6810 ?
4058 * 0x07: sensor type ?
4059 */
4060
4061 /* guess the sensor type */
4062 if (force_sensor >= 0) {
4063 sd->sensor = force_sensor;
4064 } else {
4065 if (sd->bridge == BRIDGE_TP6800) {
4066/*fixme: not sure this is working*/
4067 switch (gspca_dev->usb_buf[0] & 0x07) {
4068 case 0:
4069 sd->sensor = SENSOR_SOI763A;
4070 break;
4071 case 1:
4072 sd->sensor = SENSOR_CX0342;
4073 break;
4074 }
4075 } else {
4076 int sensor;
4077
4078 sensor = probe_6810(gspca_dev);
4079 if (sensor < 0) {
4080 pr_warn("Unknown sensor %d - forced to soi763a\n",
4081 -sensor);
4082 sensor = SENSOR_SOI763A;
4083 }
4084 sd->sensor = sensor;
4085 }
4086 }
4087 if (sd->sensor == SENSOR_SOI763A) {
4088 pr_info("Sensor soi763a\n");
4089 if (sd->bridge == BRIDGE_TP6810) {
4090 soi763a_6810_init(gspca_dev);
4091 }
4092 } else {
4093 pr_info("Sensor cx0342\n");
4094 if (sd->bridge == BRIDGE_TP6810) {
4095 cx0342_6810_init(gspca_dev);
4096 }
4097 }
4098
4099 set_dqt(gspca_dev, 0);
4100 return 0;
4101}
4102
4103/* This function is called before choosing the alt setting */
4104static int sd_isoc_init(struct gspca_dev *gspca_dev)
4105{
4106 struct sd *sd = (struct sd *) gspca_dev;
4107 static const struct cmd cx_sensor_init[] = {
4108 {CX0342_AUTO_ADC_CALIB, 0x81},
4109 {CX0342_EXPO_LINE_L, 0x37},
4110 {CX0342_EXPO_LINE_H, 0x01},
4111 {CX0342_RAW_GRGAIN_L, 0x00},
4112 {CX0342_RAW_GBGAIN_L, 0x00},
4113 {CX0342_RAW_RGAIN_L, 0x00},
4114 {CX0342_RAW_BGAIN_L, 0x00},
4115 {CX0342_SYS_CTRL_0, 0x81},
4116 };
4117 static const struct cmd cx_bridge_init[] = {
4118 {0x4d, 0x00},
4119 {0x4c, 0xff},
4120 {0x4e, 0xff},
4121 {0x4f, 0x00},
4122 };
4123 static const struct cmd ov_sensor_init[] = {
4124 {0x10, 0x75}, /* exposure */
4125 {0x76, 0x03},
4126 {0x00, 0x00}, /* gain */
4127 };
4128 static const struct cmd ov_bridge_init[] = {
4129 {0x7b, 0x90},
4130 {TP6800_R3F_FRAME_RATE, 0x87},
4131 };
4132
4133 if (sd->bridge == BRIDGE_TP6800)
4134 return 0;
4135 if (sd->sensor == SENSOR_CX0342) {
4136 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);
4137 reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
4138 i2c_w_buf(gspca_dev, cx_sensor_init,
4139 ARRAY_SIZE(cx_sensor_init));
4140 reg_w_buf(gspca_dev, cx_bridge_init,
4141 ARRAY_SIZE(cx_bridge_init));
4142 bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
4143 reg_w(gspca_dev, 0x59, 0x40);
4144 } else {
4145 reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);
4146 i2c_w_buf(gspca_dev, ov_sensor_init,
4147 ARRAY_SIZE(ov_sensor_init));
4148 reg_r(gspca_dev, 0x7b);
4149 reg_w_buf(gspca_dev, ov_bridge_init,
4150 ARRAY_SIZE(ov_bridge_init));
4151 }
4152 reg_w(gspca_dev, TP6800_R78_FORMAT,
4153 gspca_dev->curr_mode ? 0x00 : 0x01);
4154 return gspca_dev->usb_err;
4155}
4156
4157static void set_led(struct gspca_dev *gspca_dev, int on)
4158{
4159 u8 data;
4160
4161 reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
4162 data = gspca_dev->usb_buf[0];
4163 if (on)
4164 data &= ~0x40;
4165 else
4166 data |= 0x40;
4167 reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data);
4168}
4169
4170static void cx0342_6800_start(struct gspca_dev *gspca_dev)
4171{
4172 struct sd *sd = (struct sd *) gspca_dev;
4173 static const struct cmd reg_init[] = {
4174 /* fixme: is this useful? */
4175 {TP6800_R17_GPIO_IO, 0x9f},
4176 {TP6800_R16_GPIO_PD, 0x40},
4177 {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */
4178 {TP6800_R50, 0x00},
4179 {TP6800_R51, 0x00},
4180 {TP6800_R52, 0xff},
4181 {TP6800_R53, 0x03},
4182 {TP6800_R54_DARK_CFG, 0x07},
4183 {TP6800_R5C_EDGE_THRLD, 0x40},
4184 {TP6800_R7A_BLK_THRLD, 0x40},
4185 {TP6800_R2F_TIMING_CFG, 0x17},
4186 {TP6800_R30_SENSOR_CFG, 0x18}, /* G1B..RG0 */
4187 {TP6800_R37_FRONT_DARK_ST, 0x00},
4188 {TP6800_R38_FRONT_DARK_END, 0x00},
4189 {TP6800_R39_REAR_DARK_ST_L, 0x00},
4190 {TP6800_R3A_REAR_DARK_ST_H, 0x00},
4191 {TP6800_R3B_REAR_DARK_END_L, 0x00},
4192 {TP6800_R3C_REAR_DARK_END_H, 0x00},
4193 {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
4194 {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
4195 {TP6800_R21_ENDP_1_CTL, 0x03},
4196
4197 {TP6800_R31_PIXEL_START, 0x0b},
4198 {TP6800_R32_PIXEL_END_L, 0x8a},
4199 {TP6800_R33_PIXEL_END_H, 0x02},
4200 {TP6800_R34_LINE_START, 0x0e},
4201 {TP6800_R35_LINE_END_L, 0xf4},
4202 {TP6800_R36_LINE_END_H, 0x01},
4203 {TP6800_R78_FORMAT, 0x00},
4204 {TP6800_R12_SIF_ADDR_S, 0x20}, /* cx0342 i2c addr */
4205 };
4206 static const struct cmd sensor_init[] = {
4207 {CX0342_OUTPUT_CTRL, 0x07},
4208 {CX0342_BYPASS_MODE, 0x58},
4209 {CX0342_GPXLTHD_L, 0x16},
4210 {CX0342_RBPXLTHD_L, 0x16},
4211 {CX0342_PLANETHD_L, 0xc0},
4212 {CX0342_PLANETHD_H, 0x03},
4213 {CX0342_RB_GAP_L, 0xff},
4214 {CX0342_RB_GAP_H, 0x07},
4215 {CX0342_G_GAP_L, 0xff},
4216 {CX0342_G_GAP_H, 0x07},
4217 {CX0342_RST_OVERFLOW_L, 0x5c},
4218 {CX0342_RST_OVERFLOW_H, 0x01},
4219 {CX0342_DATA_OVERFLOW_L, 0xfc},
4220 {CX0342_DATA_OVERFLOW_H, 0x03},
4221 {CX0342_DATA_UNDERFLOW_L, 0x00},
4222 {CX0342_DATA_UNDERFLOW_H, 0x00},
4223 {CX0342_SYS_CTRL_0, 0x40},
4224 {CX0342_GLOBAL_GAIN, 0x01},
4225 {CX0342_CLOCK_GEN, 0x00},
4226 {CX0342_SYS_CTRL_0, 0x02},
4227 {CX0342_IDLE_CTRL, 0x05},
4228 {CX0342_ADCGN, 0x00},
4229 {CX0342_ADC_CTL, 0x00},
4230 {CX0342_LVRST_BLBIAS, 0x01},
4231 {CX0342_VTHSEL, 0x0b},
4232 {CX0342_RAMP_RIV, 0x0b},
4233 {CX0342_LDOSEL, 0x07},
4234 {CX0342_SPV_VALUE_L, 0x40},
4235 {CX0342_SPV_VALUE_H, 0x02},
4236 };
4237
4238 reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
4239 i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
4240 i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
4241 reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
4242 reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
4243 i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
4244 i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
4245 if (sd->sensor == SENSOR_CX0342)
4246 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4247 v4l2_ctrl_g_ctrl(gspca_dev->gain),
4248 v4l2_ctrl_g_ctrl(sd->blue),
4249 v4l2_ctrl_g_ctrl(sd->red));
4250 else
4251 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4252 v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
4253 set_led(gspca_dev, 1);
4254 set_resolution(gspca_dev);
4255}
4256
4257static void cx0342_6810_start(struct gspca_dev *gspca_dev)
4258{
4259 struct sd *sd = (struct sd *) gspca_dev;
4260 static const struct cmd sensor_init_2[] = {
4261 {CX0342_EXPO_LINE_L, 0x6f},
4262 {CX0342_EXPO_LINE_H, 0x02},
4263 {CX0342_RAW_GRGAIN_L, 0x00},
4264 {CX0342_RAW_GBGAIN_L, 0x00},
4265 {CX0342_RAW_RGAIN_L, 0x00},
4266 {CX0342_RAW_BGAIN_L, 0x00},
4267 {CX0342_SYS_CTRL_0, 0x81},
4268 };
4269 static const struct cmd bridge_init_2[] = {
4270 {0x4d, 0x00},
4271 {0x4c, 0xff},
4272 {0x4e, 0xff},
4273 {0x4f, 0x00},
4274 {TP6800_R7A_BLK_THRLD, 0x00},
4275 {TP6800_R79_QUALITY, 0x04},
4276 {TP6800_R79_QUALITY, 0x01},
4277 };
4278 static const struct cmd bridge_init_3[] = {
4279 {TP6800_R31_PIXEL_START, 0x08},
4280 {TP6800_R32_PIXEL_END_L, 0x87},
4281 {TP6800_R33_PIXEL_END_H, 0x02},
4282 {TP6800_R34_LINE_START, 0x0e},
4283 {TP6800_R35_LINE_END_L, 0xf4},
4284 {TP6800_R36_LINE_END_H, 0x01},
4285 };
4286 static const struct cmd sensor_init_3[] = {
4287 {CX0342_AUTO_ADC_CALIB, 0x81},
4288 {CX0342_EXPO_LINE_L, 0x6f},
4289 {CX0342_EXPO_LINE_H, 0x02},
4290 {CX0342_RAW_GRGAIN_L, 0x00},
4291 {CX0342_RAW_GBGAIN_L, 0x00},
4292 {CX0342_RAW_RGAIN_L, 0x00},
4293 {CX0342_RAW_BGAIN_L, 0x00},
4294 {CX0342_SYS_CTRL_0, 0x81},
4295 };
4296 static const struct cmd bridge_init_5[] = {
4297 {0x4d, 0x00},
4298 {0x4c, 0xff},
4299 {0x4e, 0xff},
4300 {0x4f, 0x00},
4301 };
4302 static const struct cmd sensor_init_4[] = {
4303 {CX0342_EXPO_LINE_L, 0xd3},
4304 {CX0342_EXPO_LINE_H, 0x01},
4305/*fixme: gains, but 00..80 only*/
4306 {CX0342_RAW_GRGAIN_L, 0x40},
4307 {CX0342_RAW_GBGAIN_L, 0x40},
4308 {CX0342_RAW_RGAIN_L, 0x40},
4309 {CX0342_RAW_BGAIN_L, 0x40},
4310 {CX0342_SYS_CTRL_0, 0x81},
4311 };
4312 static const struct cmd sensor_init_5[] = {
4313 {CX0342_IDLE_CTRL, 0x05},
4314 {CX0342_ADCGN, 0x00},
4315 {CX0342_ADC_CTL, 0x00},
4316 {CX0342_LVRST_BLBIAS, 0x01},
4317 {CX0342_VTHSEL, 0x0b},
4318 {CX0342_RAMP_RIV, 0x0b},
4319 {CX0342_LDOSEL, 0x07},
4320 {CX0342_SPV_VALUE_L, 0x40},
4321 {CX0342_SPV_VALUE_H, 0x02},
4322 {CX0342_AUTO_ADC_CALIB, 0x81},
4323 };
4324
4325 reg_w(gspca_dev, 0x22, gspca_dev->alt);
4326 i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2));
4327 reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
4328 reg_w_buf(gspca_dev, tp6810_cx_init_common,
4329 ARRAY_SIZE(tp6810_cx_init_common));
4330 reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
4331 if (gspca_dev->curr_mode) {
4332 reg_w(gspca_dev, 0x4a, 0x7f);
4333 reg_w(gspca_dev, 0x07, 0x05);
4334 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
4335 } else {
4336 reg_w(gspca_dev, 0x4a, 0xff);
4337 reg_w(gspca_dev, 0x07, 0x85);
4338 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
4339 }
4340 setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
4341 reg_w_buf(gspca_dev, tp6810_bridge_start,
4342 ARRAY_SIZE(tp6810_bridge_start));
4343 setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
4344 bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
4345 ARRAY_SIZE(color_gain[0]));
4346 reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
4347 i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3));
4348 reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
4349 i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4));
4350 reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
4351 i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
4352
4353 set_led(gspca_dev, 1);
4354/* setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); */
4355}
4356
4357static void soi763a_6800_start(struct gspca_dev *gspca_dev)
4358{
4359 struct sd *sd = (struct sd *) gspca_dev;
4360 static const struct cmd reg_init[] = {
4361 {TP6800_R79_QUALITY, 0x04},
4362 {TP6800_R79_QUALITY, 0x01},
4363 {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */
4364
4365 {TP6800_R50, 0x00},
4366 {TP6800_R51, 0x00},
4367 {TP6800_R52, 0xff},
4368 {TP6800_R53, 0x03},
4369 {TP6800_R54_DARK_CFG, 0x07},
4370 {TP6800_R5C_EDGE_THRLD, 0x40},
4371
4372 {TP6800_R79_QUALITY, 0x03},
4373 {TP6800_R7A_BLK_THRLD, 0x40},
4374
4375 {TP6800_R2F_TIMING_CFG, 0x46},
4376 {TP6800_R30_SENSOR_CFG, 0x10}, /* BG1..G0R */
4377 {TP6800_R37_FRONT_DARK_ST, 0x00},
4378 {TP6800_R38_FRONT_DARK_END, 0x00},
4379 {TP6800_R39_REAR_DARK_ST_L, 0x00},
4380 {TP6800_R3A_REAR_DARK_ST_H, 0x00},
4381 {TP6800_R3B_REAR_DARK_END_L, 0x00},
4382 {TP6800_R3C_REAR_DARK_END_H, 0x00},
4383 {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
4384 {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
4385 {TP6800_R21_ENDP_1_CTL, 0x03},
4386
4387 {TP6800_R3F_FRAME_RATE, 0x04}, /* 15 fps */
4388 {TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */
4389
4390 {TP6800_R31_PIXEL_START, 0x1b},
4391 {TP6800_R32_PIXEL_END_L, 0x9a},
4392 {TP6800_R33_PIXEL_END_H, 0x02},
4393 {TP6800_R34_LINE_START, 0x0f},
4394 {TP6800_R35_LINE_END_L, 0xf4},
4395 {TP6800_R36_LINE_END_H, 0x01},
4396 {TP6800_R78_FORMAT, 0x01}, /* qvga */
4397 {TP6800_R12_SIF_ADDR_S, 0x21}, /* soi763a i2c addr */
4398 {TP6800_R1A_SIF_TX_DATA2, 0x00},
4399 };
4400 static const struct cmd sensor_init[] = {
4401 {0x12, 0x48}, /* mirror - RGB */
4402 {0x13, 0xa0}, /* clock - no AGC nor AEC */
4403 {0x03, 0xa4}, /* saturation */
4404 {0x04, 0x30}, /* hue */
4405 {0x05, 0x88}, /* contrast */
4406 {0x06, 0x60}, /* brightness */
4407 {0x10, 0x41}, /* AEC */
4408 {0x11, 0x40}, /* clock rate */
4409 {0x13, 0xa0},
4410 {0x14, 0x00}, /* 640x480 */
4411 {0x15, 0x14},
4412 {0x1f, 0x41},
4413 {0x20, 0x80},
4414 {0x23, 0xee},
4415 {0x24, 0x50},
4416 {0x25, 0x7a},
4417 {0x26, 0x00},
4418 {0x27, 0xe2},
4419 {0x28, 0xb0},
4420 {0x2a, 0x00},
4421 {0x2b, 0x00},
4422 {0x2d, 0x81},
4423 {0x2f, 0x9d},
4424 {0x60, 0x80},
4425 {0x61, 0x00},
4426 {0x62, 0x88},
4427 {0x63, 0x11},
4428 {0x64, 0x89},
4429 {0x65, 0x00},
4430 {0x67, 0x94},
4431 {0x68, 0x7a},
4432 {0x69, 0x0f},
4433 {0x6c, 0x80},
4434 {0x6d, 0x80},
4435 {0x6e, 0x80},
4436 {0x6f, 0xff},
4437 {0x71, 0x20},
4438 {0x74, 0x20},
4439 {0x75, 0x86},
4440 {0x77, 0xb5},
4441 {0x17, 0x18}, /* H href start */
4442 {0x18, 0xbf}, /* H href end */
4443 {0x19, 0x03}, /* V start */
4444 {0x1a, 0xf8}, /* V end */
4445 {0x01, 0x80}, /* blue gain */
4446 {0x02, 0x80}, /* red gain */
4447 };
4448
4449 reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
4450
4451 i2c_w(gspca_dev, 0x12, 0x80); /* sensor reset */
4452 msleep(10);
4453
4454 i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
4455
4456 reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
4457 reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
4458
4459 setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
4460
4461 bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
4462 ARRAY_SIZE(color_gain[0]));
4463
4464 set_led(gspca_dev, 1);
4465 if (sd->sensor == SENSOR_CX0342)
4466 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4467 v4l2_ctrl_g_ctrl(gspca_dev->gain),
4468 v4l2_ctrl_g_ctrl(sd->blue),
4469 v4l2_ctrl_g_ctrl(sd->red));
4470 else
4471 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4472 v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
4473 if (sd->sensor == SENSOR_SOI763A)
4474 setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
4475 setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
4476}
4477
4478static void soi763a_6810_start(struct gspca_dev *gspca_dev)
4479{
4480 struct sd *sd = (struct sd *) gspca_dev;
4481 static const struct cmd bridge_init_2[] = {
4482 {TP6800_R7A_BLK_THRLD, 0x00},
4483 {TP6800_R79_QUALITY, 0x04},
4484 {TP6800_R79_QUALITY, 0x01},
4485 };
4486 static const struct cmd bridge_init_3[] = {
4487 {TP6800_R31_PIXEL_START, 0x20},
4488 {TP6800_R32_PIXEL_END_L, 0x9f},
4489 {TP6800_R33_PIXEL_END_H, 0x02},
4490 {TP6800_R34_LINE_START, 0x13},
4491 {TP6800_R35_LINE_END_L, 0xf8},
4492 {TP6800_R36_LINE_END_H, 0x01},
4493 };
4494 static const struct cmd bridge_init_6[] = {
4495 {0x08, 0xff},
4496 {0x09, 0xff},
4497 {0x0a, 0x5f},
4498 {0x0b, 0x80},
4499 };
4500
4501 reg_w(gspca_dev, 0x22, gspca_dev->alt);
4502 bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
4503 reg_w(gspca_dev, 0x59, 0x40);
4504 if (sd->sensor == SENSOR_CX0342)
4505 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4506 v4l2_ctrl_g_ctrl(gspca_dev->gain),
4507 v4l2_ctrl_g_ctrl(sd->blue),
4508 v4l2_ctrl_g_ctrl(sd->red));
4509 else
4510 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4511 v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
4512 reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
4513 reg_w_buf(gspca_dev, tp6810_ov_init_common,
4514 ARRAY_SIZE(tp6810_ov_init_common));
4515 reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
4516 if (gspca_dev->curr_mode) {
4517 reg_w(gspca_dev, 0x4a, 0x7f);
4518 reg_w(gspca_dev, 0x07, 0x05);
4519 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
4520 } else {
4521 reg_w(gspca_dev, 0x4a, 0xff);
4522 reg_w(gspca_dev, 0x07, 0x85);
4523 reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */
4524 }
4525 setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
4526 reg_w_buf(gspca_dev, tp6810_bridge_start,
4527 ARRAY_SIZE(tp6810_bridge_start));
4528
4529 if (gspca_dev->curr_mode) {
4530 reg_w(gspca_dev, 0x4f, 0x00);
4531 reg_w(gspca_dev, 0x4e, 0x7c);
4532 }
4533
4534 reg_w(gspca_dev, 0x00, 0x00);
4535
4536 setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
4537 bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
4538 ARRAY_SIZE(color_gain[0]));
4539 set_led(gspca_dev, 1);
4540 reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
4541 if (sd->sensor == SENSOR_CX0342)
4542 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4543 v4l2_ctrl_g_ctrl(gspca_dev->gain),
4544 v4l2_ctrl_g_ctrl(sd->blue),
4545 v4l2_ctrl_g_ctrl(sd->red));
4546 else
4547 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4548 v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
4549 reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
4550}
4551
4552/* -- start the camera -- */
4553static int sd_start(struct gspca_dev *gspca_dev)
4554{
4555 struct sd *sd = (struct sd *) gspca_dev;
4556
4557 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
4558 set_dqt(gspca_dev, sd->quality);
4559 if (sd->bridge == BRIDGE_TP6800) {
4560 if (sd->sensor == SENSOR_CX0342)
4561 cx0342_6800_start(gspca_dev);
4562 else
4563 soi763a_6800_start(gspca_dev);
4564 } else {
4565 if (sd->sensor == SENSOR_CX0342)
4566 cx0342_6810_start(gspca_dev);
4567 else
4568 soi763a_6810_start(gspca_dev);
4569 reg_w_buf(gspca_dev, tp6810_late_start,
4570 ARRAY_SIZE(tp6810_late_start));
4571 reg_w(gspca_dev, 0x80, 0x03);
4572 reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
4573
4574 if (sd->sensor == SENSOR_CX0342)
4575 setexposure(gspca_dev,
4576 v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4577 v4l2_ctrl_g_ctrl(gspca_dev->gain),
4578 v4l2_ctrl_g_ctrl(sd->blue),
4579 v4l2_ctrl_g_ctrl(sd->red));
4580 else
4581 setexposure(gspca_dev,
4582 v4l2_ctrl_g_ctrl(gspca_dev->exposure),
4583 v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
4584 if (sd->sensor == SENSOR_SOI763A)
4585 setquality(gspca_dev,
4586 v4l2_ctrl_g_ctrl(sd->jpegqual));
4587 if (sd->bridge == BRIDGE_TP6810)
4588 setautogain(gspca_dev,
4589 v4l2_ctrl_g_ctrl(gspca_dev->autogain));
4590 }
4591
4592 setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
4593
4594 return gspca_dev->usb_err;
4595}
4596
4597static void sd_stopN(struct gspca_dev *gspca_dev)
4598{
4599 struct sd *sd = (struct sd *) gspca_dev;
4600
4601 if (sd->bridge == BRIDGE_TP6800)
4602 reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03);
4603 set_led(gspca_dev, 0);
4604 reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
4605}
4606
4607static void sd_pkt_scan(struct gspca_dev *gspca_dev,
4608 u8 *data,
4609 int len)
4610{
4611 struct sd *sd = (struct sd *) gspca_dev;
4612
4613 /* the start of frame contains:
4614 * ff d8
4615 * ff fe
4616 * width / 16
4617 * height / 8
4618 * quality
4619 */
4620 if (sd->bridge == BRIDGE_TP6810) {
4621 if (*data != 0x5a) {
4622/*fixme: don't discard the whole frame..*/
4623 if (*data == 0xaa || *data == 0x00)
4624 return;
4625 if (*data > 0xc0) {
4626 PDEBUG(D_FRAM, "bad frame");
4627 gspca_dev->last_packet_type = DISCARD_PACKET;
4628 return;
4629 }
4630 }
4631 data++;
4632 len--;
4633 if (*data == 0xff && data[1] == 0xd8) {
4634/*fixme: there may be information in the 4 high bits*/
4635 if ((data[6] & 0x0f) != sd->quality)
4636 set_dqt(gspca_dev, data[6] & 0x0f);
4637 gspca_frame_add(gspca_dev, FIRST_PACKET,
4638 sd->jpeg_hdr, JPEG_HDR_SZ);
4639 gspca_frame_add(gspca_dev, INTER_PACKET,
4640 data + 7, len - 7);
4641 } else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
4642 gspca_frame_add(gspca_dev, LAST_PACKET,
4643 data, len);
4644 } else {
4645 gspca_frame_add(gspca_dev, INTER_PACKET,
4646 data, len);
4647 }
4648 return;
4649 }
4650
4651 switch (*data) {
4652 case 0x55:
4653 gspca_frame_add(gspca_dev, LAST_PACKET, data, 0);
4654
4655 if (len < 8
4656 || data[1] != 0xff || data[2] != 0xd8
4657 || data[3] != 0xff || data[4] != 0xfe) {
4658
4659 /* Have only seen this with corrupt frames */
4660 gspca_dev->last_packet_type = DISCARD_PACKET;
4661 return;
4662 }
4663 if (data[7] != sd->quality)
4664 set_dqt(gspca_dev, data[7]);
4665 gspca_frame_add(gspca_dev, FIRST_PACKET,
4666 sd->jpeg_hdr, JPEG_HDR_SZ);
4667 gspca_frame_add(gspca_dev, INTER_PACKET,
4668 data + 8, len - 8);
4669 break;
4670 case 0xaa:
4671 gspca_dev->last_packet_type = DISCARD_PACKET;
4672 break;
4673 case 0xcc:
4674 if (data[1] != 0xff || data[2] != 0xd8)
4675 gspca_frame_add(gspca_dev, INTER_PACKET,
4676 data + 1, len - 1);
4677 else
4678 gspca_dev->last_packet_type = DISCARD_PACKET;
4679 break;
4680 }
4681}
4682
4683static void sd_dq_callback(struct gspca_dev *gspca_dev)
4684{
4685 struct sd *sd = (struct sd *) gspca_dev;
4686 int ret, alen;
4687 int luma, expo;
4688
4689 if (sd->ag_cnt < 0)
4690 return;
4691 if (--sd->ag_cnt > 5)
4692 return;
4693 switch (sd->ag_cnt) {
4694/* case 5: */
4695 default:
4696 reg_w(gspca_dev, 0x7d, 0x00);
4697 break;
4698 case 4:
4699 reg_w(gspca_dev, 0x27, 0xb0);
4700 break;
4701 case 3:
4702 reg_w(gspca_dev, 0x0c, 0x01);
4703 break;
4704 case 2:
4705 ret = usb_bulk_msg(gspca_dev->dev,
4706 usb_rcvbulkpipe(gspca_dev->dev, 0x02),
4707 gspca_dev->usb_buf,
4708 32,
4709 &alen,
4710 500);
4711 if (ret < 0) {
4712 pr_err("bulk err %d\n", ret);
4713 break;
4714 }
4715 /* values not used (unknown) */
4716 break;
4717 case 1:
4718 reg_w(gspca_dev, 0x27, 0xd0);
4719 break;
4720 case 0:
4721 ret = usb_bulk_msg(gspca_dev->dev,
4722 usb_rcvbulkpipe(gspca_dev->dev, 0x02),
4723 gspca_dev->usb_buf,
4724 32,
4725 &alen,
4726 500);
4727 if (ret < 0) {
4728 pr_err("bulk err %d\n", ret);
4729 break;
4730 }
4731 luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] +
4732 (gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] +
4733 (gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] +
4734 (gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] +
4735 (gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] +
4736 (gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] +
4737 (gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
4738 (gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
4739 / 8;
4740 if (gspca_dev->width == 640)
4741 luma /= 4;
4742 reg_w(gspca_dev, 0x7d, 0x00);
4743
4744 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
4745 ret = gspca_expo_autogain(gspca_dev, luma,
4746 60, /* desired luma */
4747 6, /* dead zone */
4748 2, /* gain knee */
4749 70); /* expo knee */
4750 sd->ag_cnt = AG_CNT_START;
4751 if (sd->bridge == BRIDGE_TP6810) {
4752 int new_expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
4753
4754 if ((expo >= 128 && new_expo < 128)
4755 || (expo < 128 && new_expo >= 128))
4756 setframerate(gspca_dev, new_expo);
4757 }
4758 break;
4759 }
4760}
4761
4762/* get stream parameters (framerate) */
4763static void sd_get_streamparm(struct gspca_dev *gspca_dev,
4764 struct v4l2_streamparm *parm)
4765{
4766 struct sd *sd = (struct sd *) gspca_dev;
4767 struct v4l2_captureparm *cp = &parm->parm.capture;
4768 struct v4l2_fract *tpf = &cp->timeperframe;
4769 int fr, i;
4770
4771 cp->capability |= V4L2_CAP_TIMEPERFRAME;
4772 tpf->numerator = 1;
4773 i = get_fr_idx(gspca_dev);
4774 if (i & 0x80) {
4775 if (sd->bridge == BRIDGE_TP6800)
4776 fr = rates[6 - (i & 0x07)];
4777 else
4778 fr = rates_6810[7 - (i & 0x07)];
4779 } else {
4780 fr = rates[6 - i];
4781 }
4782 tpf->denominator = fr;
4783}
4784
4785/* set stream parameters (framerate) */
4786static void sd_set_streamparm(struct gspca_dev *gspca_dev,
4787 struct v4l2_streamparm *parm)
4788{
4789 struct sd *sd = (struct sd *) gspca_dev;
4790 struct v4l2_captureparm *cp = &parm->parm.capture;
4791 struct v4l2_fract *tpf = &cp->timeperframe;
4792 int fr, i;
4793
4794 sd->framerate = tpf->denominator / tpf->numerator;
4795 if (gspca_dev->streaming)
4796 setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
4797
4798 /* Return the actual framerate */
4799 i = get_fr_idx(gspca_dev);
4800 if (i & 0x80)
4801 fr = rates_6810[7 - (i & 0x07)];
4802 else
4803 fr = rates[6 - i];
4804 tpf->numerator = 1;
4805 tpf->denominator = fr;
4806}
4807
4808static int sd_set_jcomp(struct gspca_dev *gspca_dev,
4809 struct v4l2_jpegcompression *jcomp)
4810{
4811 struct sd *sd = (struct sd *) gspca_dev;
4812
4813 if (sd->sensor != SENSOR_SOI763A)
4814 return -ENOTTY;
4815 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
4816 return 0;
4817}
4818
4819static int sd_get_jcomp(struct gspca_dev *gspca_dev,
4820 struct v4l2_jpegcompression *jcomp)
4821{
4822 struct sd *sd = (struct sd *) gspca_dev;
4823
4824 if (sd->sensor != SENSOR_SOI763A)
4825 return -ENOTTY;
4826 memset(jcomp, 0, sizeof *jcomp);
4827 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
4828 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
4829 | V4L2_JPEG_MARKER_DQT;
4830 return 0;
4831}
4832
4833static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
4834{
4835 struct gspca_dev *gspca_dev =
4836 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
4837 struct sd *sd = (struct sd *)gspca_dev;
4838
4839 gspca_dev->usb_err = 0;
4840
4841 if (!gspca_dev->streaming)
4842 return 0;
4843
4844 switch (ctrl->id) {
4845 case V4L2_CID_SHARPNESS:
4846 setsharpness(gspca_dev, ctrl->val);
4847 break;
4848 case V4L2_CID_GAMMA:
4849 setgamma(gspca_dev, ctrl->val);
4850 break;
4851 case V4L2_CID_BLUE_BALANCE:
4852 setbgain(gspca_dev, ctrl->val);
4853 break;
4854 case V4L2_CID_RED_BALANCE:
4855 setrgain(gspca_dev, ctrl->val);
4856 break;
4857 case V4L2_CID_EXPOSURE:
4858 sd_setgain(gspca_dev);
4859 break;
4860 case V4L2_CID_AUTOGAIN:
4861 if (ctrl->val)
4862 break;
4863 sd_setgain(gspca_dev);
4864 break;
4865 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
4866 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
4867 break;
4868 }
4869 return gspca_dev->usb_err;
4870}
4871
4872static const struct v4l2_ctrl_ops sd_ctrl_ops = {
4873 .s_ctrl = sd_s_ctrl,
4874};
4875
4876static int sd_init_controls(struct gspca_dev *gspca_dev)
4877{
4878 struct sd *sd = (struct sd *)gspca_dev;
4879 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
4880
4881 gspca_dev->vdev.ctrl_handler = hdl;
4882 v4l2_ctrl_handler_init(hdl, 4);
4883 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4884 V4L2_CID_EXPOSURE, 1, 0xdc, 1, 0x4e);
4885 if (sd->sensor == SENSOR_CX0342) {
4886 sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4887 V4L2_CID_RED_BALANCE, 0, 4095, 1, 256);
4888 sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4889 V4L2_CID_BLUE_BALANCE, 0, 4095, 1, 256);
4890 }
4891 if (sd->sensor == SENSOR_SOI763A)
4892 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4893 V4L2_CID_GAIN, 0, 15, 1, 3);
4894 else
4895 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4896 V4L2_CID_GAIN, 0, 4095, 1, 256);
4897 sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4898 V4L2_CID_SHARPNESS, 0, 3, 1, 2);
4899 sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4900 V4L2_CID_GAMMA, 0, NGAMMA - 1, 1,
4901 (sd->sensor == SENSOR_SOI763A &&
4902 sd->bridge == BRIDGE_TP6800) ? 0 : 1);
4903 if (sd->bridge == BRIDGE_TP6810)
4904 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4905 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
4906 if (sd->sensor == SENSOR_SOI763A)
4907 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
4908 V4L2_CID_JPEG_COMPRESSION_QUALITY,
4909 0, 15, 1, (sd->bridge == BRIDGE_TP6810) ? 0 : 13);
4910
4911 if (hdl->error) {
4912 pr_err("Could not initialize controls\n");
4913 return hdl->error;
4914 }
4915 if (gspca_dev->autogain)
4916 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
4917 else
4918 v4l2_ctrl_cluster(2, &gspca_dev->exposure);
4919 return 0;
4920}
4921
4922static const struct sd_desc sd_desc = {
4923 .name = KBUILD_MODNAME,
4924 .config = sd_config,
4925 .init = sd_init,
4926 .init_controls = sd_init_controls,
4927 .isoc_init = sd_isoc_init,
4928 .start = sd_start,
4929 .stopN = sd_stopN,
4930 .pkt_scan = sd_pkt_scan,
4931 .dq_callback = sd_dq_callback,
4932 .get_streamparm = sd_get_streamparm,
4933 .set_streamparm = sd_set_streamparm,
4934 .get_jcomp = sd_get_jcomp,
4935 .set_jcomp = sd_set_jcomp,
4936};
4937
4938static const struct usb_device_id device_table[] = {
4939 {USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800},
4940 {USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810},
4941 {} /* Terminating entry */
4942};
4943
4944MODULE_DEVICE_TABLE(usb, device_table);
4945
4946static int sd_probe(struct usb_interface *interface,
4947 const struct usb_device_id *id)
4948{
4949 return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd),
4950 THIS_MODULE);
4951}
4952
4953static struct usb_driver sd_driver = {
4954 .name = KBUILD_MODNAME,
4955 .id_table = device_table,
4956 .probe = sd_probe,
4957 .disconnect = gspca_disconnect,
4958#ifdef CONFIG_PM
4959 .suspend = gspca_suspend,
4960 .resume = gspca_resume,
4961 .reset_resume = gspca_resume,
4962#endif
4963};
4964
4965module_usb_driver(sd_driver);
4966
4967module_param(force_sensor, int, 0644);
4968MODULE_PARM_DESC(force_sensor,
4969 "Force sensor. 0: cx0342, 1: soi763a");
diff --git a/drivers/media/usb/gspca/tv8532.c b/drivers/media/usb/gspca/tv8532.c
new file mode 100644
index 00000000000..8591324a53e
--- /dev/null
+++ b/drivers/media/usb/gspca/tv8532.c
@@ -0,0 +1,378 @@
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
25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26MODULE_DESCRIPTION("TV8532 USB Camera Driver");
27MODULE_LICENSE("GPL");
28
29/* specific webcam descriptor */
30struct sd {
31 struct gspca_dev gspca_dev; /* !! must be the first item */
32
33 __u8 packet;
34};
35
36static const struct v4l2_pix_format sif_mode[] = {
37 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
38 .bytesperline = 176,
39 .sizeimage = 176 * 144,
40 .colorspace = V4L2_COLORSPACE_SRGB,
41 .priv = 1},
42 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
43 .bytesperline = 352,
44 .sizeimage = 352 * 288,
45 .colorspace = V4L2_COLORSPACE_SRGB,
46 .priv = 0},
47};
48
49/* TV-8532A (ICM532A) registers (LE) */
50#define R00_PART_CONTROL 0x00
51#define LATENT_CHANGE 0x80
52#define EXPO_CHANGE 0x04
53#define R01_TIMING_CONTROL_LOW 0x01
54#define CMD_EEprom_Open 0x30
55#define CMD_EEprom_Close 0x29
56#define R03_TABLE_ADDR 0x03
57#define R04_WTRAM_DATA_L 0x04
58#define R05_WTRAM_DATA_M 0x05
59#define R06_WTRAM_DATA_H 0x06
60#define R07_TABLE_LEN 0x07
61#define R08_RAM_WRITE_ACTION 0x08
62#define R0C_AD_WIDTHL 0x0c
63#define R0D_AD_WIDTHH 0x0d
64#define R0E_AD_HEIGHTL 0x0e
65#define R0F_AD_HEIGHTH 0x0f
66#define R10_AD_COL_BEGINL 0x10
67#define R11_AD_COL_BEGINH 0x11
68#define MIRROR 0x04 /* [10] */
69#define R14_AD_ROW_BEGINL 0x14
70#define R15_AD_ROWBEGINH 0x15
71#define R1C_AD_EXPOSE_TIMEL 0x1c
72#define R20_GAIN_G1L 0x20
73#define R21_GAIN_G1H 0x21
74#define R22_GAIN_RL 0x22
75#define R23_GAIN_RH 0x23
76#define R24_GAIN_BL 0x24
77#define R25_GAIN_BH 0x25
78#define R26_GAIN_G2L 0x26
79#define R27_GAIN_G2H 0x27
80#define R28_QUANT 0x28
81#define R29_LINE 0x29
82#define R2C_POLARITY 0x2c
83#define R2D_POINT 0x2d
84#define R2E_POINTH 0x2e
85#define R2F_POINTB 0x2f
86#define R30_POINTBH 0x30
87#define R31_UPD 0x31
88#define R2A_HIGH_BUDGET 0x2a
89#define R2B_LOW_BUDGET 0x2b
90#define R34_VID 0x34
91#define R35_VIDH 0x35
92#define R36_PID 0x36
93#define R37_PIDH 0x37
94#define R39_Test1 0x39 /* GPIO */
95#define R3B_Test3 0x3b /* GPIO */
96#define R83_AD_IDH 0x83
97#define R91_AD_SLOPEREG 0x91
98#define R94_AD_BITCONTROL 0x94
99
100static const u8 eeprom_data[][3] = {
101/* dataH dataM dataL */
102 {0x01, 0x00, 0x01},
103 {0x01, 0x80, 0x11},
104 {0x05, 0x00, 0x14},
105 {0x05, 0x00, 0x1c},
106 {0x0d, 0x00, 0x1e},
107 {0x05, 0x00, 0x1f},
108 {0x05, 0x05, 0x19},
109 {0x05, 0x01, 0x1b},
110 {0x05, 0x09, 0x1e},
111 {0x0d, 0x89, 0x2e},
112 {0x05, 0x89, 0x2f},
113 {0x05, 0x0d, 0xd9},
114 {0x05, 0x09, 0xf1},
115};
116
117
118/* write 1 byte */
119static void reg_w1(struct gspca_dev *gspca_dev,
120 __u16 index, __u8 value)
121{
122 gspca_dev->usb_buf[0] = value;
123 usb_control_msg(gspca_dev->dev,
124 usb_sndctrlpipe(gspca_dev->dev, 0),
125 0x02,
126 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
127 0, /* value */
128 index, gspca_dev->usb_buf, 1, 500);
129}
130
131/* write 2 bytes */
132static void reg_w2(struct gspca_dev *gspca_dev,
133 u16 index, u16 value)
134{
135 gspca_dev->usb_buf[0] = value;
136 gspca_dev->usb_buf[1] = value >> 8;
137 usb_control_msg(gspca_dev->dev,
138 usb_sndctrlpipe(gspca_dev->dev, 0),
139 0x02,
140 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
141 0, /* value */
142 index, gspca_dev->usb_buf, 2, 500);
143}
144
145static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
146{
147 int i;
148
149 reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open);
150 for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) {
151 reg_w1(gspca_dev, R03_TABLE_ADDR, i);
152 reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]);
153 reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]);
154 reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]);
155 reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0);
156 }
157 reg_w1(gspca_dev, R07_TABLE_LEN, i);
158 reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close);
159}
160
161/* this function is called at probe time */
162static int sd_config(struct gspca_dev *gspca_dev,
163 const struct usb_device_id *id)
164{
165 struct cam *cam;
166
167 cam = &gspca_dev->cam;
168 cam->cam_mode = sif_mode;
169 cam->nmodes = ARRAY_SIZE(sif_mode);
170
171 return 0;
172}
173
174static void tv_8532_setReg(struct gspca_dev *gspca_dev)
175{
176 reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */
177 /******************************************************/
178 reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90);
179 reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01);
180 reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f);
181 reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44);
182 /* begin active line */
183 reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00);
184 /* mirror and digital gain */
185 reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a);
186
187 reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02);
188 reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00);
189 reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
190 /* = 0x84 */
191}
192
193/* this function is called at probe and resume time */
194static int sd_init(struct gspca_dev *gspca_dev)
195{
196 tv_8532WriteEEprom(gspca_dev);
197
198 return 0;
199}
200
201static void setexposure(struct gspca_dev *gspca_dev, s32 val)
202{
203 reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, val);
204 reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
205 /* 0x84 */
206}
207
208static void setgain(struct gspca_dev *gspca_dev, s32 val)
209{
210 reg_w2(gspca_dev, R20_GAIN_G1L, val);
211 reg_w2(gspca_dev, R22_GAIN_RL, val);
212 reg_w2(gspca_dev, R24_GAIN_BL, val);
213 reg_w2(gspca_dev, R26_GAIN_G2L, val);
214}
215
216/* -- start the camera -- */
217static int sd_start(struct gspca_dev *gspca_dev)
218{
219 struct sd *sd = (struct sd *) gspca_dev;
220
221 reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */
222 reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03);
223
224 /************************************************/
225 reg_w1(gspca_dev, R28_QUANT, 0x90);
226 /* 0x72 compressed mode 0x28 */
227 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
228 /* 176x144 */
229 reg_w1(gspca_dev, R29_LINE, 0x41);
230 /* CIF - 2 lines/packet */
231 } else {
232 /* 352x288 */
233 reg_w1(gspca_dev, R29_LINE, 0x81);
234 /* CIF - 2 lines/packet */
235 }
236 /************************************************/
237 reg_w1(gspca_dev, R2C_POLARITY, 0x10); /* slow clock */
238 reg_w1(gspca_dev, R2D_POINT, 0x14);
239 reg_w1(gspca_dev, R2E_POINTH, 0x01);
240 reg_w1(gspca_dev, R2F_POINTB, 0x12);
241 reg_w1(gspca_dev, R30_POINTBH, 0x01);
242
243 tv_8532_setReg(gspca_dev);
244
245 /************************************************/
246 reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */
247 msleep(200);
248 reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */
249
250 gspca_dev->empty_packet = 0; /* check the empty packets */
251 sd->packet = 0; /* ignore the first packets */
252
253 return 0;
254}
255
256static void sd_stopN(struct gspca_dev *gspca_dev)
257{
258 reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */
259}
260
261static void sd_pkt_scan(struct gspca_dev *gspca_dev,
262 u8 *data, /* isoc packet */
263 int len) /* iso packet length */
264{
265 struct sd *sd = (struct sd *) gspca_dev;
266 int packet_type0, packet_type1;
267
268 packet_type0 = packet_type1 = INTER_PACKET;
269 if (gspca_dev->empty_packet) {
270 gspca_dev->empty_packet = 0;
271 sd->packet = gspca_dev->height / 2;
272 packet_type0 = FIRST_PACKET;
273 } else if (sd->packet == 0)
274 return; /* 2 more lines in 352x288 ! */
275 sd->packet--;
276 if (sd->packet == 0)
277 packet_type1 = LAST_PACKET;
278
279 /* each packet contains:
280 * - header 2 bytes
281 * - RGRG line
282 * - 4 bytes
283 * - GBGB line
284 * - 4 bytes
285 */
286 gspca_frame_add(gspca_dev, packet_type0,
287 data + 2, gspca_dev->width);
288 gspca_frame_add(gspca_dev, packet_type1,
289 data + gspca_dev->width + 5, gspca_dev->width);
290}
291
292static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
293{
294 struct gspca_dev *gspca_dev =
295 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
296
297 gspca_dev->usb_err = 0;
298
299 if (!gspca_dev->streaming)
300 return 0;
301
302 switch (ctrl->id) {
303 case V4L2_CID_EXPOSURE:
304 setexposure(gspca_dev, ctrl->val);
305 break;
306 case V4L2_CID_GAIN:
307 setgain(gspca_dev, ctrl->val);
308 break;
309 }
310 return gspca_dev->usb_err;
311}
312
313static const struct v4l2_ctrl_ops sd_ctrl_ops = {
314 .s_ctrl = sd_s_ctrl,
315};
316
317static int sd_init_controls(struct gspca_dev *gspca_dev)
318{
319 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
320
321 gspca_dev->vdev.ctrl_handler = hdl;
322 v4l2_ctrl_handler_init(hdl, 2);
323 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
324 V4L2_CID_EXPOSURE, 0, 0x18f, 1, 0x18f);
325 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
326 V4L2_CID_GAIN, 0, 0x7ff, 1, 0x100);
327
328 if (hdl->error) {
329 pr_err("Could not initialize controls\n");
330 return hdl->error;
331 }
332 return 0;
333}
334
335/* sub-driver description */
336static const struct sd_desc sd_desc = {
337 .name = MODULE_NAME,
338 .config = sd_config,
339 .init = sd_init,
340 .init_controls = sd_init_controls,
341 .start = sd_start,
342 .stopN = sd_stopN,
343 .pkt_scan = sd_pkt_scan,
344};
345
346/* -- module initialisation -- */
347static const struct usb_device_id device_table[] = {
348 {USB_DEVICE(0x046d, 0x0920)},
349 {USB_DEVICE(0x046d, 0x0921)},
350 {USB_DEVICE(0x0545, 0x808b)},
351 {USB_DEVICE(0x0545, 0x8333)},
352 {USB_DEVICE(0x0923, 0x010f)},
353 {}
354};
355
356MODULE_DEVICE_TABLE(usb, device_table);
357
358/* -- device connect -- */
359static int sd_probe(struct usb_interface *intf,
360 const struct usb_device_id *id)
361{
362 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
363 THIS_MODULE);
364}
365
366static struct usb_driver sd_driver = {
367 .name = MODULE_NAME,
368 .id_table = device_table,
369 .probe = sd_probe,
370 .disconnect = gspca_disconnect,
371#ifdef CONFIG_PM
372 .suspend = gspca_suspend,
373 .resume = gspca_resume,
374 .reset_resume = gspca_resume,
375#endif
376};
377
378module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c
new file mode 100644
index 00000000000..e50079503d9
--- /dev/null
+++ b/drivers/media/usb/gspca/vc032x.c
@@ -0,0 +1,3850 @@
1/*
2 * Z-star vc0321 library
3 *
4 * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>
5 * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl
6 * Copyright (C) 2006 Michel Xhaard
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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25#define MODULE_NAME "vc032x"
26
27#include "gspca.h"
28
29MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
30MODULE_DESCRIPTION("GSPCA/VC032X 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 struct { /* hvflip cluster */
37 struct v4l2_ctrl *hflip;
38 struct v4l2_ctrl *vflip;
39 };
40
41 u8 image_offset;
42
43 u8 bridge;
44 u8 sensor;
45 u8 flags;
46#define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */
47#define FL_HFLIP 0x02 /* mirrored by default */
48#define FL_VFLIP 0x04 /* vertical flipped by default */
49};
50enum bridges {
51 BRIDGE_VC0321,
52 BRIDGE_VC0323,
53};
54enum sensors {
55 SENSOR_HV7131R,
56 SENSOR_MI0360,
57 SENSOR_MI1310_SOC,
58 SENSOR_MI1320,
59 SENSOR_MI1320_SOC,
60 SENSOR_OV7660,
61 SENSOR_OV7670,
62 SENSOR_PO1200,
63 SENSOR_PO3130NC,
64 SENSOR_POxxxx,
65 NSENSORS
66};
67
68
69static const struct v4l2_pix_format vc0321_mode[] = {
70 {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
71 .bytesperline = 320,
72 .sizeimage = 320 * 240 * 2,
73 .colorspace = V4L2_COLORSPACE_SRGB,
74 .priv = 1},
75 {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
76 .bytesperline = 640,
77 .sizeimage = 640 * 480 * 2,
78 .colorspace = V4L2_COLORSPACE_SRGB,
79 .priv = 0},
80};
81static const struct v4l2_pix_format vc0323_mode[] = {
82 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
83 .bytesperline = 320,
84 .sizeimage = 320 * 240 * 3 / 8 + 590,
85 .colorspace = V4L2_COLORSPACE_JPEG,
86 .priv = 1},
87 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
88 .bytesperline = 640,
89 .sizeimage = 640 * 480 * 3 / 8 + 590,
90 .colorspace = V4L2_COLORSPACE_JPEG,
91 .priv = 0},
92 {1280, 960, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */
93 .bytesperline = 1280,
94 .sizeimage = 1280 * 960 * 3 / 8 + 590,
95 .colorspace = V4L2_COLORSPACE_JPEG,
96 .priv = 2},
97};
98static const struct v4l2_pix_format bi_mode[] = {
99 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
100 .bytesperline = 320,
101 .sizeimage = 320 * 240 * 2,
102 .colorspace = V4L2_COLORSPACE_SRGB,
103 .priv = 2},
104 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
105 .bytesperline = 640,
106 .sizeimage = 640 * 480 * 2,
107 .colorspace = V4L2_COLORSPACE_SRGB,
108 .priv = 1},
109 {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
110 .bytesperline = 1280,
111 .sizeimage = 1280 * 1024 * 2,
112 .colorspace = V4L2_COLORSPACE_SRGB,
113 .priv = 0},
114};
115static const struct v4l2_pix_format svga_mode[] = {
116 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117 .bytesperline = 800,
118 .sizeimage = 800 * 600 * 1 / 4 + 590,
119 .colorspace = V4L2_COLORSPACE_JPEG,
120 .priv = 0},
121};
122
123/* OV7660/7670 registers */
124#define OV7660_REG_MVFP 0x1e
125#define OV7660_MVFP_MIRROR 0x20
126#define OV7660_MVFP_VFLIP 0x10
127
128static const u8 mi0360_matrix[9] = {
129 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50
130};
131
132static const u8 mi0360_initVGA_JPG[][4] = {
133 {0xb0, 0x03, 0x19, 0xcc},
134 {0xb0, 0x04, 0x02, 0xcc},
135 {0xb3, 0x00, 0x24, 0xcc},
136 {0xb3, 0x00, 0x25, 0xcc},
137 {0xb3, 0x08, 0x01, 0xcc},
138 {0xb3, 0x09, 0x0c, 0xcc},
139 {0xb3, 0x05, 0x01, 0xcc},
140 {0xb3, 0x06, 0x03, 0xcc},
141 {0xb3, 0x03, 0x0a, 0xcc},
142 {0xb3, 0x20, 0x00, 0xcc},
143 {0xb3, 0x21, 0x00, 0xcc},
144 {0xb3, 0x22, 0x01, 0xcc},
145 {0xb3, 0x23, 0xe0, 0xcc},
146 {0xb3, 0x04, 0x05, 0xcc},
147 {0xb3, 0x14, 0x00, 0xcc},
148 {0xb3, 0x15, 0x00, 0xcc},
149 {0xb3, 0x16, 0x02, 0xcc},
150 {0xb3, 0x17, 0x7f, 0xcc},
151 {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */
152 {0xb3, 0x34, 0x02, 0xcc},
153 {0xb3, 0x00, 0x25, 0xcc},
154 {0xbc, 0x00, 0x71, 0xcc},
155 {0xb8, 0x00, 0x13, 0xcc},
156 {0xb8, 0x27, 0x20, 0xcc},
157 {0xb8, 0x2c, 0x50, 0xcc},
158 {0xb8, 0x2d, 0xf8, 0xcc},
159 {0xb8, 0x2e, 0xf8, 0xcc},
160 {0xb8, 0x2f, 0xf8, 0xcc},
161 {0xb8, 0x30, 0x50, 0xcc},
162 {0xb8, 0x31, 0xf8, 0xcc},
163 {0xb8, 0x32, 0xf8, 0xcc},
164 {0xb8, 0x33, 0xf8, 0xcc},
165 {0xb8, 0x34, 0x50, 0xcc},
166 {0xb8, 0x35, 0x00, 0xcc},
167 {0xb8, 0x36, 0x00, 0xcc},
168 {0xb8, 0x37, 0x00, 0xcc},
169 {0xb8, 0x01, 0x79, 0xcc},
170 {0xb8, 0x08, 0xe0, 0xcc},
171 {0xb3, 0x01, 0x41, 0xcc},
172 {0xb8, 0x01, 0x79, 0xcc},
173 {0xb8, 0x14, 0x18, 0xcc},
174 {0xb8, 0xb2, 0x0a, 0xcc},
175 {0xb8, 0xb4, 0x0a, 0xcc},
176 {0xb8, 0xb5, 0x0a, 0xcc},
177 {0xb8, 0xfe, 0x00, 0xcc},
178 {0xb8, 0xff, 0x28, 0xcc},
179 {0xb9, 0x00, 0x28, 0xcc},
180 {0xb9, 0x01, 0x28, 0xcc},
181 {0xb9, 0x02, 0x28, 0xcc},
182 {0xb9, 0x03, 0x00, 0xcc},
183 {0xb9, 0x04, 0x00, 0xcc},
184 {0xb9, 0x05, 0x3c, 0xcc},
185 {0xb9, 0x06, 0x3c, 0xcc},
186 {0xb9, 0x07, 0x3c, 0xcc},
187 {0xb9, 0x08, 0x3c, 0xcc},
188 {0xb8, 0x8e, 0x00, 0xcc},
189 {0xb8, 0x8f, 0xff, 0xcc},
190 {0xb8, 0x81, 0x09, 0xcc},
191 {0x31, 0x00, 0x00, 0xbb},
192 {0x09, 0x01, 0xc7, 0xbb},
193 {0x34, 0x01, 0x00, 0xbb},
194 {0x2b, 0x00, 0x28, 0xbb},
195 {0x2c, 0x00, 0x30, 0xbb},
196 {0x2d, 0x00, 0x30, 0xbb},
197 {0x2e, 0x00, 0x28, 0xbb},
198 {0x62, 0x04, 0x11, 0xbb},
199 {0x03, 0x01, 0xe0, 0xbb},
200 {0x2c, 0x00, 0x2c, 0xbb},
201 {0x20, 0xd0, 0x00, 0xbb},
202 {0x01, 0x00, 0x08, 0xbb},
203 {0x06, 0x00, 0x10, 0xbb},
204 {0x05, 0x00, 0x20, 0xbb},
205 {0x20, 0x00, 0x00, 0xbb},
206 {0xb6, 0x00, 0x00, 0xcc},
207 {0xb6, 0x03, 0x02, 0xcc},
208 {0xb6, 0x02, 0x80, 0xcc},
209 {0xb6, 0x05, 0x01, 0xcc},
210 {0xb6, 0x04, 0xe0, 0xcc},
211 {0xb6, 0x12, 0x78, 0xcc},
212 {0xb6, 0x18, 0x02, 0xcc},
213 {0xb6, 0x17, 0x58, 0xcc},
214 {0xb6, 0x16, 0x00, 0xcc},
215 {0xb6, 0x22, 0x12, 0xcc},
216 {0xb6, 0x23, 0x0b, 0xcc},
217 {0xb3, 0x02, 0x02, 0xcc},
218 {0xbf, 0xc0, 0x39, 0xcc},
219 {0xbf, 0xc1, 0x04, 0xcc},
220 {0xbf, 0xcc, 0x10, 0xcc},
221 {0xb9, 0x12, 0x00, 0xcc},
222 {0xb9, 0x13, 0x0a, 0xcc},
223 {0xb9, 0x14, 0x0a, 0xcc},
224 {0xb9, 0x15, 0x0a, 0xcc},
225 {0xb9, 0x16, 0x0a, 0xcc},
226 {0xb9, 0x18, 0x00, 0xcc},
227 {0xb9, 0x19, 0x0f, 0xcc},
228 {0xb9, 0x1a, 0x0f, 0xcc},
229 {0xb9, 0x1b, 0x0f, 0xcc},
230 {0xb9, 0x1c, 0x0f, 0xcc},
231 {0xb8, 0x8e, 0x00, 0xcc},
232 {0xb8, 0x8f, 0xff, 0xcc},
233 {0xb6, 0x12, 0xf8, 0xcc},
234 {0xb8, 0x0c, 0x20, 0xcc},
235 {0xb8, 0x0d, 0x70, 0xcc},
236 {0xb6, 0x13, 0x13, 0xcc},
237 {0x35, 0x00, 0x60, 0xbb},
238 {0xb3, 0x5c, 0x01, 0xcc},
239 {}
240};
241static const u8 mi0360_initQVGA_JPG[][4] = {
242 {0xb0, 0x03, 0x19, 0xcc},
243 {0xb0, 0x04, 0x02, 0xcc},
244 {0xb3, 0x00, 0x24, 0xcc},
245 {0xb3, 0x00, 0x25, 0xcc},
246 {0xb3, 0x08, 0x01, 0xcc},
247 {0xb3, 0x09, 0x0c, 0xcc},
248 {0xb3, 0x05, 0x01, 0xcc},
249 {0xb3, 0x06, 0x03, 0xcc},
250 {0xb3, 0x03, 0x0a, 0xcc},
251 {0xb3, 0x20, 0x00, 0xcc},
252 {0xb3, 0x21, 0x00, 0xcc},
253 {0xb3, 0x22, 0x01, 0xcc},
254 {0xb3, 0x23, 0xe0, 0xcc},
255 {0xb3, 0x04, 0x05, 0xcc},
256 {0xb3, 0x14, 0x00, 0xcc},
257 {0xb3, 0x15, 0x00, 0xcc},
258 {0xb3, 0x16, 0x02, 0xcc},
259 {0xb3, 0x17, 0x7f, 0xcc},
260 {0xb3, 0x35, 0xdd, 0xcc},
261 {0xb3, 0x34, 0x02, 0xcc},
262 {0xb3, 0x00, 0x25, 0xcc},
263 {0xbc, 0x00, 0xd1, 0xcc},
264 {0xb8, 0x00, 0x13, 0xcc},
265 {0xb8, 0x27, 0x20, 0xcc},
266 {0xb8, 0x2c, 0x50, 0xcc},
267 {0xb8, 0x2d, 0xf8, 0xcc},
268 {0xb8, 0x2e, 0xf8, 0xcc},
269 {0xb8, 0x2f, 0xf8, 0xcc},
270 {0xb8, 0x30, 0x50, 0xcc},
271 {0xb8, 0x31, 0xf8, 0xcc},
272 {0xb8, 0x32, 0xf8, 0xcc},
273 {0xb8, 0x33, 0xf8, 0xcc},
274 {0xb8, 0x34, 0x50, 0xcc},
275 {0xb8, 0x35, 0x00, 0xcc},
276 {0xb8, 0x36, 0x00, 0xcc},
277 {0xb8, 0x37, 0x00, 0xcc},
278 {0xb8, 0x01, 0x79, 0xcc},
279 {0xb8, 0x08, 0xe0, 0xcc},
280 {0xb3, 0x01, 0x41, 0xcc},
281 {0xb8, 0x01, 0x79, 0xcc},
282 {0xb8, 0x14, 0x18, 0xcc},
283 {0xb8, 0xb2, 0x0a, 0xcc},
284 {0xb8, 0xb4, 0x0a, 0xcc},
285 {0xb8, 0xb5, 0x0a, 0xcc},
286 {0xb8, 0xfe, 0x00, 0xcc},
287 {0xb8, 0xff, 0x28, 0xcc},
288 {0xb9, 0x00, 0x28, 0xcc},
289 {0xb9, 0x01, 0x28, 0xcc},
290 {0xb9, 0x02, 0x28, 0xcc},
291 {0xb9, 0x03, 0x00, 0xcc},
292 {0xb9, 0x04, 0x00, 0xcc},
293 {0xb9, 0x05, 0x3c, 0xcc},
294 {0xb9, 0x06, 0x3c, 0xcc},
295 {0xb9, 0x07, 0x3c, 0xcc},
296 {0xb9, 0x08, 0x3c, 0xcc},
297 {0xb8, 0x8e, 0x00, 0xcc},
298 {0xb8, 0x8f, 0xff, 0xcc},
299 {0xb8, 0x81, 0x09, 0xcc},
300 {0x31, 0x00, 0x00, 0xbb},
301 {0x09, 0x01, 0xc7, 0xbb},
302 {0x34, 0x01, 0x00, 0xbb},
303 {0x2b, 0x00, 0x28, 0xbb},
304 {0x2c, 0x00, 0x30, 0xbb},
305 {0x2d, 0x00, 0x30, 0xbb},
306 {0x2e, 0x00, 0x28, 0xbb},
307 {0x62, 0x04, 0x11, 0xbb},
308 {0x03, 0x01, 0xe0, 0xbb},
309 {0x2c, 0x00, 0x2c, 0xbb},
310 {0x20, 0xd0, 0x00, 0xbb},
311 {0x01, 0x00, 0x08, 0xbb},
312 {0x06, 0x00, 0x10, 0xbb},
313 {0x05, 0x00, 0x20, 0xbb},
314 {0x20, 0x00, 0x00, 0xbb},
315 {0xb6, 0x00, 0x00, 0xcc},
316 {0xb6, 0x03, 0x01, 0xcc},
317 {0xb6, 0x02, 0x40, 0xcc},
318 {0xb6, 0x05, 0x00, 0xcc},
319 {0xb6, 0x04, 0xf0, 0xcc},
320 {0xb6, 0x12, 0x78, 0xcc},
321 {0xb6, 0x18, 0x00, 0xcc},
322 {0xb6, 0x17, 0x96, 0xcc},
323 {0xb6, 0x16, 0x00, 0xcc},
324 {0xb6, 0x22, 0x12, 0xcc},
325 {0xb6, 0x23, 0x0b, 0xcc},
326 {0xb3, 0x02, 0x02, 0xcc},
327 {0xbf, 0xc0, 0x39, 0xcc},
328 {0xbf, 0xc1, 0x04, 0xcc},
329 {0xbf, 0xcc, 0x10, 0xcc},
330 {0xb9, 0x12, 0x00, 0xcc},
331 {0xb9, 0x13, 0x0a, 0xcc},
332 {0xb9, 0x14, 0x0a, 0xcc},
333 {0xb9, 0x15, 0x0a, 0xcc},
334 {0xb9, 0x16, 0x0a, 0xcc},
335 {0xb9, 0x18, 0x00, 0xcc},
336 {0xb9, 0x19, 0x0f, 0xcc},
337 {0xb9, 0x1a, 0x0f, 0xcc},
338 {0xb9, 0x1b, 0x0f, 0xcc},
339 {0xb9, 0x1c, 0x0f, 0xcc},
340 {0xb8, 0x8e, 0x00, 0xcc},
341 {0xb8, 0x8f, 0xff, 0xcc},
342 {0xb6, 0x12, 0xf8, 0xcc},
343 {0xb6, 0x13, 0x13, 0xcc},
344 {0xbc, 0x02, 0x18, 0xcc},
345 {0xbc, 0x03, 0x50, 0xcc},
346 {0xbc, 0x04, 0x18, 0xcc},
347 {0xbc, 0x05, 0x00, 0xcc},
348 {0xbc, 0x06, 0x00, 0xcc},
349 {0xbc, 0x08, 0x30, 0xcc},
350 {0xbc, 0x09, 0x40, 0xcc},
351 {0xbc, 0x0a, 0x10, 0xcc},
352 {0xb8, 0x0c, 0x20, 0xcc},
353 {0xb8, 0x0d, 0x70, 0xcc},
354 {0xbc, 0x0b, 0x00, 0xcc},
355 {0xbc, 0x0c, 0x00, 0xcc},
356 {0x35, 0x00, 0xef, 0xbb},
357 {0xb3, 0x5c, 0x01, 0xcc},
358 {}
359};
360
361static const u8 mi1310_socinitVGA_JPG[][4] = {
362 {0xb0, 0x03, 0x19, 0xcc},
363 {0xb0, 0x04, 0x02, 0xcc},
364 {0xb3, 0x00, 0x64, 0xcc},
365 {0xb3, 0x00, 0x65, 0xcc},
366 {0xb3, 0x05, 0x00, 0xcc},
367 {0xb3, 0x06, 0x00, 0xcc},
368 {0xb3, 0x08, 0x01, 0xcc},
369 {0xb3, 0x09, 0x0c, 0xcc},
370 {0xb3, 0x34, 0x02, 0xcc},
371 {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */
372 {0xb3, 0x02, 0x00, 0xcc},
373 {0xb3, 0x03, 0x0a, 0xcc},
374 {0xb3, 0x04, 0x05, 0xcc},
375 {0xb3, 0x20, 0x00, 0xcc},
376 {0xb3, 0x21, 0x00, 0xcc},
377 {0xb3, 0x22, 0x03, 0xcc},
378 {0xb3, 0x23, 0xc0, 0xcc},
379 {0xb3, 0x14, 0x00, 0xcc},
380 {0xb3, 0x15, 0x00, 0xcc},
381 {0xb3, 0x16, 0x04, 0xcc},
382 {0xb3, 0x17, 0xff, 0xcc},
383 {0xb3, 0x00, 0x65, 0xcc},
384 {0xb8, 0x00, 0x00, 0xcc},
385 {0xbc, 0x00, 0xd0, 0xcc},
386 {0xbc, 0x01, 0x01, 0xcc},
387 {0xf0, 0x00, 0x02, 0xbb},
388 {0xc8, 0x9f, 0x0b, 0xbb},
389 {0x5b, 0x00, 0x01, 0xbb},
390 {0x2f, 0xde, 0x20, 0xbb},
391 {0xf0, 0x00, 0x00, 0xbb},
392 {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
393 {0xf0, 0x00, 0x01, 0xbb},
394 {0x05, 0x00, 0x07, 0xbb},
395 {0x34, 0x00, 0x00, 0xbb},
396 {0x35, 0xff, 0x00, 0xbb},
397 {0xdc, 0x07, 0x02, 0xbb},
398 {0xdd, 0x3c, 0x18, 0xbb},
399 {0xde, 0x92, 0x6d, 0xbb},
400 {0xdf, 0xcd, 0xb1, 0xbb},
401 {0xe0, 0xff, 0xe7, 0xbb},
402 {0x06, 0xf0, 0x0d, 0xbb},
403 {0x06, 0x70, 0x0e, 0xbb},
404 {0x4c, 0x00, 0x01, 0xbb},
405 {0x4d, 0x00, 0x01, 0xbb},
406 {0xf0, 0x00, 0x02, 0xbb},
407 {0x2e, 0x0c, 0x55, 0xbb},
408 {0x21, 0xb6, 0x6e, 0xbb},
409 {0x36, 0x30, 0x10, 0xbb},
410 {0x37, 0x00, 0xc1, 0xbb},
411 {0xf0, 0x00, 0x00, 0xbb},
412 {0x07, 0x00, 0x84, 0xbb},
413 {0x08, 0x02, 0x4a, 0xbb},
414 {0x05, 0x01, 0x10, 0xbb},
415 {0x06, 0x00, 0x39, 0xbb},
416 {0xf0, 0x00, 0x02, 0xbb},
417 {0x58, 0x02, 0x67, 0xbb},
418 {0x57, 0x02, 0x00, 0xbb},
419 {0x5a, 0x02, 0x67, 0xbb},
420 {0x59, 0x02, 0x00, 0xbb},
421 {0x5c, 0x12, 0x0d, 0xbb},
422 {0x5d, 0x16, 0x11, 0xbb},
423 {0x39, 0x06, 0x18, 0xbb},
424 {0x3a, 0x06, 0x18, 0xbb},
425 {0x3b, 0x06, 0x18, 0xbb},
426 {0x3c, 0x06, 0x18, 0xbb},
427 {0x64, 0x7b, 0x5b, 0xbb},
428 {0xf0, 0x00, 0x02, 0xbb},
429 {0x36, 0x30, 0x10, 0xbb},
430 {0x37, 0x00, 0xc0, 0xbb},
431 {0xbc, 0x0e, 0x00, 0xcc},
432 {0xbc, 0x0f, 0x05, 0xcc},
433 {0xbc, 0x10, 0xc0, 0xcc},
434 {0xbc, 0x11, 0x03, 0xcc},
435 {0xb6, 0x00, 0x00, 0xcc},
436 {0xb6, 0x03, 0x02, 0xcc},
437 {0xb6, 0x02, 0x80, 0xcc},
438 {0xb6, 0x05, 0x01, 0xcc},
439 {0xb6, 0x04, 0xe0, 0xcc},
440 {0xb6, 0x12, 0xf8, 0xcc},
441 {0xb6, 0x13, 0x25, 0xcc},
442 {0xb6, 0x18, 0x02, 0xcc},
443 {0xb6, 0x17, 0x58, 0xcc},
444 {0xb6, 0x16, 0x00, 0xcc},
445 {0xb6, 0x22, 0x12, 0xcc},
446 {0xb6, 0x23, 0x0b, 0xcc},
447 {0xbf, 0xc0, 0x39, 0xcc},
448 {0xbf, 0xc1, 0x04, 0xcc},
449 {0xbf, 0xcc, 0x00, 0xcc},
450 {0xbc, 0x02, 0x18, 0xcc},
451 {0xbc, 0x03, 0x50, 0xcc},
452 {0xbc, 0x04, 0x18, 0xcc},
453 {0xbc, 0x05, 0x00, 0xcc},
454 {0xbc, 0x06, 0x00, 0xcc},
455 {0xbc, 0x08, 0x30, 0xcc},
456 {0xbc, 0x09, 0x40, 0xcc},
457 {0xbc, 0x0a, 0x10, 0xcc},
458 {0xbc, 0x0b, 0x00, 0xcc},
459 {0xbc, 0x0c, 0x00, 0xcc},
460 {0xb3, 0x5c, 0x01, 0xcc},
461 {0xf0, 0x00, 0x01, 0xbb},
462 {0x80, 0x00, 0x03, 0xbb},
463 {0x81, 0xc7, 0x14, 0xbb},
464 {0x82, 0xeb, 0xe8, 0xbb},
465 {0x83, 0xfe, 0xf4, 0xbb},
466 {0x84, 0xcd, 0x10, 0xbb},
467 {0x85, 0xf3, 0xee, 0xbb},
468 {0x86, 0xff, 0xf1, 0xbb},
469 {0x87, 0xcd, 0x10, 0xbb},
470 {0x88, 0xf3, 0xee, 0xbb},
471 {0x89, 0x01, 0xf1, 0xbb},
472 {0x8a, 0xe5, 0x17, 0xbb},
473 {0x8b, 0xe8, 0xe2, 0xbb},
474 {0x8c, 0xf7, 0xed, 0xbb},
475 {0x8d, 0x00, 0xff, 0xbb},
476 {0x8e, 0xec, 0x10, 0xbb},
477 {0x8f, 0xf0, 0xed, 0xbb},
478 {0x90, 0xf9, 0xf2, 0xbb},
479 {0x91, 0x00, 0x00, 0xbb},
480 {0x92, 0xe9, 0x0d, 0xbb},
481 {0x93, 0xf4, 0xf2, 0xbb},
482 {0x94, 0xfb, 0xf5, 0xbb},
483 {0x95, 0x00, 0xff, 0xbb},
484 {0xb6, 0x0f, 0x08, 0xbb},
485 {0xb7, 0x3d, 0x16, 0xbb},
486 {0xb8, 0x0c, 0x04, 0xbb},
487 {0xb9, 0x1c, 0x07, 0xbb},
488 {0xba, 0x0a, 0x03, 0xbb},
489 {0xbb, 0x1b, 0x09, 0xbb},
490 {0xbc, 0x17, 0x0d, 0xbb},
491 {0xbd, 0x23, 0x1d, 0xbb},
492 {0xbe, 0x00, 0x28, 0xbb},
493 {0xbf, 0x11, 0x09, 0xbb},
494 {0xc0, 0x16, 0x15, 0xbb},
495 {0xc1, 0x00, 0x1b, 0xbb},
496 {0xc2, 0x0e, 0x07, 0xbb},
497 {0xc3, 0x14, 0x10, 0xbb},
498 {0xc4, 0x00, 0x17, 0xbb},
499 {0x06, 0x74, 0x8e, 0xbb},
500 {0xf0, 0x00, 0x01, 0xbb},
501 {0x06, 0xf4, 0x8e, 0xbb},
502 {0x00, 0x00, 0x50, 0xdd},
503 {0x06, 0x74, 0x8e, 0xbb},
504 {0xf0, 0x00, 0x02, 0xbb},
505 {0x24, 0x50, 0x20, 0xbb},
506 {0xf0, 0x00, 0x02, 0xbb},
507 {0x34, 0x0c, 0x50, 0xbb},
508 {0xb3, 0x01, 0x41, 0xcc},
509 {0xf0, 0x00, 0x00, 0xbb},
510 {0x03, 0x03, 0xc0, 0xbb},
511 {},
512};
513static const u8 mi1310_socinitQVGA_JPG[][4] = {
514 {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc},
515 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
516 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc},
517 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
518 {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc},
519 {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc},
520 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
521 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc},
522 {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
523 {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc},
524 {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
525 {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc},
526 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb},
527 {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
528 {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
529 {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
530 {0xf0, 0x00, 0x01, 0xbb},
531 {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb},
532 {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb},
533 {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb},
534 {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb},
535 {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb},
536 {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb},
537 {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb},
538 {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
539 {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
540 {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb},
541 {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb},
542 {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb},
543 {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb},
544 {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
545 {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb},
546 {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb},
547 {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb},
548 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
549 {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
550 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
551 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
552 {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc},
553 {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc},
554 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc},
555 {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc},
556 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
557 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
558 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
559 {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb},
560 {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb},
561 {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb},
562 {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb},
563 {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb},
564 {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb},
565 {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb},
566 {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb},
567 {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb},
568 {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
569 {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb},
570 {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb},
571 {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb},
572 {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb},
573 {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb},
574 {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb},
575 {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb},
576 {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb},
577 {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb},
578 {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb},
579 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb},
580 {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb},
581 {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb},
582 {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb},
583 {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
584 {0x03, 0x03, 0xc0, 0xbb},
585 {},
586};
587static const u8 mi1310_soc_InitSXGA_JPG[][4] = {
588 {0xb0, 0x03, 0x19, 0xcc},
589 {0xb0, 0x04, 0x02, 0xcc},
590 {0xb3, 0x00, 0x64, 0xcc},
591 {0xb3, 0x00, 0x65, 0xcc},
592 {0xb3, 0x05, 0x00, 0xcc},
593 {0xb3, 0x06, 0x00, 0xcc},
594 {0xb3, 0x08, 0x01, 0xcc},
595 {0xb3, 0x09, 0x0c, 0xcc},
596 {0xb3, 0x34, 0x02, 0xcc},
597 {0xb3, 0x35, 0xdd, 0xcc},
598 {0xb3, 0x02, 0x00, 0xcc},
599 {0xb3, 0x03, 0x0a, 0xcc},
600 {0xb3, 0x04, 0x0d, 0xcc},
601 {0xb3, 0x20, 0x00, 0xcc},
602 {0xb3, 0x21, 0x00, 0xcc},
603 {0xb3, 0x22, 0x03, 0xcc},
604 {0xb3, 0x23, 0xc0, 0xcc},
605 {0xb3, 0x14, 0x00, 0xcc},
606 {0xb3, 0x15, 0x00, 0xcc},
607 {0xb3, 0x16, 0x04, 0xcc},
608 {0xb3, 0x17, 0xff, 0xcc},
609 {0xb3, 0x00, 0x65, 0xcc},
610 {0xb8, 0x00, 0x00, 0xcc},
611 {0xbc, 0x00, 0x70, 0xcc},
612 {0xbc, 0x01, 0x01, 0xcc},
613 {0xf0, 0x00, 0x02, 0xbb},
614 {0xc8, 0x9f, 0x0b, 0xbb},
615 {0x5b, 0x00, 0x01, 0xbb},
616 {0xf0, 0x00, 0x00, 0xbb},
617 {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
618 {0xf0, 0x00, 0x01, 0xbb},
619 {0x05, 0x00, 0x07, 0xbb},
620 {0x34, 0x00, 0x00, 0xbb},
621 {0x35, 0xff, 0x00, 0xbb},
622 {0xdc, 0x07, 0x02, 0xbb},
623 {0xdd, 0x3c, 0x18, 0xbb},
624 {0xde, 0x92, 0x6d, 0xbb},
625 {0xdf, 0xcd, 0xb1, 0xbb},
626 {0xe0, 0xff, 0xe7, 0xbb},
627 {0x06, 0xf0, 0x0d, 0xbb},
628 {0x06, 0x70, 0x0e, 0xbb},
629 {0x4c, 0x00, 0x01, 0xbb},
630 {0x4d, 0x00, 0x01, 0xbb},
631 {0xf0, 0x00, 0x02, 0xbb},
632 {0x2e, 0x0c, 0x60, 0xbb},
633 {0x21, 0xb6, 0x6e, 0xbb},
634 {0x37, 0x01, 0x40, 0xbb},
635 {0xf0, 0x00, 0x00, 0xbb},
636 {0x07, 0x00, 0x84, 0xbb},
637 {0x08, 0x02, 0x4a, 0xbb},
638 {0x05, 0x01, 0x10, 0xbb},
639 {0x06, 0x00, 0x39, 0xbb},
640 {0xf0, 0x00, 0x02, 0xbb},
641 {0x58, 0x02, 0x67, 0xbb},
642 {0x57, 0x02, 0x00, 0xbb},
643 {0x5a, 0x02, 0x67, 0xbb},
644 {0x59, 0x02, 0x00, 0xbb},
645 {0x5c, 0x12, 0x0d, 0xbb},
646 {0x5d, 0x16, 0x11, 0xbb},
647 {0x39, 0x06, 0x18, 0xbb},
648 {0x3a, 0x06, 0x18, 0xbb},
649 {0x3b, 0x06, 0x18, 0xbb},
650 {0x3c, 0x06, 0x18, 0xbb},
651 {0x64, 0x7b, 0x5b, 0xbb},
652 {0xb6, 0x00, 0x00, 0xcc},
653 {0xb6, 0x03, 0x05, 0xcc},
654 {0xb6, 0x02, 0x00, 0xcc},
655 {0xb6, 0x05, 0x03, 0xcc},
656 {0xb6, 0x04, 0xc0, 0xcc},
657 {0xb6, 0x12, 0xf8, 0xcc},
658 {0xb6, 0x13, 0x29, 0xcc},
659 {0xb6, 0x18, 0x09, 0xcc},
660 {0xb6, 0x17, 0x60, 0xcc},
661 {0xb6, 0x16, 0x00, 0xcc},
662 {0xb6, 0x22, 0x12, 0xcc},
663 {0xb6, 0x23, 0x0b, 0xcc},
664 {0xbf, 0xc0, 0x39, 0xcc},
665 {0xbf, 0xc1, 0x04, 0xcc},
666 {0xbf, 0xcc, 0x00, 0xcc},
667 {0xb3, 0x01, 0x41, 0xcc},
668 {0x00, 0x00, 0x80, 0xdd},
669 {0xf0, 0x00, 0x02, 0xbb},
670 {0x00, 0x00, 0x10, 0xdd},
671 {0x22, 0xa0, 0x78, 0xbb},
672 {0x23, 0xa0, 0x78, 0xbb},
673 {0x24, 0x7f, 0x00, 0xbb},
674 {0x28, 0xea, 0x02, 0xbb},
675 {0x29, 0x86, 0x7a, 0xbb},
676 {0x5e, 0x52, 0x4c, 0xbb},
677 {0x5f, 0x20, 0x24, 0xbb},
678 {0x60, 0x00, 0x02, 0xbb},
679 {0x02, 0x00, 0xee, 0xbb},
680 {0x03, 0x39, 0x23, 0xbb},
681 {0x04, 0x07, 0x24, 0xbb},
682 {0x09, 0x00, 0xc0, 0xbb},
683 {0x0a, 0x00, 0x79, 0xbb},
684 {0x0b, 0x00, 0x04, 0xbb},
685 {0x0c, 0x00, 0x5c, 0xbb},
686 {0x0d, 0x00, 0xd9, 0xbb},
687 {0x0e, 0x00, 0x53, 0xbb},
688 {0x0f, 0x00, 0x21, 0xbb},
689 {0x10, 0x00, 0xa4, 0xbb},
690 {0x11, 0x00, 0xe5, 0xbb},
691 {0x15, 0x00, 0x00, 0xbb},
692 {0x16, 0x00, 0x00, 0xbb},
693 {0x17, 0x00, 0x00, 0xbb},
694 {0x18, 0x00, 0x00, 0xbb},
695 {0x19, 0x00, 0x00, 0xbb},
696 {0x1a, 0x00, 0x00, 0xbb},
697 {0x1b, 0x00, 0x00, 0xbb},
698 {0x1c, 0x00, 0x00, 0xbb},
699 {0x1d, 0x00, 0x00, 0xbb},
700 {0x1e, 0x00, 0x00, 0xbb},
701 {0xf0, 0x00, 0x01, 0xbb},
702 {0x00, 0x00, 0x20, 0xdd},
703 {0x06, 0xf0, 0x8e, 0xbb},
704 {0x00, 0x00, 0x80, 0xdd},
705 {0x06, 0x70, 0x8e, 0xbb},
706 {0xf0, 0x00, 0x02, 0xbb},
707 {0x00, 0x00, 0x20, 0xdd},
708 {0x5e, 0x6a, 0x53, 0xbb},
709 {0x5f, 0x40, 0x2c, 0xbb},
710 {0xf0, 0x00, 0x01, 0xbb},
711 {0x00, 0x00, 0x20, 0xdd},
712 {0x58, 0x00, 0x00, 0xbb},
713 {0x53, 0x09, 0x03, 0xbb},
714 {0x54, 0x31, 0x18, 0xbb},
715 {0x55, 0x8b, 0x5f, 0xbb},
716 {0x56, 0xc0, 0xa9, 0xbb},
717 {0x57, 0xe0, 0xd2, 0xbb},
718 {0xe1, 0x00, 0x00, 0xbb},
719 {0xdc, 0x09, 0x03, 0xbb},
720 {0xdd, 0x31, 0x18, 0xbb},
721 {0xde, 0x8b, 0x5f, 0xbb},
722 {0xdf, 0xc0, 0xa9, 0xbb},
723 {0xe0, 0xe0, 0xd2, 0xbb},
724 {0xb3, 0x5c, 0x01, 0xcc},
725 {0xf0, 0x00, 0x01, 0xbb},
726 {0x06, 0xf0, 0x8e, 0xbb},
727 {0xf0, 0x00, 0x02, 0xbb},
728 {0x2f, 0xde, 0x20, 0xbb},
729 {0xf0, 0x00, 0x02, 0xbb},
730 {0x24, 0x50, 0x20, 0xbb},
731 {0xbc, 0x0e, 0x00, 0xcc},
732 {0xbc, 0x0f, 0x05, 0xcc},
733 {0xbc, 0x10, 0xc0, 0xcc},
734 {0xf0, 0x00, 0x02, 0xbb},
735 {0x34, 0x0c, 0x50, 0xbb},
736 {0xbc, 0x11, 0x03, 0xcc},
737 {0xf0, 0x00, 0x01, 0xbb},
738 {0x80, 0x00, 0x03, 0xbb},
739 {0x81, 0xc7, 0x14, 0xbb},
740 {0x82, 0xeb, 0xe8, 0xbb},
741 {0x83, 0xfe, 0xf4, 0xbb},
742 {0x84, 0xcd, 0x10, 0xbb},
743 {0x85, 0xf3, 0xee, 0xbb},
744 {0x86, 0xff, 0xf1, 0xbb},
745 {0x87, 0xcd, 0x10, 0xbb},
746 {0x88, 0xf3, 0xee, 0xbb},
747 {0x89, 0x01, 0xf1, 0xbb},
748 {0x8a, 0xe5, 0x17, 0xbb},
749 {0x8b, 0xe8, 0xe2, 0xbb},
750 {0x8c, 0xf7, 0xed, 0xbb},
751 {0x8d, 0x00, 0xff, 0xbb},
752 {0x8e, 0xec, 0x10, 0xbb},
753 {0x8f, 0xf0, 0xed, 0xbb},
754 {0x90, 0xf9, 0xf2, 0xbb},
755 {0x91, 0x00, 0x00, 0xbb},
756 {0x92, 0xe9, 0x0d, 0xbb},
757 {0x93, 0xf4, 0xf2, 0xbb},
758 {0x94, 0xfb, 0xf5, 0xbb},
759 {0x95, 0x00, 0xff, 0xbb},
760 {0xb6, 0x0f, 0x08, 0xbb},
761 {0xb7, 0x3d, 0x16, 0xbb},
762 {0xb8, 0x0c, 0x04, 0xbb},
763 {0xb9, 0x1c, 0x07, 0xbb},
764 {0xba, 0x0a, 0x03, 0xbb},
765 {0xbb, 0x1b, 0x09, 0xbb},
766 {0xbc, 0x17, 0x0d, 0xbb},
767 {0xbd, 0x23, 0x1d, 0xbb},
768 {0xbe, 0x00, 0x28, 0xbb},
769 {0xbf, 0x11, 0x09, 0xbb},
770 {0xc0, 0x16, 0x15, 0xbb},
771 {0xc1, 0x00, 0x1b, 0xbb},
772 {0xc2, 0x0e, 0x07, 0xbb},
773 {0xc3, 0x14, 0x10, 0xbb},
774 {0xc4, 0x00, 0x17, 0xbb},
775 {0x06, 0x74, 0x8e, 0xbb},
776 {0xf0, 0x00, 0x00, 0xbb},
777 {0x03, 0x03, 0xc0, 0xbb},
778 {}
779};
780
781static const u8 mi1320_gamma[17] = {
782 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
783 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
784};
785static const u8 mi1320_matrix[9] = {
786 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52
787};
788static const u8 mi1320_initVGA_data[][4] = {
789 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
790 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
791 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
792 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
793 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
794 {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
795 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
796 {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */
797 {0xb3, 0x02, 0x00, 0xcc},
798 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
799 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
800 {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc},
801 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
802 {0xb3, 0x16, 0x04, 0xcc}, {0xb3, 0x17, 0xff, 0xcc},
803 {0xb3, 0x00, 0x67, 0xcc}, {0xbc, 0x00, 0xd0, 0xcc},
804 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
805 {0x0d, 0x00, 0x09, 0xbb}, {0x00, 0x01, 0x00, 0xdd},
806 {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
807 {0xa1, 0x05, 0x00, 0xbb}, {0xa4, 0x03, 0xc0, 0xbb},
808 {0xf0, 0x00, 0x02, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
809 {0xc8, 0x9f, 0x0b, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
810 {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
811 {0x20, 0x01, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
812 {0xf0, 0x00, 0x01, 0xbb}, {0x9d, 0x3c, 0xa0, 0xbb},
813 {0x47, 0x30, 0x30, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
814 {0x0a, 0x80, 0x11, 0xbb}, {0x35, 0x00, 0x22, 0xbb},
815 {0xf0, 0x00, 0x02, 0xbb}, {0x9d, 0xc5, 0x05, 0xbb},
816 {0xdc, 0x0f, 0xfc, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
817 {0x06, 0x74, 0x0e, 0xbb}, {0x80, 0x00, 0x06, 0xbb},
818 {0x81, 0x04, 0x00, 0xbb}, {0x82, 0x01, 0x02, 0xbb},
819 {0x83, 0x03, 0x02, 0xbb}, {0x84, 0x05, 0x00, 0xbb},
820 {0x85, 0x01, 0x00, 0xbb}, {0x86, 0x03, 0x02, 0xbb},
821 {0x87, 0x05, 0x00, 0xbb}, {0x88, 0x01, 0x00, 0xbb},
822 {0x89, 0x02, 0x02, 0xbb}, {0x8a, 0xfd, 0x04, 0xbb},
823 {0x8b, 0xfc, 0xfd, 0xbb}, {0x8c, 0xff, 0xfd, 0xbb},
824 {0x8d, 0x00, 0x00, 0xbb}, {0x8e, 0xfe, 0x05, 0xbb},
825 {0x8f, 0xfc, 0xfd, 0xbb}, {0x90, 0xfe, 0xfd, 0xbb},
826 {0x91, 0x00, 0x00, 0xbb}, {0x92, 0xfe, 0x03, 0xbb},
827 {0x93, 0xfd, 0xfe, 0xbb}, {0x94, 0xff, 0xfd, 0xbb},
828 {0x95, 0x00, 0x00, 0xbb}, {0xb6, 0x07, 0x05, 0xbb},
829 {0xb7, 0x13, 0x06, 0xbb}, {0xb8, 0x08, 0x06, 0xbb},
830 {0xb9, 0x14, 0x08, 0xbb}, {0xba, 0x06, 0x05, 0xbb},
831 {0xbb, 0x13, 0x06, 0xbb}, {0xbc, 0x03, 0x01, 0xbb},
832 {0xbd, 0x03, 0x04, 0xbb}, {0xbe, 0x00, 0x02, 0xbb},
833 {0xbf, 0x03, 0x01, 0xbb}, {0xc0, 0x02, 0x04, 0xbb},
834 {0xc1, 0x00, 0x04, 0xbb}, {0xc2, 0x02, 0x01, 0xbb},
835 {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb},
836 {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb},
837 {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb},
838 {0x08, 0x00, 0x27, 0xbb},
839 {0x20, 0x01, 0x00, 0xbb}, /* h/v flips - was 03 */
840 {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb},
841 {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
842 {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb},
843 {0x3a, 0x06, 0x1b, 0xbb}, {0x3b, 0x00, 0x95, 0xbb},
844 {0x3c, 0x04, 0xdb, 0xbb}, {0x57, 0x02, 0x00, 0xbb},
845 {0x58, 0x02, 0x66, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
846 {0x5a, 0x01, 0x33, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
847 {0x5d, 0x16, 0x11, 0xbb}, {0x64, 0x5e, 0x1c, 0xbb},
848 {0xf0, 0x00, 0x02, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
849 {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
850 {0x36, 0x68, 0x10, 0xbb}, {0x00, 0x00, 0x30, 0xdd},
851 {0x37, 0x82, 0x00, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
852 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
853 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
854 {0xb6, 0x03, 0x05, 0xcc}, {0xb6, 0x02, 0x00, 0xcc},
855 {0xb6, 0x05, 0x04, 0xcc}, {0xb6, 0x04, 0x00, 0xcc},
856 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x29, 0xcc},
857 {0xb6, 0x18, 0x0a, 0xcc}, {0xb6, 0x17, 0x00, 0xcc},
858 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
859 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x26, 0xcc},
860 {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc},
861 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
862 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
863 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
864 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
865 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
866 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
867 {}
868};
869static const u8 mi1320_initQVGA_data[][4] = {
870 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
871 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
872 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
873 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
874 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x01, 0xcc},
875 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
876 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
877 {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
878 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
879 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
880 {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
881 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
882 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
883 {0xb3, 0x00, 0x65, 0xcc}, {0xb8, 0x00, 0x00, 0xcc},
884 {0xbc, 0x00, 0xd0, 0xcc}, {0xbc, 0x01, 0x01, 0xcc},
885 {0xf0, 0x00, 0x00, 0xbb}, {0x0d, 0x00, 0x09, 0xbb},
886 {0x00, 0x01, 0x00, 0xdd}, {0x0d, 0x00, 0x08, 0xbb},
887 {0xf0, 0x00, 0x00, 0xbb}, {0x02, 0x00, 0x64, 0xbb},
888 {0x05, 0x01, 0x78, 0xbb}, {0x06, 0x00, 0x11, 0xbb},
889 {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb},
890 {0x20, 0x01, 0x00, 0xbb}, {0x21, 0x80, 0x00, 0xbb},
891 {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb},
892 {0x59, 0x00, 0xff, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
893 {0x9d, 0x3c, 0xa0, 0xbb}, {0x47, 0x30, 0x30, 0xbb},
894 {0xf0, 0x00, 0x00, 0xbb}, {0x0a, 0x80, 0x11, 0xbb},
895 {0x35, 0x00, 0x22, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
896 {0x9d, 0xc5, 0x05, 0xbb}, {0xdc, 0x0f, 0xfc, 0xbb},
897 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0x74, 0x0e, 0xbb},
898 {0x80, 0x00, 0x06, 0xbb}, {0x81, 0x04, 0x00, 0xbb},
899 {0x82, 0x01, 0x02, 0xbb}, {0x83, 0x03, 0x02, 0xbb},
900 {0x84, 0x05, 0x00, 0xbb}, {0x85, 0x01, 0x00, 0xbb},
901 {0x86, 0x03, 0x02, 0xbb}, {0x87, 0x05, 0x00, 0xbb},
902 {0x88, 0x01, 0x00, 0xbb}, {0x89, 0x02, 0x02, 0xbb},
903 {0x8a, 0xfd, 0x04, 0xbb}, {0x8b, 0xfc, 0xfd, 0xbb},
904 {0x8c, 0xff, 0xfd, 0xbb}, {0x8d, 0x00, 0x00, 0xbb},
905 {0x8e, 0xfe, 0x05, 0xbb}, {0x8f, 0xfc, 0xfd, 0xbb},
906 {0x90, 0xfe, 0xfd, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
907 {0x92, 0xfe, 0x03, 0xbb}, {0x93, 0xfd, 0xfe, 0xbb},
908 {0x94, 0xff, 0xfd, 0xbb}, {0x95, 0x00, 0x00, 0xbb},
909 {0xb6, 0x07, 0x05, 0xbb}, {0xb7, 0x13, 0x06, 0xbb},
910 {0xb8, 0x08, 0x06, 0xbb}, {0xb9, 0x14, 0x08, 0xbb},
911 {0xba, 0x06, 0x05, 0xbb}, {0xbb, 0x13, 0x06, 0xbb},
912 {0xbc, 0x03, 0x01, 0xbb}, {0xbd, 0x03, 0x04, 0xbb},
913 {0xbe, 0x00, 0x02, 0xbb}, {0xbf, 0x03, 0x01, 0xbb},
914 {0xc0, 0x02, 0x04, 0xbb}, {0xc1, 0x00, 0x04, 0xbb},
915 {0xc2, 0x02, 0x01, 0xbb}, {0xc3, 0x01, 0x03, 0xbb},
916 {0xc4, 0x00, 0x04, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
917 {0xc8, 0x00, 0x00, 0xbb}, {0x2e, 0x00, 0x00, 0xbb},
918 {0x2e, 0x0c, 0x5b, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
919 {0x39, 0x03, 0xca, 0xbb}, {0x3a, 0x06, 0x80, 0xbb},
920 {0x3b, 0x01, 0x52, 0xbb}, {0x3c, 0x05, 0x40, 0xbb},
921 {0x57, 0x01, 0x9c, 0xbb}, {0x58, 0x01, 0xee, 0xbb},
922 {0x59, 0x00, 0xf0, 0xbb}, {0x5a, 0x01, 0x20, 0xbb},
923 {0x5c, 0x1d, 0x17, 0xbb}, {0x5d, 0x22, 0x1c, 0xbb},
924 {0x64, 0x1e, 0x1c, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
925 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x68, 0x10, 0xbb},
926 {0x00, 0x00, 0x30, 0xdd}, {0x37, 0x81, 0x00, 0xbb},
927 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
928 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
929 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
930 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
931 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
932 {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc},
933 {0xbf, 0xcc, 0x04, 0xcc}, {0xb3, 0x5c, 0x01, 0xcc},
934 {0xb3, 0x01, 0x41, 0xcc},
935 {}
936};
937
938static const u8 mi1320_soc_InitVGA[][4] = {
939 {0xb3, 0x01, 0x01, 0xcc},
940 {0xb0, 0x03, 0x19, 0xcc},
941 {0xb0, 0x04, 0x02, 0xcc},
942 {0x00, 0x00, 0x30, 0xdd},
943 {0xb3, 0x00, 0x64, 0xcc},
944 {0xb3, 0x00, 0x67, 0xcc},
945 {0xb3, 0x05, 0x01, 0xcc},
946 {0xb3, 0x06, 0x01, 0xcc},
947 {0xb3, 0x08, 0x01, 0xcc},
948 {0xb3, 0x09, 0x0c, 0xcc},
949 {0xb3, 0x34, 0x02, 0xcc},
950 {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */
951 {0xb3, 0x02, 0x00, 0xcc},
952 {0xb3, 0x03, 0x0a, 0xcc},
953 {0xb3, 0x04, 0x05, 0xcc},
954 {0xb3, 0x20, 0x00, 0xcc},
955 {0xb3, 0x21, 0x00, 0xcc},
956 {0xb3, 0x22, 0x01, 0xcc},
957 {0xb3, 0x23, 0xe0, 0xcc},
958 {0xb3, 0x14, 0x00, 0xcc},
959 {0xb3, 0x15, 0x00, 0xcc},
960 {0xb3, 0x16, 0x02, 0xcc},
961 {0xb3, 0x17, 0x7f, 0xcc},
962 {0xb3, 0x00, 0x67, 0xcc},
963 {0xb8, 0x00, 0x00, 0xcc},
964 {0xbc, 0x00, 0x71, 0xcc},
965 {0xbc, 0x01, 0x01, 0xcc},
966 {0xb3, 0x5c, 0x01, 0xcc},
967 {0xf0, 0x00, 0x02, 0xbb},
968 {0x00, 0x00, 0x10, 0xdd},
969 {0xc8, 0x00, 0x00, 0xbb},
970 {0x00, 0x00, 0x30, 0xdd},
971 {0xf0, 0x00, 0x00, 0xbb},
972 {0x00, 0x00, 0x10, 0xdd},
973 {0x07, 0x00, 0xe0, 0xbb},
974 {0x08, 0x00, 0x0b, 0xbb},
975 {0x21, 0x00, 0x0c, 0xbb},
976 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
977 {0xbf, 0xc0, 0x26, 0xcc},
978 {0xbf, 0xc1, 0x02, 0xcc},
979 {0xbf, 0xcc, 0x04, 0xcc},
980 {0xb3, 0x01, 0x41, 0xcc},
981 {0xf0, 0x00, 0x00, 0xbb},
982 {0x05, 0x01, 0x78, 0xbb},
983 {0x06, 0x00, 0x11, 0xbb},
984 {0x07, 0x01, 0x42, 0xbb},
985 {0x08, 0x00, 0x11, 0xbb},
986 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
987 {0x21, 0x80, 0x00, 0xbb},
988 {0x22, 0x0d, 0x0f, 0xbb},
989 {0x24, 0x80, 0x00, 0xbb},
990 {0x59, 0x00, 0xff, 0xbb},
991 {0xf0, 0x00, 0x02, 0xbb},
992 {0x39, 0x03, 0xca, 0xbb},
993 {0x3a, 0x06, 0x80, 0xbb},
994 {0x3b, 0x01, 0x52, 0xbb},
995 {0x3c, 0x05, 0x40, 0xbb},
996 {0x57, 0x01, 0x9c, 0xbb},
997 {0x58, 0x01, 0xee, 0xbb},
998 {0x59, 0x00, 0xf0, 0xbb},
999 {0x5a, 0x01, 0x20, 0xbb},
1000 {0x5c, 0x1d, 0x17, 0xbb},
1001 {0x5d, 0x22, 0x1c, 0xbb},
1002 {0x64, 0x1e, 0x1c, 0xbb},
1003 {0x5b, 0x00, 0x00, 0xbb},
1004 {0xf0, 0x00, 0x02, 0xbb},
1005 {0x22, 0xa0, 0x78, 0xbb},
1006 {0x23, 0xa0, 0x78, 0xbb},
1007 {0x24, 0x7f, 0x00, 0xbb},
1008 {0x28, 0xea, 0x02, 0xbb},
1009 {0x29, 0x86, 0x7a, 0xbb},
1010 {0x5e, 0x52, 0x4c, 0xbb},
1011 {0x5f, 0x20, 0x24, 0xbb},
1012 {0x60, 0x00, 0x02, 0xbb},
1013 {0x02, 0x00, 0xee, 0xbb},
1014 {0x03, 0x39, 0x23, 0xbb},
1015 {0x04, 0x07, 0x24, 0xbb},
1016 {0x09, 0x00, 0xc0, 0xbb},
1017 {0x0a, 0x00, 0x79, 0xbb},
1018 {0x0b, 0x00, 0x04, 0xbb},
1019 {0x0c, 0x00, 0x5c, 0xbb},
1020 {0x0d, 0x00, 0xd9, 0xbb},
1021 {0x0e, 0x00, 0x53, 0xbb},
1022 {0x0f, 0x00, 0x21, 0xbb},
1023 {0x10, 0x00, 0xa4, 0xbb},
1024 {0x11, 0x00, 0xe5, 0xbb},
1025 {0x15, 0x00, 0x00, 0xbb},
1026 {0x16, 0x00, 0x00, 0xbb},
1027 {0x17, 0x00, 0x00, 0xbb},
1028 {0x18, 0x00, 0x00, 0xbb},
1029 {0x19, 0x00, 0x00, 0xbb},
1030 {0x1a, 0x00, 0x00, 0xbb},
1031 {0x1b, 0x00, 0x00, 0xbb},
1032 {0x1c, 0x00, 0x00, 0xbb},
1033 {0x1d, 0x00, 0x00, 0xbb},
1034 {0x1e, 0x00, 0x00, 0xbb},
1035 {0xf0, 0x00, 0x01, 0xbb},
1036 {0x06, 0xe0, 0x0e, 0xbb},
1037 {0x06, 0x60, 0x0e, 0xbb},
1038 {0xb3, 0x5c, 0x01, 0xcc},
1039 {}
1040};
1041static const u8 mi1320_soc_InitQVGA[][4] = {
1042 {0xb3, 0x01, 0x01, 0xcc},
1043 {0xb0, 0x03, 0x19, 0xcc},
1044 {0xb0, 0x04, 0x02, 0xcc},
1045 {0x00, 0x00, 0x30, 0xdd},
1046 {0xb3, 0x00, 0x64, 0xcc},
1047 {0xb3, 0x00, 0x67, 0xcc},
1048 {0xb3, 0x05, 0x01, 0xcc},
1049 {0xb3, 0x06, 0x01, 0xcc},
1050 {0xb3, 0x08, 0x01, 0xcc},
1051 {0xb3, 0x09, 0x0c, 0xcc},
1052 {0xb3, 0x34, 0x02, 0xcc},
1053 {0xb3, 0x35, 0xc8, 0xcc},
1054 {0xb3, 0x02, 0x00, 0xcc},
1055 {0xb3, 0x03, 0x0a, 0xcc},
1056 {0xb3, 0x04, 0x05, 0xcc},
1057 {0xb3, 0x20, 0x00, 0xcc},
1058 {0xb3, 0x21, 0x00, 0xcc},
1059 {0xb3, 0x22, 0x01, 0xcc},
1060 {0xb3, 0x23, 0xe0, 0xcc},
1061 {0xb3, 0x14, 0x00, 0xcc},
1062 {0xb3, 0x15, 0x00, 0xcc},
1063 {0xb3, 0x16, 0x02, 0xcc},
1064 {0xb3, 0x17, 0x7f, 0xcc},
1065 {0xb3, 0x00, 0x67, 0xcc},
1066 {0xb8, 0x00, 0x00, 0xcc},
1067 {0xbc, 0x00, 0xd1, 0xcc},
1068 {0xbc, 0x01, 0x01, 0xcc},
1069 {0xb3, 0x5c, 0x01, 0xcc},
1070 {0xf0, 0x00, 0x02, 0xbb},
1071 {0x00, 0x00, 0x10, 0xdd},
1072 {0xc8, 0x00, 0x00, 0xbb},
1073 {0x00, 0x00, 0x30, 0xdd},
1074 {0xf0, 0x00, 0x00, 0xbb},
1075 {0x00, 0x00, 0x10, 0xdd},
1076 {0x07, 0x00, 0xe0, 0xbb},
1077 {0x08, 0x00, 0x0b, 0xbb},
1078 {0x21, 0x00, 0x0c, 0xbb},
1079 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1080 {0xbf, 0xc0, 0x26, 0xcc},
1081 {0xbf, 0xc1, 0x02, 0xcc},
1082 {0xbf, 0xcc, 0x04, 0xcc},
1083 {0xbc, 0x02, 0x18, 0xcc},
1084 {0xbc, 0x03, 0x50, 0xcc},
1085 {0xbc, 0x04, 0x18, 0xcc},
1086 {0xbc, 0x05, 0x00, 0xcc},
1087 {0xbc, 0x06, 0x00, 0xcc},
1088 {0xbc, 0x08, 0x30, 0xcc},
1089 {0xbc, 0x09, 0x40, 0xcc},
1090 {0xbc, 0x0a, 0x10, 0xcc},
1091 {0xbc, 0x0b, 0x00, 0xcc},
1092 {0xbc, 0x0c, 0x00, 0xcc},
1093 {0xb3, 0x01, 0x41, 0xcc},
1094 {0xf0, 0x00, 0x00, 0xbb},
1095 {0x05, 0x01, 0x78, 0xbb},
1096 {0x06, 0x00, 0x11, 0xbb},
1097 {0x07, 0x01, 0x42, 0xbb},
1098 {0x08, 0x00, 0x11, 0xbb},
1099 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1100 {0x21, 0x80, 0x00, 0xbb},
1101 {0x22, 0x0d, 0x0f, 0xbb},
1102 {0x24, 0x80, 0x00, 0xbb},
1103 {0x59, 0x00, 0xff, 0xbb},
1104 {0xf0, 0x00, 0x02, 0xbb},
1105 {0x39, 0x03, 0xca, 0xbb},
1106 {0x3a, 0x06, 0x80, 0xbb},
1107 {0x3b, 0x01, 0x52, 0xbb},
1108 {0x3c, 0x05, 0x40, 0xbb},
1109 {0x57, 0x01, 0x9c, 0xbb},
1110 {0x58, 0x01, 0xee, 0xbb},
1111 {0x59, 0x00, 0xf0, 0xbb},
1112 {0x5a, 0x01, 0x20, 0xbb},
1113 {0x5c, 0x1d, 0x17, 0xbb},
1114 {0x5d, 0x22, 0x1c, 0xbb},
1115 {0x64, 0x1e, 0x1c, 0xbb},
1116 {0x5b, 0x00, 0x00, 0xbb},
1117 {0xf0, 0x00, 0x02, 0xbb},
1118 {0x22, 0xa0, 0x78, 0xbb},
1119 {0x23, 0xa0, 0x78, 0xbb},
1120 {0x24, 0x7f, 0x00, 0xbb},
1121 {0x28, 0xea, 0x02, 0xbb},
1122 {0x29, 0x86, 0x7a, 0xbb},
1123 {0x5e, 0x52, 0x4c, 0xbb},
1124 {0x5f, 0x20, 0x24, 0xbb},
1125 {0x60, 0x00, 0x02, 0xbb},
1126 {0x02, 0x00, 0xee, 0xbb},
1127 {0x03, 0x39, 0x23, 0xbb},
1128 {0x04, 0x07, 0x24, 0xbb},
1129 {0x09, 0x00, 0xc0, 0xbb},
1130 {0x0a, 0x00, 0x79, 0xbb},
1131 {0x0b, 0x00, 0x04, 0xbb},
1132 {0x0c, 0x00, 0x5c, 0xbb},
1133 {0x0d, 0x00, 0xd9, 0xbb},
1134 {0x0e, 0x00, 0x53, 0xbb},
1135 {0x0f, 0x00, 0x21, 0xbb},
1136 {0x10, 0x00, 0xa4, 0xbb},
1137 {0x11, 0x00, 0xe5, 0xbb},
1138 {0x15, 0x00, 0x00, 0xbb},
1139 {0x16, 0x00, 0x00, 0xbb},
1140 {0x17, 0x00, 0x00, 0xbb},
1141 {0x18, 0x00, 0x00, 0xbb},
1142 {0x19, 0x00, 0x00, 0xbb},
1143 {0x1a, 0x00, 0x00, 0xbb},
1144 {0x1b, 0x00, 0x00, 0xbb},
1145 {0x1c, 0x00, 0x00, 0xbb},
1146 {0x1d, 0x00, 0x00, 0xbb},
1147 {0x1e, 0x00, 0x00, 0xbb},
1148 {0xf0, 0x00, 0x01, 0xbb},
1149 {0x06, 0xe0, 0x0e, 0xbb},
1150 {0x06, 0x60, 0x0e, 0xbb},
1151 {0xb3, 0x5c, 0x01, 0xcc},
1152 {}
1153};
1154static const u8 mi1320_soc_InitSXGA[][4] = {
1155 {0xb3, 0x01, 0x01, 0xcc},
1156 {0xb0, 0x03, 0x19, 0xcc},
1157 {0x00, 0x00, 0x30, 0xdd},
1158 {0xb3, 0x00, 0x64, 0xcc},
1159 {0xb3, 0x00, 0x67, 0xcc},
1160 {0xb3, 0x05, 0x01, 0xcc},
1161 {0xb3, 0x06, 0x01, 0xcc},
1162 {0xb3, 0x08, 0x01, 0xcc},
1163 {0xb3, 0x09, 0x0c, 0xcc},
1164 {0xb3, 0x34, 0x02, 0xcc},
1165 {0xb3, 0x35, 0xc8, 0xcc},
1166 {0xb3, 0x02, 0x00, 0xcc},
1167 {0xb3, 0x03, 0x0a, 0xcc},
1168 {0xb3, 0x04, 0x05, 0xcc},
1169 {0xb3, 0x20, 0x00, 0xcc},
1170 {0xb3, 0x21, 0x00, 0xcc},
1171 {0xb3, 0x22, 0x04, 0xcc},
1172 {0xb3, 0x23, 0x00, 0xcc},
1173 {0xb3, 0x14, 0x00, 0xcc},
1174 {0xb3, 0x15, 0x00, 0xcc},
1175 {0xb3, 0x16, 0x04, 0xcc},
1176 {0xb3, 0x17, 0xff, 0xcc},
1177 {0xb3, 0x00, 0x67, 0xcc},
1178 {0xbc, 0x00, 0x71, 0xcc},
1179 {0xbc, 0x01, 0x01, 0xcc},
1180 {0xb3, 0x5c, 0x01, 0xcc},
1181 {0xf0, 0x00, 0x02, 0xbb},
1182 {0x00, 0x00, 0x30, 0xdd},
1183 {0xc8, 0x9f, 0x0b, 0xbb},
1184 {0x00, 0x00, 0x20, 0xdd},
1185 {0x5b, 0x00, 0x01, 0xbb},
1186 {0x00, 0x00, 0x20, 0xdd},
1187 {0xf0, 0x00, 0x00, 0xbb},
1188 {0x00, 0x00, 0x30, 0xdd},
1189 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1190 {0x00, 0x00, 0x20, 0xdd},
1191 {0xbf, 0xc0, 0x26, 0xcc},
1192 {0xbf, 0xc1, 0x02, 0xcc},
1193 {0xbf, 0xcc, 0x04, 0xcc},
1194 {0xb3, 0x01, 0x41, 0xcc},
1195 {0xf0, 0x00, 0x00, 0xbb},
1196 {0x05, 0x01, 0x78, 0xbb},
1197 {0x06, 0x00, 0x11, 0xbb},
1198 {0x07, 0x01, 0x42, 0xbb},
1199 {0x08, 0x00, 0x11, 0xbb},
1200 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1201 {0x21, 0x80, 0x00, 0xbb},
1202 {0x22, 0x0d, 0x0f, 0xbb},
1203 {0x24, 0x80, 0x00, 0xbb},
1204 {0x59, 0x00, 0xff, 0xbb},
1205 {0xf0, 0x00, 0x02, 0xbb},
1206 {0x39, 0x03, 0xca, 0xbb},
1207 {0x3a, 0x06, 0x80, 0xbb},
1208 {0x3b, 0x01, 0x52, 0xbb},
1209 {0x3c, 0x05, 0x40, 0xbb},
1210 {0x57, 0x01, 0x9c, 0xbb},
1211 {0x58, 0x01, 0xee, 0xbb},
1212 {0x59, 0x00, 0xf0, 0xbb},
1213 {0x5a, 0x01, 0x20, 0xbb},
1214 {0x5c, 0x1d, 0x17, 0xbb},
1215 {0x5d, 0x22, 0x1c, 0xbb},
1216 {0x64, 0x1e, 0x1c, 0xbb},
1217 {0x5b, 0x00, 0x00, 0xbb},
1218 {0xf0, 0x00, 0x02, 0xbb},
1219 {0x22, 0xa0, 0x78, 0xbb},
1220 {0x23, 0xa0, 0x78, 0xbb},
1221 {0x24, 0x7f, 0x00, 0xbb},
1222 {0x28, 0xea, 0x02, 0xbb},
1223 {0x29, 0x86, 0x7a, 0xbb},
1224 {0x5e, 0x52, 0x4c, 0xbb},
1225 {0x5f, 0x20, 0x24, 0xbb},
1226 {0x60, 0x00, 0x02, 0xbb},
1227 {0x02, 0x00, 0xee, 0xbb},
1228 {0x03, 0x39, 0x23, 0xbb},
1229 {0x04, 0x07, 0x24, 0xbb},
1230 {0x09, 0x00, 0xc0, 0xbb},
1231 {0x0a, 0x00, 0x79, 0xbb},
1232 {0x0b, 0x00, 0x04, 0xbb},
1233 {0x0c, 0x00, 0x5c, 0xbb},
1234 {0x0d, 0x00, 0xd9, 0xbb},
1235 {0x0e, 0x00, 0x53, 0xbb},
1236 {0x0f, 0x00, 0x21, 0xbb},
1237 {0x10, 0x00, 0xa4, 0xbb},
1238 {0x11, 0x00, 0xe5, 0xbb},
1239 {0x15, 0x00, 0x00, 0xbb},
1240 {0x16, 0x00, 0x00, 0xbb},
1241 {0x17, 0x00, 0x00, 0xbb},
1242 {0x18, 0x00, 0x00, 0xbb},
1243 {0x19, 0x00, 0x00, 0xbb},
1244 {0x1a, 0x00, 0x00, 0xbb},
1245 {0x1b, 0x00, 0x00, 0xbb},
1246 {0x1c, 0x00, 0x00, 0xbb},
1247 {0x1d, 0x00, 0x00, 0xbb},
1248 {0x1e, 0x00, 0x00, 0xbb},
1249 {0xf0, 0x00, 0x01, 0xbb},
1250 {0x06, 0xe0, 0x0e, 0xbb},
1251 {0x06, 0x60, 0x0e, 0xbb},
1252 {0xb3, 0x5c, 0x01, 0xcc},
1253 {0xf0, 0x00, 0x00, 0xbb},
1254 {0x05, 0x01, 0x13, 0xbb},
1255 {0x06, 0x00, 0x11, 0xbb},
1256 {0x07, 0x00, 0x85, 0xbb},
1257 {0x08, 0x00, 0x27, 0xbb},
1258 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1259 {0x21, 0x80, 0x00, 0xbb},
1260 {0x22, 0x0d, 0x0f, 0xbb},
1261 {0x24, 0x80, 0x00, 0xbb},
1262 {0x59, 0x00, 0xff, 0xbb},
1263 {0xf0, 0x00, 0x02, 0xbb},
1264 {0x39, 0x03, 0x0d, 0xbb},
1265 {0x3a, 0x06, 0x1b, 0xbb},
1266 {0x3b, 0x00, 0x95, 0xbb},
1267 {0x3c, 0x04, 0xdb, 0xbb},
1268 {0x57, 0x02, 0x00, 0xbb},
1269 {0x58, 0x02, 0x66, 0xbb},
1270 {0x59, 0x00, 0xff, 0xbb},
1271 {0x5a, 0x01, 0x33, 0xbb},
1272 {0x5c, 0x12, 0x0d, 0xbb},
1273 {0x5d, 0x16, 0x11, 0xbb},
1274 {0x64, 0x5e, 0x1c, 0xbb},
1275 {}
1276};
1277static const u8 po3130_gamma[17] = {
1278 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1279 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1280};
1281static const u8 po3130_matrix[9] = {
1282 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
1283};
1284
1285static const u8 po3130_initVGA_data[][4] = {
1286 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1287 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
1288 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
1289 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
1290 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
1291 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
1292 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
1293 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
1294 {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc},
1295 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1296 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1297 {0xb3, 0x34, 0x01, 0xcc},
1298 {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */
1299 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc},
1300 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
1301 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1302 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
1303 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
1304 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
1305 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
1306 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
1307 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
1308 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
1309 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
1310 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
1311 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
1312 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
1313 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
1314 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
1315 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
1316 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
1317 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
1318 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
1319 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
1320 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
1321 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
1322 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
1323 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
1324 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
1325 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
1326 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
1327 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
1328 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
1329 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
1330 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
1331 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
1332 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
1333 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1334 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1335 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1336 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1337 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1338 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1339 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
1340 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
1341 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
1342 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
1343 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
1344 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
1345 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
1346 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1347 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1348 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1349 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1350 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1351 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1352 {0x00, 0x7e, 0xea, 0xaa},
1353 {0x00, 0x4c, 0x07, 0xaa},
1354 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
1355 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
1356/* {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
1357 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, */
1358 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
1359 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
1360 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
1361 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
1362 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
1363 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
1364 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
1365 {0xb9, 0x08, 0x3c, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
1366 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
1367 {}
1368};
1369static const u8 po3130_rundata[][4] = {
1370 {0x00, 0x47, 0x45, 0xaa}, {0x00, 0x48, 0x9b, 0xaa},
1371 {0x00, 0x49, 0x3a, 0xaa}, {0x00, 0x4a, 0x01, 0xaa},
1372 {0x00, 0x44, 0x40, 0xaa},
1373/* {0x00, 0xd5, 0x7c, 0xaa}, */
1374 {0x00, 0xad, 0x04, 0xaa}, {0x00, 0xae, 0x00, 0xaa},
1375 {0x00, 0xb0, 0x78, 0xaa}, {0x00, 0x98, 0x02, 0xaa},
1376 {0x00, 0x94, 0x25, 0xaa}, {0x00, 0x95, 0x25, 0xaa},
1377 {0x00, 0x59, 0x68, 0xaa}, {0x00, 0x44, 0x20, 0xaa},
1378 {0x00, 0x17, 0x50, 0xaa}, {0x00, 0x19, 0x50, 0xaa},
1379 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0xd1, 0x3c, 0xaa},
1380 {0x00, 0x1e, 0x06, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
1381 {}
1382};
1383
1384static const u8 po3130_initQVGA_data[][4] = {
1385 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1386 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x09, 0xcc},
1387 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
1388 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
1389 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
1390 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
1391 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
1392 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
1393 {0xb3, 0x23, 0xe0, 0xcc}, {0xb8, 0x08, 0xe0, 0xcc},
1394 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1395 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1396 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
1397 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
1398 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
1399 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1400 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
1401 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
1402 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
1403 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
1404 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
1405 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
1406 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
1407 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
1408 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
1409 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
1410 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
1411 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
1412 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
1413 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
1414 {0x00, 0x59, 0x6f, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
1415 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
1416 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
1417 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
1418 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
1419 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
1420 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
1421 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
1422 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
1423 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
1424 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
1425 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
1426 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
1427 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
1428 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
1429 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
1430 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
1431 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1432 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1433 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1434 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1435 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1436 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1437 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
1438 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
1439 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
1440 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
1441 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
1442 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
1443 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
1444 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1445 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1446 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1447 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1448 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1449 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1450 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0x4c, 0x07, 0xaa},
1451 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
1452 {0x00, 0x59, 0x66, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
1453 {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
1454 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
1455 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
1456 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
1457 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
1458 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
1459 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
1460 {0xb9, 0x08, 0x3c, 0xcc}, {0xbc, 0x02, 0x18, 0xcc},
1461 {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc},
1462 {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
1463 {0xbc, 0x08, 0x30, 0xcc}, {0xbc, 0x09, 0x40, 0xcc},
1464 {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc},
1465 {0xbc, 0x0c, 0x00, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
1466 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
1467 {}
1468};
1469
1470static const u8 hv7131r_gamma[17] = {
1471 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1472 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1473};
1474static const u8 hv7131r_matrix[9] = {
1475 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
1476};
1477static const u8 hv7131r_initVGA_data[][4] = {
1478 {0xb3, 0x01, 0x01, 0xcc},
1479 {0xb0, 0x03, 0x19, 0xcc},
1480 {0xb0, 0x04, 0x02, 0xcc},
1481 {0x00, 0x00, 0x20, 0xdd},
1482 {0xb3, 0x00, 0x24, 0xcc},
1483 {0xb3, 0x00, 0x25, 0xcc},
1484 {0xb3, 0x08, 0x01, 0xcc},
1485 {0xb3, 0x09, 0x0c, 0xcc},
1486 {0xb3, 0x05, 0x01, 0xcc},
1487 {0xb3, 0x06, 0x03, 0xcc},
1488 {0xb3, 0x01, 0x45, 0xcc},
1489 {0xb3, 0x03, 0x0b, 0xcc},
1490 {0xb3, 0x04, 0x05, 0xcc},
1491 {0xb3, 0x20, 0x00, 0xcc},
1492 {0xb3, 0x21, 0x00, 0xcc},
1493 {0xb3, 0x22, 0x01, 0xcc},
1494 {0xb3, 0x23, 0xe0, 0xcc},
1495 {0xb3, 0x14, 0x00, 0xcc},
1496 {0xb3, 0x15, 0x02, 0xcc},
1497 {0xb3, 0x16, 0x02, 0xcc},
1498 {0xb3, 0x17, 0x7f, 0xcc},
1499 {0xb3, 0x34, 0x01, 0xcc},
1500 {0xb3, 0x35, 0x91, 0xcc}, /* i2c add: 11 */
1501 {0xb3, 0x00, 0x27, 0xcc},
1502 {0xbc, 0x00, 0x73, 0xcc},
1503 {0xb8, 0x00, 0x23, 0xcc},
1504 {0xb8, 0x2c, 0x50, 0xcc},
1505 {0xb8, 0x2d, 0xf8, 0xcc},
1506 {0xb8, 0x2e, 0xf8, 0xcc},
1507 {0xb8, 0x2f, 0xf8, 0xcc},
1508 {0xb8, 0x30, 0x50, 0xcc},
1509 {0xb8, 0x31, 0xf8, 0xcc},
1510 {0xb8, 0x32, 0xf8, 0xcc},
1511 {0xb8, 0x33, 0xf8, 0xcc},
1512 {0xb8, 0x34, 0x58, 0xcc},
1513 {0xb8, 0x35, 0x00, 0xcc},
1514 {0xb8, 0x36, 0x00, 0xcc},
1515 {0xb8, 0x37, 0x00, 0xcc},
1516 {0xb8, 0x27, 0x20, 0xcc},
1517 {0xb8, 0x01, 0x7d, 0xcc},
1518 {0xb8, 0x81, 0x09, 0xcc},
1519 {0xb3, 0x01, 0x41, 0xcc},
1520 {0xb8, 0x8e, 0x00, 0xcc},
1521 {0xb8, 0x8f, 0xff, 0xcc},
1522 {0x00, 0x01, 0x0c, 0xaa},
1523 {0x00, 0x14, 0x01, 0xaa},
1524 {0x00, 0x15, 0xe6, 0xaa},
1525 {0x00, 0x16, 0x02, 0xaa},
1526 {0x00, 0x17, 0x86, 0xaa},
1527 {0x00, 0x23, 0x00, 0xaa},
1528 {0x00, 0x25, 0x03, 0xaa},
1529 {0x00, 0x26, 0xa9, 0xaa},
1530 {0x00, 0x27, 0x80, 0xaa},
1531 {0x00, 0x30, 0x18, 0xaa},
1532 {0xb6, 0x00, 0x00, 0xcc},
1533 {0xb6, 0x03, 0x02, 0xcc},
1534 {0xb6, 0x02, 0x80, 0xcc},
1535 {0xb6, 0x05, 0x01, 0xcc},
1536 {0xb6, 0x04, 0xe0, 0xcc},
1537 {0xb6, 0x12, 0x78, 0xcc},
1538 {0xb6, 0x18, 0x02, 0xcc},
1539 {0xb6, 0x17, 0x58, 0xcc},
1540 {0xb6, 0x16, 0x00, 0xcc},
1541 {0xb6, 0x22, 0x12, 0xcc},
1542 {0xb6, 0x23, 0x0b, 0xcc},
1543 {0xb3, 0x02, 0x02, 0xcc},
1544 {0xbf, 0xc0, 0x39, 0xcc},
1545 {0xbf, 0xc1, 0x04, 0xcc},
1546 {0xbf, 0xcc, 0x10, 0xcc},
1547 {0xb6, 0x12, 0xf8, 0xcc},
1548 {0xb6, 0x13, 0x13, 0xcc},
1549 {0xb9, 0x12, 0x00, 0xcc},
1550 {0xb9, 0x13, 0x0a, 0xcc},
1551 {0xb9, 0x14, 0x0a, 0xcc},
1552 {0xb9, 0x15, 0x0a, 0xcc},
1553 {0xb9, 0x16, 0x0a, 0xcc},
1554 {0xb8, 0x0c, 0x20, 0xcc},
1555 {0xb8, 0x0d, 0x70, 0xcc},
1556 {0xb9, 0x18, 0x00, 0xcc},
1557 {0xb9, 0x19, 0x0f, 0xcc},
1558 {0xb9, 0x1a, 0x0f, 0xcc},
1559 {0xb9, 0x1b, 0x0f, 0xcc},
1560 {0xb9, 0x1c, 0x0f, 0xcc},
1561 {0xb3, 0x5c, 0x01, 0xcc},
1562 {}
1563};
1564
1565static const u8 hv7131r_initQVGA_data[][4] = {
1566 {0xb3, 0x01, 0x01, 0xcc},
1567 {0xb0, 0x03, 0x19, 0xcc},
1568 {0xb0, 0x04, 0x02, 0xcc},
1569 {0x00, 0x00, 0x20, 0xdd},
1570 {0xb3, 0x00, 0x24, 0xcc},
1571 {0xb3, 0x00, 0x25, 0xcc},
1572 {0xb3, 0x08, 0x01, 0xcc},
1573 {0xb3, 0x09, 0x0c, 0xcc},
1574 {0xb3, 0x05, 0x01, 0xcc},
1575 {0xb3, 0x06, 0x03, 0xcc},
1576 {0xb3, 0x01, 0x45, 0xcc},
1577 {0xb3, 0x03, 0x0b, 0xcc},
1578 {0xb3, 0x04, 0x05, 0xcc},
1579 {0xb3, 0x20, 0x00, 0xcc},
1580 {0xb3, 0x21, 0x00, 0xcc},
1581 {0xb3, 0x22, 0x01, 0xcc},
1582 {0xb3, 0x23, 0xe0, 0xcc},
1583 {0xb3, 0x14, 0x00, 0xcc},
1584 {0xb3, 0x15, 0x02, 0xcc},
1585 {0xb3, 0x16, 0x02, 0xcc},
1586 {0xb3, 0x17, 0x7f, 0xcc},
1587 {0xb3, 0x34, 0x01, 0xcc},
1588 {0xb3, 0x35, 0x91, 0xcc},
1589 {0xb3, 0x00, 0x27, 0xcc},
1590 {0xbc, 0x00, 0xd3, 0xcc},
1591 {0xb8, 0x00, 0x23, 0xcc},
1592 {0xb8, 0x2c, 0x50, 0xcc},
1593 {0xb8, 0x2d, 0xf8, 0xcc},
1594 {0xb8, 0x2e, 0xf8, 0xcc},
1595 {0xb8, 0x2f, 0xf8, 0xcc},
1596 {0xb8, 0x30, 0x50, 0xcc},
1597 {0xb8, 0x31, 0xf8, 0xcc},
1598 {0xb8, 0x32, 0xf8, 0xcc},
1599 {0xb8, 0x33, 0xf8, 0xcc},
1600 {0xb8, 0x34, 0x58, 0xcc},
1601 {0xb8, 0x35, 0x00, 0xcc},
1602 {0xb8, 0x36, 0x00, 0xcc},
1603 {0xb8, 0x37, 0x00, 0xcc},
1604 {0xb8, 0x27, 0x20, 0xcc},
1605 {0xb8, 0x01, 0x7d, 0xcc},
1606 {0xb8, 0x81, 0x09, 0xcc},
1607 {0xb3, 0x01, 0x41, 0xcc},
1608 {0xb8, 0x8e, 0x00, 0xcc},
1609 {0xb8, 0x8f, 0xff, 0xcc},
1610 {0x00, 0x01, 0x0c, 0xaa},
1611 {0x00, 0x14, 0x01, 0xaa},
1612 {0x00, 0x15, 0xe6, 0xaa},
1613 {0x00, 0x16, 0x02, 0xaa},
1614 {0x00, 0x17, 0x86, 0xaa},
1615 {0x00, 0x23, 0x00, 0xaa},
1616 {0x00, 0x25, 0x03, 0xaa},
1617 {0x00, 0x26, 0xa9, 0xaa},
1618 {0x00, 0x27, 0x80, 0xaa},
1619 {0x00, 0x30, 0x18, 0xaa},
1620 {0xb6, 0x00, 0x00, 0xcc},
1621 {0xb6, 0x03, 0x01, 0xcc},
1622 {0xb6, 0x02, 0x40, 0xcc},
1623 {0xb6, 0x05, 0x00, 0xcc},
1624 {0xb6, 0x04, 0xf0, 0xcc},
1625 {0xb6, 0x12, 0x78, 0xcc},
1626 {0xb6, 0x18, 0x00, 0xcc},
1627 {0xb6, 0x17, 0x96, 0xcc},
1628 {0xb6, 0x16, 0x00, 0xcc},
1629 {0xb6, 0x22, 0x12, 0xcc},
1630 {0xb6, 0x23, 0x0b, 0xcc},
1631 {0xb3, 0x02, 0x02, 0xcc},
1632 {0xbf, 0xc0, 0x39, 0xcc},
1633 {0xbf, 0xc1, 0x04, 0xcc},
1634 {0xbf, 0xcc, 0x10, 0xcc},
1635 {0xbc, 0x02, 0x18, 0xcc},
1636 {0xbc, 0x03, 0x50, 0xcc},
1637 {0xbc, 0x04, 0x18, 0xcc},
1638 {0xbc, 0x05, 0x00, 0xcc},
1639 {0xbc, 0x06, 0x00, 0xcc},
1640 {0xbc, 0x08, 0x30, 0xcc},
1641 {0xbc, 0x09, 0x40, 0xcc},
1642 {0xbc, 0x0a, 0x10, 0xcc},
1643 {0xbc, 0x0b, 0x00, 0xcc},
1644 {0xbc, 0x0c, 0x00, 0xcc},
1645 {0xb9, 0x12, 0x00, 0xcc},
1646 {0xb9, 0x13, 0x0a, 0xcc},
1647 {0xb9, 0x14, 0x0a, 0xcc},
1648 {0xb9, 0x15, 0x0a, 0xcc},
1649 {0xb9, 0x16, 0x0a, 0xcc},
1650 {0xb9, 0x18, 0x00, 0xcc},
1651 {0xb9, 0x19, 0x0f, 0xcc},
1652 {0xb8, 0x0c, 0x20, 0xcc},
1653 {0xb8, 0x0d, 0x70, 0xcc},
1654 {0xb9, 0x1a, 0x0f, 0xcc},
1655 {0xb9, 0x1b, 0x0f, 0xcc},
1656 {0xb9, 0x1c, 0x0f, 0xcc},
1657 {0xb6, 0x12, 0xf8, 0xcc},
1658 {0xb6, 0x13, 0x13, 0xcc},
1659 {0xb3, 0x5c, 0x01, 0xcc},
1660 {}
1661};
1662
1663static const u8 ov7660_gamma[17] = {
1664 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1665 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1666};
1667static const u8 ov7660_matrix[9] = {
1668 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62
1669};
1670static const u8 ov7660_initVGA_data[][4] = {
1671 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1672 {0x00, 0x00, 0x50, 0xdd},
1673 {0xb0, 0x03, 0x01, 0xcc},
1674 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
1675 {0xb3, 0x05, 0x01, 0xcc},
1676 {0xb3, 0x06, 0x03, 0xcc},
1677 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
1678 {0xb3, 0x05, 0x00, 0xcc},
1679 {0xb3, 0x06, 0x01, 0xcc},
1680 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
1681 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1682 {0xb3, 0x21, 0x00, 0xcc},
1683 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
1684 {0xb3, 0x1f, 0x02, 0xcc},
1685 {0xb3, 0x34, 0x01, 0xcc},
1686 {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
1687 {0xb3, 0x00, 0x26, 0xcc},
1688 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
1689 {0xb8, 0x01, 0x7d, 0xcc},
1690 {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1691 {0xb8, 0x27, 0x20, 0xcc},
1692 {0xb8, 0x8f, 0x50, 0xcc},
1693 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
1694 {0x00, 0x12, 0x80, 0xaa},
1695 {0x00, 0x12, 0x05, 0xaa},
1696 {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */
1697 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
1698 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
1699 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
1700 {0x00, 0x13, 0xa7, 0xaa},
1701 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
1702 {0x00, 0x36, 0x00, 0xaa},
1703 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
1704 {0x00, 0x39, 0x43, 0xaa},
1705 {0x00, 0x8d, 0xcf, 0xaa},
1706 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
1707 {0x00, 0x0f, 0x62, 0xaa},
1708 {0x00, 0x35, 0x84, 0xaa},
1709 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
1710 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
1711 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
1712 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
1713 {0x00, 0x01, 0x80, 0xaa},
1714 {0x00, 0x02, 0x80, 0xaa},
1715 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
1716 {0xb9, 0x00, 0x28, 0xcc},
1717 {0xb9, 0x01, 0x28, 0xcc}, {0xb9, 0x02, 0x28, 0xcc},
1718 {0xb9, 0x03, 0x00, 0xcc},
1719 {0xb9, 0x04, 0x00, 0xcc},
1720 {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
1721 {0xb9, 0x07, 0x3c, 0xcc},
1722 {0xb9, 0x08, 0x3c, 0xcc},
1723
1724 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
1725
1726 {0x00, 0x29, 0x3c, 0xaa}, {0xb3, 0x01, 0x45, 0xcc},
1727 {}
1728};
1729static const u8 ov7660_initQVGA_data[][4] = {
1730 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1731 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
1732 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
1733 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x03, 0xcc},
1734 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
1735 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
1736 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
1737 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1738 {0xb3, 0x21, 0x00, 0xcc},
1739 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
1740 {0xb3, 0x1f, 0x02, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
1741 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
1742 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
1743 {0xb8, 0x01, 0x7d, 0xcc},
1744/* sizer */
1745 {0xbc, 0x00, 0xd3, 0xcc},
1746 {0xb8, 0x81, 0x09, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1747 {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x8f, 0x50, 0xcc},
1748 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
1749 {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa},
1750 {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */
1751 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
1752 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
1753 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
1754 {0x00, 0x13, 0xa7, 0xaa},
1755 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
1756 {0x00, 0x36, 0x00, 0xaa},
1757 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
1758 {0x00, 0x39, 0x43, 0xaa}, {0x00, 0x8d, 0xcf, 0xaa},
1759 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
1760 {0x00, 0x0f, 0x62, 0xaa}, {0x00, 0x35, 0x84, 0xaa},
1761 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
1762 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
1763 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
1764 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
1765 {0x00, 0x01, 0x80, 0xaa},
1766 {0x00, 0x02, 0x80, 0xaa},
1767/* sizer filters */
1768 {0xbc, 0x02, 0x08, 0xcc},
1769 {0xbc, 0x03, 0x70, 0xcc},
1770 {0xb8, 0x35, 0x00, 0xcc},
1771 {0xb8, 0x36, 0x00, 0xcc},
1772 {0xb8, 0x37, 0x00, 0xcc},
1773 {0xbc, 0x04, 0x08, 0xcc},
1774 {0xbc, 0x05, 0x00, 0xcc},
1775 {0xbc, 0x06, 0x00, 0xcc},
1776 {0xbc, 0x08, 0x3c, 0xcc},
1777 {0xbc, 0x09, 0x40, 0xcc},
1778 {0xbc, 0x0a, 0x04, 0xcc},
1779 {0xbc, 0x0b, 0x00, 0xcc},
1780 {0xbc, 0x0c, 0x00, 0xcc},
1781/* */
1782 {0xb8, 0xfe, 0x00, 0xcc},
1783 {0xb8, 0xff, 0x28, 0xcc},
1784/* */
1785 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
1786 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
1787 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
1788 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
1789 {0xb9, 0x08, 0x3c, 0xcc},
1790/* */
1791 {0xb8, 0x8e, 0x00, 0xcc},
1792 {0xb8, 0x8f, 0xff, 0xcc}, /* ff */
1793 {0x00, 0x29, 0x3c, 0xaa},
1794 {0xb3, 0x01, 0x45, 0xcc}, /* 45 */
1795 {}
1796};
1797
1798static const u8 ov7660_50HZ[][4] = {
1799 {0x00, 0x3b, 0x08, 0xaa},
1800 {0x00, 0x9d, 0x40, 0xaa},
1801 {0x00, 0x13, 0xa7, 0xaa},
1802 {}
1803};
1804
1805static const u8 ov7660_60HZ[][4] = {
1806 {0x00, 0x3b, 0x00, 0xaa},
1807 {0x00, 0x9e, 0x40, 0xaa},
1808 {0x00, 0x13, 0xa7, 0xaa},
1809 {}
1810};
1811
1812static const u8 ov7660_NoFliker[][4] = {
1813 {0x00, 0x13, 0x87, 0xaa},
1814 {}
1815};
1816
1817static const u8 ov7670_InitVGA[][4] = {
1818 {0xb3, 0x01, 0x05, 0xcc},
1819 {0x00, 0x00, 0x30, 0xdd},
1820 {0xb0, 0x03, 0x19, 0xcc},
1821 {0x00, 0x00, 0x10, 0xdd},
1822 {0xb0, 0x04, 0x02, 0xcc},
1823 {0x00, 0x00, 0x10, 0xdd},
1824 {0xb3, 0x00, 0x66, 0xcc},
1825 {0xb3, 0x00, 0x67, 0xcc},
1826 {0xb0, 0x16, 0x01, 0xcc},
1827 {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
1828 {0xb3, 0x34, 0x01, 0xcc},
1829 {0xb3, 0x05, 0x01, 0xcc},
1830 {0xb3, 0x06, 0x01, 0xcc},
1831 {0xb3, 0x08, 0x01, 0xcc},
1832 {0xb3, 0x09, 0x0c, 0xcc},
1833 {0xb3, 0x02, 0x02, 0xcc},
1834 {0xb3, 0x03, 0x1f, 0xcc},
1835 {0xb3, 0x14, 0x00, 0xcc},
1836 {0xb3, 0x15, 0x00, 0xcc},
1837 {0xb3, 0x16, 0x02, 0xcc},
1838 {0xb3, 0x17, 0x7f, 0xcc},
1839 {0xb3, 0x04, 0x05, 0xcc},
1840 {0xb3, 0x20, 0x00, 0xcc},
1841 {0xb3, 0x21, 0x00, 0xcc},
1842 {0xb3, 0x22, 0x01, 0xcc},
1843 {0xb3, 0x23, 0xe0, 0xcc},
1844 {0xbc, 0x00, 0x41, 0xcc},
1845 {0xbc, 0x01, 0x01, 0xcc},
1846 {0x00, 0x12, 0x80, 0xaa},
1847 {0x00, 0x00, 0x20, 0xdd},
1848 {0x00, 0x12, 0x00, 0xaa},
1849 {0x00, 0x11, 0x40, 0xaa},
1850 {0x00, 0x6b, 0x0a, 0xaa},
1851 {0x00, 0x3a, 0x04, 0xaa},
1852 {0x00, 0x40, 0xc0, 0xaa},
1853 {0x00, 0x8c, 0x00, 0xaa},
1854 {0x00, 0x7a, 0x29, 0xaa},
1855 {0x00, 0x7b, 0x0e, 0xaa},
1856 {0x00, 0x7c, 0x1a, 0xaa},
1857 {0x00, 0x7d, 0x31, 0xaa},
1858 {0x00, 0x7e, 0x53, 0xaa},
1859 {0x00, 0x7f, 0x60, 0xaa},
1860 {0x00, 0x80, 0x6b, 0xaa},
1861 {0x00, 0x81, 0x73, 0xaa},
1862 {0x00, 0x82, 0x7b, 0xaa},
1863 {0x00, 0x83, 0x82, 0xaa},
1864 {0x00, 0x84, 0x89, 0xaa},
1865 {0x00, 0x85, 0x96, 0xaa},
1866 {0x00, 0x86, 0xa1, 0xaa},
1867 {0x00, 0x87, 0xb7, 0xaa},
1868 {0x00, 0x88, 0xcc, 0xaa},
1869 {0x00, 0x89, 0xe1, 0xaa},
1870 {0x00, 0x13, 0xe0, 0xaa},
1871 {0x00, 0x00, 0x00, 0xaa},
1872 {0x00, 0x10, 0x00, 0xaa},
1873 {0x00, 0x0d, 0x40, 0xaa},
1874 {0x00, 0x14, 0x28, 0xaa},
1875 {0x00, 0xa5, 0x05, 0xaa},
1876 {0x00, 0xab, 0x07, 0xaa},
1877 {0x00, 0x24, 0x95, 0xaa},
1878 {0x00, 0x25, 0x33, 0xaa},
1879 {0x00, 0x26, 0xe3, 0xaa},
1880 {0x00, 0x9f, 0x88, 0xaa},
1881 {0x00, 0xa0, 0x78, 0xaa},
1882 {0x00, 0x55, 0x90, 0xaa},
1883 {0x00, 0xa1, 0x03, 0xaa},
1884 {0x00, 0xa6, 0xe0, 0xaa},
1885 {0x00, 0xa7, 0xd8, 0xaa},
1886 {0x00, 0xa8, 0xf0, 0xaa},
1887 {0x00, 0xa9, 0x90, 0xaa},
1888 {0x00, 0xaa, 0x14, 0xaa},
1889 {0x00, 0x13, 0xe5, 0xaa},
1890 {0x00, 0x0e, 0x61, 0xaa},
1891 {0x00, 0x0f, 0x4b, 0xaa},
1892 {0x00, 0x16, 0x02, 0xaa},
1893 {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */
1894 {0x00, 0x21, 0x02, 0xaa},
1895 {0x00, 0x22, 0x91, 0xaa},
1896 {0x00, 0x29, 0x07, 0xaa},
1897 {0x00, 0x33, 0x0b, 0xaa},
1898 {0x00, 0x35, 0x0b, 0xaa},
1899 {0x00, 0x37, 0x1d, 0xaa},
1900 {0x00, 0x38, 0x71, 0xaa},
1901 {0x00, 0x39, 0x2a, 0xaa},
1902 {0x00, 0x3c, 0x78, 0xaa},
1903 {0x00, 0x4d, 0x40, 0xaa},
1904 {0x00, 0x4e, 0x20, 0xaa},
1905 {0x00, 0x74, 0x19, 0xaa},
1906 {0x00, 0x8d, 0x4f, 0xaa},
1907 {0x00, 0x8e, 0x00, 0xaa},
1908 {0x00, 0x8f, 0x00, 0xaa},
1909 {0x00, 0x90, 0x00, 0xaa},
1910 {0x00, 0x91, 0x00, 0xaa},
1911 {0x00, 0x96, 0x00, 0xaa},
1912 {0x00, 0x9a, 0x80, 0xaa},
1913 {0x00, 0xb0, 0x84, 0xaa},
1914 {0x00, 0xb1, 0x0c, 0xaa},
1915 {0x00, 0xb2, 0x0e, 0xaa},
1916 {0x00, 0xb3, 0x82, 0xaa},
1917 {0x00, 0xb8, 0x0a, 0xaa},
1918 {0x00, 0x43, 0x14, 0xaa},
1919 {0x00, 0x44, 0xf0, 0xaa},
1920 {0x00, 0x45, 0x45, 0xaa},
1921 {0x00, 0x46, 0x63, 0xaa},
1922 {0x00, 0x47, 0x2d, 0xaa},
1923 {0x00, 0x48, 0x46, 0xaa},
1924 {0x00, 0x59, 0x88, 0xaa},
1925 {0x00, 0x5a, 0xa0, 0xaa},
1926 {0x00, 0x5b, 0xc6, 0xaa},
1927 {0x00, 0x5c, 0x7d, 0xaa},
1928 {0x00, 0x5d, 0x5f, 0xaa},
1929 {0x00, 0x5e, 0x19, 0xaa},
1930 {0x00, 0x6c, 0x0a, 0xaa},
1931 {0x00, 0x6d, 0x55, 0xaa},
1932 {0x00, 0x6e, 0x11, 0xaa},
1933 {0x00, 0x6f, 0x9e, 0xaa},
1934 {0x00, 0x69, 0x00, 0xaa},
1935 {0x00, 0x6a, 0x40, 0xaa},
1936 {0x00, 0x01, 0x40, 0xaa},
1937 {0x00, 0x02, 0x40, 0xaa},
1938 {0x00, 0x13, 0xe7, 0xaa},
1939 {0x00, 0x5f, 0xf0, 0xaa},
1940 {0x00, 0x60, 0xf0, 0xaa},
1941 {0x00, 0x61, 0xf0, 0xaa},
1942 {0x00, 0x27, 0xa0, 0xaa},
1943 {0x00, 0x28, 0x80, 0xaa},
1944 {0x00, 0x2c, 0x90, 0xaa},
1945 {0x00, 0x4f, 0x66, 0xaa},
1946 {0x00, 0x50, 0x66, 0xaa},
1947 {0x00, 0x51, 0x00, 0xaa},
1948 {0x00, 0x52, 0x22, 0xaa},
1949 {0x00, 0x53, 0x5e, 0xaa},
1950 {0x00, 0x54, 0x80, 0xaa},
1951 {0x00, 0x58, 0x9e, 0xaa},
1952 {0x00, 0x41, 0x08, 0xaa},
1953 {0x00, 0x3f, 0x00, 0xaa},
1954 {0x00, 0x75, 0x85, 0xaa},
1955 {0x00, 0x76, 0xe1, 0xaa},
1956 {0x00, 0x4c, 0x00, 0xaa},
1957 {0x00, 0x77, 0x0a, 0xaa},
1958 {0x00, 0x3d, 0x88, 0xaa},
1959 {0x00, 0x4b, 0x09, 0xaa},
1960 {0x00, 0xc9, 0x60, 0xaa},
1961 {0x00, 0x41, 0x38, 0xaa},
1962 {0x00, 0x62, 0x30, 0xaa},
1963 {0x00, 0x63, 0x30, 0xaa},
1964 {0x00, 0x64, 0x08, 0xaa},
1965 {0x00, 0x94, 0x07, 0xaa},
1966 {0x00, 0x95, 0x0b, 0xaa},
1967 {0x00, 0x65, 0x00, 0xaa},
1968 {0x00, 0x66, 0x05, 0xaa},
1969 {0x00, 0x56, 0x50, 0xaa},
1970 {0x00, 0x34, 0x11, 0xaa},
1971 {0x00, 0xa4, 0x88, 0xaa},
1972 {0x00, 0x96, 0x00, 0xaa},
1973 {0x00, 0x97, 0x30, 0xaa},
1974 {0x00, 0x98, 0x20, 0xaa},
1975 {0x00, 0x99, 0x30, 0xaa},
1976 {0x00, 0x9a, 0x84, 0xaa},
1977 {0x00, 0x9b, 0x29, 0xaa},
1978 {0x00, 0x9c, 0x03, 0xaa},
1979 {0x00, 0x78, 0x04, 0xaa},
1980 {0x00, 0x79, 0x01, 0xaa},
1981 {0x00, 0xc8, 0xf0, 0xaa},
1982 {0x00, 0x79, 0x0f, 0xaa},
1983 {0x00, 0xc8, 0x00, 0xaa},
1984 {0x00, 0x79, 0x10, 0xaa},
1985 {0x00, 0xc8, 0x7e, 0xaa},
1986 {0x00, 0x79, 0x0a, 0xaa},
1987 {0x00, 0xc8, 0x80, 0xaa},
1988 {0x00, 0x79, 0x0b, 0xaa},
1989 {0x00, 0xc8, 0x01, 0xaa},
1990 {0x00, 0x79, 0x0c, 0xaa},
1991 {0x00, 0xc8, 0x0f, 0xaa},
1992 {0x00, 0x79, 0x0d, 0xaa},
1993 {0x00, 0xc8, 0x20, 0xaa},
1994 {0x00, 0x79, 0x09, 0xaa},
1995 {0x00, 0xc8, 0x80, 0xaa},
1996 {0x00, 0x79, 0x02, 0xaa},
1997 {0x00, 0xc8, 0xc0, 0xaa},
1998 {0x00, 0x79, 0x03, 0xaa},
1999 {0x00, 0xc8, 0x40, 0xaa},
2000 {0x00, 0x79, 0x05, 0xaa},
2001 {0x00, 0xc8, 0x30, 0xaa},
2002 {0x00, 0x79, 0x26, 0xaa},
2003 {0x00, 0x11, 0x40, 0xaa},
2004 {0x00, 0x3a, 0x04, 0xaa},
2005 {0x00, 0x12, 0x00, 0xaa},
2006 {0x00, 0x40, 0xc0, 0xaa},
2007 {0x00, 0x8c, 0x00, 0xaa},
2008 {0x00, 0x17, 0x14, 0xaa},
2009 {0x00, 0x18, 0x02, 0xaa},
2010 {0x00, 0x32, 0x92, 0xaa},
2011 {0x00, 0x19, 0x02, 0xaa},
2012 {0x00, 0x1a, 0x7a, 0xaa},
2013 {0x00, 0x03, 0x0a, 0xaa},
2014 {0x00, 0x0c, 0x00, 0xaa},
2015 {0x00, 0x3e, 0x00, 0xaa},
2016 {0x00, 0x70, 0x3a, 0xaa},
2017 {0x00, 0x71, 0x35, 0xaa},
2018 {0x00, 0x72, 0x11, 0xaa},
2019 {0x00, 0x73, 0xf0, 0xaa},
2020 {0x00, 0xa2, 0x02, 0xaa},
2021 {0x00, 0xb1, 0x00, 0xaa},
2022 {0x00, 0xb1, 0x0c, 0xaa},
2023 {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */
2024 {0x00, 0xaa, 0x14, 0xaa},
2025 {0x00, 0x24, 0x80, 0xaa},
2026 {0x00, 0x25, 0x74, 0xaa},
2027 {0x00, 0x26, 0xd3, 0xaa},
2028 {0x00, 0x0d, 0x00, 0xaa},
2029 {0x00, 0x14, 0x18, 0xaa},
2030 {0x00, 0x9d, 0x99, 0xaa},
2031 {0x00, 0x9e, 0x7f, 0xaa},
2032 {0x00, 0x64, 0x08, 0xaa},
2033 {0x00, 0x94, 0x07, 0xaa},
2034 {0x00, 0x95, 0x06, 0xaa},
2035 {0x00, 0x66, 0x05, 0xaa},
2036 {0x00, 0x41, 0x08, 0xaa},
2037 {0x00, 0x3f, 0x00, 0xaa},
2038 {0x00, 0x75, 0x07, 0xaa},
2039 {0x00, 0x76, 0xe1, 0xaa},
2040 {0x00, 0x4c, 0x00, 0xaa},
2041 {0x00, 0x77, 0x00, 0xaa},
2042 {0x00, 0x3d, 0xc2, 0xaa},
2043 {0x00, 0x4b, 0x09, 0xaa},
2044 {0x00, 0xc9, 0x60, 0xaa},
2045 {0x00, 0x41, 0x38, 0xaa},
2046 {0xbf, 0xc0, 0x26, 0xcc},
2047 {0xbf, 0xc1, 0x02, 0xcc},
2048 {0xbf, 0xcc, 0x04, 0xcc},
2049 {0xb3, 0x5c, 0x01, 0xcc},
2050 {0xb3, 0x01, 0x45, 0xcc},
2051 {0x00, 0x77, 0x05, 0xaa},
2052 {},
2053};
2054
2055static const u8 ov7670_InitQVGA[][4] = {
2056 {0xb3, 0x01, 0x05, 0xcc},
2057 {0x00, 0x00, 0x30, 0xdd},
2058 {0xb0, 0x03, 0x19, 0xcc},
2059 {0x00, 0x00, 0x10, 0xdd},
2060 {0xb0, 0x04, 0x02, 0xcc},
2061 {0x00, 0x00, 0x10, 0xdd},
2062 {0xb3, 0x00, 0x66, 0xcc},
2063 {0xb3, 0x00, 0x67, 0xcc},
2064 {0xb0, 0x16, 0x01, 0xcc},
2065 {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
2066 {0xb3, 0x34, 0x01, 0xcc},
2067 {0xb3, 0x05, 0x01, 0xcc},
2068 {0xb3, 0x06, 0x01, 0xcc},
2069 {0xb3, 0x08, 0x01, 0xcc},
2070 {0xb3, 0x09, 0x0c, 0xcc},
2071 {0xb3, 0x02, 0x02, 0xcc},
2072 {0xb3, 0x03, 0x1f, 0xcc},
2073 {0xb3, 0x14, 0x00, 0xcc},
2074 {0xb3, 0x15, 0x00, 0xcc},
2075 {0xb3, 0x16, 0x02, 0xcc},
2076 {0xb3, 0x17, 0x7f, 0xcc},
2077 {0xb3, 0x04, 0x05, 0xcc},
2078 {0xb3, 0x20, 0x00, 0xcc},
2079 {0xb3, 0x21, 0x00, 0xcc},
2080 {0xb3, 0x22, 0x01, 0xcc},
2081 {0xb3, 0x23, 0xe0, 0xcc},
2082 {0xbc, 0x00, 0xd1, 0xcc},
2083 {0xbc, 0x01, 0x01, 0xcc},
2084 {0x00, 0x12, 0x80, 0xaa},
2085 {0x00, 0x00, 0x20, 0xdd},
2086 {0x00, 0x12, 0x00, 0xaa},
2087 {0x00, 0x11, 0x40, 0xaa},
2088 {0x00, 0x6b, 0x0a, 0xaa},
2089 {0x00, 0x3a, 0x04, 0xaa},
2090 {0x00, 0x40, 0xc0, 0xaa},
2091 {0x00, 0x8c, 0x00, 0xaa},
2092 {0x00, 0x7a, 0x29, 0xaa},
2093 {0x00, 0x7b, 0x0e, 0xaa},
2094 {0x00, 0x7c, 0x1a, 0xaa},
2095 {0x00, 0x7d, 0x31, 0xaa},
2096 {0x00, 0x7e, 0x53, 0xaa},
2097 {0x00, 0x7f, 0x60, 0xaa},
2098 {0x00, 0x80, 0x6b, 0xaa},
2099 {0x00, 0x81, 0x73, 0xaa},
2100 {0x00, 0x82, 0x7b, 0xaa},
2101 {0x00, 0x83, 0x82, 0xaa},
2102 {0x00, 0x84, 0x89, 0xaa},
2103 {0x00, 0x85, 0x96, 0xaa},
2104 {0x00, 0x86, 0xa1, 0xaa},
2105 {0x00, 0x87, 0xb7, 0xaa},
2106 {0x00, 0x88, 0xcc, 0xaa},
2107 {0x00, 0x89, 0xe1, 0xaa},
2108 {0x00, 0x13, 0xe0, 0xaa},
2109 {0x00, 0x00, 0x00, 0xaa},
2110 {0x00, 0x10, 0x00, 0xaa},
2111 {0x00, 0x0d, 0x40, 0xaa},
2112 {0x00, 0x14, 0x28, 0xaa},
2113 {0x00, 0xa5, 0x05, 0xaa},
2114 {0x00, 0xab, 0x07, 0xaa},
2115 {0x00, 0x24, 0x95, 0xaa},
2116 {0x00, 0x25, 0x33, 0xaa},
2117 {0x00, 0x26, 0xe3, 0xaa},
2118 {0x00, 0x9f, 0x88, 0xaa},
2119 {0x00, 0xa0, 0x78, 0xaa},
2120 {0x00, 0x55, 0x90, 0xaa},
2121 {0x00, 0xa1, 0x03, 0xaa},
2122 {0x00, 0xa6, 0xe0, 0xaa},
2123 {0x00, 0xa7, 0xd8, 0xaa},
2124 {0x00, 0xa8, 0xf0, 0xaa},
2125 {0x00, 0xa9, 0x90, 0xaa},
2126 {0x00, 0xaa, 0x14, 0xaa},
2127 {0x00, 0x13, 0xe5, 0xaa},
2128 {0x00, 0x0e, 0x61, 0xaa},
2129 {0x00, 0x0f, 0x4b, 0xaa},
2130 {0x00, 0x16, 0x02, 0xaa},
2131 {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */
2132 {0x00, 0x21, 0x02, 0xaa},
2133 {0x00, 0x22, 0x91, 0xaa},
2134 {0x00, 0x29, 0x07, 0xaa},
2135 {0x00, 0x33, 0x0b, 0xaa},
2136 {0x00, 0x35, 0x0b, 0xaa},
2137 {0x00, 0x37, 0x1d, 0xaa},
2138 {0x00, 0x38, 0x71, 0xaa},
2139 {0x00, 0x39, 0x2a, 0xaa},
2140 {0x00, 0x3c, 0x78, 0xaa},
2141 {0x00, 0x4d, 0x40, 0xaa},
2142 {0x00, 0x4e, 0x20, 0xaa},
2143 {0x00, 0x74, 0x19, 0xaa},
2144 {0x00, 0x8d, 0x4f, 0xaa},
2145 {0x00, 0x8e, 0x00, 0xaa},
2146 {0x00, 0x8f, 0x00, 0xaa},
2147 {0x00, 0x90, 0x00, 0xaa},
2148 {0x00, 0x91, 0x00, 0xaa},
2149 {0x00, 0x96, 0x00, 0xaa},
2150 {0x00, 0x9a, 0x80, 0xaa},
2151 {0x00, 0xb0, 0x84, 0xaa},
2152 {0x00, 0xb1, 0x0c, 0xaa},
2153 {0x00, 0xb2, 0x0e, 0xaa},
2154 {0x00, 0xb3, 0x82, 0xaa},
2155 {0x00, 0xb8, 0x0a, 0xaa},
2156 {0x00, 0x43, 0x14, 0xaa},
2157 {0x00, 0x44, 0xf0, 0xaa},
2158 {0x00, 0x45, 0x45, 0xaa},
2159 {0x00, 0x46, 0x63, 0xaa},
2160 {0x00, 0x47, 0x2d, 0xaa},
2161 {0x00, 0x48, 0x46, 0xaa},
2162 {0x00, 0x59, 0x88, 0xaa},
2163 {0x00, 0x5a, 0xa0, 0xaa},
2164 {0x00, 0x5b, 0xc6, 0xaa},
2165 {0x00, 0x5c, 0x7d, 0xaa},
2166 {0x00, 0x5d, 0x5f, 0xaa},
2167 {0x00, 0x5e, 0x19, 0xaa},
2168 {0x00, 0x6c, 0x0a, 0xaa},
2169 {0x00, 0x6d, 0x55, 0xaa},
2170 {0x00, 0x6e, 0x11, 0xaa},
2171 {0x00, 0x6f, 0x9e, 0xaa},
2172 {0x00, 0x69, 0x00, 0xaa},
2173 {0x00, 0x6a, 0x40, 0xaa},
2174 {0x00, 0x01, 0x40, 0xaa},
2175 {0x00, 0x02, 0x40, 0xaa},
2176 {0x00, 0x13, 0xe7, 0xaa},
2177 {0x00, 0x5f, 0xf0, 0xaa},
2178 {0x00, 0x60, 0xf0, 0xaa},
2179 {0x00, 0x61, 0xf0, 0xaa},
2180 {0x00, 0x27, 0xa0, 0xaa},
2181 {0x00, 0x28, 0x80, 0xaa},
2182 {0x00, 0x2c, 0x90, 0xaa},
2183 {0x00, 0x4f, 0x66, 0xaa},
2184 {0x00, 0x50, 0x66, 0xaa},
2185 {0x00, 0x51, 0x00, 0xaa},
2186 {0x00, 0x52, 0x22, 0xaa},
2187 {0x00, 0x53, 0x5e, 0xaa},
2188 {0x00, 0x54, 0x80, 0xaa},
2189 {0x00, 0x58, 0x9e, 0xaa},
2190 {0x00, 0x41, 0x08, 0xaa},
2191 {0x00, 0x3f, 0x00, 0xaa},
2192 {0x00, 0x75, 0x85, 0xaa},
2193 {0x00, 0x76, 0xe1, 0xaa},
2194 {0x00, 0x4c, 0x00, 0xaa},
2195 {0x00, 0x77, 0x0a, 0xaa},
2196 {0x00, 0x3d, 0x88, 0xaa},
2197 {0x00, 0x4b, 0x09, 0xaa},
2198 {0x00, 0xc9, 0x60, 0xaa},
2199 {0x00, 0x41, 0x38, 0xaa},
2200 {0x00, 0x62, 0x30, 0xaa},
2201 {0x00, 0x63, 0x30, 0xaa},
2202 {0x00, 0x64, 0x08, 0xaa},
2203 {0x00, 0x94, 0x07, 0xaa},
2204 {0x00, 0x95, 0x0b, 0xaa},
2205 {0x00, 0x65, 0x00, 0xaa},
2206 {0x00, 0x66, 0x05, 0xaa},
2207 {0x00, 0x56, 0x50, 0xaa},
2208 {0x00, 0x34, 0x11, 0xaa},
2209 {0x00, 0xa4, 0x88, 0xaa},
2210 {0x00, 0x96, 0x00, 0xaa},
2211 {0x00, 0x97, 0x30, 0xaa},
2212 {0x00, 0x98, 0x20, 0xaa},
2213 {0x00, 0x99, 0x30, 0xaa},
2214 {0x00, 0x9a, 0x84, 0xaa},
2215 {0x00, 0x9b, 0x29, 0xaa},
2216 {0x00, 0x9c, 0x03, 0xaa},
2217 {0x00, 0x78, 0x04, 0xaa},
2218 {0x00, 0x79, 0x01, 0xaa},
2219 {0x00, 0xc8, 0xf0, 0xaa},
2220 {0x00, 0x79, 0x0f, 0xaa},
2221 {0x00, 0xc8, 0x00, 0xaa},
2222 {0x00, 0x79, 0x10, 0xaa},
2223 {0x00, 0xc8, 0x7e, 0xaa},
2224 {0x00, 0x79, 0x0a, 0xaa},
2225 {0x00, 0xc8, 0x80, 0xaa},
2226 {0x00, 0x79, 0x0b, 0xaa},
2227 {0x00, 0xc8, 0x01, 0xaa},
2228 {0x00, 0x79, 0x0c, 0xaa},
2229 {0x00, 0xc8, 0x0f, 0xaa},
2230 {0x00, 0x79, 0x0d, 0xaa},
2231 {0x00, 0xc8, 0x20, 0xaa},
2232 {0x00, 0x79, 0x09, 0xaa},
2233 {0x00, 0xc8, 0x80, 0xaa},
2234 {0x00, 0x79, 0x02, 0xaa},
2235 {0x00, 0xc8, 0xc0, 0xaa},
2236 {0x00, 0x79, 0x03, 0xaa},
2237 {0x00, 0xc8, 0x40, 0xaa},
2238 {0x00, 0x79, 0x05, 0xaa},
2239 {0x00, 0xc8, 0x30, 0xaa},
2240 {0x00, 0x79, 0x26, 0xaa},
2241 {0x00, 0x11, 0x40, 0xaa},
2242 {0x00, 0x3a, 0x04, 0xaa},
2243 {0x00, 0x12, 0x00, 0xaa},
2244 {0x00, 0x40, 0xc0, 0xaa},
2245 {0x00, 0x8c, 0x00, 0xaa},
2246 {0x00, 0x17, 0x14, 0xaa},
2247 {0x00, 0x18, 0x02, 0xaa},
2248 {0x00, 0x32, 0x92, 0xaa},
2249 {0x00, 0x19, 0x02, 0xaa},
2250 {0x00, 0x1a, 0x7a, 0xaa},
2251 {0x00, 0x03, 0x0a, 0xaa},
2252 {0x00, 0x0c, 0x00, 0xaa},
2253 {0x00, 0x3e, 0x00, 0xaa},
2254 {0x00, 0x70, 0x3a, 0xaa},
2255 {0x00, 0x71, 0x35, 0xaa},
2256 {0x00, 0x72, 0x11, 0xaa},
2257 {0x00, 0x73, 0xf0, 0xaa},
2258 {0x00, 0xa2, 0x02, 0xaa},
2259 {0x00, 0xb1, 0x00, 0xaa},
2260 {0x00, 0xb1, 0x0c, 0xaa},
2261 {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */
2262 {0x00, 0xaa, 0x14, 0xaa},
2263 {0x00, 0x24, 0x80, 0xaa},
2264 {0x00, 0x25, 0x74, 0xaa},
2265 {0x00, 0x26, 0xd3, 0xaa},
2266 {0x00, 0x0d, 0x00, 0xaa},
2267 {0x00, 0x14, 0x18, 0xaa},
2268 {0x00, 0x9d, 0x99, 0xaa},
2269 {0x00, 0x9e, 0x7f, 0xaa},
2270 {0x00, 0x64, 0x08, 0xaa},
2271 {0x00, 0x94, 0x07, 0xaa},
2272 {0x00, 0x95, 0x06, 0xaa},
2273 {0x00, 0x66, 0x05, 0xaa},
2274 {0x00, 0x41, 0x08, 0xaa},
2275 {0x00, 0x3f, 0x00, 0xaa},
2276 {0x00, 0x75, 0x07, 0xaa},
2277 {0x00, 0x76, 0xe1, 0xaa},
2278 {0x00, 0x4c, 0x00, 0xaa},
2279 {0x00, 0x77, 0x00, 0xaa},
2280 {0x00, 0x3d, 0xc2, 0xaa},
2281 {0x00, 0x4b, 0x09, 0xaa},
2282 {0x00, 0xc9, 0x60, 0xaa},
2283 {0x00, 0x41, 0x38, 0xaa},
2284 {0xbc, 0x02, 0x18, 0xcc},
2285 {0xbc, 0x03, 0x50, 0xcc},
2286 {0xbc, 0x04, 0x18, 0xcc},
2287 {0xbc, 0x05, 0x00, 0xcc},
2288 {0xbc, 0x06, 0x00, 0xcc},
2289 {0xbc, 0x08, 0x30, 0xcc},
2290 {0xbc, 0x09, 0x40, 0xcc},
2291 {0xbc, 0x0a, 0x10, 0xcc},
2292 {0xbc, 0x0b, 0x00, 0xcc},
2293 {0xbc, 0x0c, 0x00, 0xcc},
2294 {0xbf, 0xc0, 0x26, 0xcc},
2295 {0xbf, 0xc1, 0x02, 0xcc},
2296 {0xbf, 0xcc, 0x04, 0xcc},
2297 {0xb3, 0x5c, 0x01, 0xcc},
2298 {0xb3, 0x01, 0x45, 0xcc},
2299 {0x00, 0x77, 0x05, 0xaa},
2300 {},
2301};
2302
2303/* PO1200 - values from usbvm326.inf and ms-win trace */
2304static const u8 po1200_gamma[17] = {
2305 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
2306 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
2307};
2308static const u8 po1200_matrix[9] = {
2309 0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e
2310};
2311static const u8 po1200_initVGA_data[][4] = {
2312 {0xb0, 0x03, 0x19, 0xcc}, /* reset? */
2313 {0xb0, 0x03, 0x19, 0xcc},
2314/* {0x00, 0x00, 0x33, 0xdd}, */
2315 {0xb0, 0x04, 0x02, 0xcc},
2316 {0xb0, 0x02, 0x02, 0xcc},
2317 {0xb3, 0x5d, 0x00, 0xcc},
2318 {0xb3, 0x01, 0x01, 0xcc},
2319 {0xb3, 0x00, 0x64, 0xcc},
2320 {0xb3, 0x00, 0x65, 0xcc},
2321 {0xb3, 0x05, 0x01, 0xcc},
2322 {0xb3, 0x06, 0x01, 0xcc},
2323 {0xb3, 0x5c, 0x01, 0xcc},
2324 {0xb3, 0x08, 0x01, 0xcc},
2325 {0xb3, 0x09, 0x0c, 0xcc},
2326 {0xb3, 0x00, 0x67, 0xcc},
2327 {0xb3, 0x02, 0xb2, 0xcc},
2328 {0xb3, 0x03, 0x18, 0xcc},
2329 {0xb3, 0x04, 0x15, 0xcc},
2330 {0xb3, 0x20, 0x00, 0xcc},
2331 {0xb3, 0x21, 0x00, 0xcc},
2332 {0xb3, 0x22, 0x02, 0xcc},
2333 {0xb3, 0x23, 0x58, 0xcc},
2334 {0xb3, 0x14, 0x00, 0xcc},
2335 {0xb3, 0x15, 0x00, 0xcc},
2336 {0xb3, 0x16, 0x03, 0xcc},
2337 {0xb3, 0x17, 0x1f, 0xcc},
2338 {0xbc, 0x00, 0x71, 0xcc},
2339 {0xbc, 0x01, 0x01, 0xcc},
2340 {0xb0, 0x54, 0x13, 0xcc},
2341 {0xb3, 0x00, 0x67, 0xcc},
2342 {0xb3, 0x34, 0x01, 0xcc},
2343 {0xb3, 0x35, 0xdc, 0xcc}, /* i2c add: 5c */
2344 {0x00, 0x03, 0x00, 0xaa},
2345 {0x00, 0x12, 0x05, 0xaa},
2346 {0x00, 0x13, 0x02, 0xaa},
2347 {0x00, 0x1e, 0xc6, 0xaa}, /* h/v flip */
2348 {0x00, 0x21, 0x00, 0xaa},
2349 {0x00, 0x25, 0x02, 0xaa},
2350 {0x00, 0x3c, 0x4f, 0xaa},
2351 {0x00, 0x3f, 0xe0, 0xaa},
2352 {0x00, 0x42, 0xff, 0xaa},
2353 {0x00, 0x45, 0x34, 0xaa},
2354 {0x00, 0x55, 0xfe, 0xaa},
2355 {0x00, 0x59, 0xd3, 0xaa},
2356 {0x00, 0x5e, 0x04, 0xaa},
2357 {0x00, 0x61, 0xb8, 0xaa}, /* sharpness */
2358 {0x00, 0x62, 0x02, 0xaa},
2359 {0x00, 0xa7, 0x31, 0xaa},
2360 {0x00, 0xa9, 0x66, 0xaa},
2361 {0x00, 0xb0, 0x00, 0xaa},
2362 {0x00, 0xb1, 0x00, 0xaa},
2363 {0x00, 0xb3, 0x11, 0xaa},
2364 {0x00, 0xb6, 0x26, 0xaa},
2365 {0x00, 0xb7, 0x20, 0xaa},
2366 {0x00, 0xba, 0x04, 0xaa},
2367 {0x00, 0x88, 0x42, 0xaa},
2368 {0x00, 0x89, 0x9a, 0xaa},
2369 {0x00, 0x8a, 0x88, 0xaa},
2370 {0x00, 0x8b, 0x8e, 0xaa},
2371 {0x00, 0x8c, 0x3e, 0xaa},
2372 {0x00, 0x8d, 0x90, 0xaa},
2373 {0x00, 0x8e, 0x87, 0xaa},
2374 {0x00, 0x8f, 0x96, 0xaa},
2375 {0x00, 0x90, 0x3d, 0xaa},
2376 {0x00, 0x64, 0x00, 0xaa},
2377 {0x00, 0x65, 0x10, 0xaa},
2378 {0x00, 0x66, 0x20, 0xaa},
2379 {0x00, 0x67, 0x2b, 0xaa},
2380 {0x00, 0x68, 0x36, 0xaa},
2381 {0x00, 0x69, 0x49, 0xaa},
2382 {0x00, 0x6a, 0x5a, 0xaa},
2383 {0x00, 0x6b, 0x7f, 0xaa},
2384 {0x00, 0x6c, 0x9b, 0xaa},
2385 {0x00, 0x6d, 0xba, 0xaa},
2386 {0x00, 0x6e, 0xd4, 0xaa},
2387 {0x00, 0x6f, 0xea, 0xaa},
2388 {0x00, 0x70, 0x00, 0xaa},
2389 {0x00, 0x71, 0x10, 0xaa},
2390 {0x00, 0x72, 0x20, 0xaa},
2391 {0x00, 0x73, 0x2b, 0xaa},
2392 {0x00, 0x74, 0x36, 0xaa},
2393 {0x00, 0x75, 0x49, 0xaa},
2394 {0x00, 0x76, 0x5a, 0xaa},
2395 {0x00, 0x77, 0x7f, 0xaa},
2396 {0x00, 0x78, 0x9b, 0xaa},
2397 {0x00, 0x79, 0xba, 0xaa},
2398 {0x00, 0x7a, 0xd4, 0xaa},
2399 {0x00, 0x7b, 0xea, 0xaa},
2400 {0x00, 0x7c, 0x00, 0xaa},
2401 {0x00, 0x7d, 0x10, 0xaa},
2402 {0x00, 0x7e, 0x20, 0xaa},
2403 {0x00, 0x7f, 0x2b, 0xaa},
2404 {0x00, 0x80, 0x36, 0xaa},
2405 {0x00, 0x81, 0x49, 0xaa},
2406 {0x00, 0x82, 0x5a, 0xaa},
2407 {0x00, 0x83, 0x7f, 0xaa},
2408 {0x00, 0x84, 0x9b, 0xaa},
2409 {0x00, 0x85, 0xba, 0xaa},
2410 {0x00, 0x86, 0xd4, 0xaa},
2411 {0x00, 0x87, 0xea, 0xaa},
2412 {0x00, 0x57, 0x2a, 0xaa},
2413 {0x00, 0x03, 0x01, 0xaa},
2414 {0x00, 0x04, 0x10, 0xaa},
2415 {0x00, 0x05, 0x10, 0xaa},
2416 {0x00, 0x06, 0x10, 0xaa},
2417 {0x00, 0x07, 0x10, 0xaa},
2418 {0x00, 0x08, 0x13, 0xaa},
2419 {0x00, 0x0a, 0x00, 0xaa},
2420 {0x00, 0x0b, 0x10, 0xaa},
2421 {0x00, 0x0c, 0x20, 0xaa},
2422 {0x00, 0x0d, 0x18, 0xaa},
2423 {0x00, 0x22, 0x01, 0xaa},
2424 {0x00, 0x23, 0x60, 0xaa},
2425 {0x00, 0x25, 0x08, 0xaa},
2426 {0x00, 0x26, 0x82, 0xaa},
2427 {0x00, 0x2e, 0x0f, 0xaa},
2428 {0x00, 0x2f, 0x1e, 0xaa},
2429 {0x00, 0x30, 0x2d, 0xaa},
2430 {0x00, 0x31, 0x3c, 0xaa},
2431 {0x00, 0x32, 0x4b, 0xaa},
2432 {0x00, 0x33, 0x5a, 0xaa},
2433 {0x00, 0x34, 0x69, 0xaa},
2434 {0x00, 0x35, 0x78, 0xaa},
2435 {0x00, 0x36, 0x87, 0xaa},
2436 {0x00, 0x37, 0x96, 0xaa},
2437 {0x00, 0x38, 0xa5, 0xaa},
2438 {0x00, 0x39, 0xb4, 0xaa},
2439 {0x00, 0x3a, 0xc3, 0xaa},
2440 {0x00, 0x3b, 0xd2, 0xaa},
2441 {0x00, 0x3c, 0xe1, 0xaa},
2442 {0x00, 0x3e, 0xff, 0xaa},
2443 {0x00, 0x3f, 0xff, 0xaa},
2444 {0x00, 0x40, 0xff, 0xaa},
2445 {0x00, 0x41, 0xff, 0xaa},
2446 {0x00, 0x42, 0xff, 0xaa},
2447 {0x00, 0x43, 0xff, 0xaa},
2448 {0x00, 0x03, 0x00, 0xaa},
2449 {0x00, 0x03, 0x00, 0xaa},
2450 {0x00, 0x20, 0xc4, 0xaa},
2451 {0x00, 0x13, 0x03, 0xaa},
2452 {0x00, 0x3c, 0x50, 0xaa},
2453 {0x00, 0x61, 0x6a, 0xaa}, /* sharpness? */
2454 {0x00, 0x51, 0x5b, 0xaa},
2455 {0x00, 0x52, 0x91, 0xaa},
2456 {0x00, 0x53, 0x4c, 0xaa},
2457 {0x00, 0x54, 0x50, 0xaa},
2458 {0x00, 0x56, 0x02, 0xaa},
2459 {0xb6, 0x00, 0x00, 0xcc},
2460 {0xb6, 0x03, 0x03, 0xcc},
2461 {0xb6, 0x02, 0x20, 0xcc},
2462 {0xb6, 0x05, 0x02, 0xcc},
2463 {0xb6, 0x04, 0x58, 0xcc},
2464 {0xb6, 0x12, 0xf8, 0xcc},
2465 {0xb6, 0x13, 0x21, 0xcc},
2466 {0xb6, 0x18, 0x03, 0xcc},
2467 {0xb6, 0x17, 0xa9, 0xcc},
2468 {0xb6, 0x16, 0x80, 0xcc},
2469 {0xb6, 0x22, 0x12, 0xcc},
2470 {0xb6, 0x23, 0x0b, 0xcc},
2471 {0xbf, 0xc0, 0x39, 0xcc},
2472 {0xbf, 0xc1, 0x04, 0xcc},
2473 {0xbf, 0xcc, 0x00, 0xcc},
2474 {0xb8, 0x06, 0x20, 0xcc},
2475 {0xb8, 0x07, 0x03, 0xcc},
2476 {0xb8, 0x08, 0x58, 0xcc},
2477 {0xb8, 0x09, 0x02, 0xcc},
2478 {0xb3, 0x01, 0x41, 0xcc},
2479 {0x00, 0x03, 0x00, 0xaa},
2480 {0x00, 0xd9, 0x0f, 0xaa},
2481 {0x00, 0xda, 0xaa, 0xaa},
2482 {0x00, 0xd9, 0x10, 0xaa},
2483 {0x00, 0xda, 0xaa, 0xaa},
2484 {0x00, 0xd9, 0x11, 0xaa},
2485 {0x00, 0xda, 0x00, 0xaa},
2486 {0x00, 0xd9, 0x12, 0xaa},
2487 {0x00, 0xda, 0xff, 0xaa},
2488 {0x00, 0xd9, 0x13, 0xaa},
2489 {0x00, 0xda, 0xff, 0xaa},
2490 {0x00, 0xe8, 0x11, 0xaa},
2491 {0x00, 0xe9, 0x12, 0xaa},
2492 {0x00, 0xea, 0x5c, 0xaa},
2493 {0x00, 0xeb, 0xff, 0xaa},
2494 {0x00, 0xd8, 0x80, 0xaa},
2495 {0x00, 0xe6, 0x02, 0xaa},
2496 {0x00, 0xd6, 0x40, 0xaa},
2497 {0x00, 0xe3, 0x05, 0xaa},
2498 {0x00, 0xe0, 0x40, 0xaa},
2499 {0x00, 0xde, 0x03, 0xaa},
2500 {0x00, 0xdf, 0x03, 0xaa},
2501 {0x00, 0xdb, 0x02, 0xaa},
2502 {0x00, 0xdc, 0x00, 0xaa},
2503 {0x00, 0xdd, 0x03, 0xaa},
2504 {0x00, 0xe1, 0x08, 0xaa},
2505 {0x00, 0xe2, 0x01, 0xaa},
2506 {0x00, 0xd6, 0x40, 0xaa},
2507 {0x00, 0xe4, 0x40, 0xaa},
2508 {0x00, 0xa8, 0x8f, 0xaa},
2509 {0x00, 0xb4, 0x16, 0xaa},
2510 {0xb0, 0x02, 0x06, 0xcc},
2511 {0xb0, 0x18, 0x06, 0xcc},
2512 {0xb0, 0x19, 0x06, 0xcc},
2513 {0xb3, 0x5d, 0x18, 0xcc},
2514 {0xb3, 0x05, 0x00, 0xcc},
2515 {0xb3, 0x06, 0x00, 0xcc},
2516 {0x00, 0xb4, 0x0e, 0xaa},
2517 {0x00, 0xb5, 0x49, 0xaa},
2518 {0x00, 0xb6, 0x1c, 0xaa},
2519 {0x00, 0xb7, 0x96, 0xaa},
2520/* end of usbvm326.inf - start of ms-win trace */
2521 {0xb6, 0x12, 0xf8, 0xcc},
2522 {0xb6, 0x13, 0x3d, 0xcc},
2523/*read b306*/
2524 {0x00, 0x03, 0x00, 0xaa},
2525 {0x00, 0x1a, 0x09, 0xaa},
2526 {0x00, 0x1b, 0x8a, 0xaa},
2527/*read b827*/
2528 {0xb8, 0x27, 0x00, 0xcc},
2529 {0xb8, 0x26, 0x60, 0xcc},
2530 {0xb8, 0x26, 0x60, 0xcc},
2531/*gamma - to do?*/
2532 {0x00, 0x03, 0x00, 0xaa},
2533 {0x00, 0xae, 0x84, 0xaa},
2534/*gamma again*/
2535 {0x00, 0x03, 0x00, 0xaa},
2536 {0x00, 0x96, 0xa0, 0xaa},
2537/*matrix*/
2538 {0x00, 0x03, 0x00, 0xaa},
2539 {0x00, 0x91, 0x35, 0xaa},
2540 {0x00, 0x92, 0x22, 0xaa},
2541/*gamma*/
2542 {0x00, 0x03, 0x00, 0xaa},
2543 {0x00, 0x95, 0x85, 0xaa},
2544/*matrix*/
2545 {0x00, 0x03, 0x00, 0xaa},
2546 {0x00, 0x4d, 0x20, 0xaa},
2547 {0xb8, 0x22, 0x40, 0xcc},
2548 {0xb8, 0x23, 0x40, 0xcc},
2549 {0xb8, 0x24, 0x40, 0xcc},
2550 {0xb8, 0x81, 0x09, 0xcc},
2551 {0x00, 0x00, 0x64, 0xdd},
2552 {0x00, 0x03, 0x01, 0xaa},
2553/*read 46*/
2554 {0x00, 0x46, 0x3c, 0xaa},
2555 {0x00, 0x03, 0x00, 0xaa},
2556 {0x00, 0x16, 0x40, 0xaa},
2557 {0x00, 0x17, 0x40, 0xaa},
2558 {0x00, 0x18, 0x40, 0xaa},
2559 {0x00, 0x19, 0x41, 0xaa},
2560 {0x00, 0x03, 0x01, 0xaa},
2561 {0x00, 0x46, 0x3c, 0xaa},
2562 {0x00, 0x00, 0x18, 0xdd},
2563/*read bfff*/
2564 {0x00, 0x03, 0x00, 0xaa},
2565 {0x00, 0xb4, 0x1c, 0xaa},
2566 {0x00, 0xb5, 0x92, 0xaa},
2567 {0x00, 0xb6, 0x39, 0xaa},
2568 {0x00, 0xb7, 0x24, 0xaa},
2569/*write 89 0400 1415*/
2570 {}
2571};
2572
2573static const u8 poxxxx_init_common[][4] = {
2574 {0xb3, 0x00, 0x04, 0xcc},
2575 {0x00, 0x00, 0x10, 0xdd},
2576 {0xb3, 0x00, 0x64, 0xcc},
2577 {0x00, 0x00, 0x10, 0xdd},
2578 {0xb3, 0x00, 0x65, 0xcc},
2579 {0x00, 0x00, 0x10, 0xdd},
2580 {0xb3, 0x00, 0x67, 0xcc},
2581 {0xb0, 0x03, 0x09, 0xcc},
2582 {0xb3, 0x05, 0x00, 0xcc},
2583 {0xb3, 0x06, 0x00, 0xcc},
2584 {0xb3, 0x5c, 0x01, 0xcc},
2585 {0xb3, 0x08, 0x01, 0xcc},
2586 {0xb3, 0x09, 0x0c, 0xcc},
2587 {0xb3, 0x34, 0x01, 0xcc},
2588 {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */
2589 {0xb3, 0x02, 0xb0, 0xcc},
2590 {0xb3, 0x03, 0x18, 0xcc},
2591 {0xb3, 0x04, 0x15, 0xcc},
2592 {0xb3, 0x20, 0x00, 0xcc},
2593 {0xb3, 0x21, 0x00, 0xcc},
2594 {0xb3, 0x22, 0x04, 0xcc}, /* sensor height = 1024 */
2595 {0xb3, 0x23, 0x00, 0xcc},
2596 {0xb3, 0x14, 0x00, 0xcc},
2597 {0xb3, 0x15, 0x00, 0xcc},
2598 {0xb3, 0x16, 0x04, 0xcc}, /* sensor width = 1280 */
2599 {0xb3, 0x17, 0xff, 0xcc},
2600 {0xb3, 0x2c, 0x03, 0xcc},
2601 {0xb3, 0x2d, 0x56, 0xcc},
2602 {0xb3, 0x2e, 0x02, 0xcc},
2603 {0xb3, 0x2f, 0x0a, 0xcc},
2604 {0xb3, 0x40, 0x00, 0xcc},
2605 {0xb3, 0x41, 0x34, 0xcc},
2606 {0xb3, 0x42, 0x01, 0xcc},
2607 {0xb3, 0x43, 0xe0, 0xcc},
2608 {0xbc, 0x00, 0x71, 0xcc},
2609 {0xbc, 0x01, 0x01, 0xcc},
2610 {0xb3, 0x01, 0x41, 0xcc},
2611 {0xb3, 0x4d, 0x00, 0xcc},
2612 {0x00, 0x0b, 0x2a, 0xaa},
2613 {0x00, 0x0e, 0x03, 0xaa},
2614 {0x00, 0x0f, 0xea, 0xaa},
2615 {0x00, 0x12, 0x08, 0xaa},
2616 {0x00, 0x1e, 0x06, 0xaa},
2617 {0x00, 0x21, 0x00, 0xaa},
2618 {0x00, 0x31, 0x1f, 0xaa},
2619 {0x00, 0x33, 0x38, 0xaa},
2620 {0x00, 0x36, 0xc0, 0xaa},
2621 {0x00, 0x37, 0xc8, 0xaa},
2622 {0x00, 0x3b, 0x36, 0xaa},
2623 {0x00, 0x4b, 0xfe, 0xaa},
2624 {0x00, 0x4d, 0x2e, 0xaa},
2625 {0x00, 0x51, 0x1c, 0xaa},
2626 {0x00, 0x52, 0x01, 0xaa},
2627 {0x00, 0x55, 0x0a, 0xaa},
2628 {0x00, 0x56, 0x0a, 0xaa},
2629 {0x00, 0x57, 0x07, 0xaa},
2630 {0x00, 0x58, 0x07, 0xaa},
2631 {0x00, 0x59, 0x04, 0xaa},
2632 {0x00, 0x70, 0x68, 0xaa},
2633 {0x00, 0x71, 0x04, 0xaa},
2634 {0x00, 0x72, 0x10, 0xaa},
2635 {0x00, 0x80, 0x71, 0xaa},
2636 {0x00, 0x81, 0x08, 0xaa},
2637 {0x00, 0x82, 0x00, 0xaa},
2638 {0x00, 0x83, 0x55, 0xaa},
2639 {0x00, 0x84, 0x06, 0xaa},
2640 {0x00, 0x85, 0x06, 0xaa},
2641 {0x00, 0x8b, 0x25, 0xaa},
2642 {0x00, 0x8c, 0x00, 0xaa},
2643 {0x00, 0x8d, 0x86, 0xaa},
2644 {0x00, 0x8e, 0x82, 0xaa},
2645 {0x00, 0x8f, 0x2d, 0xaa},
2646 {0x00, 0x90, 0x8b, 0xaa},
2647 {0x00, 0x91, 0x81, 0xaa},
2648 {0x00, 0x92, 0x81, 0xaa},
2649 {0x00, 0x93, 0x23, 0xaa},
2650 {0x00, 0xa3, 0x2a, 0xaa},
2651 {0x00, 0xa4, 0x03, 0xaa},
2652 {0x00, 0xa5, 0xea, 0xaa},
2653 {0x00, 0xb0, 0x68, 0xaa},
2654 {0x00, 0xbc, 0x04, 0xaa},
2655 {0x00, 0xbe, 0x3b, 0xaa},
2656 {0x00, 0x4e, 0x40, 0xaa},
2657 {0x00, 0x06, 0x04, 0xaa},
2658 {0x00, 0x07, 0x03, 0xaa},
2659 {0x00, 0xcd, 0x18, 0xaa},
2660 {0x00, 0x28, 0x03, 0xaa},
2661 {0x00, 0x29, 0xef, 0xaa},
2662/* reinit on alt 2 (qvga) or alt7 (vga) */
2663 {0xb3, 0x05, 0x00, 0xcc},
2664 {0xb3, 0x06, 0x00, 0xcc},
2665 {0xb8, 0x00, 0x01, 0xcc},
2666
2667 {0x00, 0x1d, 0x85, 0xaa},
2668 {0x00, 0x1e, 0xc6, 0xaa},
2669 {0x00, 0x00, 0x40, 0xdd},
2670 {0x00, 0x1d, 0x05, 0xaa},
2671 {}
2672};
2673static const u8 poxxxx_gamma[][4] = {
2674 {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */
2675 {0x00, 0x73, 0x00, 0xaa},
2676 {0x00, 0x74, 0x0a, 0xaa},
2677 {0x00, 0x75, 0x16, 0xaa},
2678 {0x00, 0x76, 0x25, 0xaa},
2679 {0x00, 0x77, 0x34, 0xaa},
2680 {0x00, 0x78, 0x49, 0xaa},
2681 {0x00, 0x79, 0x5a, 0xaa},
2682 {0x00, 0x7a, 0x7f, 0xaa},
2683 {0x00, 0x7b, 0x9b, 0xaa},
2684 {0x00, 0x7c, 0xba, 0xaa},
2685 {0x00, 0x7d, 0xd4, 0xaa},
2686 {0x00, 0x7e, 0xea, 0xaa},
2687
2688 {0x00, 0xd6, 0x62, 0xaa}, /* gamma 1 */
2689 {0x00, 0x73, 0x00, 0xaa},
2690 {0x00, 0x74, 0x0a, 0xaa},
2691 {0x00, 0x75, 0x16, 0xaa},
2692 {0x00, 0x76, 0x25, 0xaa},
2693 {0x00, 0x77, 0x34, 0xaa},
2694 {0x00, 0x78, 0x49, 0xaa},
2695 {0x00, 0x79, 0x5a, 0xaa},
2696 {0x00, 0x7a, 0x7f, 0xaa},
2697 {0x00, 0x7b, 0x9b, 0xaa},
2698 {0x00, 0x7c, 0xba, 0xaa},
2699 {0x00, 0x7d, 0xd4, 0xaa},
2700 {0x00, 0x7e, 0xea, 0xaa},
2701
2702 {0x00, 0xd6, 0xa2, 0xaa}, /* gamma 2 */
2703 {0x00, 0x73, 0x00, 0xaa},
2704 {0x00, 0x74, 0x0a, 0xaa},
2705 {0x00, 0x75, 0x16, 0xaa},
2706 {0x00, 0x76, 0x25, 0xaa},
2707 {0x00, 0x77, 0x34, 0xaa},
2708 {0x00, 0x78, 0x49, 0xaa},
2709 {0x00, 0x79, 0x5a, 0xaa},
2710 {0x00, 0x7a, 0x7f, 0xaa},
2711 {0x00, 0x7b, 0x9b, 0xaa},
2712 {0x00, 0x7c, 0xba, 0xaa},
2713 {0x00, 0x7d, 0xd4, 0xaa},
2714 {0x00, 0x7e, 0xea, 0xaa},
2715 {}
2716};
2717static const u8 poxxxx_init_start_3[][4] = {
2718 {0x00, 0xb8, 0x28, 0xaa},
2719 {0x00, 0xb9, 0x1e, 0xaa},
2720 {0x00, 0xb6, 0x14, 0xaa},
2721 {0x00, 0xb7, 0x0f, 0xaa},
2722 {0x00, 0x5c, 0x10, 0xaa},
2723 {0x00, 0x5d, 0x18, 0xaa},
2724 {0x00, 0x5e, 0x24, 0xaa},
2725 {0x00, 0x5f, 0x24, 0xaa},
2726 {0x00, 0x86, 0x1a, 0xaa},
2727 {0x00, 0x60, 0x00, 0xaa},
2728 {0x00, 0x61, 0x1b, 0xaa},
2729 {0x00, 0x62, 0x30, 0xaa},
2730 {0x00, 0x63, 0x40, 0xaa},
2731 {0x00, 0x87, 0x1a, 0xaa},
2732 {0x00, 0x64, 0x00, 0xaa},
2733 {0x00, 0x65, 0x08, 0xaa},
2734 {0x00, 0x66, 0x10, 0xaa},
2735 {0x00, 0x67, 0x20, 0xaa},
2736 {0x00, 0x88, 0x10, 0xaa},
2737 {0x00, 0x68, 0x00, 0xaa},
2738 {0x00, 0x69, 0x08, 0xaa},
2739 {0x00, 0x6a, 0x0f, 0xaa},
2740 {0x00, 0x6b, 0x0f, 0xaa},
2741 {0x00, 0x89, 0x07, 0xaa},
2742 {0x00, 0xd5, 0x4c, 0xaa},
2743 {0x00, 0x0a, 0x00, 0xaa},
2744 {0x00, 0x0b, 0x2a, 0xaa},
2745 {0x00, 0x0e, 0x03, 0xaa},
2746 {0x00, 0x0f, 0xea, 0xaa},
2747 {0x00, 0xa2, 0x00, 0xaa},
2748 {0x00, 0xa3, 0x2a, 0xaa},
2749 {0x00, 0xa4, 0x03, 0xaa},
2750 {0x00, 0xa5, 0xea, 0xaa},
2751 {}
2752};
2753static const u8 poxxxx_initVGA[][4] = {
2754 {0x00, 0x20, 0x11, 0xaa},
2755 {0x00, 0x33, 0x38, 0xaa},
2756 {0x00, 0xbb, 0x0d, 0xaa},
2757 {0xb3, 0x22, 0x01, 0xcc}, /* change to 640x480 */
2758 {0xb3, 0x23, 0xe0, 0xcc},
2759 {0xb3, 0x16, 0x02, 0xcc},
2760 {0xb3, 0x17, 0x7f, 0xcc},
2761 {0xb3, 0x02, 0xb0, 0xcc},
2762 {0xb3, 0x06, 0x00, 0xcc},
2763 {0xb3, 0x5c, 0x01, 0xcc},
2764 {0x00, 0x04, 0x06, 0xaa},
2765 {0x00, 0x05, 0x3f, 0xaa},
2766 {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */
2767 {}
2768};
2769static const u8 poxxxx_initQVGA[][4] = {
2770 {0x00, 0x20, 0x33, 0xaa},
2771 {0x00, 0x33, 0x38, 0xaa},
2772 {0x00, 0xbb, 0x0d, 0xaa},
2773 {0xb3, 0x22, 0x00, 0xcc}, /* change to 320x240 */
2774 {0xb3, 0x23, 0xf0, 0xcc},
2775 {0xb3, 0x16, 0x01, 0xcc},
2776 {0xb3, 0x17, 0x3f, 0xcc},
2777 {0xb3, 0x02, 0xb0, 0xcc},
2778 {0xb3, 0x06, 0x01, 0xcc},
2779 {0xb3, 0x5c, 0x00, 0xcc},
2780 {0x00, 0x04, 0x06, 0xaa},
2781 {0x00, 0x05, 0x3f, 0xaa},
2782 {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */
2783 {}
2784};
2785static const u8 poxxxx_init_end_1[][4] = {
2786 {0x00, 0x47, 0x25, 0xaa},
2787 {0x00, 0x48, 0x80, 0xaa},
2788 {0x00, 0x49, 0x1f, 0xaa},
2789 {0x00, 0x4a, 0x40, 0xaa},
2790 {0x00, 0x44, 0x40, 0xaa},
2791 {0x00, 0xab, 0x4a, 0xaa},
2792 {0x00, 0xb1, 0x00, 0xaa},
2793 {0x00, 0xb2, 0x04, 0xaa},
2794 {0x00, 0xb3, 0x08, 0xaa},
2795 {0x00, 0xb4, 0x0b, 0xaa},
2796 {0x00, 0xb5, 0x0d, 0xaa},
2797 {}
2798};
2799static const u8 poxxxx_init_end_2[][4] = {
2800 {0x00, 0x1d, 0x85, 0xaa},
2801 {0x00, 0x1e, 0x06, 0xaa},
2802 {0x00, 0x1d, 0x05, 0xaa},
2803 {}
2804};
2805
2806struct sensor_info {
2807 s8 sensorId;
2808 u8 I2cAdd;
2809 u8 IdAdd;
2810 u16 VpId;
2811 u8 m1;
2812 u8 m2;
2813 u8 op;
2814};
2815
2816/* probe values */
2817static const struct sensor_info vc0321_probe_data[] = {
2818/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
2819/* 0 OV9640 */
2820 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
2821/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
2822 {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
2823/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
2824 {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
2825/* 3 MI1310 */
2826 {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
2827/* 4 MI360 - tested in vc032x_probe_sensor */
2828/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
2829/* 5 7131R */
2830 {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
2831/* 6 OV7649 */
2832 {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
2833/* 7 PAS302BCW */
2834 {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
2835/* 8 OV7660 */
2836 {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
2837/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
2838/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
2839/* 10 PO1030KC */
2840 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
2841/* 11 MI1310_SOC */
2842 {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
2843/* 12 OV9650 */
2844 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
2845/* 13 S5K532 */
2846 {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
2847/* 14 MI360_SOC - ??? */
2848/* 15 PO1200N */
2849 {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
2850/* 16 PO3030K */
2851 {-1, 0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01},
2852/* 17 PO2030 */
2853 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
2854/* ?? */
2855 {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
2856 {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
2857};
2858static const struct sensor_info vc0323_probe_data[] = {
2859/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
2860/* 0 OV9640 */
2861 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
2862/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
2863 {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
2864/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
2865 {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
2866/* 3 MI1310 */
2867 {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
2868/* 4 MI360 - tested in vc032x_probe_sensor */
2869/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
2870/* 5 7131R */
2871 {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
2872/* 6 OV7649 */
2873 {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
2874/* 7 PAS302BCW */
2875 {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
2876/* 8 OV7660 */
2877 {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
2878/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
2879/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
2880/* 10 PO1030KC */
2881 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
2882/* 11 MI1310_SOC */
2883 {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
2884/* 12 OV9650 */
2885 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
2886/* 13 S5K532 */
2887 {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
2888/* 14 MI360_SOC - ??? */
2889/* 15 PO1200N */
2890 {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
2891/* 16 ?? */
2892 {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
2893/* 17 PO2030 */
2894 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
2895/* ?? */
2896 {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
2897 {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
2898/*fixme: not in the ms-win probe - may be found before? */
2899 {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
2900};
2901
2902/* read 'len' bytes in gspca_dev->usb_buf */
2903static void reg_r_i(struct gspca_dev *gspca_dev,
2904 u16 req,
2905 u16 index,
2906 u16 len)
2907{
2908 int ret;
2909
2910 if (gspca_dev->usb_err < 0)
2911 return;
2912 ret = usb_control_msg(gspca_dev->dev,
2913 usb_rcvctrlpipe(gspca_dev->dev, 0),
2914 req,
2915 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2916 1, /* value */
2917 index, gspca_dev->usb_buf, len,
2918 500);
2919 if (ret < 0) {
2920 pr_err("reg_r err %d\n", ret);
2921 gspca_dev->usb_err = ret;
2922 }
2923}
2924static void reg_r(struct gspca_dev *gspca_dev,
2925 u16 req,
2926 u16 index,
2927 u16 len)
2928{
2929 reg_r_i(gspca_dev, req, index, len);
2930#ifdef GSPCA_DEBUG
2931 if (gspca_dev->usb_err < 0)
2932 return;
2933 if (len == 1)
2934 PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index,
2935 gspca_dev->usb_buf[0]);
2936 else
2937 PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph",
2938 req, index, 3, gspca_dev->usb_buf);
2939#endif
2940}
2941
2942static void reg_w_i(struct gspca_dev *gspca_dev,
2943 u16 req,
2944 u16 value,
2945 u16 index)
2946{
2947 int ret;
2948
2949 if (gspca_dev->usb_err < 0)
2950 return;
2951 ret = usb_control_msg(gspca_dev->dev,
2952 usb_sndctrlpipe(gspca_dev->dev, 0),
2953 req,
2954 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2955 value, index, NULL, 0,
2956 500);
2957 if (ret < 0) {
2958 pr_err("reg_w err %d\n", ret);
2959 gspca_dev->usb_err = ret;
2960 }
2961}
2962static void reg_w(struct gspca_dev *gspca_dev,
2963 u16 req,
2964 u16 value,
2965 u16 index)
2966{
2967#ifdef GSPCA_DEBUG
2968 if (gspca_dev->usb_err < 0)
2969 return;
2970 PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
2971#endif
2972 reg_w_i(gspca_dev, req, value, index);
2973}
2974
2975static u16 read_sensor_register(struct gspca_dev *gspca_dev,
2976 u16 address)
2977{
2978 u8 ldata, mdata, hdata;
2979 int retry = 50;
2980
2981 reg_r(gspca_dev, 0xa1, 0xb33f, 1);
2982 if (!(gspca_dev->usb_buf[0] & 0x02)) {
2983 pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
2984 return 0;
2985 }
2986 reg_w(gspca_dev, 0xa0, address, 0xb33a);
2987 reg_w(gspca_dev, 0xa0, 0x02, 0xb339);
2988
2989 do {
2990 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
2991 if (gspca_dev->usb_buf[0] == 0x00)
2992 break;
2993 msleep(40);
2994 } while (--retry >= 0);
2995
2996 reg_r(gspca_dev, 0xa1, 0xb33e, 1);
2997 ldata = gspca_dev->usb_buf[0];
2998 reg_r(gspca_dev, 0xa1, 0xb33d, 1);
2999 mdata = gspca_dev->usb_buf[0];
3000 reg_r(gspca_dev, 0xa1, 0xb33c, 1);
3001 hdata = gspca_dev->usb_buf[0];
3002 if (hdata != 0 && mdata != 0 && ldata != 0)
3003 PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x",
3004 hdata, mdata, ldata);
3005 reg_r(gspca_dev, 0xa1, 0xb334, 1);
3006 if (gspca_dev->usb_buf[0] == 0x02)
3007 return (hdata << 8) + mdata;
3008 return hdata;
3009}
3010
3011static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
3012{
3013 struct sd *sd = (struct sd *) gspca_dev;
3014 int i, n;
3015 u16 value;
3016 const struct sensor_info *ptsensor_info;
3017
3018/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/
3019 if (sd->flags & FL_SAMSUNG) {
3020 reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
3021 reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
3022 /* select the back sensor */
3023 }
3024
3025 reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
3026 PDEBUG(D_PROBE, "vc032%d check sensor header %02x",
3027 sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]);
3028 if (sd->bridge == BRIDGE_VC0321) {
3029 ptsensor_info = vc0321_probe_data;
3030 n = ARRAY_SIZE(vc0321_probe_data);
3031 } else {
3032 ptsensor_info = vc0323_probe_data;
3033 n = ARRAY_SIZE(vc0323_probe_data);
3034 }
3035 for (i = 0; i < n; i++) {
3036 reg_w(gspca_dev, 0xa0, 0x02, 0xb334);
3037 reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300);
3038 reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300);
3039 reg_w(gspca_dev, 0xa0, 0x01, 0xb308);
3040 reg_w(gspca_dev, 0xa0, 0x0c, 0xb309);
3041 reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
3042 reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301);
3043 value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd);
3044 if (value == 0 && ptsensor_info->IdAdd == 0x82)
3045 value = read_sensor_register(gspca_dev, 0x83);
3046 if (value != 0) {
3047 PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
3048 value, i);
3049 if (value == ptsensor_info->VpId)
3050 return ptsensor_info->sensorId;
3051
3052 switch (value) {
3053 case 0x3130:
3054 return SENSOR_PO3130NC;
3055 case 0x7673:
3056 return SENSOR_OV7670;
3057 case 0x8243:
3058 return SENSOR_MI0360;
3059 }
3060 }
3061 ptsensor_info++;
3062 }
3063 return -1;
3064}
3065
3066static void i2c_write(struct gspca_dev *gspca_dev,
3067 u8 reg, const u8 *val,
3068 u8 size) /* 1 or 2 */
3069{
3070 int retry;
3071
3072#ifdef GSPCA_DEBUG
3073 if (gspca_dev->usb_err < 0)
3074 return;
3075 if (size == 1)
3076 PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val);
3077 else
3078 PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]);
3079#endif
3080 reg_r_i(gspca_dev, 0xa1, 0xb33f, 1);
3081/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
3082 reg_w_i(gspca_dev, 0xa0, size, 0xb334);
3083 reg_w_i(gspca_dev, 0xa0, reg, 0xb33a);
3084 reg_w_i(gspca_dev, 0xa0, val[0], 0xb336);
3085 if (size > 1)
3086 reg_w_i(gspca_dev, 0xa0, val[1], 0xb337);
3087 reg_w_i(gspca_dev, 0xa0, 0x01, 0xb339);
3088 retry = 4;
3089 do {
3090 reg_r_i(gspca_dev, 0xa1, 0xb33b, 1);
3091 if (gspca_dev->usb_buf[0] == 0)
3092 break;
3093 msleep(20);
3094 } while (--retry > 0);
3095 if (retry <= 0)
3096 pr_err("i2c_write timeout\n");
3097}
3098
3099static void put_tab_to_reg(struct gspca_dev *gspca_dev,
3100 const u8 *tab, u8 tabsize, u16 addr)
3101{
3102 int j;
3103 u16 ad = addr;
3104
3105 for (j = 0; j < tabsize; j++)
3106 reg_w(gspca_dev, 0xa0, tab[j], ad++);
3107}
3108
3109static void usb_exchange(struct gspca_dev *gspca_dev,
3110 const u8 data[][4])
3111{
3112 int i = 0;
3113
3114 for (;;) {
3115 switch (data[i][3]) {
3116 default:
3117 return;
3118 case 0xcc: /* normal write */
3119 reg_w(gspca_dev, 0xa0, data[i][2],
3120 (data[i][0]) << 8 | data[i][1]);
3121 break;
3122 case 0xaa: /* i2c op */
3123 i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
3124 break;
3125 case 0xbb: /* i2c op */
3126 i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
3127 break;
3128 case 0xdd:
3129 msleep(data[i][1] * 256 + data[i][2] + 10);
3130 break;
3131 }
3132 i++;
3133 }
3134 /*not reached*/
3135}
3136
3137
3138/* this function is called at probe time */
3139static int sd_config(struct gspca_dev *gspca_dev,
3140 const struct usb_device_id *id)
3141{
3142 struct sd *sd = (struct sd *) gspca_dev;
3143
3144 sd->bridge = id->driver_info >> 8;
3145 sd->flags = id->driver_info & 0xff;
3146
3147 if (id->idVendor == 0x046d &&
3148 (id->idProduct == 0x0892 || id->idProduct == 0x0896))
3149 sd->sensor = SENSOR_POxxxx; /* no probe */
3150
3151 return 0;
3152}
3153
3154/* this function is called at probe and resume time */
3155static int sd_init(struct gspca_dev *gspca_dev)
3156{
3157 struct sd *sd = (struct sd *) gspca_dev;
3158 struct cam *cam;
3159 int sensor;
3160 /* number of packets per ISOC message */
3161 static u8 npkt[NSENSORS] = {
3162 [SENSOR_HV7131R] = 64,
3163 [SENSOR_MI0360] = 32,
3164 [SENSOR_MI1310_SOC] = 32,
3165 [SENSOR_MI1320] = 64,
3166 [SENSOR_MI1320_SOC] = 128,
3167 [SENSOR_OV7660] = 32,
3168 [SENSOR_OV7670] = 64,
3169 [SENSOR_PO1200] = 128,
3170 [SENSOR_PO3130NC] = 128,
3171 [SENSOR_POxxxx] = 128,
3172 };
3173
3174 if (sd->sensor != SENSOR_POxxxx)
3175 sensor = vc032x_probe_sensor(gspca_dev);
3176 else
3177 sensor = sd->sensor;
3178
3179 switch (sensor) {
3180 case -1:
3181 pr_err("Unknown sensor...\n");
3182 return -EINVAL;
3183 case SENSOR_HV7131R:
3184 PDEBUG(D_PROBE, "Find Sensor HV7131R");
3185 break;
3186 case SENSOR_MI0360:
3187 PDEBUG(D_PROBE, "Find Sensor MI0360");
3188 sd->bridge = BRIDGE_VC0323;
3189 break;
3190 case SENSOR_MI1310_SOC:
3191 PDEBUG(D_PROBE, "Find Sensor MI1310_SOC");
3192 break;
3193 case SENSOR_MI1320:
3194 PDEBUG(D_PROBE, "Find Sensor MI1320");
3195 break;
3196 case SENSOR_MI1320_SOC:
3197 PDEBUG(D_PROBE, "Find Sensor MI1320_SOC");
3198 break;
3199 case SENSOR_OV7660:
3200 PDEBUG(D_PROBE, "Find Sensor OV7660");
3201 break;
3202 case SENSOR_OV7670:
3203 PDEBUG(D_PROBE, "Find Sensor OV7670");
3204 break;
3205 case SENSOR_PO1200:
3206 PDEBUG(D_PROBE, "Find Sensor PO1200");
3207 break;
3208 case SENSOR_PO3130NC:
3209 PDEBUG(D_PROBE, "Find Sensor PO3130NC");
3210 break;
3211 case SENSOR_POxxxx:
3212 PDEBUG(D_PROBE, "Sensor POxxxx");
3213 break;
3214 }
3215 sd->sensor = sensor;
3216
3217 cam = &gspca_dev->cam;
3218 if (sd->bridge == BRIDGE_VC0321) {
3219 cam->cam_mode = vc0321_mode;
3220 cam->nmodes = ARRAY_SIZE(vc0321_mode);
3221 } else {
3222 switch (sensor) {
3223 case SENSOR_PO1200:
3224 cam->cam_mode = svga_mode;
3225 cam->nmodes = ARRAY_SIZE(svga_mode);
3226 break;
3227 case SENSOR_MI1310_SOC:
3228 cam->cam_mode = vc0323_mode;
3229 cam->nmodes = ARRAY_SIZE(vc0323_mode);
3230 break;
3231 case SENSOR_MI1320_SOC:
3232 cam->cam_mode = bi_mode;
3233 cam->nmodes = ARRAY_SIZE(bi_mode);
3234 break;
3235 case SENSOR_OV7670:
3236 cam->cam_mode = bi_mode;
3237 cam->nmodes = ARRAY_SIZE(bi_mode) - 1;
3238 break;
3239 default:
3240 cam->cam_mode = vc0323_mode;
3241 cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
3242 break;
3243 }
3244 }
3245 cam->npkt = npkt[sd->sensor];
3246
3247 if (sd->sensor == SENSOR_OV7670)
3248 sd->flags |= FL_HFLIP | FL_VFLIP;
3249
3250 if (sd->bridge == BRIDGE_VC0321) {
3251 reg_r(gspca_dev, 0x8a, 0, 3);
3252 reg_w(gspca_dev, 0x87, 0x00, 0x0f0f);
3253 reg_r(gspca_dev, 0x8b, 0, 3);
3254 reg_w(gspca_dev, 0x88, 0x00, 0x0202);
3255 if (sd->sensor == SENSOR_POxxxx) {
3256 reg_r(gspca_dev, 0xa1, 0xb300, 1);
3257 if (gspca_dev->usb_buf[0] != 0) {
3258 reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
3259 reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
3260 }
3261 reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
3262 }
3263 }
3264 return gspca_dev->usb_err;
3265}
3266
3267static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
3268{
3269 u8 data;
3270
3271 data = val;
3272 if (data >= 0x80)
3273 data &= 0x7f;
3274 else
3275 data = 0xff ^ data;
3276 i2c_write(gspca_dev, 0x98, &data, 1);
3277}
3278
3279static void setcontrast(struct gspca_dev *gspca_dev, u8 val)
3280{
3281 i2c_write(gspca_dev, 0x99, &val, 1);
3282}
3283
3284static void setcolors(struct gspca_dev *gspca_dev, u8 val)
3285{
3286 u8 data;
3287
3288 data = val - (val >> 3) - 1;
3289 i2c_write(gspca_dev, 0x94, &data, 1);
3290 i2c_write(gspca_dev, 0x95, &val, 1);
3291}
3292
3293static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip)
3294{
3295 struct sd *sd = (struct sd *) gspca_dev;
3296 u8 data[2];
3297
3298 if (sd->flags & FL_HFLIP)
3299 hflip = !hflip;
3300 if (sd->flags & FL_VFLIP)
3301 vflip = !vflip;
3302 switch (sd->sensor) {
3303 case SENSOR_MI1310_SOC:
3304 case SENSOR_MI1320:
3305 case SENSOR_MI1320_SOC:
3306 data[0] = data[1] = 0; /* select page 0 */
3307 i2c_write(gspca_dev, 0xf0, data, 2);
3308 data[0] = sd->sensor == SENSOR_MI1310_SOC ? 0x03 : 0x01;
3309 data[1] = 0x02 * hflip
3310 | 0x01 * vflip;
3311 i2c_write(gspca_dev, 0x20, data, 2);
3312 break;
3313 case SENSOR_OV7660:
3314 case SENSOR_OV7670:
3315 data[0] = sd->sensor == SENSOR_OV7660 ? 0x01 : 0x07;
3316 data[0] |= OV7660_MVFP_MIRROR * hflip
3317 | OV7660_MVFP_VFLIP * vflip;
3318 i2c_write(gspca_dev, OV7660_REG_MVFP, data, 1);
3319 break;
3320 case SENSOR_PO1200:
3321 data[0] = 0;
3322 i2c_write(gspca_dev, 0x03, data, 1);
3323 data[0] = 0x80 * hflip
3324 | 0x40 * vflip
3325 | 0x06;
3326 i2c_write(gspca_dev, 0x1e, data, 1);
3327 break;
3328 }
3329}
3330
3331static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
3332{
3333 struct sd *sd = (struct sd *) gspca_dev;
3334 static const u8 (*ov7660_freq_tb[3])[4] =
3335 {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
3336
3337 if (sd->sensor != SENSOR_OV7660)
3338 return;
3339 usb_exchange(gspca_dev, ov7660_freq_tb[val]);
3340}
3341
3342static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
3343{
3344 struct sd *sd = (struct sd *) gspca_dev;
3345 u8 data;
3346
3347 switch (sd->sensor) {
3348 case SENSOR_PO1200:
3349 data = 0;
3350 i2c_write(gspca_dev, 0x03, &data, 1);
3351 if (val < 0)
3352 data = 0x6a;
3353 else
3354 data = 0xb5 + val * 3;
3355 i2c_write(gspca_dev, 0x61, &data, 1);
3356 break;
3357 case SENSOR_POxxxx:
3358 if (val < 0)
3359 data = 0x7e; /* def = max */
3360 else
3361 data = 0x60 + val * 0x0f;
3362 i2c_write(gspca_dev, 0x59, &data, 1);
3363 break;
3364 }
3365}
3366static void setgain(struct gspca_dev *gspca_dev, u8 val)
3367{
3368 i2c_write(gspca_dev, 0x15, &val, 1);
3369}
3370
3371static void setexposure(struct gspca_dev *gspca_dev, s32 val)
3372{
3373 u8 data;
3374
3375 data = val >> 8;
3376 i2c_write(gspca_dev, 0x1a, &data, 1);
3377 data = val;
3378 i2c_write(gspca_dev, 0x1b, &data, 1);
3379}
3380
3381static void setautogain(struct gspca_dev *gspca_dev, s32 val)
3382{
3383 static const u8 data[2] = {0x28, 0x3c};
3384
3385 i2c_write(gspca_dev, 0xd1, &data[val], 1);
3386}
3387
3388static void setgamma(struct gspca_dev *gspca_dev)
3389{
3390/*fixme:to do */
3391 usb_exchange(gspca_dev, poxxxx_gamma);
3392}
3393
3394static void setbacklight(struct gspca_dev *gspca_dev, s32 val)
3395{
3396 u16 v;
3397 u8 data;
3398
3399 data = (val << 4) | 0x0f;
3400 i2c_write(gspca_dev, 0xaa, &data, 1);
3401 v = 613 + 12 * val;
3402 data = v >> 8;
3403 i2c_write(gspca_dev, 0xc4, &data, 1);
3404 data = v;
3405 i2c_write(gspca_dev, 0xc5, &data, 1);
3406 v = 1093 - 12 * val;
3407 data = v >> 8;
3408 i2c_write(gspca_dev, 0xc6, &data, 1);
3409 data = v;
3410 i2c_write(gspca_dev, 0xc7, &data, 1);
3411 v = 342 + 9 * val;
3412 data = v >> 8;
3413 i2c_write(gspca_dev, 0xc8, &data, 1);
3414 data = v;
3415 i2c_write(gspca_dev, 0xc9, &data, 1);
3416 v = 702 - 9 * val;
3417 data = v >> 8;
3418 i2c_write(gspca_dev, 0xca, &data, 1);
3419 data = v;
3420 i2c_write(gspca_dev, 0xcb, &data, 1);
3421}
3422
3423static void setwb(struct gspca_dev *gspca_dev)
3424{
3425/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
3426 static const u8 data[2] = {0x00, 0x00};
3427
3428 i2c_write(gspca_dev, 0x16, &data[0], 1);
3429 i2c_write(gspca_dev, 0x18, &data[1], 1);
3430}
3431
3432static int sd_start(struct gspca_dev *gspca_dev)
3433{
3434 struct sd *sd = (struct sd *) gspca_dev;
3435 const u8 (*init)[4];
3436 const u8 *GammaT = NULL;
3437 const u8 *MatrixT = NULL;
3438 int mode;
3439 static const u8 (*mi1320_soc_init[])[4] = {
3440 mi1320_soc_InitSXGA,
3441 mi1320_soc_InitVGA,
3442 mi1320_soc_InitQVGA,
3443 };
3444
3445/*fixme: back sensor only*/
3446 if (sd->flags & FL_SAMSUNG) {
3447 reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
3448 reg_w(gspca_dev, 0xa9, 0x8348, 0x000e);
3449 reg_w(gspca_dev, 0xa9, 0x0000, 0x001a);
3450 }
3451
3452 /* Assume start use the good resolution from gspca_dev->mode */
3453 if (sd->bridge == BRIDGE_VC0321) {
3454 reg_w(gspca_dev, 0xa0, 0xff, 0xbfec);
3455 reg_w(gspca_dev, 0xa0, 0xff, 0xbfed);
3456 reg_w(gspca_dev, 0xa0, 0xff, 0xbfee);
3457 reg_w(gspca_dev, 0xa0, 0xff, 0xbfef);
3458 sd->image_offset = 46;
3459 } else {
3460 if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
3461 == V4L2_PIX_FMT_JPEG)
3462 sd->image_offset = 0;
3463 else
3464 sd->image_offset = 32;
3465 }
3466
3467 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
3468 switch (sd->sensor) {
3469 case SENSOR_HV7131R:
3470 GammaT = hv7131r_gamma;
3471 MatrixT = hv7131r_matrix;
3472 if (mode)
3473 init = hv7131r_initQVGA_data; /* 320x240 */
3474 else
3475 init = hv7131r_initVGA_data; /* 640x480 */
3476 break;
3477 case SENSOR_OV7660:
3478 GammaT = ov7660_gamma;
3479 MatrixT = ov7660_matrix;
3480 if (mode)
3481 init = ov7660_initQVGA_data; /* 320x240 */
3482 else
3483 init = ov7660_initVGA_data; /* 640x480 */
3484 break;
3485 case SENSOR_MI0360:
3486 GammaT = mi1320_gamma;
3487 MatrixT = mi0360_matrix;
3488 if (mode)
3489 init = mi0360_initQVGA_JPG; /* 320x240 */
3490 else
3491 init = mi0360_initVGA_JPG; /* 640x480 */
3492 break;
3493 case SENSOR_MI1310_SOC:
3494 GammaT = mi1320_gamma;
3495 MatrixT = mi1320_matrix;
3496 switch (mode) {
3497 case 1:
3498 init = mi1310_socinitQVGA_JPG; /* 320x240 */
3499 break;
3500 case 0:
3501 init = mi1310_socinitVGA_JPG; /* 640x480 */
3502 break;
3503 default:
3504 init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */
3505 break;
3506 }
3507 break;
3508 case SENSOR_MI1320:
3509 GammaT = mi1320_gamma;
3510 MatrixT = mi1320_matrix;
3511 if (mode)
3512 init = mi1320_initQVGA_data; /* 320x240 */
3513 else
3514 init = mi1320_initVGA_data; /* 640x480 */
3515 break;
3516 case SENSOR_MI1320_SOC:
3517 GammaT = mi1320_gamma;
3518 MatrixT = mi1320_matrix;
3519 init = mi1320_soc_init[mode];
3520 break;
3521 case SENSOR_OV7670:
3522 init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA;
3523 break;
3524 case SENSOR_PO3130NC:
3525 GammaT = po3130_gamma;
3526 MatrixT = po3130_matrix;
3527 if (mode)
3528 init = po3130_initQVGA_data; /* 320x240 */
3529 else
3530 init = po3130_initVGA_data; /* 640x480 */
3531 usb_exchange(gspca_dev, init);
3532 init = po3130_rundata;
3533 break;
3534 case SENSOR_PO1200:
3535 GammaT = po1200_gamma;
3536 MatrixT = po1200_matrix;
3537 init = po1200_initVGA_data;
3538 break;
3539 default:
3540/* case SENSOR_POxxxx: */
3541 usb_exchange(gspca_dev, poxxxx_init_common);
3542 setgamma(gspca_dev);
3543 usb_exchange(gspca_dev, poxxxx_init_start_3);
3544 if (mode)
3545 init = poxxxx_initQVGA;
3546 else
3547 init = poxxxx_initVGA;
3548 usb_exchange(gspca_dev, init);
3549 reg_r(gspca_dev, 0x8c, 0x0000, 3);
3550 reg_w(gspca_dev, 0xa0,
3551 gspca_dev->usb_buf[2] & 1 ? 0 : 1,
3552 0xb35c);
3553 msleep(300);
3554/*fixme: i2c read 04 and 05*/
3555 init = poxxxx_init_end_1;
3556 break;
3557 }
3558 usb_exchange(gspca_dev, init);
3559 if (GammaT && MatrixT) {
3560 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
3561 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
3562 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
3563 put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
3564
3565 switch (sd->sensor) {
3566 case SENSOR_PO1200:
3567 case SENSOR_HV7131R:
3568 reg_w(gspca_dev, 0x89, 0x0400, 0x1415);
3569 break;
3570 case SENSOR_MI1310_SOC:
3571 reg_w(gspca_dev, 0x89, 0x058c, 0x0000);
3572 break;
3573 }
3574 msleep(100);
3575 }
3576 switch (sd->sensor) {
3577 case SENSOR_OV7670:
3578 reg_w(gspca_dev, 0x87, 0xffff, 0xffff);
3579 reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1);
3580 reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
3581 break;
3582 case SENSOR_POxxxx:
3583 usb_exchange(gspca_dev, poxxxx_init_end_2);
3584 setwb(gspca_dev);
3585 msleep(80); /* led on */
3586 reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
3587 break;
3588 }
3589 return gspca_dev->usb_err;
3590}
3591
3592static void sd_stopN(struct gspca_dev *gspca_dev)
3593{
3594 struct sd *sd = (struct sd *) gspca_dev;
3595
3596 switch (sd->sensor) {
3597 case SENSOR_MI1310_SOC:
3598 reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
3599 break;
3600 case SENSOR_POxxxx:
3601 return;
3602 default:
3603 if (!(sd->flags & FL_SAMSUNG))
3604 reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
3605 break;
3606 }
3607 reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
3608 reg_w(gspca_dev, 0xa0, 0x09, 0xb003);
3609}
3610
3611/* called on streamoff with alt 0 and on disconnect */
3612static void sd_stop0(struct gspca_dev *gspca_dev)
3613{
3614 struct sd *sd = (struct sd *) gspca_dev;
3615
3616 if (!gspca_dev->present)
3617 return;
3618/*fixme: is this useful?*/
3619 if (sd->sensor == SENSOR_MI1310_SOC)
3620 reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
3621 else if (!(sd->flags & FL_SAMSUNG))
3622 reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
3623
3624 if (sd->sensor == SENSOR_POxxxx) {
3625 reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
3626 reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
3627 reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
3628 }
3629}
3630
3631static void sd_pkt_scan(struct gspca_dev *gspca_dev,
3632 u8 *data, /* isoc packet */
3633 int len) /* iso pkt length */
3634{
3635 struct sd *sd = (struct sd *) gspca_dev;
3636
3637 if (data[0] == 0xff && data[1] == 0xd8) {
3638 PDEBUG(D_PACK,
3639 "vc032x header packet found len %d", len);
3640 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
3641 data += sd->image_offset;
3642 len -= sd->image_offset;
3643 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
3644 return;
3645 }
3646
3647 /* The vc0321 sends some additional data after sending the complete
3648 * frame, we ignore this. */
3649 if (sd->bridge == BRIDGE_VC0321) {
3650 int size, l;
3651
3652 l = gspca_dev->image_len;
3653 size = gspca_dev->frsz;
3654 if (len > size - l)
3655 len = size - l;
3656 }
3657 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
3658}
3659
3660static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
3661{
3662 struct gspca_dev *gspca_dev =
3663 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
3664 struct sd *sd = (struct sd *)gspca_dev;
3665
3666 gspca_dev->usb_err = 0;
3667
3668 if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
3669 return 0;
3670
3671 switch (ctrl->id) {
3672 case V4L2_CID_BRIGHTNESS:
3673 setbrightness(gspca_dev, ctrl->val);
3674 break;
3675 case V4L2_CID_CONTRAST:
3676 setcontrast(gspca_dev, ctrl->val);
3677 break;
3678 case V4L2_CID_SATURATION:
3679 setcolors(gspca_dev, ctrl->val);
3680 break;
3681 case V4L2_CID_HFLIP:
3682 sethvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
3683 break;
3684 case V4L2_CID_SHARPNESS:
3685 setsharpness(gspca_dev, ctrl->val);
3686 break;
3687 case V4L2_CID_AUTOGAIN:
3688 setautogain(gspca_dev, ctrl->val);
3689 break;
3690 case V4L2_CID_GAIN:
3691 setgain(gspca_dev, ctrl->val);
3692 break;
3693 case V4L2_CID_EXPOSURE:
3694 setexposure(gspca_dev, ctrl->val);
3695 break;
3696 case V4L2_CID_BACKLIGHT_COMPENSATION:
3697 setbacklight(gspca_dev, ctrl->val);
3698 break;
3699 case V4L2_CID_POWER_LINE_FREQUENCY:
3700 setlightfreq(gspca_dev, ctrl->val);
3701 break;
3702 }
3703 return gspca_dev->usb_err;
3704}
3705
3706static const struct v4l2_ctrl_ops sd_ctrl_ops = {
3707 .s_ctrl = sd_s_ctrl,
3708};
3709
3710static int sd_init_controls(struct gspca_dev *gspca_dev)
3711{
3712 struct sd *sd = (struct sd *)gspca_dev;
3713 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
3714 bool has_brightness = false;
3715 bool has_contrast = false;
3716 bool has_sat = false;
3717 bool has_hvflip = false;
3718 bool has_freq = false;
3719 bool has_backlight = false;
3720 bool has_exposure = false;
3721 bool has_autogain = false;
3722 bool has_gain = false;
3723 bool has_sharpness = false;
3724
3725 switch (sd->sensor) {
3726 case SENSOR_HV7131R:
3727 case SENSOR_MI0360:
3728 case SENSOR_PO3130NC:
3729 break;
3730 case SENSOR_MI1310_SOC:
3731 case SENSOR_MI1320:
3732 case SENSOR_MI1320_SOC:
3733 case SENSOR_OV7660:
3734 has_hvflip = true;
3735 break;
3736 case SENSOR_OV7670:
3737 has_hvflip = has_freq = true;
3738 break;
3739 case SENSOR_PO1200:
3740 has_hvflip = has_sharpness = true;
3741 break;
3742 case SENSOR_POxxxx:
3743 has_brightness = has_contrast = has_sat = has_backlight =
3744 has_exposure = has_autogain = has_gain =
3745 has_sharpness = true;
3746 break;
3747 }
3748
3749 gspca_dev->vdev.ctrl_handler = hdl;
3750 v4l2_ctrl_handler_init(hdl, 8);
3751 if (has_brightness)
3752 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3753 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
3754 if (has_contrast)
3755 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3756 V4L2_CID_CONTRAST, 0, 255, 1, 127);
3757 if (has_sat)
3758 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3759 V4L2_CID_SATURATION, 1, 127, 1, 63);
3760 if (has_hvflip) {
3761 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3762 V4L2_CID_HFLIP, 0, 1, 1, 0);
3763 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3764 V4L2_CID_VFLIP, 0, 1, 1, 0);
3765 }
3766 if (has_sharpness)
3767 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3768 V4L2_CID_SHARPNESS, -1, 2, 1, -1);
3769 if (has_freq)
3770 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
3771 V4L2_CID_POWER_LINE_FREQUENCY,
3772 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
3773 V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
3774 if (has_autogain)
3775 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3776 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
3777 if (has_gain)
3778 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3779 V4L2_CID_GAIN, 0, 78, 1, 0);
3780 if (has_exposure)
3781 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3782 V4L2_CID_EXPOSURE, 0, 4095, 1, 450);
3783 if (has_backlight)
3784 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3785 V4L2_CID_BACKLIGHT_COMPENSATION, 0, 15, 1, 15);
3786
3787 if (hdl->error) {
3788 pr_err("Could not initialize controls\n");
3789 return hdl->error;
3790 }
3791 if (sd->hflip)
3792 v4l2_ctrl_cluster(2, &sd->hflip);
3793 return 0;
3794}
3795
3796/* sub-driver description */
3797static const struct sd_desc sd_desc = {
3798 .name = MODULE_NAME,
3799 .init_controls = sd_init_controls,
3800 .config = sd_config,
3801 .init = sd_init,
3802 .start = sd_start,
3803 .stopN = sd_stopN,
3804 .stop0 = sd_stop0,
3805 .pkt_scan = sd_pkt_scan,
3806};
3807
3808/* -- module initialisation -- */
3809#define BF(bridge, flags) \
3810 .driver_info = (BRIDGE_ ## bridge << 8) \
3811 | (flags)
3812static const struct usb_device_id device_table[] = {
3813 {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)},
3814 {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)},
3815 {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)},
3816 {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)},
3817 {USB_DEVICE(0x0ac8, 0x0321), BF(VC0321, 0)},
3818 {USB_DEVICE(0x0ac8, 0x0323), BF(VC0323, 0)},
3819 {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)},
3820 {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)},
3821 {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)},
3822 {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, FL_SAMSUNG)},
3823 {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)},
3824 {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)},
3825 {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)},
3826 {}
3827};
3828MODULE_DEVICE_TABLE(usb, device_table);
3829
3830/* -- device connect -- */
3831static int sd_probe(struct usb_interface *intf,
3832 const struct usb_device_id *id)
3833{
3834 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
3835 THIS_MODULE);
3836}
3837
3838static struct usb_driver sd_driver = {
3839 .name = MODULE_NAME,
3840 .id_table = device_table,
3841 .probe = sd_probe,
3842 .disconnect = gspca_disconnect,
3843#ifdef CONFIG_PM
3844 .suspend = gspca_suspend,
3845 .resume = gspca_resume,
3846 .reset_resume = gspca_resume,
3847#endif
3848};
3849
3850module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c
new file mode 100644
index 00000000000..b1a64b91266
--- /dev/null
+++ b/drivers/media/usb/gspca/vicam.c
@@ -0,0 +1,365 @@
1/*
2 * gspca ViCam subdriver
3 *
4 * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
5 *
6 * Based on the usbvideo vicam driver, which is:
7 *
8 * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
9 * Christopher L Cheney (ccheney@cheney.cx),
10 * Pavel Machek (pavel@ucw.cz),
11 * John Tyner (jtyner@cs.ucr.edu),
12 * Monroe Williams (monroe@pobox.com)
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#define MODULE_NAME "vicam"
32#define HEADER_SIZE 64
33
34#include <linux/workqueue.h>
35#include <linux/slab.h>
36#include <linux/firmware.h>
37#include <linux/ihex.h>
38#include "gspca.h"
39
40#define VICAM_FIRMWARE "vicam/firmware.fw"
41
42MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
43MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
44MODULE_LICENSE("GPL");
45MODULE_FIRMWARE(VICAM_FIRMWARE);
46
47struct sd {
48 struct gspca_dev gspca_dev; /* !! must be the first item */
49 struct work_struct work_struct;
50 struct workqueue_struct *work_thread;
51};
52
53/* The vicam sensor has a resolution of 512 x 244, with I believe square
54 pixels, but this is forced to a 4:3 ratio by optics. So it has
55 non square pixels :( */
56static struct v4l2_pix_format vicam_mode[] = {
57 { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
58 .bytesperline = 256,
59 .sizeimage = 256 * 122,
60 .colorspace = V4L2_COLORSPACE_SRGB,},
61 /* 2 modes with somewhat more square pixels */
62 { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
63 .bytesperline = 256,
64 .sizeimage = 256 * 200,
65 .colorspace = V4L2_COLORSPACE_SRGB,},
66 { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
67 .bytesperline = 256,
68 .sizeimage = 256 * 240,
69 .colorspace = V4L2_COLORSPACE_SRGB,},
70#if 0 /* This mode has extremely non square pixels, testing use only */
71 { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
72 .bytesperline = 512,
73 .sizeimage = 512 * 122,
74 .colorspace = V4L2_COLORSPACE_SRGB,},
75#endif
76 { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
77 .bytesperline = 512,
78 .sizeimage = 512 * 244,
79 .colorspace = V4L2_COLORSPACE_SRGB,},
80};
81
82static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
83 u16 value, u16 index, u8 *data, u16 len)
84{
85 int ret;
86
87 ret = usb_control_msg(gspca_dev->dev,
88 usb_sndctrlpipe(gspca_dev->dev, 0),
89 request,
90 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
91 value, index, data, len, 1000);
92 if (ret < 0)
93 pr_err("control msg req %02X error %d\n", request, ret);
94
95 return ret;
96}
97
98static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
99{
100 int ret;
101
102 ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
103 if (ret < 0)
104 return ret;
105
106 if (state)
107 ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
108
109 return ret;
110}
111
112/*
113 * request and read a block of data - see warning on vicam_command.
114 */
115static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
116{
117 int ret, unscaled_height, act_len = 0;
118 u8 *req_data = gspca_dev->usb_buf;
119 s32 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
120 s32 gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
121
122 memset(req_data, 0, 16);
123 req_data[0] = gain;
124 if (gspca_dev->width == 256)
125 req_data[1] |= 0x01; /* low nibble x-scale */
126 if (gspca_dev->height <= 122) {
127 req_data[1] |= 0x10; /* high nibble y-scale */
128 unscaled_height = gspca_dev->height * 2;
129 } else
130 unscaled_height = gspca_dev->height;
131 req_data[2] = 0x90; /* unknown, does not seem to do anything */
132 if (unscaled_height <= 200)
133 req_data[3] = 0x06; /* vend? */
134 else if (unscaled_height <= 242) /* Yes 242 not 240 */
135 req_data[3] = 0x07; /* vend? */
136 else /* Up to 244 lines with req_data[3] == 0x08 */
137 req_data[3] = 0x08; /* vend? */
138
139 if (expo < 256) {
140 /* Frame rate maxed out, use partial frame expo time */
141 req_data[4] = 255 - expo;
142 req_data[5] = 0x00;
143 req_data[6] = 0x00;
144 req_data[7] = 0x01;
145 } else {
146 /* Modify frame rate */
147 req_data[4] = 0x00;
148 req_data[5] = 0x00;
149 req_data[6] = expo & 0xFF;
150 req_data[7] = expo >> 8;
151 }
152 req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */
153 /* bytes 9-15 do not seem to affect exposure or image quality */
154
155 mutex_lock(&gspca_dev->usb_lock);
156 ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
157 mutex_unlock(&gspca_dev->usb_lock);
158 if (ret < 0)
159 return ret;
160
161 ret = usb_bulk_msg(gspca_dev->dev,
162 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
163 data, size, &act_len, 10000);
164 /* successful, it returns 0, otherwise negative */
165 if (ret < 0 || act_len != size) {
166 pr_err("bulk read fail (%d) len %d/%d\n",
167 ret, act_len, size);
168 return -EIO;
169 }
170 return 0;
171}
172
173/* This function is called as a workqueue function and runs whenever the camera
174 * is streaming data. Because it is a workqueue function it is allowed to sleep
175 * so we can use synchronous USB calls. To avoid possible collisions with other
176 * threads attempting to use the camera's USB interface we take the gspca
177 * usb_lock when performing USB operations. In practice the only thing we need
178 * to protect against is the usb_set_interface call that gspca makes during
179 * stream_off as the camera doesn't provide any controls that the user could try
180 * to change.
181 */
182static void vicam_dostream(struct work_struct *work)
183{
184 struct sd *sd = container_of(work, struct sd, work_struct);
185 struct gspca_dev *gspca_dev = &sd->gspca_dev;
186 int ret, frame_sz;
187 u8 *buffer;
188
189 frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
190 HEADER_SIZE;
191 buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
192 if (!buffer) {
193 pr_err("Couldn't allocate USB buffer\n");
194 goto exit;
195 }
196
197 while (gspca_dev->dev && gspca_dev->streaming) {
198#ifdef CONFIG_PM
199 if (gspca_dev->frozen)
200 break;
201#endif
202 ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
203 if (ret < 0)
204 break;
205
206 /* Note the frame header contents seem to be completely
207 constant, they do not change with either image, or
208 settings. So we simply discard it. The frames have
209 a very similar 64 byte footer, which we don't even
210 bother reading from the cam */
211 gspca_frame_add(gspca_dev, FIRST_PACKET,
212 buffer + HEADER_SIZE,
213 frame_sz - HEADER_SIZE);
214 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
215 }
216exit:
217 kfree(buffer);
218}
219
220/* This function is called at probe time just before sd_init */
221static int sd_config(struct gspca_dev *gspca_dev,
222 const struct usb_device_id *id)
223{
224 struct cam *cam = &gspca_dev->cam;
225 struct sd *sd = (struct sd *)gspca_dev;
226
227 /* We don't use the buffer gspca allocates so make it small. */
228 cam->bulk = 1;
229 cam->bulk_size = 64;
230 cam->cam_mode = vicam_mode;
231 cam->nmodes = ARRAY_SIZE(vicam_mode);
232
233 INIT_WORK(&sd->work_struct, vicam_dostream);
234
235 return 0;
236}
237
238/* this function is called at probe and resume time */
239static int sd_init(struct gspca_dev *gspca_dev)
240{
241 int ret;
242 const struct ihex_binrec *rec;
243 const struct firmware *uninitialized_var(fw);
244 u8 *firmware_buf;
245
246 ret = request_ihex_firmware(&fw, VICAM_FIRMWARE,
247 &gspca_dev->dev->dev);
248 if (ret) {
249 pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
250 return ret;
251 }
252
253 firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
254 if (!firmware_buf) {
255 ret = -ENOMEM;
256 goto exit;
257 }
258 for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
259 memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
260 ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
261 be16_to_cpu(rec->len));
262 if (ret < 0)
263 break;
264 }
265
266 kfree(firmware_buf);
267exit:
268 release_firmware(fw);
269 return ret;
270}
271
272/* Set up for getting frames. */
273static int sd_start(struct gspca_dev *gspca_dev)
274{
275 struct sd *sd = (struct sd *)gspca_dev;
276 int ret;
277
278 ret = vicam_set_camera_power(gspca_dev, 1);
279 if (ret < 0)
280 return ret;
281
282 /* Start the workqueue function to do the streaming */
283 sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
284 queue_work(sd->work_thread, &sd->work_struct);
285
286 return 0;
287}
288
289/* called on streamoff with alt==0 and on disconnect */
290/* the usb_lock is held at entry - restore on exit */
291static void sd_stop0(struct gspca_dev *gspca_dev)
292{
293 struct sd *dev = (struct sd *)gspca_dev;
294
295 /* wait for the work queue to terminate */
296 mutex_unlock(&gspca_dev->usb_lock);
297 /* This waits for vicam_dostream to finish */
298 destroy_workqueue(dev->work_thread);
299 dev->work_thread = NULL;
300 mutex_lock(&gspca_dev->usb_lock);
301
302 if (gspca_dev->dev)
303 vicam_set_camera_power(gspca_dev, 0);
304}
305
306static int sd_init_controls(struct gspca_dev *gspca_dev)
307{
308 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
309
310 gspca_dev->vdev.ctrl_handler = hdl;
311 v4l2_ctrl_handler_init(hdl, 2);
312 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, NULL,
313 V4L2_CID_EXPOSURE, 0, 2047, 1, 256);
314 gspca_dev->gain = v4l2_ctrl_new_std(hdl, NULL,
315 V4L2_CID_GAIN, 0, 255, 1, 200);
316
317 if (hdl->error) {
318 pr_err("Could not initialize controls\n");
319 return hdl->error;
320 }
321 return 0;
322}
323
324/* Table of supported USB devices */
325static const struct usb_device_id device_table[] = {
326 {USB_DEVICE(0x04c1, 0x009d)},
327 {USB_DEVICE(0x0602, 0x1001)},
328 {}
329};
330
331MODULE_DEVICE_TABLE(usb, device_table);
332
333/* sub-driver description */
334static const struct sd_desc sd_desc = {
335 .name = MODULE_NAME,
336 .config = sd_config,
337 .init = sd_init,
338 .init_controls = sd_init_controls,
339 .start = sd_start,
340 .stop0 = sd_stop0,
341};
342
343/* -- device connect -- */
344static int sd_probe(struct usb_interface *intf,
345 const struct usb_device_id *id)
346{
347 return gspca_dev_probe(intf, id,
348 &sd_desc,
349 sizeof(struct sd),
350 THIS_MODULE);
351}
352
353static struct usb_driver sd_driver = {
354 .name = MODULE_NAME,
355 .id_table = device_table,
356 .probe = sd_probe,
357 .disconnect = gspca_disconnect,
358#ifdef CONFIG_PM
359 .suspend = gspca_suspend,
360 .resume = gspca_resume,
361 .reset_resume = gspca_resume,
362#endif
363};
364
365module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
new file mode 100644
index 00000000000..9e3a909e0a0
--- /dev/null
+++ b/drivers/media/usb/gspca/w996Xcf.c
@@ -0,0 +1,567 @@
1/**
2 *
3 * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip.
4 *
5 * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
6 *
7 * This module is adapted from the in kernel v4l1 w9968cf driver:
8 *
9 * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
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/* Note this is not a stand alone driver, it gets included in ov519.c, this
28 is a bit of a hack, but it needs the driver code for a lot of different
29 ov sensors which is already present in ov519.c (the old v4l1 driver used
30 the ovchipcam framework). When we have the time we really should move
31 the sensor drivers to v4l2 sub drivers, and properly split of this
32 driver from ov519.c */
33
34#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
35
36#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */
37
38#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
39#define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET])
40
41static const struct v4l2_pix_format w9968cf_vga_mode[] = {
42 {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
43 .bytesperline = 160 * 2,
44 .sizeimage = 160 * 120 * 2,
45 .colorspace = V4L2_COLORSPACE_JPEG},
46 {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
47 .bytesperline = 176 * 2,
48 .sizeimage = 176 * 144 * 2,
49 .colorspace = V4L2_COLORSPACE_JPEG},
50 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
51 .bytesperline = 320 * 2,
52 .sizeimage = 320 * 240 * 2,
53 .colorspace = V4L2_COLORSPACE_JPEG},
54 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
55 .bytesperline = 352 * 2,
56 .sizeimage = 352 * 288 * 2,
57 .colorspace = V4L2_COLORSPACE_JPEG},
58 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
59 .bytesperline = 640 * 2,
60 .sizeimage = 640 * 480 * 2,
61 .colorspace = V4L2_COLORSPACE_JPEG},
62};
63
64static void reg_w(struct sd *sd, u16 index, u16 value);
65
66/*--------------------------------------------------------------------------
67 Write 64-bit data to the fast serial bus registers.
68 Return 0 on success, -1 otherwise.
69 --------------------------------------------------------------------------*/
70static void w9968cf_write_fsb(struct sd *sd, u16* data)
71{
72 struct usb_device *udev = sd->gspca_dev.dev;
73 u16 value;
74 int ret;
75
76 if (sd->gspca_dev.usb_err < 0)
77 return;
78
79 value = *data++;
80 memcpy(sd->gspca_dev.usb_buf, data, 6);
81
82 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
83 USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
84 value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
85 if (ret < 0) {
86 pr_err("Write FSB registers failed (%d)\n", ret);
87 sd->gspca_dev.usb_err = ret;
88 }
89}
90
91/*--------------------------------------------------------------------------
92 Write data to the serial bus control register.
93 Return 0 on success, a negative number otherwise.
94 --------------------------------------------------------------------------*/
95static void w9968cf_write_sb(struct sd *sd, u16 value)
96{
97 int ret;
98
99 if (sd->gspca_dev.usb_err < 0)
100 return;
101
102 /* We don't use reg_w here, as that would cause all writes when
103 bitbanging i2c to be logged, making the logs impossible to read */
104 ret = usb_control_msg(sd->gspca_dev.dev,
105 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
106 0,
107 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
108 value, 0x01, NULL, 0, 500);
109
110 udelay(W9968CF_I2C_BUS_DELAY);
111
112 if (ret < 0) {
113 pr_err("Write SB reg [01] %04x failed\n", value);
114 sd->gspca_dev.usb_err = ret;
115 }
116}
117
118/*--------------------------------------------------------------------------
119 Read data from the serial bus control register.
120 Return 0 on success, a negative number otherwise.
121 --------------------------------------------------------------------------*/
122static int w9968cf_read_sb(struct sd *sd)
123{
124 int ret;
125
126 if (sd->gspca_dev.usb_err < 0)
127 return -1;
128
129 /* We don't use reg_r here, as the w9968cf is special and has 16
130 bit registers instead of 8 bit */
131 ret = usb_control_msg(sd->gspca_dev.dev,
132 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
133 1,
134 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
135 0, 0x01, sd->gspca_dev.usb_buf, 2, 500);
136 if (ret >= 0) {
137 ret = sd->gspca_dev.usb_buf[0] |
138 (sd->gspca_dev.usb_buf[1] << 8);
139 } else {
140 pr_err("Read SB reg [01] failed\n");
141 sd->gspca_dev.usb_err = ret;
142 }
143
144 udelay(W9968CF_I2C_BUS_DELAY);
145
146 return ret;
147}
148
149/*--------------------------------------------------------------------------
150 Upload quantization tables for the JPEG compression.
151 This function is called by w9968cf_start_transfer().
152 Return 0 on success, a negative number otherwise.
153 --------------------------------------------------------------------------*/
154static void w9968cf_upload_quantizationtables(struct sd *sd)
155{
156 u16 a, b;
157 int i, j;
158
159 reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
160
161 for (i = 0, j = 0; i < 32; i++, j += 2) {
162 a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8);
163 b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8);
164 reg_w(sd, 0x40 + i, a);
165 reg_w(sd, 0x60 + i, b);
166 }
167 reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
168}
169
170/****************************************************************************
171 * Low-level I2C I/O functions. *
172 * The adapter supports the following I2C transfer functions: *
173 * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) *
174 * i2c_adap_read_byte_data() *
175 * i2c_adap_read_byte() *
176 ****************************************************************************/
177
178static void w9968cf_smbus_start(struct sd *sd)
179{
180 w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
181 w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
182}
183
184static void w9968cf_smbus_stop(struct sd *sd)
185{
186 w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
187 w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
188 w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
189}
190
191static void w9968cf_smbus_write_byte(struct sd *sd, u8 v)
192{
193 u8 bit;
194 int sda;
195
196 for (bit = 0 ; bit < 8 ; bit++) {
197 sda = (v & 0x80) ? 2 : 0;
198 v <<= 1;
199 /* SDE=1, SDA=sda, SCL=0 */
200 w9968cf_write_sb(sd, 0x10 | sda);
201 /* SDE=1, SDA=sda, SCL=1 */
202 w9968cf_write_sb(sd, 0x11 | sda);
203 /* SDE=1, SDA=sda, SCL=0 */
204 w9968cf_write_sb(sd, 0x10 | sda);
205 }
206}
207
208static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v)
209{
210 u8 bit;
211
212 /* No need to ensure SDA is high as we are always called after
213 read_ack which ends with SDA high */
214 *v = 0;
215 for (bit = 0 ; bit < 8 ; bit++) {
216 *v <<= 1;
217 /* SDE=1, SDA=1, SCL=1 */
218 w9968cf_write_sb(sd, 0x0013);
219 *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0;
220 /* SDE=1, SDA=1, SCL=0 */
221 w9968cf_write_sb(sd, 0x0012);
222 }
223}
224
225static void w9968cf_smbus_write_nack(struct sd *sd)
226{
227 /* No need to ensure SDA is high as we are always called after
228 read_byte which ends with SDA high */
229 w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
230 w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
231}
232
233static void w9968cf_smbus_read_ack(struct sd *sd)
234{
235 int sda;
236
237 /* Ensure SDA is high before raising clock to avoid a spurious stop */
238 w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
239 w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
240 sda = w9968cf_read_sb(sd);
241 w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
242 if (sda >= 0 && (sda & 0x08)) {
243 PDEBUG(D_USBI, "Did not receive i2c ACK");
244 sd->gspca_dev.usb_err = -EIO;
245 }
246}
247
248/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
249static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
250{
251 u16* data = (u16 *)sd->gspca_dev.usb_buf;
252
253 data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
254 data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0;
255 data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0);
256 data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0;
257 data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0;
258 data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0);
259 data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0;
260 data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0;
261 data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0);
262 data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0;
263
264 w9968cf_write_fsb(sd, data);
265
266 data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0);
267 data[0] |= (reg & 0x40) ? 0x0540 : 0x0;
268 data[0] |= (reg & 0x20) ? 0x5000 : 0x0;
269 data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0);
270 data[1] |= (reg & 0x10) ? 0x0054 : 0x0;
271 data[1] |= (reg & 0x08) ? 0x1500 : 0x0;
272 data[1] |= (reg & 0x04) ? 0x4000 : 0x0;
273 data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0);
274 data[2] |= (reg & 0x02) ? 0x0150 : 0x0;
275 data[2] |= (reg & 0x01) ? 0x5400 : 0x0;
276 data[3] = 0x001d;
277
278 w9968cf_write_fsb(sd, data);
279
280 data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
281 data[0] |= (value & 0x40) ? 0x0540 : 0x0;
282 data[0] |= (value & 0x20) ? 0x5000 : 0x0;
283 data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0);
284 data[1] |= (value & 0x10) ? 0x0054 : 0x0;
285 data[1] |= (value & 0x08) ? 0x1500 : 0x0;
286 data[1] |= (value & 0x04) ? 0x4000 : 0x0;
287 data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0);
288 data[2] |= (value & 0x02) ? 0x0150 : 0x0;
289 data[2] |= (value & 0x01) ? 0x5400 : 0x0;
290 data[3] = 0xfe1d;
291
292 w9968cf_write_fsb(sd, data);
293
294 PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
295}
296
297/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
298static int w9968cf_i2c_r(struct sd *sd, u8 reg)
299{
300 int ret = 0;
301 u8 value;
302
303 /* Fast serial bus data control disable */
304 w9968cf_write_sb(sd, 0x0013); /* don't change ! */
305
306 w9968cf_smbus_start(sd);
307 w9968cf_smbus_write_byte(sd, sd->sensor_addr);
308 w9968cf_smbus_read_ack(sd);
309 w9968cf_smbus_write_byte(sd, reg);
310 w9968cf_smbus_read_ack(sd);
311 w9968cf_smbus_stop(sd);
312 w9968cf_smbus_start(sd);
313 w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
314 w9968cf_smbus_read_ack(sd);
315 w9968cf_smbus_read_byte(sd, &value);
316 /* signal we don't want to read anymore, the v4l1 driver used to
317 send an ack here which is very wrong! (and then fixed
318 the issues this gave by retrying reads) */
319 w9968cf_smbus_write_nack(sd);
320 w9968cf_smbus_stop(sd);
321
322 /* Fast serial bus data control re-enable */
323 w9968cf_write_sb(sd, 0x0030);
324
325 if (sd->gspca_dev.usb_err >= 0) {
326 ret = value;
327 PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
328 } else
329 PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg);
330
331 return ret;
332}
333
334/*--------------------------------------------------------------------------
335 Turn on the LED on some webcams. A beep should be heard too.
336 Return 0 on success, a negative number otherwise.
337 --------------------------------------------------------------------------*/
338static void w9968cf_configure(struct sd *sd)
339{
340 reg_w(sd, 0x00, 0xff00); /* power-down */
341 reg_w(sd, 0x00, 0xbf17); /* reset everything */
342 reg_w(sd, 0x00, 0xbf10); /* normal operation */
343 reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
344 reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
345 reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
346 reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
347
348 sd->stopped = 1;
349}
350
351static void w9968cf_init(struct sd *sd)
352{
353 unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2),
354 y0 = 0x0000,
355 u0 = y0 + hw_bufsize / 2,
356 v0 = u0 + hw_bufsize / 4,
357 y1 = v0 + hw_bufsize / 4,
358 u1 = y1 + hw_bufsize / 2,
359 v1 = u1 + hw_bufsize / 4;
360
361 reg_w(sd, 0x00, 0xff00); /* power off */
362 reg_w(sd, 0x00, 0xbf10); /* power on */
363
364 reg_w(sd, 0x03, 0x405d); /* DRAM timings */
365 reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
366
367 reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
368 reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */
369 reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
370 reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */
371 reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
372 reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */
373
374 reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
375 reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */
376 reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
377 reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */
378 reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
379 reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */
380
381 reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
382 reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */
383
384 reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
385 reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */
386
387 reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
388 reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
389 reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
390 reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
391}
392
393static void w9968cf_set_crop_window(struct sd *sd)
394{
395 int start_cropx, start_cropy, x, y, fw, fh, cw, ch,
396 max_width, max_height;
397
398 if (sd->sif) {
399 max_width = 352;
400 max_height = 288;
401 } else {
402 max_width = 640;
403 max_height = 480;
404 }
405
406 if (sd->sensor == SEN_OV7620) {
407 /*
408 * Sigh, this is dependend on the clock / framerate changes
409 * made by the frequency control, sick.
410 *
411 * Note we cannot use v4l2_ctrl_g_ctrl here, as we get called
412 * from ov519.c:setfreq() with the ctrl lock held!
413 */
414 if (sd->freq->val == 1) {
415 start_cropx = 277;
416 start_cropy = 37;
417 } else {
418 start_cropx = 105;
419 start_cropy = 37;
420 }
421 } else {
422 start_cropx = 320;
423 start_cropy = 35;
424 }
425
426 /* Work around to avoid FP arithmetics */
427 #define SC(x) ((x) << 10)
428
429 /* Scaling factors */
430 fw = SC(sd->gspca_dev.width) / max_width;
431 fh = SC(sd->gspca_dev.height) / max_height;
432
433 cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
434 ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
435
436 sd->sensor_width = max_width;
437 sd->sensor_height = max_height;
438
439 x = (max_width - cw) / 2;
440 y = (max_height - ch) / 2;
441
442 reg_w(sd, 0x10, start_cropx + x);
443 reg_w(sd, 0x11, start_cropy + y);
444 reg_w(sd, 0x12, start_cropx + x + cw);
445 reg_w(sd, 0x13, start_cropy + y + ch);
446}
447
448static void w9968cf_mode_init_regs(struct sd *sd)
449{
450 int val, vs_polarity, hs_polarity;
451
452 w9968cf_set_crop_window(sd);
453
454 reg_w(sd, 0x14, sd->gspca_dev.width);
455 reg_w(sd, 0x15, sd->gspca_dev.height);
456
457 /* JPEG width & height */
458 reg_w(sd, 0x30, sd->gspca_dev.width);
459 reg_w(sd, 0x31, sd->gspca_dev.height);
460
461 /* Y & UV frame buffer strides (in WORD) */
462 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
463 V4L2_PIX_FMT_JPEG) {
464 reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
465 reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
466 } else
467 reg_w(sd, 0x2c, sd->gspca_dev.width);
468
469 reg_w(sd, 0x00, 0xbf17); /* reset everything */
470 reg_w(sd, 0x00, 0xbf10); /* normal operation */
471
472 /* Transfer size in WORDS (for UYVY format only) */
473 val = sd->gspca_dev.width * sd->gspca_dev.height;
474 reg_w(sd, 0x3d, val & 0xffff); /* low bits */
475 reg_w(sd, 0x3e, val >> 16); /* high bits */
476
477 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
478 V4L2_PIX_FMT_JPEG) {
479 /* We may get called multiple times (usb isoc bw negotiat.) */
480 jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
481 sd->gspca_dev.width, 0x22); /* JPEG 420 */
482 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
483 w9968cf_upload_quantizationtables(sd);
484 v4l2_ctrl_grab(sd->jpegqual, true);
485 }
486
487 /* Video Capture Control Register */
488 if (sd->sensor == SEN_OV7620) {
489 /* Seems to work around a bug in the image sensor */
490 vs_polarity = 1;
491 hs_polarity = 1;
492 } else {
493 vs_polarity = 1;
494 hs_polarity = 0;
495 }
496
497 val = (vs_polarity << 12) | (hs_polarity << 11);
498
499 /* NOTE: We may not have enough memory to do double buffering while
500 doing compression (amount of memory differs per model cam).
501 So we use the second image buffer also as jpeg stream buffer
502 (see w9968cf_init), and disable double buffering. */
503 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
504 V4L2_PIX_FMT_JPEG) {
505 /* val |= 0x0002; YUV422P */
506 val |= 0x0003; /* YUV420P */
507 } else
508 val |= 0x0080; /* Enable HW double buffering */
509
510 /* val |= 0x0020; enable clamping */
511 /* val |= 0x0008; enable (1-2-1) filter */
512 /* val |= 0x000c; enable (2-3-6-3-2) filter */
513
514 val |= 0x8000; /* capt. enable */
515
516 reg_w(sd, 0x16, val);
517
518 sd->gspca_dev.empty_packet = 0;
519}
520
521static void w9968cf_stop0(struct sd *sd)
522{
523 v4l2_ctrl_grab(sd->jpegqual, false);
524 reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
525 reg_w(sd, 0x16, 0x0000); /* stop video capture */
526}
527
528/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF
529 for the next frame). This seems to simply not be true when operating
530 in JPEG mode, in this case there may be empty packets within the
531 frame. So in JPEG mode use the JPEG SOI marker to detect SOF.
532
533 Note to make things even more interesting the w9968cf sends *PLANAR* jpeg,
534 to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS,
535 V-data, EOI. */
536static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev,
537 u8 *data, /* isoc packet */
538 int len) /* iso packet length */
539{
540 struct sd *sd = (struct sd *) gspca_dev;
541
542 if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat ==
543 V4L2_PIX_FMT_JPEG) {
544 if (len >= 2 &&
545 data[0] == 0xff &&
546 data[1] == 0xd8) {
547 gspca_frame_add(gspca_dev, LAST_PACKET,
548 NULL, 0);
549 gspca_frame_add(gspca_dev, FIRST_PACKET,
550 sd->jpeg_hdr, JPEG_HDR_SZ);
551 /* Strip the ff d8, our own header (which adds
552 huffman and quantization tables) already has this */
553 len -= 2;
554 data += 2;
555 }
556 } else {
557 /* In UYVY mode an empty packet signals EOF */
558 if (gspca_dev->empty_packet) {
559 gspca_frame_add(gspca_dev, LAST_PACKET,
560 NULL, 0);
561 gspca_frame_add(gspca_dev, FIRST_PACKET,
562 NULL, 0);
563 gspca_dev->empty_packet = 0;
564 }
565 }
566 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
567}
diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c
new file mode 100644
index 00000000000..13b8d395d21
--- /dev/null
+++ b/drivers/media/usb/gspca/xirlink_cit.c
@@ -0,0 +1,3145 @@
1/*
2 * USB IBM C-It Video Camera driver
3 *
4 * Supports Xirlink C-It Video Camera, IBM PC Camera,
5 * IBM NetCamera and Veo Stingray.
6 *
7 * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
8 *
9 * This driver is based on earlier work of:
10 *
11 * (C) Copyright 1999 Johannes Erdfelt
12 * (C) Copyright 1999 Randy Dunlap
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#define MODULE_NAME "xirlink-cit"
33
34#include <linux/input.h>
35#include "gspca.h"
36
37MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
38MODULE_DESCRIPTION("Xirlink C-IT");
39MODULE_LICENSE("GPL");
40
41/* FIXME we should autodetect this */
42static int ibm_netcam_pro;
43module_param(ibm_netcam_pro, int, 0);
44MODULE_PARM_DESC(ibm_netcam_pro,
45 "Use IBM Netcamera Pro init sequences for Model 3 cams");
46
47/* FIXME this should be handled through the V4L2 input selection API */
48static int rca_input;
49module_param(rca_input, int, 0644);
50MODULE_PARM_DESC(rca_input,
51 "Use rca input instead of ccd sensor on Model 3 cams");
52
53/* specific webcam descriptor */
54struct sd {
55 struct gspca_dev gspca_dev; /* !! must be the first item */
56 struct v4l2_ctrl *lighting;
57 u8 model;
58#define CIT_MODEL0 0 /* bcd version 0.01 cams ie the xvp-500 */
59#define CIT_MODEL1 1 /* The model 1 - 4 nomenclature comes from the old */
60#define CIT_MODEL2 2 /* ibmcam driver */
61#define CIT_MODEL3 3
62#define CIT_MODEL4 4
63#define CIT_IBM_NETCAM_PRO 5
64 u8 input_index;
65 u8 button_state;
66 u8 stop_on_control_change;
67 u8 sof_read;
68 u8 sof_len;
69};
70
71static void sd_stop0(struct gspca_dev *gspca_dev);
72
73static const struct v4l2_pix_format cif_yuv_mode[] = {
74 {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
75 .bytesperline = 176,
76 .sizeimage = 176 * 144 * 3 / 2 + 4,
77 .colorspace = V4L2_COLORSPACE_SRGB},
78 {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
79 .bytesperline = 352,
80 .sizeimage = 352 * 288 * 3 / 2 + 4,
81 .colorspace = V4L2_COLORSPACE_SRGB},
82};
83
84static const struct v4l2_pix_format vga_yuv_mode[] = {
85 {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
86 .bytesperline = 160,
87 .sizeimage = 160 * 120 * 3 / 2 + 4,
88 .colorspace = V4L2_COLORSPACE_SRGB},
89 {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
90 .bytesperline = 320,
91 .sizeimage = 320 * 240 * 3 / 2 + 4,
92 .colorspace = V4L2_COLORSPACE_SRGB},
93 {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
94 .bytesperline = 640,
95 .sizeimage = 640 * 480 * 3 / 2 + 4,
96 .colorspace = V4L2_COLORSPACE_SRGB},
97};
98
99static const struct v4l2_pix_format model0_mode[] = {
100 {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
101 .bytesperline = 160,
102 .sizeimage = 160 * 120 * 3 / 2 + 4,
103 .colorspace = V4L2_COLORSPACE_SRGB},
104 {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
105 .bytesperline = 176,
106 .sizeimage = 176 * 144 * 3 / 2 + 4,
107 .colorspace = V4L2_COLORSPACE_SRGB},
108 {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
109 .bytesperline = 320,
110 .sizeimage = 320 * 240 * 3 / 2 + 4,
111 .colorspace = V4L2_COLORSPACE_SRGB},
112};
113
114static const struct v4l2_pix_format model2_mode[] = {
115 {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
116 .bytesperline = 160,
117 .sizeimage = 160 * 120 * 3 / 2 + 4,
118 .colorspace = V4L2_COLORSPACE_SRGB},
119 {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
120 .bytesperline = 176,
121 .sizeimage = 176 * 144 * 3 / 2 + 4,
122 .colorspace = V4L2_COLORSPACE_SRGB},
123 {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
124 .bytesperline = 320,
125 .sizeimage = 320 * 240 + 4,
126 .colorspace = V4L2_COLORSPACE_SRGB},
127 {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
128 .bytesperline = 352,
129 .sizeimage = 352 * 288 + 4,
130 .colorspace = V4L2_COLORSPACE_SRGB},
131};
132
133/*
134 * 01.01.08 - Added for RCA video in support -LO
135 * This struct is used to init the Model3 cam to use the RCA video in port
136 * instead of the CCD sensor.
137 */
138static const u16 rca_initdata[][3] = {
139 {0, 0x0000, 0x010c},
140 {0, 0x0006, 0x012c},
141 {0, 0x0078, 0x012d},
142 {0, 0x0046, 0x012f},
143 {0, 0xd141, 0x0124},
144 {0, 0x0000, 0x0127},
145 {0, 0xfea8, 0x0124},
146 {1, 0x0000, 0x0116},
147 {0, 0x0064, 0x0116},
148 {1, 0x0000, 0x0115},
149 {0, 0x0003, 0x0115},
150 {0, 0x0008, 0x0123},
151 {0, 0x0000, 0x0117},
152 {0, 0x0000, 0x0112},
153 {0, 0x0080, 0x0100},
154 {0, 0x0000, 0x0100},
155 {1, 0x0000, 0x0116},
156 {0, 0x0060, 0x0116},
157 {0, 0x0002, 0x0112},
158 {0, 0x0000, 0x0123},
159 {0, 0x0001, 0x0117},
160 {0, 0x0040, 0x0108},
161 {0, 0x0019, 0x012c},
162 {0, 0x0040, 0x0116},
163 {0, 0x000a, 0x0115},
164 {0, 0x000b, 0x0115},
165 {0, 0x0078, 0x012d},
166 {0, 0x0046, 0x012f},
167 {0, 0xd141, 0x0124},
168 {0, 0x0000, 0x0127},
169 {0, 0xfea8, 0x0124},
170 {0, 0x0064, 0x0116},
171 {0, 0x0000, 0x0115},
172 {0, 0x0001, 0x0115},
173 {0, 0xffff, 0x0124},
174 {0, 0xfff9, 0x0124},
175 {0, 0x0086, 0x0127},
176 {0, 0xfff8, 0x0124},
177 {0, 0xfffd, 0x0124},
178 {0, 0x00aa, 0x0127},
179 {0, 0xfff8, 0x0124},
180 {0, 0xfffd, 0x0124},
181 {0, 0x0000, 0x0127},
182 {0, 0xfff8, 0x0124},
183 {0, 0xfffd, 0x0124},
184 {0, 0xfffa, 0x0124},
185 {0, 0xffff, 0x0124},
186 {0, 0xfff9, 0x0124},
187 {0, 0x0086, 0x0127},
188 {0, 0xfff8, 0x0124},
189 {0, 0xfffd, 0x0124},
190 {0, 0x00f2, 0x0127},
191 {0, 0xfff8, 0x0124},
192 {0, 0xfffd, 0x0124},
193 {0, 0x000f, 0x0127},
194 {0, 0xfff8, 0x0124},
195 {0, 0xfffd, 0x0124},
196 {0, 0xfffa, 0x0124},
197 {0, 0xffff, 0x0124},
198 {0, 0xfff9, 0x0124},
199 {0, 0x0086, 0x0127},
200 {0, 0xfff8, 0x0124},
201 {0, 0xfffd, 0x0124},
202 {0, 0x00f8, 0x0127},
203 {0, 0xfff8, 0x0124},
204 {0, 0xfffd, 0x0124},
205 {0, 0x00fc, 0x0127},
206 {0, 0xfff8, 0x0124},
207 {0, 0xfffd, 0x0124},
208 {0, 0xfffa, 0x0124},
209 {0, 0xffff, 0x0124},
210 {0, 0xfff9, 0x0124},
211 {0, 0x0086, 0x0127},
212 {0, 0xfff8, 0x0124},
213 {0, 0xfffd, 0x0124},
214 {0, 0x00f9, 0x0127},
215 {0, 0xfff8, 0x0124},
216 {0, 0xfffd, 0x0124},
217 {0, 0x003c, 0x0127},
218 {0, 0xfff8, 0x0124},
219 {0, 0xfffd, 0x0124},
220 {0, 0xfffa, 0x0124},
221 {0, 0xffff, 0x0124},
222 {0, 0xfff9, 0x0124},
223 {0, 0x0086, 0x0127},
224 {0, 0xfff8, 0x0124},
225 {0, 0xfffd, 0x0124},
226 {0, 0x0027, 0x0127},
227 {0, 0xfff8, 0x0124},
228 {0, 0xfffd, 0x0124},
229 {0, 0x0019, 0x0127},
230 {0, 0xfff8, 0x0124},
231 {0, 0xfffd, 0x0124},
232 {0, 0xfffa, 0x0124},
233 {0, 0xfff9, 0x0124},
234 {0, 0x0086, 0x0127},
235 {0, 0xfff8, 0x0124},
236 {0, 0xfffd, 0x0124},
237 {0, 0x0037, 0x0127},
238 {0, 0xfff8, 0x0124},
239 {0, 0xfffd, 0x0124},
240 {0, 0x0000, 0x0127},
241 {0, 0xfff8, 0x0124},
242 {0, 0xfffd, 0x0124},
243 {0, 0x0021, 0x0127},
244 {0, 0xfff8, 0x0124},
245 {0, 0xfffd, 0x0124},
246 {0, 0xfffa, 0x0124},
247 {0, 0xfff9, 0x0124},
248 {0, 0x0086, 0x0127},
249 {0, 0xfff8, 0x0124},
250 {0, 0xfffd, 0x0124},
251 {0, 0x0038, 0x0127},
252 {0, 0xfff8, 0x0124},
253 {0, 0xfffd, 0x0124},
254 {0, 0x0006, 0x0127},
255 {0, 0xfff8, 0x0124},
256 {0, 0xfffd, 0x0124},
257 {0, 0x0045, 0x0127},
258 {0, 0xfff8, 0x0124},
259 {0, 0xfffd, 0x0124},
260 {0, 0xfffa, 0x0124},
261 {0, 0xfff9, 0x0124},
262 {0, 0x0086, 0x0127},
263 {0, 0xfff8, 0x0124},
264 {0, 0xfffd, 0x0124},
265 {0, 0x0037, 0x0127},
266 {0, 0xfff8, 0x0124},
267 {0, 0xfffd, 0x0124},
268 {0, 0x0001, 0x0127},
269 {0, 0xfff8, 0x0124},
270 {0, 0xfffd, 0x0124},
271 {0, 0x002a, 0x0127},
272 {0, 0xfff8, 0x0124},
273 {0, 0xfffd, 0x0124},
274 {0, 0xfffa, 0x0124},
275 {0, 0xfff9, 0x0124},
276 {0, 0x0086, 0x0127},
277 {0, 0xfff8, 0x0124},
278 {0, 0xfffd, 0x0124},
279 {0, 0x0038, 0x0127},
280 {0, 0xfff8, 0x0124},
281 {0, 0xfffd, 0x0124},
282 {0, 0x0000, 0x0127},
283 {0, 0xfff8, 0x0124},
284 {0, 0xfffd, 0x0124},
285 {0, 0x000e, 0x0127},
286 {0, 0xfff8, 0x0124},
287 {0, 0xfffd, 0x0124},
288 {0, 0xfffa, 0x0124},
289 {0, 0xfff9, 0x0124},
290 {0, 0x0086, 0x0127},
291 {0, 0xfff8, 0x0124},
292 {0, 0xfffd, 0x0124},
293 {0, 0x0037, 0x0127},
294 {0, 0xfff8, 0x0124},
295 {0, 0xfffd, 0x0124},
296 {0, 0x0001, 0x0127},
297 {0, 0xfff8, 0x0124},
298 {0, 0xfffd, 0x0124},
299 {0, 0x002b, 0x0127},
300 {0, 0xfff8, 0x0124},
301 {0, 0xfffd, 0x0124},
302 {0, 0xfffa, 0x0124},
303 {0, 0xfff9, 0x0124},
304 {0, 0x0086, 0x0127},
305 {0, 0xfff8, 0x0124},
306 {0, 0xfffd, 0x0124},
307 {0, 0x0038, 0x0127},
308 {0, 0xfff8, 0x0124},
309 {0, 0xfffd, 0x0124},
310 {0, 0x0001, 0x0127},
311 {0, 0xfff8, 0x0124},
312 {0, 0xfffd, 0x0124},
313 {0, 0x00f4, 0x0127},
314 {0, 0xfff8, 0x0124},
315 {0, 0xfffd, 0x0124},
316 {0, 0xfffa, 0x0124},
317 {0, 0xfff9, 0x0124},
318 {0, 0x0086, 0x0127},
319 {0, 0xfff8, 0x0124},
320 {0, 0xfffd, 0x0124},
321 {0, 0x0037, 0x0127},
322 {0, 0xfff8, 0x0124},
323 {0, 0xfffd, 0x0124},
324 {0, 0x0001, 0x0127},
325 {0, 0xfff8, 0x0124},
326 {0, 0xfffd, 0x0124},
327 {0, 0x002c, 0x0127},
328 {0, 0xfff8, 0x0124},
329 {0, 0xfffd, 0x0124},
330 {0, 0xfffa, 0x0124},
331 {0, 0xfff9, 0x0124},
332 {0, 0x0086, 0x0127},
333 {0, 0xfff8, 0x0124},
334 {0, 0xfffd, 0x0124},
335 {0, 0x0038, 0x0127},
336 {0, 0xfff8, 0x0124},
337 {0, 0xfffd, 0x0124},
338 {0, 0x0001, 0x0127},
339 {0, 0xfff8, 0x0124},
340 {0, 0xfffd, 0x0124},
341 {0, 0x0004, 0x0127},
342 {0, 0xfff8, 0x0124},
343 {0, 0xfffd, 0x0124},
344 {0, 0xfffa, 0x0124},
345 {0, 0xfff9, 0x0124},
346 {0, 0x0086, 0x0127},
347 {0, 0xfff8, 0x0124},
348 {0, 0xfffd, 0x0124},
349 {0, 0x0037, 0x0127},
350 {0, 0xfff8, 0x0124},
351 {0, 0xfffd, 0x0124},
352 {0, 0x0001, 0x0127},
353 {0, 0xfff8, 0x0124},
354 {0, 0xfffd, 0x0124},
355 {0, 0x002d, 0x0127},
356 {0, 0xfff8, 0x0124},
357 {0, 0xfffd, 0x0124},
358 {0, 0xfffa, 0x0124},
359 {0, 0xfff9, 0x0124},
360 {0, 0x0086, 0x0127},
361 {0, 0xfff8, 0x0124},
362 {0, 0xfffd, 0x0124},
363 {0, 0x0038, 0x0127},
364 {0, 0xfff8, 0x0124},
365 {0, 0xfffd, 0x0124},
366 {0, 0x0000, 0x0127},
367 {0, 0xfff8, 0x0124},
368 {0, 0xfffd, 0x0124},
369 {0, 0x0014, 0x0127},
370 {0, 0xfff8, 0x0124},
371 {0, 0xfffd, 0x0124},
372 {0, 0xfffa, 0x0124},
373 {0, 0xfff9, 0x0124},
374 {0, 0x0086, 0x0127},
375 {0, 0xfff8, 0x0124},
376 {0, 0xfffd, 0x0124},
377 {0, 0x0037, 0x0127},
378 {0, 0xfff8, 0x0124},
379 {0, 0xfffd, 0x0124},
380 {0, 0x0001, 0x0127},
381 {0, 0xfff8, 0x0124},
382 {0, 0xfffd, 0x0124},
383 {0, 0x002e, 0x0127},
384 {0, 0xfff8, 0x0124},
385 {0, 0xfffd, 0x0124},
386 {0, 0xfffa, 0x0124},
387 {0, 0xfff9, 0x0124},
388 {0, 0x0086, 0x0127},
389 {0, 0xfff8, 0x0124},
390 {0, 0xfffd, 0x0124},
391 {0, 0x0038, 0x0127},
392 {0, 0xfff8, 0x0124},
393 {0, 0xfffd, 0x0124},
394 {0, 0x0003, 0x0127},
395 {0, 0xfff8, 0x0124},
396 {0, 0xfffd, 0x0124},
397 {0, 0x0000, 0x0127},
398 {0, 0xfff8, 0x0124},
399 {0, 0xfffd, 0x0124},
400 {0, 0xfffa, 0x0124},
401 {0, 0xfff9, 0x0124},
402 {0, 0x0086, 0x0127},
403 {0, 0xfff8, 0x0124},
404 {0, 0xfffd, 0x0124},
405 {0, 0x0037, 0x0127},
406 {0, 0xfff8, 0x0124},
407 {0, 0xfffd, 0x0124},
408 {0, 0x0001, 0x0127},
409 {0, 0xfff8, 0x0124},
410 {0, 0xfffd, 0x0124},
411 {0, 0x002f, 0x0127},
412 {0, 0xfff8, 0x0124},
413 {0, 0xfffd, 0x0124},
414 {0, 0xfffa, 0x0124},
415 {0, 0xfff9, 0x0124},
416 {0, 0x0086, 0x0127},
417 {0, 0xfff8, 0x0124},
418 {0, 0xfffd, 0x0124},
419 {0, 0x0038, 0x0127},
420 {0, 0xfff8, 0x0124},
421 {0, 0xfffd, 0x0124},
422 {0, 0x0003, 0x0127},
423 {0, 0xfff8, 0x0124},
424 {0, 0xfffd, 0x0124},
425 {0, 0x0014, 0x0127},
426 {0, 0xfff8, 0x0124},
427 {0, 0xfffd, 0x0124},
428 {0, 0xfffa, 0x0124},
429 {0, 0xfff9, 0x0124},
430 {0, 0x0086, 0x0127},
431 {0, 0xfff8, 0x0124},
432 {0, 0xfffd, 0x0124},
433 {0, 0x0037, 0x0127},
434 {0, 0xfff8, 0x0124},
435 {0, 0xfffd, 0x0124},
436 {0, 0x0001, 0x0127},
437 {0, 0xfff8, 0x0124},
438 {0, 0xfffd, 0x0124},
439 {0, 0x0040, 0x0127},
440 {0, 0xfff8, 0x0124},
441 {0, 0xfffd, 0x0124},
442 {0, 0xfffa, 0x0124},
443 {0, 0xfff9, 0x0124},
444 {0, 0x0086, 0x0127},
445 {0, 0xfff8, 0x0124},
446 {0, 0xfffd, 0x0124},
447 {0, 0x0038, 0x0127},
448 {0, 0xfff8, 0x0124},
449 {0, 0xfffd, 0x0124},
450 {0, 0x0000, 0x0127},
451 {0, 0xfff8, 0x0124},
452 {0, 0xfffd, 0x0124},
453 {0, 0x0040, 0x0127},
454 {0, 0xfff8, 0x0124},
455 {0, 0xfffd, 0x0124},
456 {0, 0xfffa, 0x0124},
457 {0, 0xfff9, 0x0124},
458 {0, 0x0086, 0x0127},
459 {0, 0xfff8, 0x0124},
460 {0, 0xfffd, 0x0124},
461 {0, 0x0037, 0x0127},
462 {0, 0xfff8, 0x0124},
463 {0, 0xfffd, 0x0124},
464 {0, 0x0001, 0x0127},
465 {0, 0xfff8, 0x0124},
466 {0, 0xfffd, 0x0124},
467 {0, 0x0053, 0x0127},
468 {0, 0xfff8, 0x0124},
469 {0, 0xfffd, 0x0124},
470 {0, 0xfffa, 0x0124},
471 {0, 0xfff9, 0x0124},
472 {0, 0x0086, 0x0127},
473 {0, 0xfff8, 0x0124},
474 {0, 0xfffd, 0x0124},
475 {0, 0x0038, 0x0127},
476 {0, 0xfff8, 0x0124},
477 {0, 0xfffd, 0x0124},
478 {0, 0x0000, 0x0127},
479 {0, 0xfff8, 0x0124},
480 {0, 0xfffd, 0x0124},
481 {0, 0x0038, 0x0127},
482 {0, 0xfff8, 0x0124},
483 {0, 0xfffd, 0x0124},
484 {0, 0xfffa, 0x0124},
485 {0, 0x0000, 0x0101},
486 {0, 0x00a0, 0x0103},
487 {0, 0x0078, 0x0105},
488 {0, 0x0000, 0x010a},
489 {0, 0x0024, 0x010b},
490 {0, 0x0028, 0x0119},
491 {0, 0x0088, 0x011b},
492 {0, 0x0002, 0x011d},
493 {0, 0x0003, 0x011e},
494 {0, 0x0000, 0x0129},
495 {0, 0x00fc, 0x012b},
496 {0, 0x0008, 0x0102},
497 {0, 0x0000, 0x0104},
498 {0, 0x0008, 0x011a},
499 {0, 0x0028, 0x011c},
500 {0, 0x0021, 0x012a},
501 {0, 0x0000, 0x0118},
502 {0, 0x0000, 0x0132},
503 {0, 0x0000, 0x0109},
504 {0, 0xfff9, 0x0124},
505 {0, 0x0086, 0x0127},
506 {0, 0xfff8, 0x0124},
507 {0, 0xfffd, 0x0124},
508 {0, 0x0037, 0x0127},
509 {0, 0xfff8, 0x0124},
510 {0, 0xfffd, 0x0124},
511 {0, 0x0001, 0x0127},
512 {0, 0xfff8, 0x0124},
513 {0, 0xfffd, 0x0124},
514 {0, 0x0031, 0x0127},
515 {0, 0xfff8, 0x0124},
516 {0, 0xfffd, 0x0124},
517 {0, 0xfffa, 0x0124},
518 {0, 0xfff9, 0x0124},
519 {0, 0x0086, 0x0127},
520 {0, 0xfff8, 0x0124},
521 {0, 0xfffd, 0x0124},
522 {0, 0x0038, 0x0127},
523 {0, 0xfff8, 0x0124},
524 {0, 0xfffd, 0x0124},
525 {0, 0x0000, 0x0127},
526 {0, 0xfff8, 0x0124},
527 {0, 0xfffd, 0x0124},
528 {0, 0x0000, 0x0127},
529 {0, 0xfff8, 0x0124},
530 {0, 0xfffd, 0x0124},
531 {0, 0xfffa, 0x0124},
532 {0, 0xfff9, 0x0124},
533 {0, 0x0086, 0x0127},
534 {0, 0xfff8, 0x0124},
535 {0, 0xfffd, 0x0124},
536 {0, 0x0037, 0x0127},
537 {0, 0xfff8, 0x0124},
538 {0, 0xfffd, 0x0124},
539 {0, 0x0001, 0x0127},
540 {0, 0xfff8, 0x0124},
541 {0, 0xfffd, 0x0124},
542 {0, 0x0040, 0x0127},
543 {0, 0xfff8, 0x0124},
544 {0, 0xfffd, 0x0124},
545 {0, 0xfffa, 0x0124},
546 {0, 0xfff9, 0x0124},
547 {0, 0x0086, 0x0127},
548 {0, 0xfff8, 0x0124},
549 {0, 0xfffd, 0x0124},
550 {0, 0x0038, 0x0127},
551 {0, 0xfff8, 0x0124},
552 {0, 0xfffd, 0x0124},
553 {0, 0x0000, 0x0127},
554 {0, 0xfff8, 0x0124},
555 {0, 0xfffd, 0x0124},
556 {0, 0x0040, 0x0127},
557 {0, 0xfff8, 0x0124},
558 {0, 0xfffd, 0x0124},
559 {0, 0xfffa, 0x0124},
560 {0, 0xfff9, 0x0124},
561 {0, 0x0086, 0x0127},
562 {0, 0xfff8, 0x0124},
563 {0, 0xfffd, 0x0124},
564 {0, 0x0037, 0x0127},
565 {0, 0xfff8, 0x0124},
566 {0, 0xfffd, 0x0124},
567 {0, 0x0000, 0x0127},
568 {0, 0xfff8, 0x0124},
569 {0, 0xfffd, 0x0124},
570 {0, 0x00dc, 0x0127},
571 {0, 0xfff8, 0x0124},
572 {0, 0xfffd, 0x0124},
573 {0, 0xfffa, 0x0124},
574 {0, 0xfff9, 0x0124},
575 {0, 0x0086, 0x0127},
576 {0, 0xfff8, 0x0124},
577 {0, 0xfffd, 0x0124},
578 {0, 0x0038, 0x0127},
579 {0, 0xfff8, 0x0124},
580 {0, 0xfffd, 0x0124},
581 {0, 0x0000, 0x0127},
582 {0, 0xfff8, 0x0124},
583 {0, 0xfffd, 0x0124},
584 {0, 0x0000, 0x0127},
585 {0, 0xfff8, 0x0124},
586 {0, 0xfffd, 0x0124},
587 {0, 0xfffa, 0x0124},
588 {0, 0xfff9, 0x0124},
589 {0, 0x0086, 0x0127},
590 {0, 0xfff8, 0x0124},
591 {0, 0xfffd, 0x0124},
592 {0, 0x0037, 0x0127},
593 {0, 0xfff8, 0x0124},
594 {0, 0xfffd, 0x0124},
595 {0, 0x0001, 0x0127},
596 {0, 0xfff8, 0x0124},
597 {0, 0xfffd, 0x0124},
598 {0, 0x0032, 0x0127},
599 {0, 0xfff8, 0x0124},
600 {0, 0xfffd, 0x0124},
601 {0, 0xfffa, 0x0124},
602 {0, 0xfff9, 0x0124},
603 {0, 0x0086, 0x0127},
604 {0, 0xfff8, 0x0124},
605 {0, 0xfffd, 0x0124},
606 {0, 0x0038, 0x0127},
607 {0, 0xfff8, 0x0124},
608 {0, 0xfffd, 0x0124},
609 {0, 0x0001, 0x0127},
610 {0, 0xfff8, 0x0124},
611 {0, 0xfffd, 0x0124},
612 {0, 0x0020, 0x0127},
613 {0, 0xfff8, 0x0124},
614 {0, 0xfffd, 0x0124},
615 {0, 0xfffa, 0x0124},
616 {0, 0xfff9, 0x0124},
617 {0, 0x0086, 0x0127},
618 {0, 0xfff8, 0x0124},
619 {0, 0xfffd, 0x0124},
620 {0, 0x0037, 0x0127},
621 {0, 0xfff8, 0x0124},
622 {0, 0xfffd, 0x0124},
623 {0, 0x0001, 0x0127},
624 {0, 0xfff8, 0x0124},
625 {0, 0xfffd, 0x0124},
626 {0, 0x0040, 0x0127},
627 {0, 0xfff8, 0x0124},
628 {0, 0xfffd, 0x0124},
629 {0, 0xfffa, 0x0124},
630 {0, 0xfff9, 0x0124},
631 {0, 0x0086, 0x0127},
632 {0, 0xfff8, 0x0124},
633 {0, 0xfffd, 0x0124},
634 {0, 0x0038, 0x0127},
635 {0, 0xfff8, 0x0124},
636 {0, 0xfffd, 0x0124},
637 {0, 0x0000, 0x0127},
638 {0, 0xfff8, 0x0124},
639 {0, 0xfffd, 0x0124},
640 {0, 0x0040, 0x0127},
641 {0, 0xfff8, 0x0124},
642 {0, 0xfffd, 0x0124},
643 {0, 0xfffa, 0x0124},
644 {0, 0xfff9, 0x0124},
645 {0, 0x0086, 0x0127},
646 {0, 0xfff8, 0x0124},
647 {0, 0xfffd, 0x0124},
648 {0, 0x0037, 0x0127},
649 {0, 0xfff8, 0x0124},
650 {0, 0xfffd, 0x0124},
651 {0, 0x0000, 0x0127},
652 {0, 0xfff8, 0x0124},
653 {0, 0xfffd, 0x0124},
654 {0, 0x0030, 0x0127},
655 {0, 0xfff8, 0x0124},
656 {0, 0xfffd, 0x0124},
657 {0, 0xfffa, 0x0124},
658 {0, 0xfff9, 0x0124},
659 {0, 0x0086, 0x0127},
660 {0, 0xfff8, 0x0124},
661 {0, 0xfffd, 0x0124},
662 {0, 0x0038, 0x0127},
663 {0, 0xfff8, 0x0124},
664 {0, 0xfffd, 0x0124},
665 {0, 0x0008, 0x0127},
666 {0, 0xfff8, 0x0124},
667 {0, 0xfffd, 0x0124},
668 {0, 0x0000, 0x0127},
669 {0, 0xfff8, 0x0124},
670 {0, 0xfffd, 0x0124},
671 {0, 0xfffa, 0x0124},
672 {0, 0x0003, 0x0111},
673};
674
675/* TESTME the old ibmcam driver repeats certain commands to Model1 cameras, we
676 do the same for now (testing needed to see if this is really necessary) */
677static const int cit_model1_ntries = 5;
678static const int cit_model1_ntries2 = 2;
679
680static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
681{
682 struct usb_device *udev = gspca_dev->dev;
683 int err;
684
685 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
686 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
687 value, index, NULL, 0, 1000);
688 if (err < 0)
689 pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
690 index, value, err);
691
692 return 0;
693}
694
695static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
696{
697 struct usb_device *udev = gspca_dev->dev;
698 __u8 *buf = gspca_dev->usb_buf;
699 int res;
700
701 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01,
702 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
703 0x00, index, buf, 8, 1000);
704 if (res < 0) {
705 pr_err("Failed to read a register (index 0x%04X, error %d)\n",
706 index, res);
707 return res;
708 }
709
710 if (verbose)
711 PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]);
712
713 return 0;
714}
715
716/*
717 * cit_send_FF_04_02()
718 *
719 * This procedure sends magic 3-command prefix to the camera.
720 * The purpose of this prefix is not known.
721 *
722 * History:
723 * 1/2/00 Created.
724 */
725static void cit_send_FF_04_02(struct gspca_dev *gspca_dev)
726{
727 cit_write_reg(gspca_dev, 0x00FF, 0x0127);
728 cit_write_reg(gspca_dev, 0x0004, 0x0124);
729 cit_write_reg(gspca_dev, 0x0002, 0x0124);
730}
731
732static void cit_send_00_04_06(struct gspca_dev *gspca_dev)
733{
734 cit_write_reg(gspca_dev, 0x0000, 0x0127);
735 cit_write_reg(gspca_dev, 0x0004, 0x0124);
736 cit_write_reg(gspca_dev, 0x0006, 0x0124);
737}
738
739static void cit_send_x_00(struct gspca_dev *gspca_dev, unsigned short x)
740{
741 cit_write_reg(gspca_dev, x, 0x0127);
742 cit_write_reg(gspca_dev, 0x0000, 0x0124);
743}
744
745static void cit_send_x_00_05(struct gspca_dev *gspca_dev, unsigned short x)
746{
747 cit_send_x_00(gspca_dev, x);
748 cit_write_reg(gspca_dev, 0x0005, 0x0124);
749}
750
751static void cit_send_x_00_05_02(struct gspca_dev *gspca_dev, unsigned short x)
752{
753 cit_write_reg(gspca_dev, x, 0x0127);
754 cit_write_reg(gspca_dev, 0x0000, 0x0124);
755 cit_write_reg(gspca_dev, 0x0005, 0x0124);
756 cit_write_reg(gspca_dev, 0x0002, 0x0124);
757}
758
759static void cit_send_x_01_00_05(struct gspca_dev *gspca_dev, u16 x)
760{
761 cit_write_reg(gspca_dev, x, 0x0127);
762 cit_write_reg(gspca_dev, 0x0001, 0x0124);
763 cit_write_reg(gspca_dev, 0x0000, 0x0124);
764 cit_write_reg(gspca_dev, 0x0005, 0x0124);
765}
766
767static void cit_send_x_00_05_02_01(struct gspca_dev *gspca_dev, u16 x)
768{
769 cit_write_reg(gspca_dev, x, 0x0127);
770 cit_write_reg(gspca_dev, 0x0000, 0x0124);
771 cit_write_reg(gspca_dev, 0x0005, 0x0124);
772 cit_write_reg(gspca_dev, 0x0002, 0x0124);
773 cit_write_reg(gspca_dev, 0x0001, 0x0124);
774}
775
776static void cit_send_x_00_05_02_08_01(struct gspca_dev *gspca_dev, u16 x)
777{
778 cit_write_reg(gspca_dev, x, 0x0127);
779 cit_write_reg(gspca_dev, 0x0000, 0x0124);
780 cit_write_reg(gspca_dev, 0x0005, 0x0124);
781 cit_write_reg(gspca_dev, 0x0002, 0x0124);
782 cit_write_reg(gspca_dev, 0x0008, 0x0124);
783 cit_write_reg(gspca_dev, 0x0001, 0x0124);
784}
785
786static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
787{
788 cit_send_x_01_00_05(gspca_dev, 0x0088);
789 cit_send_x_00_05(gspca_dev, fkey);
790 cit_send_x_00_05_02_08_01(gspca_dev, val);
791 cit_send_x_00_05(gspca_dev, 0x0088);
792 cit_send_x_00_05_02_01(gspca_dev, fkey);
793 cit_send_x_00_05(gspca_dev, 0x0089);
794 cit_send_x_00(gspca_dev, fkey);
795 cit_send_00_04_06(gspca_dev);
796 cit_read_reg(gspca_dev, 0x0126, 0);
797 cit_send_FF_04_02(gspca_dev);
798}
799
800static void cit_PacketFormat2(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
801{
802 cit_send_x_01_00_05(gspca_dev, 0x0088);
803 cit_send_x_00_05(gspca_dev, fkey);
804 cit_send_x_00_05_02(gspca_dev, val);
805}
806
807static void cit_model2_Packet2(struct gspca_dev *gspca_dev)
808{
809 cit_write_reg(gspca_dev, 0x00ff, 0x012d);
810 cit_write_reg(gspca_dev, 0xfea3, 0x0124);
811}
812
813static void cit_model2_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
814{
815 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
816 cit_write_reg(gspca_dev, 0x00ff, 0x012e);
817 cit_write_reg(gspca_dev, v1, 0x012f);
818 cit_write_reg(gspca_dev, 0x00ff, 0x0130);
819 cit_write_reg(gspca_dev, 0xc719, 0x0124);
820 cit_write_reg(gspca_dev, v2, 0x0127);
821
822 cit_model2_Packet2(gspca_dev);
823}
824
825/*
826 * cit_model3_Packet1()
827 *
828 * 00_0078_012d
829 * 00_0097_012f
830 * 00_d141_0124
831 * 00_0096_0127
832 * 00_fea8_0124
833*/
834static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
835{
836 cit_write_reg(gspca_dev, 0x0078, 0x012d);
837 cit_write_reg(gspca_dev, v1, 0x012f);
838 cit_write_reg(gspca_dev, 0xd141, 0x0124);
839 cit_write_reg(gspca_dev, v2, 0x0127);
840 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
841}
842
843static void cit_model4_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
844{
845 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
846 cit_write_reg(gspca_dev, v1, 0x012f);
847 cit_write_reg(gspca_dev, 0xd141, 0x0124);
848 cit_write_reg(gspca_dev, v2, 0x0127);
849 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
850}
851
852static void cit_model4_BrightnessPacket(struct gspca_dev *gspca_dev, u16 val)
853{
854 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
855 cit_write_reg(gspca_dev, 0x0026, 0x012f);
856 cit_write_reg(gspca_dev, 0xd141, 0x0124);
857 cit_write_reg(gspca_dev, val, 0x0127);
858 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
859 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
860 cit_write_reg(gspca_dev, 0x0038, 0x012d);
861 cit_write_reg(gspca_dev, 0x0004, 0x012f);
862 cit_write_reg(gspca_dev, 0xd145, 0x0124);
863 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
864}
865
866/* this function is called at probe time */
867static int sd_config(struct gspca_dev *gspca_dev,
868 const struct usb_device_id *id)
869{
870 struct sd *sd = (struct sd *) gspca_dev;
871 struct cam *cam;
872
873 sd->model = id->driver_info;
874 if (sd->model == CIT_MODEL3 && ibm_netcam_pro)
875 sd->model = CIT_IBM_NETCAM_PRO;
876
877 cam = &gspca_dev->cam;
878 switch (sd->model) {
879 case CIT_MODEL0:
880 cam->cam_mode = model0_mode;
881 cam->nmodes = ARRAY_SIZE(model0_mode);
882 sd->sof_len = 4;
883 break;
884 case CIT_MODEL1:
885 cam->cam_mode = cif_yuv_mode;
886 cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
887 sd->sof_len = 4;
888 break;
889 case CIT_MODEL2:
890 cam->cam_mode = model2_mode + 1; /* no 160x120 */
891 cam->nmodes = 3;
892 break;
893 case CIT_MODEL3:
894 cam->cam_mode = vga_yuv_mode;
895 cam->nmodes = ARRAY_SIZE(vga_yuv_mode);
896 sd->stop_on_control_change = 1;
897 sd->sof_len = 4;
898 break;
899 case CIT_MODEL4:
900 cam->cam_mode = model2_mode;
901 cam->nmodes = ARRAY_SIZE(model2_mode);
902 break;
903 case CIT_IBM_NETCAM_PRO:
904 cam->cam_mode = vga_yuv_mode;
905 cam->nmodes = 2; /* no 640 x 480 */
906 cam->input_flags = V4L2_IN_ST_VFLIP;
907 sd->stop_on_control_change = 1;
908 sd->sof_len = 4;
909 break;
910 }
911
912 return 0;
913}
914
915static int cit_init_model0(struct gspca_dev *gspca_dev)
916{
917 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
918 cit_write_reg(gspca_dev, 0x0001, 0x0112); /* turn on autogain ? */
919 cit_write_reg(gspca_dev, 0x0000, 0x0400);
920 cit_write_reg(gspca_dev, 0x0001, 0x0400);
921 cit_write_reg(gspca_dev, 0x0000, 0x0420);
922 cit_write_reg(gspca_dev, 0x0001, 0x0420);
923 cit_write_reg(gspca_dev, 0x000d, 0x0409);
924 cit_write_reg(gspca_dev, 0x0002, 0x040a);
925 cit_write_reg(gspca_dev, 0x0018, 0x0405);
926 cit_write_reg(gspca_dev, 0x0008, 0x0435);
927 cit_write_reg(gspca_dev, 0x0026, 0x040b);
928 cit_write_reg(gspca_dev, 0x0007, 0x0437);
929 cit_write_reg(gspca_dev, 0x0015, 0x042f);
930 cit_write_reg(gspca_dev, 0x002b, 0x0439);
931 cit_write_reg(gspca_dev, 0x0026, 0x043a);
932 cit_write_reg(gspca_dev, 0x0008, 0x0438);
933 cit_write_reg(gspca_dev, 0x001e, 0x042b);
934 cit_write_reg(gspca_dev, 0x0041, 0x042c);
935
936 return 0;
937}
938
939static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
940{
941 cit_read_reg(gspca_dev, 0x128, 1);
942 cit_write_reg(gspca_dev, 0x0003, 0x0133);
943 cit_write_reg(gspca_dev, 0x0000, 0x0117);
944 cit_write_reg(gspca_dev, 0x0008, 0x0123);
945 cit_write_reg(gspca_dev, 0x0000, 0x0100);
946 cit_read_reg(gspca_dev, 0x0116, 0);
947 cit_write_reg(gspca_dev, 0x0060, 0x0116);
948 cit_write_reg(gspca_dev, 0x0002, 0x0112);
949 cit_write_reg(gspca_dev, 0x0000, 0x0133);
950 cit_write_reg(gspca_dev, 0x0000, 0x0123);
951 cit_write_reg(gspca_dev, 0x0001, 0x0117);
952 cit_write_reg(gspca_dev, 0x0040, 0x0108);
953 cit_write_reg(gspca_dev, 0x0019, 0x012c);
954 cit_write_reg(gspca_dev, 0x0060, 0x0116);
955 cit_write_reg(gspca_dev, 0x0002, 0x0115);
956 cit_write_reg(gspca_dev, 0x000b, 0x0115);
957
958 cit_write_reg(gspca_dev, 0x0078, 0x012d);
959 cit_write_reg(gspca_dev, 0x0001, 0x012f);
960 cit_write_reg(gspca_dev, 0xd141, 0x0124);
961 cit_write_reg(gspca_dev, 0x0079, 0x012d);
962 cit_write_reg(gspca_dev, 0x00ff, 0x0130);
963 cit_write_reg(gspca_dev, 0xcd41, 0x0124);
964 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
965 cit_read_reg(gspca_dev, 0x0126, 1);
966
967 cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
968 cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
969 cit_model3_Packet1(gspca_dev, 0x000b, 0x0000);
970 cit_model3_Packet1(gspca_dev, 0x000c, 0x0008);
971 cit_model3_Packet1(gspca_dev, 0x000d, 0x003a);
972 cit_model3_Packet1(gspca_dev, 0x000e, 0x0060);
973 cit_model3_Packet1(gspca_dev, 0x000f, 0x0060);
974 cit_model3_Packet1(gspca_dev, 0x0010, 0x0008);
975 cit_model3_Packet1(gspca_dev, 0x0011, 0x0004);
976 cit_model3_Packet1(gspca_dev, 0x0012, 0x0028);
977 cit_model3_Packet1(gspca_dev, 0x0013, 0x0002);
978 cit_model3_Packet1(gspca_dev, 0x0014, 0x0000);
979 cit_model3_Packet1(gspca_dev, 0x0015, 0x00fb);
980 cit_model3_Packet1(gspca_dev, 0x0016, 0x0002);
981 cit_model3_Packet1(gspca_dev, 0x0017, 0x0037);
982 cit_model3_Packet1(gspca_dev, 0x0018, 0x0036);
983 cit_model3_Packet1(gspca_dev, 0x001e, 0x0000);
984 cit_model3_Packet1(gspca_dev, 0x001f, 0x0008);
985 cit_model3_Packet1(gspca_dev, 0x0020, 0x00c1);
986 cit_model3_Packet1(gspca_dev, 0x0021, 0x0034);
987 cit_model3_Packet1(gspca_dev, 0x0022, 0x0034);
988 cit_model3_Packet1(gspca_dev, 0x0025, 0x0002);
989 cit_model3_Packet1(gspca_dev, 0x0028, 0x0022);
990 cit_model3_Packet1(gspca_dev, 0x0029, 0x000a);
991 cit_model3_Packet1(gspca_dev, 0x002b, 0x0000);
992 cit_model3_Packet1(gspca_dev, 0x002c, 0x0000);
993 cit_model3_Packet1(gspca_dev, 0x002d, 0x00ff);
994 cit_model3_Packet1(gspca_dev, 0x002e, 0x00ff);
995 cit_model3_Packet1(gspca_dev, 0x002f, 0x00ff);
996 cit_model3_Packet1(gspca_dev, 0x0030, 0x00ff);
997 cit_model3_Packet1(gspca_dev, 0x0031, 0x00ff);
998 cit_model3_Packet1(gspca_dev, 0x0032, 0x0007);
999 cit_model3_Packet1(gspca_dev, 0x0033, 0x0005);
1000 cit_model3_Packet1(gspca_dev, 0x0037, 0x0040);
1001 cit_model3_Packet1(gspca_dev, 0x0039, 0x0000);
1002 cit_model3_Packet1(gspca_dev, 0x003a, 0x0000);
1003 cit_model3_Packet1(gspca_dev, 0x003b, 0x0001);
1004 cit_model3_Packet1(gspca_dev, 0x003c, 0x0000);
1005 cit_model3_Packet1(gspca_dev, 0x0040, 0x000c);
1006 cit_model3_Packet1(gspca_dev, 0x0041, 0x00fb);
1007 cit_model3_Packet1(gspca_dev, 0x0042, 0x0002);
1008 cit_model3_Packet1(gspca_dev, 0x0043, 0x0000);
1009 cit_model3_Packet1(gspca_dev, 0x0045, 0x0000);
1010 cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
1011 cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
1012 cit_model3_Packet1(gspca_dev, 0x0048, 0x0000);
1013 cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
1014 cit_model3_Packet1(gspca_dev, 0x004a, 0x00ff);
1015 cit_model3_Packet1(gspca_dev, 0x004b, 0x00ff);
1016 cit_model3_Packet1(gspca_dev, 0x004c, 0x00ff);
1017 cit_model3_Packet1(gspca_dev, 0x004f, 0x0000);
1018 cit_model3_Packet1(gspca_dev, 0x0050, 0x0000);
1019 cit_model3_Packet1(gspca_dev, 0x0051, 0x0002);
1020 cit_model3_Packet1(gspca_dev, 0x0055, 0x0000);
1021 cit_model3_Packet1(gspca_dev, 0x0056, 0x0000);
1022 cit_model3_Packet1(gspca_dev, 0x0057, 0x0000);
1023 cit_model3_Packet1(gspca_dev, 0x0058, 0x0002);
1024 cit_model3_Packet1(gspca_dev, 0x0059, 0x0000);
1025 cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);
1026 cit_model3_Packet1(gspca_dev, 0x005d, 0x0022);
1027 cit_model3_Packet1(gspca_dev, 0x005e, 0x003c);
1028 cit_model3_Packet1(gspca_dev, 0x005f, 0x0050);
1029 cit_model3_Packet1(gspca_dev, 0x0060, 0x0044);
1030 cit_model3_Packet1(gspca_dev, 0x0061, 0x0005);
1031 cit_model3_Packet1(gspca_dev, 0x006a, 0x007e);
1032 cit_model3_Packet1(gspca_dev, 0x006f, 0x0000);
1033 cit_model3_Packet1(gspca_dev, 0x0072, 0x001b);
1034 cit_model3_Packet1(gspca_dev, 0x0073, 0x0005);
1035 cit_model3_Packet1(gspca_dev, 0x0074, 0x000a);
1036 cit_model3_Packet1(gspca_dev, 0x0075, 0x001b);
1037 cit_model3_Packet1(gspca_dev, 0x0076, 0x002a);
1038 cit_model3_Packet1(gspca_dev, 0x0077, 0x003c);
1039 cit_model3_Packet1(gspca_dev, 0x0078, 0x0050);
1040 cit_model3_Packet1(gspca_dev, 0x007b, 0x0000);
1041 cit_model3_Packet1(gspca_dev, 0x007c, 0x0011);
1042 cit_model3_Packet1(gspca_dev, 0x007d, 0x0024);
1043 cit_model3_Packet1(gspca_dev, 0x007e, 0x0043);
1044 cit_model3_Packet1(gspca_dev, 0x007f, 0x005a);
1045 cit_model3_Packet1(gspca_dev, 0x0084, 0x0020);
1046 cit_model3_Packet1(gspca_dev, 0x0085, 0x0033);
1047 cit_model3_Packet1(gspca_dev, 0x0086, 0x000a);
1048 cit_model3_Packet1(gspca_dev, 0x0087, 0x0030);
1049 cit_model3_Packet1(gspca_dev, 0x0088, 0x0070);
1050 cit_model3_Packet1(gspca_dev, 0x008b, 0x0008);
1051 cit_model3_Packet1(gspca_dev, 0x008f, 0x0000);
1052 cit_model3_Packet1(gspca_dev, 0x0090, 0x0006);
1053 cit_model3_Packet1(gspca_dev, 0x0091, 0x0028);
1054 cit_model3_Packet1(gspca_dev, 0x0092, 0x005a);
1055 cit_model3_Packet1(gspca_dev, 0x0093, 0x0082);
1056 cit_model3_Packet1(gspca_dev, 0x0096, 0x0014);
1057 cit_model3_Packet1(gspca_dev, 0x0097, 0x0020);
1058 cit_model3_Packet1(gspca_dev, 0x0098, 0x0000);
1059 cit_model3_Packet1(gspca_dev, 0x00b0, 0x0046);
1060 cit_model3_Packet1(gspca_dev, 0x00b1, 0x0000);
1061 cit_model3_Packet1(gspca_dev, 0x00b2, 0x0000);
1062 cit_model3_Packet1(gspca_dev, 0x00b3, 0x0004);
1063 cit_model3_Packet1(gspca_dev, 0x00b4, 0x0007);
1064 cit_model3_Packet1(gspca_dev, 0x00b6, 0x0002);
1065 cit_model3_Packet1(gspca_dev, 0x00b7, 0x0004);
1066 cit_model3_Packet1(gspca_dev, 0x00bb, 0x0000);
1067 cit_model3_Packet1(gspca_dev, 0x00bc, 0x0001);
1068 cit_model3_Packet1(gspca_dev, 0x00bd, 0x0000);
1069 cit_model3_Packet1(gspca_dev, 0x00bf, 0x0000);
1070 cit_model3_Packet1(gspca_dev, 0x00c0, 0x00c8);
1071 cit_model3_Packet1(gspca_dev, 0x00c1, 0x0014);
1072 cit_model3_Packet1(gspca_dev, 0x00c2, 0x0001);
1073 cit_model3_Packet1(gspca_dev, 0x00c3, 0x0000);
1074 cit_model3_Packet1(gspca_dev, 0x00c4, 0x0004);
1075 cit_model3_Packet1(gspca_dev, 0x00cb, 0x00bf);
1076 cit_model3_Packet1(gspca_dev, 0x00cc, 0x00bf);
1077 cit_model3_Packet1(gspca_dev, 0x00cd, 0x00bf);
1078 cit_model3_Packet1(gspca_dev, 0x00ce, 0x0000);
1079 cit_model3_Packet1(gspca_dev, 0x00cf, 0x0020);
1080 cit_model3_Packet1(gspca_dev, 0x00d0, 0x0040);
1081 cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
1082 cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
1083 cit_model3_Packet1(gspca_dev, 0x00d2, 0x00bf);
1084 cit_model3_Packet1(gspca_dev, 0x00d3, 0x00bf);
1085 cit_model3_Packet1(gspca_dev, 0x00ea, 0x0008);
1086 cit_model3_Packet1(gspca_dev, 0x00eb, 0x0000);
1087 cit_model3_Packet1(gspca_dev, 0x00ec, 0x00e8);
1088 cit_model3_Packet1(gspca_dev, 0x00ed, 0x0001);
1089 cit_model3_Packet1(gspca_dev, 0x00ef, 0x0022);
1090 cit_model3_Packet1(gspca_dev, 0x00f0, 0x0000);
1091 cit_model3_Packet1(gspca_dev, 0x00f2, 0x0028);
1092 cit_model3_Packet1(gspca_dev, 0x00f4, 0x0002);
1093 cit_model3_Packet1(gspca_dev, 0x00f5, 0x0000);
1094 cit_model3_Packet1(gspca_dev, 0x00fa, 0x0000);
1095 cit_model3_Packet1(gspca_dev, 0x00fb, 0x0001);
1096 cit_model3_Packet1(gspca_dev, 0x00fc, 0x0000);
1097 cit_model3_Packet1(gspca_dev, 0x00fd, 0x0000);
1098 cit_model3_Packet1(gspca_dev, 0x00fe, 0x0000);
1099 cit_model3_Packet1(gspca_dev, 0x00ff, 0x0000);
1100
1101 cit_model3_Packet1(gspca_dev, 0x00be, 0x0003);
1102 cit_model3_Packet1(gspca_dev, 0x00c8, 0x0000);
1103 cit_model3_Packet1(gspca_dev, 0x00c9, 0x0020);
1104 cit_model3_Packet1(gspca_dev, 0x00ca, 0x0040);
1105 cit_model3_Packet1(gspca_dev, 0x0053, 0x0001);
1106 cit_model3_Packet1(gspca_dev, 0x0082, 0x000e);
1107 cit_model3_Packet1(gspca_dev, 0x0083, 0x0020);
1108 cit_model3_Packet1(gspca_dev, 0x0034, 0x003c);
1109 cit_model3_Packet1(gspca_dev, 0x006e, 0x0055);
1110 cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);
1111 cit_model3_Packet1(gspca_dev, 0x0063, 0x0008);
1112 cit_model3_Packet1(gspca_dev, 0x0066, 0x000a);
1113 cit_model3_Packet1(gspca_dev, 0x0067, 0x0006);
1114 cit_model3_Packet1(gspca_dev, 0x006b, 0x0010);
1115 cit_model3_Packet1(gspca_dev, 0x005a, 0x0001);
1116 cit_model3_Packet1(gspca_dev, 0x005b, 0x000a);
1117 cit_model3_Packet1(gspca_dev, 0x0023, 0x0006);
1118 cit_model3_Packet1(gspca_dev, 0x0026, 0x0004);
1119 cit_model3_Packet1(gspca_dev, 0x0036, 0x0069);
1120 cit_model3_Packet1(gspca_dev, 0x0038, 0x0064);
1121 cit_model3_Packet1(gspca_dev, 0x003d, 0x0003);
1122 cit_model3_Packet1(gspca_dev, 0x003e, 0x0001);
1123 cit_model3_Packet1(gspca_dev, 0x00b8, 0x0014);
1124 cit_model3_Packet1(gspca_dev, 0x00b9, 0x0014);
1125 cit_model3_Packet1(gspca_dev, 0x00e6, 0x0004);
1126 cit_model3_Packet1(gspca_dev, 0x00e8, 0x0001);
1127
1128 return 0;
1129}
1130
1131/* this function is called at probe and resume time */
1132static int sd_init(struct gspca_dev *gspca_dev)
1133{
1134 struct sd *sd = (struct sd *) gspca_dev;
1135
1136 switch (sd->model) {
1137 case CIT_MODEL0:
1138 cit_init_model0(gspca_dev);
1139 sd_stop0(gspca_dev);
1140 break;
1141 case CIT_MODEL1:
1142 case CIT_MODEL2:
1143 case CIT_MODEL3:
1144 case CIT_MODEL4:
1145 break; /* All is done in sd_start */
1146 case CIT_IBM_NETCAM_PRO:
1147 cit_init_ibm_netcam_pro(gspca_dev);
1148 sd_stop0(gspca_dev);
1149 break;
1150 }
1151 return 0;
1152}
1153
1154static int cit_set_brightness(struct gspca_dev *gspca_dev, s32 val)
1155{
1156 struct sd *sd = (struct sd *) gspca_dev;
1157 int i;
1158
1159 switch (sd->model) {
1160 case CIT_MODEL0:
1161 case CIT_IBM_NETCAM_PRO:
1162 /* No (known) brightness control for these */
1163 break;
1164 case CIT_MODEL1:
1165 /* Model 1: Brightness range 0 - 63 */
1166 cit_Packet_Format1(gspca_dev, 0x0031, val);
1167 cit_Packet_Format1(gspca_dev, 0x0032, val);
1168 cit_Packet_Format1(gspca_dev, 0x0033, val);
1169 break;
1170 case CIT_MODEL2:
1171 /* Model 2: Brightness range 0x60 - 0xee */
1172 /* Scale 0 - 63 to 0x60 - 0xee */
1173 i = 0x60 + val * 2254 / 1000;
1174 cit_model2_Packet1(gspca_dev, 0x001a, i);
1175 break;
1176 case CIT_MODEL3:
1177 /* Model 3: Brightness range 'i' in [0x0C..0x3F] */
1178 i = val;
1179 if (i < 0x0c)
1180 i = 0x0c;
1181 cit_model3_Packet1(gspca_dev, 0x0036, i);
1182 break;
1183 case CIT_MODEL4:
1184 /* Model 4: Brightness range 'i' in [0x04..0xb4] */
1185 /* Scale 0 - 63 to 0x04 - 0xb4 */
1186 i = 0x04 + val * 2794 / 1000;
1187 cit_model4_BrightnessPacket(gspca_dev, i);
1188 break;
1189 }
1190
1191 return 0;
1192}
1193
1194static int cit_set_contrast(struct gspca_dev *gspca_dev, s32 val)
1195{
1196 struct sd *sd = (struct sd *) gspca_dev;
1197
1198 switch (sd->model) {
1199 case CIT_MODEL0: {
1200 int i;
1201 /* gain 0-15, 0-20 -> 0-15 */
1202 i = val * 1000 / 1333;
1203 cit_write_reg(gspca_dev, i, 0x0422);
1204 /* gain 0-31, may not be lower then 0x0422, 0-20 -> 0-31 */
1205 i = val * 2000 / 1333;
1206 cit_write_reg(gspca_dev, i, 0x0423);
1207 /* gain 0-127, may not be lower then 0x0423, 0-20 -> 0-63 */
1208 i = val * 4000 / 1333;
1209 cit_write_reg(gspca_dev, i, 0x0424);
1210 /* gain 0-127, may not be lower then 0x0424, , 0-20 -> 0-127 */
1211 i = val * 8000 / 1333;
1212 cit_write_reg(gspca_dev, i, 0x0425);
1213 break;
1214 }
1215 case CIT_MODEL2:
1216 case CIT_MODEL4:
1217 /* These models do not have this control. */
1218 break;
1219 case CIT_MODEL1:
1220 {
1221 /* Scale 0 - 20 to 15 - 0 */
1222 int i, new_contrast = (20 - val) * 1000 / 1333;
1223 for (i = 0; i < cit_model1_ntries; i++) {
1224 cit_Packet_Format1(gspca_dev, 0x0014, new_contrast);
1225 cit_send_FF_04_02(gspca_dev);
1226 }
1227 break;
1228 }
1229 case CIT_MODEL3:
1230 { /* Preset hardware values */
1231 static const struct {
1232 unsigned short cv1;
1233 unsigned short cv2;
1234 unsigned short cv3;
1235 } cv[7] = {
1236 { 0x05, 0x05, 0x0f }, /* Minimum */
1237 { 0x04, 0x04, 0x16 },
1238 { 0x02, 0x03, 0x16 },
1239 { 0x02, 0x08, 0x16 },
1240 { 0x01, 0x0c, 0x16 },
1241 { 0x01, 0x0e, 0x16 },
1242 { 0x01, 0x10, 0x16 } /* Maximum */
1243 };
1244 int i = val / 3;
1245 cit_model3_Packet1(gspca_dev, 0x0067, cv[i].cv1);
1246 cit_model3_Packet1(gspca_dev, 0x005b, cv[i].cv2);
1247 cit_model3_Packet1(gspca_dev, 0x005c, cv[i].cv3);
1248 break;
1249 }
1250 case CIT_IBM_NETCAM_PRO:
1251 cit_model3_Packet1(gspca_dev, 0x005b, val + 1);
1252 break;
1253 }
1254 return 0;
1255}
1256
1257static int cit_set_hue(struct gspca_dev *gspca_dev, s32 val)
1258{
1259 struct sd *sd = (struct sd *) gspca_dev;
1260
1261 switch (sd->model) {
1262 case CIT_MODEL0:
1263 case CIT_MODEL1:
1264 case CIT_IBM_NETCAM_PRO:
1265 /* No hue control for these models */
1266 break;
1267 case CIT_MODEL2:
1268 cit_model2_Packet1(gspca_dev, 0x0024, val);
1269 /* cit_model2_Packet1(gspca_dev, 0x0020, sat); */
1270 break;
1271 case CIT_MODEL3: {
1272 /* Model 3: Brightness range 'i' in [0x05..0x37] */
1273 /* TESTME according to the ibmcam driver this does not work */
1274 if (0) {
1275 /* Scale 0 - 127 to 0x05 - 0x37 */
1276 int i = 0x05 + val * 1000 / 2540;
1277 cit_model3_Packet1(gspca_dev, 0x007e, i);
1278 }
1279 break;
1280 }
1281 case CIT_MODEL4:
1282 /* HDG: taken from ibmcam, setting the color gains does not
1283 * really belong here.
1284 *
1285 * I am not sure r/g/b_gain variables exactly control gain
1286 * of those channels. Most likely they subtly change some
1287 * very internal image processing settings in the camera.
1288 * In any case, here is what they do, and feel free to tweak:
1289 *
1290 * r_gain: seriously affects red gain
1291 * g_gain: seriously affects green gain
1292 * b_gain: seriously affects blue gain
1293 * hue: changes average color from violet (0) to red (0xFF)
1294 */
1295 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
1296 cit_write_reg(gspca_dev, 0x001e, 0x012f);
1297 cit_write_reg(gspca_dev, 0xd141, 0x0124);
1298 cit_write_reg(gspca_dev, 160, 0x0127); /* Green gain */
1299 cit_write_reg(gspca_dev, 160, 0x012e); /* Red gain */
1300 cit_write_reg(gspca_dev, 160, 0x0130); /* Blue gain */
1301 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
1302 cit_write_reg(gspca_dev, val, 0x012d); /* Hue */
1303 cit_write_reg(gspca_dev, 0xf545, 0x0124);
1304 break;
1305 }
1306 return 0;
1307}
1308
1309static int cit_set_sharpness(struct gspca_dev *gspca_dev, s32 val)
1310{
1311 struct sd *sd = (struct sd *) gspca_dev;
1312
1313 switch (sd->model) {
1314 case CIT_MODEL0:
1315 case CIT_MODEL2:
1316 case CIT_MODEL4:
1317 case CIT_IBM_NETCAM_PRO:
1318 /* These models do not have this control */
1319 break;
1320 case CIT_MODEL1: {
1321 int i;
1322 const unsigned short sa[] = {
1323 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
1324
1325 for (i = 0; i < cit_model1_ntries; i++)
1326 cit_PacketFormat2(gspca_dev, 0x0013, sa[val]);
1327 break;
1328 }
1329 case CIT_MODEL3:
1330 { /*
1331 * "Use a table of magic numbers.
1332 * This setting doesn't really change much.
1333 * But that's how Windows does it."
1334 */
1335 static const struct {
1336 unsigned short sv1;
1337 unsigned short sv2;
1338 unsigned short sv3;
1339 unsigned short sv4;
1340 } sv[7] = {
1341 { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */
1342 { 0x01, 0x04, 0x05, 0x14 },
1343 { 0x02, 0x04, 0x05, 0x14 },
1344 { 0x03, 0x04, 0x05, 0x14 },
1345 { 0x03, 0x05, 0x05, 0x14 },
1346 { 0x03, 0x06, 0x05, 0x14 },
1347 { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */
1348 };
1349 cit_model3_Packet1(gspca_dev, 0x0060, sv[val].sv1);
1350 cit_model3_Packet1(gspca_dev, 0x0061, sv[val].sv2);
1351 cit_model3_Packet1(gspca_dev, 0x0062, sv[val].sv3);
1352 cit_model3_Packet1(gspca_dev, 0x0063, sv[val].sv4);
1353 break;
1354 }
1355 }
1356 return 0;
1357}
1358
1359/*
1360 * cit_set_lighting()
1361 *
1362 * Camera model 1:
1363 * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
1364 *
1365 * Camera model 2:
1366 * We have 16 levels of lighting, 0 for bright light and up to 15 for
1367 * low light. But values above 5 or so are useless because camera is
1368 * not really capable to produce anything worth viewing at such light.
1369 * This setting may be altered only in certain camera state.
1370 *
1371 * Low lighting forces slower FPS.
1372 *
1373 * History:
1374 * 1/5/00 Created.
1375 * 2/20/00 Added support for Model 2 cameras.
1376 */
1377static void cit_set_lighting(struct gspca_dev *gspca_dev, s32 val)
1378{
1379 struct sd *sd = (struct sd *) gspca_dev;
1380
1381 switch (sd->model) {
1382 case CIT_MODEL0:
1383 case CIT_MODEL2:
1384 case CIT_MODEL3:
1385 case CIT_MODEL4:
1386 case CIT_IBM_NETCAM_PRO:
1387 break;
1388 case CIT_MODEL1: {
1389 int i;
1390 for (i = 0; i < cit_model1_ntries; i++)
1391 cit_Packet_Format1(gspca_dev, 0x0027, val);
1392 break;
1393 }
1394 }
1395}
1396
1397static void cit_set_hflip(struct gspca_dev *gspca_dev, s32 val)
1398{
1399 struct sd *sd = (struct sd *) gspca_dev;
1400
1401 switch (sd->model) {
1402 case CIT_MODEL0:
1403 if (val)
1404 cit_write_reg(gspca_dev, 0x0020, 0x0115);
1405 else
1406 cit_write_reg(gspca_dev, 0x0040, 0x0115);
1407 break;
1408 case CIT_MODEL1:
1409 case CIT_MODEL2:
1410 case CIT_MODEL3:
1411 case CIT_MODEL4:
1412 case CIT_IBM_NETCAM_PRO:
1413 break;
1414 }
1415}
1416
1417static int cit_restart_stream(struct gspca_dev *gspca_dev)
1418{
1419 struct sd *sd = (struct sd *) gspca_dev;
1420
1421 switch (sd->model) {
1422 case CIT_MODEL0:
1423 case CIT_MODEL1:
1424 cit_write_reg(gspca_dev, 0x0001, 0x0114);
1425 /* Fall through */
1426 case CIT_MODEL2:
1427 case CIT_MODEL4:
1428 cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
1429 usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
1430 break;
1431 case CIT_MODEL3:
1432 case CIT_IBM_NETCAM_PRO:
1433 cit_write_reg(gspca_dev, 0x0001, 0x0114);
1434 cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
1435 usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
1436 /* Clear button events from while we were not streaming */
1437 cit_write_reg(gspca_dev, 0x0001, 0x0113);
1438 break;
1439 }
1440
1441 sd->sof_read = 0;
1442
1443 return 0;
1444}
1445
1446static int cit_get_packet_size(struct gspca_dev *gspca_dev)
1447{
1448 struct usb_host_interface *alt;
1449 struct usb_interface *intf;
1450
1451 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
1452 alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
1453 if (!alt) {
1454 pr_err("Couldn't get altsetting\n");
1455 return -EIO;
1456 }
1457
1458 return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
1459}
1460
1461/* Calculate the clockdiv giving us max fps given the available bandwidth */
1462static int cit_get_clock_div(struct gspca_dev *gspca_dev)
1463{
1464 int clock_div = 7; /* 0=30 1=25 2=20 3=15 4=12 5=7.5 6=6 7=3fps ?? */
1465 int fps[8] = { 30, 25, 20, 15, 12, 8, 6, 3 };
1466 int packet_size;
1467
1468 packet_size = cit_get_packet_size(gspca_dev);
1469 if (packet_size < 0)
1470 return packet_size;
1471
1472 while (clock_div > 3 &&
1473 1000 * packet_size >
1474 gspca_dev->width * gspca_dev->height *
1475 fps[clock_div - 1] * 3 / 2)
1476 clock_div--;
1477
1478 PDEBUG(D_PROBE,
1479 "PacketSize: %d, res: %dx%d -> using clockdiv: %d (%d fps)",
1480 packet_size, gspca_dev->width, gspca_dev->height, clock_div,
1481 fps[clock_div]);
1482
1483 return clock_div;
1484}
1485
1486static int cit_start_model0(struct gspca_dev *gspca_dev)
1487{
1488 const unsigned short compression = 0; /* 0=none, 7=best frame rate */
1489 int clock_div;
1490
1491 clock_div = cit_get_clock_div(gspca_dev);
1492 if (clock_div < 0)
1493 return clock_div;
1494
1495 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
1496 cit_write_reg(gspca_dev, 0x0003, 0x0438);
1497 cit_write_reg(gspca_dev, 0x001e, 0x042b);
1498 cit_write_reg(gspca_dev, 0x0041, 0x042c);
1499 cit_write_reg(gspca_dev, 0x0008, 0x0436);
1500 cit_write_reg(gspca_dev, 0x0024, 0x0403);
1501 cit_write_reg(gspca_dev, 0x002c, 0x0404);
1502 cit_write_reg(gspca_dev, 0x0002, 0x0426);
1503 cit_write_reg(gspca_dev, 0x0014, 0x0427);
1504
1505 switch (gspca_dev->width) {
1506 case 160: /* 160x120 */
1507 cit_write_reg(gspca_dev, 0x0004, 0x010b);
1508 cit_write_reg(gspca_dev, 0x0001, 0x010a);
1509 cit_write_reg(gspca_dev, 0x0010, 0x0102);
1510 cit_write_reg(gspca_dev, 0x00a0, 0x0103);
1511 cit_write_reg(gspca_dev, 0x0000, 0x0104);
1512 cit_write_reg(gspca_dev, 0x0078, 0x0105);
1513 break;
1514
1515 case 176: /* 176x144 */
1516 cit_write_reg(gspca_dev, 0x0006, 0x010b);
1517 cit_write_reg(gspca_dev, 0x0000, 0x010a);
1518 cit_write_reg(gspca_dev, 0x0005, 0x0102);
1519 cit_write_reg(gspca_dev, 0x00b0, 0x0103);
1520 cit_write_reg(gspca_dev, 0x0000, 0x0104);
1521 cit_write_reg(gspca_dev, 0x0090, 0x0105);
1522 break;
1523
1524 case 320: /* 320x240 */
1525 cit_write_reg(gspca_dev, 0x0008, 0x010b);
1526 cit_write_reg(gspca_dev, 0x0004, 0x010a);
1527 cit_write_reg(gspca_dev, 0x0005, 0x0102);
1528 cit_write_reg(gspca_dev, 0x00a0, 0x0103);
1529 cit_write_reg(gspca_dev, 0x0010, 0x0104);
1530 cit_write_reg(gspca_dev, 0x0078, 0x0105);
1531 break;
1532 }
1533
1534 cit_write_reg(gspca_dev, compression, 0x0109);
1535 cit_write_reg(gspca_dev, clock_div, 0x0111);
1536
1537 return 0;
1538}
1539
1540static int cit_start_model1(struct gspca_dev *gspca_dev)
1541{
1542 struct sd *sd = (struct sd *) gspca_dev;
1543 int i, clock_div;
1544
1545 clock_div = cit_get_clock_div(gspca_dev);
1546 if (clock_div < 0)
1547 return clock_div;
1548
1549 cit_read_reg(gspca_dev, 0x0128, 1);
1550 cit_read_reg(gspca_dev, 0x0100, 0);
1551 cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
1552 cit_read_reg(gspca_dev, 0x0100, 0);
1553 cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
1554 cit_read_reg(gspca_dev, 0x0100, 0);
1555 cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
1556 cit_write_reg(gspca_dev, 0x01, 0x0108);
1557
1558 cit_write_reg(gspca_dev, 0x03, 0x0112);
1559 cit_read_reg(gspca_dev, 0x0115, 0);
1560 cit_write_reg(gspca_dev, 0x06, 0x0115);
1561 cit_read_reg(gspca_dev, 0x0116, 0);
1562 cit_write_reg(gspca_dev, 0x44, 0x0116);
1563 cit_read_reg(gspca_dev, 0x0116, 0);
1564 cit_write_reg(gspca_dev, 0x40, 0x0116);
1565 cit_read_reg(gspca_dev, 0x0115, 0);
1566 cit_write_reg(gspca_dev, 0x0e, 0x0115);
1567 cit_write_reg(gspca_dev, 0x19, 0x012c);
1568
1569 cit_Packet_Format1(gspca_dev, 0x00, 0x1e);
1570 cit_Packet_Format1(gspca_dev, 0x39, 0x0d);
1571 cit_Packet_Format1(gspca_dev, 0x39, 0x09);
1572 cit_Packet_Format1(gspca_dev, 0x3b, 0x00);
1573 cit_Packet_Format1(gspca_dev, 0x28, 0x22);
1574 cit_Packet_Format1(gspca_dev, 0x27, 0x00);
1575 cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
1576 cit_Packet_Format1(gspca_dev, 0x39, 0x08);
1577
1578 for (i = 0; i < cit_model1_ntries; i++)
1579 cit_Packet_Format1(gspca_dev, 0x2c, 0x00);
1580
1581 for (i = 0; i < cit_model1_ntries; i++)
1582 cit_Packet_Format1(gspca_dev, 0x30, 0x14);
1583
1584 cit_PacketFormat2(gspca_dev, 0x39, 0x02);
1585 cit_PacketFormat2(gspca_dev, 0x01, 0xe1);
1586 cit_PacketFormat2(gspca_dev, 0x02, 0xcd);
1587 cit_PacketFormat2(gspca_dev, 0x03, 0xcd);
1588 cit_PacketFormat2(gspca_dev, 0x04, 0xfa);
1589 cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
1590 cit_PacketFormat2(gspca_dev, 0x39, 0x00);
1591
1592 cit_PacketFormat2(gspca_dev, 0x39, 0x02);
1593 cit_PacketFormat2(gspca_dev, 0x0a, 0x37);
1594 cit_PacketFormat2(gspca_dev, 0x0b, 0xb8);
1595 cit_PacketFormat2(gspca_dev, 0x0c, 0xf3);
1596 cit_PacketFormat2(gspca_dev, 0x0d, 0xe3);
1597 cit_PacketFormat2(gspca_dev, 0x0e, 0x0d);
1598 cit_PacketFormat2(gspca_dev, 0x0f, 0xf2);
1599 cit_PacketFormat2(gspca_dev, 0x10, 0xd5);
1600 cit_PacketFormat2(gspca_dev, 0x11, 0xba);
1601 cit_PacketFormat2(gspca_dev, 0x12, 0x53);
1602 cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
1603 cit_PacketFormat2(gspca_dev, 0x39, 0x00);
1604
1605 cit_PacketFormat2(gspca_dev, 0x39, 0x02);
1606 cit_PacketFormat2(gspca_dev, 0x16, 0x00);
1607 cit_PacketFormat2(gspca_dev, 0x17, 0x28);
1608 cit_PacketFormat2(gspca_dev, 0x18, 0x7d);
1609 cit_PacketFormat2(gspca_dev, 0x19, 0xbe);
1610 cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
1611 cit_PacketFormat2(gspca_dev, 0x39, 0x00);
1612
1613 for (i = 0; i < cit_model1_ntries; i++)
1614 cit_Packet_Format1(gspca_dev, 0x00, 0x18);
1615 for (i = 0; i < cit_model1_ntries; i++)
1616 cit_Packet_Format1(gspca_dev, 0x13, 0x18);
1617 for (i = 0; i < cit_model1_ntries; i++)
1618 cit_Packet_Format1(gspca_dev, 0x14, 0x06);
1619
1620 /* TESTME These are handled through controls
1621 KEEP until someone can test leaving this out is ok */
1622 if (0) {
1623 /* This is default brightness */
1624 for (i = 0; i < cit_model1_ntries; i++)
1625 cit_Packet_Format1(gspca_dev, 0x31, 0x37);
1626 for (i = 0; i < cit_model1_ntries; i++)
1627 cit_Packet_Format1(gspca_dev, 0x32, 0x46);
1628 for (i = 0; i < cit_model1_ntries; i++)
1629 cit_Packet_Format1(gspca_dev, 0x33, 0x55);
1630 }
1631
1632 cit_Packet_Format1(gspca_dev, 0x2e, 0x04);
1633 for (i = 0; i < cit_model1_ntries; i++)
1634 cit_Packet_Format1(gspca_dev, 0x2d, 0x04);
1635 for (i = 0; i < cit_model1_ntries; i++)
1636 cit_Packet_Format1(gspca_dev, 0x29, 0x80);
1637 cit_Packet_Format1(gspca_dev, 0x2c, 0x01);
1638 cit_Packet_Format1(gspca_dev, 0x30, 0x17);
1639 cit_Packet_Format1(gspca_dev, 0x39, 0x08);
1640 for (i = 0; i < cit_model1_ntries; i++)
1641 cit_Packet_Format1(gspca_dev, 0x34, 0x00);
1642
1643 cit_write_reg(gspca_dev, 0x00, 0x0101);
1644 cit_write_reg(gspca_dev, 0x00, 0x010a);
1645
1646 switch (gspca_dev->width) {
1647 case 128: /* 128x96 */
1648 cit_write_reg(gspca_dev, 0x80, 0x0103);
1649 cit_write_reg(gspca_dev, 0x60, 0x0105);
1650 cit_write_reg(gspca_dev, 0x0c, 0x010b);
1651 cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
1652 cit_write_reg(gspca_dev, 0x0b, 0x011d);
1653 cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
1654 cit_write_reg(gspca_dev, 0x00, 0x0129);
1655 break;
1656 case 176: /* 176x144 */
1657 cit_write_reg(gspca_dev, 0xb0, 0x0103);
1658 cit_write_reg(gspca_dev, 0x8f, 0x0105);
1659 cit_write_reg(gspca_dev, 0x06, 0x010b);
1660 cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
1661 cit_write_reg(gspca_dev, 0x0d, 0x011d);
1662 cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
1663 cit_write_reg(gspca_dev, 0x03, 0x0129);
1664 break;
1665 case 352: /* 352x288 */
1666 cit_write_reg(gspca_dev, 0xb0, 0x0103);
1667 cit_write_reg(gspca_dev, 0x90, 0x0105);
1668 cit_write_reg(gspca_dev, 0x02, 0x010b);
1669 cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
1670 cit_write_reg(gspca_dev, 0x05, 0x011d);
1671 cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
1672 cit_write_reg(gspca_dev, 0x00, 0x0129);
1673 break;
1674 }
1675
1676 cit_write_reg(gspca_dev, 0xff, 0x012b);
1677
1678 /* TESTME These are handled through controls
1679 KEEP until someone can test leaving this out is ok */
1680 if (0) {
1681 /* This is another brightness - don't know why */
1682 for (i = 0; i < cit_model1_ntries; i++)
1683 cit_Packet_Format1(gspca_dev, 0x31, 0xc3);
1684 for (i = 0; i < cit_model1_ntries; i++)
1685 cit_Packet_Format1(gspca_dev, 0x32, 0xd2);
1686 for (i = 0; i < cit_model1_ntries; i++)
1687 cit_Packet_Format1(gspca_dev, 0x33, 0xe1);
1688
1689 /* Default contrast */
1690 for (i = 0; i < cit_model1_ntries; i++)
1691 cit_Packet_Format1(gspca_dev, 0x14, 0x0a);
1692
1693 /* Default sharpness */
1694 for (i = 0; i < cit_model1_ntries2; i++)
1695 cit_PacketFormat2(gspca_dev, 0x13, 0x1a);
1696
1697 /* Default lighting conditions */
1698 cit_Packet_Format1(gspca_dev, 0x0027,
1699 v4l2_ctrl_g_ctrl(sd->lighting));
1700 }
1701
1702 /* Assorted init */
1703 switch (gspca_dev->width) {
1704 case 128: /* 128x96 */
1705 cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
1706 cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
1707 cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
1708 cit_write_reg(gspca_dev, 0x36, 0x0102);
1709 cit_write_reg(gspca_dev, 0x1a, 0x0104);
1710 cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
1711 cit_write_reg(gspca_dev, 0x2b, 0x011c);
1712 cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
1713 break;
1714 case 176: /* 176x144 */
1715 cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
1716 cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
1717 cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
1718 cit_write_reg(gspca_dev, 0x04, 0x0102);
1719 cit_write_reg(gspca_dev, 0x02, 0x0104);
1720 cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
1721 cit_write_reg(gspca_dev, 0x2b, 0x011c);
1722 cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
1723 break;
1724 case 352: /* 352x288 */
1725 cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
1726 cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
1727 cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
1728 cit_write_reg(gspca_dev, 0x08, 0x0102);
1729 cit_write_reg(gspca_dev, 0x01, 0x0104);
1730 cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
1731 cit_write_reg(gspca_dev, 0x2f, 0x011c);
1732 cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
1733 break;
1734 }
1735
1736 cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
1737 cit_write_reg(gspca_dev, clock_div, 0x0111);
1738
1739 return 0;
1740}
1741
1742static int cit_start_model2(struct gspca_dev *gspca_dev)
1743{
1744 struct sd *sd = (struct sd *) gspca_dev;
1745 int clock_div = 0;
1746
1747 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
1748 cit_read_reg(gspca_dev, 0x0116, 0);
1749 cit_write_reg(gspca_dev, 0x0060, 0x0116);
1750 cit_write_reg(gspca_dev, 0x0002, 0x0112);
1751 cit_write_reg(gspca_dev, 0x00bc, 0x012c);
1752 cit_write_reg(gspca_dev, 0x0008, 0x012b);
1753 cit_write_reg(gspca_dev, 0x0000, 0x0108);
1754 cit_write_reg(gspca_dev, 0x0001, 0x0133);
1755 cit_write_reg(gspca_dev, 0x0001, 0x0102);
1756 switch (gspca_dev->width) {
1757 case 176: /* 176x144 */
1758 cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
1759 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1760 cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */
1761 cit_write_reg(gspca_dev, 0x00b9, 0x010a); /* Unique to this mode */
1762 cit_write_reg(gspca_dev, 0x0038, 0x0119); /* Unique to this mode */
1763 /* TESTME HDG: this does not seem right
1764 (it is 2 for all other resolutions) */
1765 sd->sof_len = 10;
1766 break;
1767 case 320: /* 320x240 */
1768 cit_write_reg(gspca_dev, 0x0028, 0x0103); /* Unique to this mode */
1769 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1770 cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
1771 cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
1772 cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
1773 sd->sof_len = 2;
1774 break;
1775 /* case VIDEOSIZE_352x240: */
1776 cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
1777 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1778 cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
1779 cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
1780 cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
1781 sd->sof_len = 2;
1782 break;
1783 case 352: /* 352x288 */
1784 cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
1785 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1786 cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */
1787 cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
1788 cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
1789 sd->sof_len = 2;
1790 break;
1791 }
1792
1793 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
1794
1795 switch (gspca_dev->width) {
1796 case 176: /* 176x144 */
1797 cit_write_reg(gspca_dev, 0x0050, 0x0111);
1798 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
1799 break;
1800 case 320: /* 320x240 */
1801 case 352: /* 352x288 */
1802 cit_write_reg(gspca_dev, 0x0040, 0x0111);
1803 cit_write_reg(gspca_dev, 0x00c0, 0x0111);
1804 break;
1805 }
1806 cit_write_reg(gspca_dev, 0x009b, 0x010f);
1807 cit_write_reg(gspca_dev, 0x00bb, 0x010f);
1808
1809 /*
1810 * Hardware settings, may affect CMOS sensor; not user controls!
1811 * -------------------------------------------------------------
1812 * 0x0004: no effect
1813 * 0x0006: hardware effect
1814 * 0x0008: no effect
1815 * 0x000a: stops video stream, probably important h/w setting
1816 * 0x000c: changes color in hardware manner (not user setting)
1817 * 0x0012: changes number of colors (does not affect speed)
1818 * 0x002a: no effect
1819 * 0x002c: hardware setting (related to scan lines)
1820 * 0x002e: stops video stream, probably important h/w setting
1821 */
1822 cit_model2_Packet1(gspca_dev, 0x000a, 0x005c);
1823 cit_model2_Packet1(gspca_dev, 0x0004, 0x0000);
1824 cit_model2_Packet1(gspca_dev, 0x0006, 0x00fb);
1825 cit_model2_Packet1(gspca_dev, 0x0008, 0x0000);
1826 cit_model2_Packet1(gspca_dev, 0x000c, 0x0009);
1827 cit_model2_Packet1(gspca_dev, 0x0012, 0x000a);
1828 cit_model2_Packet1(gspca_dev, 0x002a, 0x0000);
1829 cit_model2_Packet1(gspca_dev, 0x002c, 0x0000);
1830 cit_model2_Packet1(gspca_dev, 0x002e, 0x0008);
1831
1832 /*
1833 * Function 0x0030 pops up all over the place. Apparently
1834 * it is a hardware control register, with every bit assigned to
1835 * do something.
1836 */
1837 cit_model2_Packet1(gspca_dev, 0x0030, 0x0000);
1838
1839 /*
1840 * Magic control of CMOS sensor. Only lower values like
1841 * 0-3 work, and picture shifts left or right. Don't change.
1842 */
1843 switch (gspca_dev->width) {
1844 case 176: /* 176x144 */
1845 cit_model2_Packet1(gspca_dev, 0x0014, 0x0002);
1846 cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
1847 cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
1848 clock_div = 6;
1849 break;
1850 case 320: /* 320x240 */
1851 cit_model2_Packet1(gspca_dev, 0x0014, 0x0009);
1852 cit_model2_Packet1(gspca_dev, 0x0016, 0x0005); /* Horizontal shift */
1853 cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */
1854 clock_div = 8;
1855 break;
1856 /* case VIDEOSIZE_352x240: */
1857 /* This mode doesn't work as Windows programs it; changed to work */
1858 cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */
1859 cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */
1860 cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
1861 clock_div = 10;
1862 break;
1863 case 352: /* 352x288 */
1864 cit_model2_Packet1(gspca_dev, 0x0014, 0x0003);
1865 cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
1866 cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
1867 clock_div = 16;
1868 break;
1869 }
1870
1871 /* TESTME These are handled through controls
1872 KEEP until someone can test leaving this out is ok */
1873 if (0)
1874 cit_model2_Packet1(gspca_dev, 0x001a, 0x005a);
1875
1876 /*
1877 * We have our own frame rate setting varying from 0 (slowest) to 6
1878 * (fastest). The camera model 2 allows frame rate in range [0..0x1F]
1879 # where 0 is also the slowest setting. However for all practical
1880 # reasons high settings make no sense because USB is not fast enough
1881 # to support high FPS. Be aware that the picture datastream will be
1882 # severely disrupted if you ask for frame rate faster than allowed
1883 # for the video size - see below:
1884 *
1885 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
1886 * -----------------------------------------------------------------
1887 * 176x144: [6..31]
1888 * 320x240: [8..31]
1889 * 352x240: [10..31]
1890 * 352x288: [16..31] I have to raise lower threshold for stability...
1891 *
1892 * As usual, slower FPS provides better sensitivity.
1893 */
1894 cit_model2_Packet1(gspca_dev, 0x001c, clock_div);
1895
1896 /*
1897 * This setting does not visibly affect pictures; left it here
1898 * because it was present in Windows USB data stream. This function
1899 * does not allow arbitrary values and apparently is a bit mask, to
1900 * be activated only at appropriate time. Don't change it randomly!
1901 */
1902 switch (gspca_dev->width) {
1903 case 176: /* 176x144 */
1904 cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2);
1905 break;
1906 case 320: /* 320x240 */
1907 cit_model2_Packet1(gspca_dev, 0x0026, 0x0044);
1908 break;
1909 /* case VIDEOSIZE_352x240: */
1910 cit_model2_Packet1(gspca_dev, 0x0026, 0x0046);
1911 break;
1912 case 352: /* 352x288 */
1913 cit_model2_Packet1(gspca_dev, 0x0026, 0x0048);
1914 break;
1915 }
1916
1917 cit_model2_Packet1(gspca_dev, 0x0028, v4l2_ctrl_g_ctrl(sd->lighting));
1918 /* model2 cannot change the backlight compensation while streaming */
1919 v4l2_ctrl_grab(sd->lighting, true);
1920
1921 /* color balance rg2 */
1922 cit_model2_Packet1(gspca_dev, 0x001e, 0x002f);
1923 /* saturation */
1924 cit_model2_Packet1(gspca_dev, 0x0020, 0x0034);
1925 /* color balance yb */
1926 cit_model2_Packet1(gspca_dev, 0x0022, 0x00a0);
1927
1928 /* Hardware control command */
1929 cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
1930
1931 return 0;
1932}
1933
1934static int cit_start_model3(struct gspca_dev *gspca_dev)
1935{
1936 const unsigned short compression = 0; /* 0=none, 7=best frame rate */
1937 int i, clock_div = 0;
1938
1939 /* HDG not in ibmcam driver, added to see if it helps with
1940 auto-detecting between model3 and ibm netcamera pro */
1941 cit_read_reg(gspca_dev, 0x128, 1);
1942
1943 cit_write_reg(gspca_dev, 0x0000, 0x0100);
1944 cit_read_reg(gspca_dev, 0x0116, 0);
1945 cit_write_reg(gspca_dev, 0x0060, 0x0116);
1946 cit_write_reg(gspca_dev, 0x0002, 0x0112);
1947 cit_write_reg(gspca_dev, 0x0000, 0x0123);
1948 cit_write_reg(gspca_dev, 0x0001, 0x0117);
1949 cit_write_reg(gspca_dev, 0x0040, 0x0108);
1950 cit_write_reg(gspca_dev, 0x0019, 0x012c);
1951 cit_write_reg(gspca_dev, 0x0060, 0x0116);
1952 cit_write_reg(gspca_dev, 0x0002, 0x0115);
1953 cit_write_reg(gspca_dev, 0x0003, 0x0115);
1954 cit_read_reg(gspca_dev, 0x0115, 0);
1955 cit_write_reg(gspca_dev, 0x000b, 0x0115);
1956
1957 /* TESTME HDG not in ibmcam driver, added to see if it helps with
1958 auto-detecting between model3 and ibm netcamera pro */
1959 if (0) {
1960 cit_write_reg(gspca_dev, 0x0078, 0x012d);
1961 cit_write_reg(gspca_dev, 0x0001, 0x012f);
1962 cit_write_reg(gspca_dev, 0xd141, 0x0124);
1963 cit_write_reg(gspca_dev, 0x0079, 0x012d);
1964 cit_write_reg(gspca_dev, 0x00ff, 0x0130);
1965 cit_write_reg(gspca_dev, 0xcd41, 0x0124);
1966 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
1967 cit_read_reg(gspca_dev, 0x0126, 1);
1968 }
1969
1970 cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
1971 cit_model3_Packet1(gspca_dev, 0x000b, 0x00f6);
1972 cit_model3_Packet1(gspca_dev, 0x000c, 0x0002);
1973 cit_model3_Packet1(gspca_dev, 0x000d, 0x0020);
1974 cit_model3_Packet1(gspca_dev, 0x000e, 0x0033);
1975 cit_model3_Packet1(gspca_dev, 0x000f, 0x0007);
1976 cit_model3_Packet1(gspca_dev, 0x0010, 0x0000);
1977 cit_model3_Packet1(gspca_dev, 0x0011, 0x0070);
1978 cit_model3_Packet1(gspca_dev, 0x0012, 0x0030);
1979 cit_model3_Packet1(gspca_dev, 0x0013, 0x0000);
1980 cit_model3_Packet1(gspca_dev, 0x0014, 0x0001);
1981 cit_model3_Packet1(gspca_dev, 0x0015, 0x0001);
1982 cit_model3_Packet1(gspca_dev, 0x0016, 0x0001);
1983 cit_model3_Packet1(gspca_dev, 0x0017, 0x0001);
1984 cit_model3_Packet1(gspca_dev, 0x0018, 0x0000);
1985 cit_model3_Packet1(gspca_dev, 0x001e, 0x00c3);
1986 cit_model3_Packet1(gspca_dev, 0x0020, 0x0000);
1987 cit_model3_Packet1(gspca_dev, 0x0028, 0x0010);
1988 cit_model3_Packet1(gspca_dev, 0x0029, 0x0054);
1989 cit_model3_Packet1(gspca_dev, 0x002a, 0x0013);
1990 cit_model3_Packet1(gspca_dev, 0x002b, 0x0007);
1991 cit_model3_Packet1(gspca_dev, 0x002d, 0x0028);
1992 cit_model3_Packet1(gspca_dev, 0x002e, 0x0000);
1993 cit_model3_Packet1(gspca_dev, 0x0031, 0x0000);
1994 cit_model3_Packet1(gspca_dev, 0x0032, 0x0000);
1995 cit_model3_Packet1(gspca_dev, 0x0033, 0x0000);
1996 cit_model3_Packet1(gspca_dev, 0x0034, 0x0000);
1997 cit_model3_Packet1(gspca_dev, 0x0035, 0x0038);
1998 cit_model3_Packet1(gspca_dev, 0x003a, 0x0001);
1999 cit_model3_Packet1(gspca_dev, 0x003c, 0x001e);
2000 cit_model3_Packet1(gspca_dev, 0x003f, 0x000a);
2001 cit_model3_Packet1(gspca_dev, 0x0041, 0x0000);
2002 cit_model3_Packet1(gspca_dev, 0x0046, 0x003f);
2003 cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
2004 cit_model3_Packet1(gspca_dev, 0x0050, 0x0005);
2005 cit_model3_Packet1(gspca_dev, 0x0052, 0x001a);
2006 cit_model3_Packet1(gspca_dev, 0x0053, 0x0003);
2007 cit_model3_Packet1(gspca_dev, 0x005a, 0x006b);
2008 cit_model3_Packet1(gspca_dev, 0x005d, 0x001e);
2009 cit_model3_Packet1(gspca_dev, 0x005e, 0x0030);
2010 cit_model3_Packet1(gspca_dev, 0x005f, 0x0041);
2011 cit_model3_Packet1(gspca_dev, 0x0064, 0x0008);
2012 cit_model3_Packet1(gspca_dev, 0x0065, 0x0015);
2013 cit_model3_Packet1(gspca_dev, 0x0068, 0x000f);
2014 cit_model3_Packet1(gspca_dev, 0x0079, 0x0000);
2015 cit_model3_Packet1(gspca_dev, 0x007a, 0x0000);
2016 cit_model3_Packet1(gspca_dev, 0x007c, 0x003f);
2017 cit_model3_Packet1(gspca_dev, 0x0082, 0x000f);
2018 cit_model3_Packet1(gspca_dev, 0x0085, 0x0000);
2019 cit_model3_Packet1(gspca_dev, 0x0099, 0x0000);
2020 cit_model3_Packet1(gspca_dev, 0x009b, 0x0023);
2021 cit_model3_Packet1(gspca_dev, 0x009c, 0x0022);
2022 cit_model3_Packet1(gspca_dev, 0x009d, 0x0096);
2023 cit_model3_Packet1(gspca_dev, 0x009e, 0x0096);
2024 cit_model3_Packet1(gspca_dev, 0x009f, 0x000a);
2025
2026 switch (gspca_dev->width) {
2027 case 160:
2028 cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
2029 cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
2030 cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
2031 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2032 cit_write_reg(gspca_dev, 0x0024, 0x010b); /* Differs everywhere */
2033 cit_write_reg(gspca_dev, 0x00a9, 0x0119);
2034 cit_write_reg(gspca_dev, 0x0016, 0x011b);
2035 cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
2036 cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
2037 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2038 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2039 cit_write_reg(gspca_dev, 0x0018, 0x0102);
2040 cit_write_reg(gspca_dev, 0x0004, 0x0104);
2041 cit_write_reg(gspca_dev, 0x0004, 0x011a);
2042 cit_write_reg(gspca_dev, 0x0028, 0x011c);
2043 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2044 cit_write_reg(gspca_dev, 0x0000, 0x0118);
2045 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2046 cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
2047 cit_write_reg(gspca_dev, compression, 0x0109);
2048 clock_div = 3;
2049 break;
2050 case 320:
2051 cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
2052 cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
2053 cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
2054 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2055 cit_write_reg(gspca_dev, 0x0028, 0x010b); /* Differs everywhere */
2056 cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same */
2057 cit_write_reg(gspca_dev, 0x0000, 0x011e);
2058 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2059 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2060 /* 4 commands from 160x120 skipped */
2061 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2062 cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
2063 cit_write_reg(gspca_dev, compression, 0x0109);
2064 cit_write_reg(gspca_dev, 0x00d9, 0x0119);
2065 cit_write_reg(gspca_dev, 0x0006, 0x011b);
2066 cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
2067 cit_write_reg(gspca_dev, 0x0010, 0x0104);
2068 cit_write_reg(gspca_dev, 0x0004, 0x011a);
2069 cit_write_reg(gspca_dev, 0x003f, 0x011c);
2070 cit_write_reg(gspca_dev, 0x001c, 0x0118);
2071 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2072 clock_div = 5;
2073 break;
2074 case 640:
2075 cit_write_reg(gspca_dev, 0x00f0, 0x0105);
2076 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2077 cit_write_reg(gspca_dev, 0x0038, 0x010b); /* Differs everywhere */
2078 cit_write_reg(gspca_dev, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
2079 cit_write_reg(gspca_dev, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
2080 cit_write_reg(gspca_dev, 0x0004, 0x011d); /* NC */
2081 cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
2082 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2083 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2084 cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
2085 cit_write_reg(gspca_dev, 0x0016, 0x0104); /* NC */
2086 cit_write_reg(gspca_dev, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
2087 cit_write_reg(gspca_dev, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
2088 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2089 cit_write_reg(gspca_dev, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
2090 cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
2091 cit_write_reg(gspca_dev, compression, 0x0109);
2092 cit_write_reg(gspca_dev, 0x0040, 0x0101);
2093 cit_write_reg(gspca_dev, 0x0040, 0x0103);
2094 cit_write_reg(gspca_dev, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
2095 clock_div = 7;
2096 break;
2097 }
2098
2099 cit_model3_Packet1(gspca_dev, 0x007e, 0x000e); /* Hue */
2100 cit_model3_Packet1(gspca_dev, 0x0036, 0x0011); /* Brightness */
2101 cit_model3_Packet1(gspca_dev, 0x0060, 0x0002); /* Sharpness */
2102 cit_model3_Packet1(gspca_dev, 0x0061, 0x0004); /* Sharpness */
2103 cit_model3_Packet1(gspca_dev, 0x0062, 0x0005); /* Sharpness */
2104 cit_model3_Packet1(gspca_dev, 0x0063, 0x0014); /* Sharpness */
2105 cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */
2106 cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */
2107 cit_model3_Packet1(gspca_dev, 0x0067, 0x0001); /* Contrast */
2108 cit_model3_Packet1(gspca_dev, 0x005b, 0x000c); /* Contrast */
2109 cit_model3_Packet1(gspca_dev, 0x005c, 0x0016); /* Contrast */
2110 cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
2111 cit_model3_Packet1(gspca_dev, 0x002c, 0x0003); /* Was 1, broke 640x480 */
2112 cit_model3_Packet1(gspca_dev, 0x002f, 0x002a);
2113 cit_model3_Packet1(gspca_dev, 0x0030, 0x0029);
2114 cit_model3_Packet1(gspca_dev, 0x0037, 0x0002);
2115 cit_model3_Packet1(gspca_dev, 0x0038, 0x0059);
2116 cit_model3_Packet1(gspca_dev, 0x003d, 0x002e);
2117 cit_model3_Packet1(gspca_dev, 0x003e, 0x0028);
2118 cit_model3_Packet1(gspca_dev, 0x0078, 0x0005);
2119 cit_model3_Packet1(gspca_dev, 0x007b, 0x0011);
2120 cit_model3_Packet1(gspca_dev, 0x007d, 0x004b);
2121 cit_model3_Packet1(gspca_dev, 0x007f, 0x0022);
2122 cit_model3_Packet1(gspca_dev, 0x0080, 0x000c);
2123 cit_model3_Packet1(gspca_dev, 0x0081, 0x000b);
2124 cit_model3_Packet1(gspca_dev, 0x0083, 0x00fd);
2125 cit_model3_Packet1(gspca_dev, 0x0086, 0x000b);
2126 cit_model3_Packet1(gspca_dev, 0x0087, 0x000b);
2127 cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);
2128 cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */
2129 cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */
2130 cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
2131
2132 /* FIXME we should probably use cit_get_clock_div() here (in
2133 combination with isoc negotiation using the programmable isoc size)
2134 like with the IBM netcam pro). */
2135 cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */
2136
2137 switch (gspca_dev->width) {
2138 case 160:
2139 cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
2140 cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
2141 cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
2142 cit_model3_Packet1(gspca_dev, 0x0040, 0x000a);
2143 cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
2144 break;
2145 case 320:
2146 cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
2147 cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
2148 cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
2149 cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
2150 cit_model3_Packet1(gspca_dev, 0x0051, 0x000b);
2151 break;
2152 case 640:
2153 cit_model3_Packet1(gspca_dev, 0x001f, 0x0002); /* !Same */
2154 cit_model3_Packet1(gspca_dev, 0x0039, 0x003e); /* !Same */
2155 cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
2156 cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
2157 break;
2158 }
2159
2160/* if (sd->input_index) { */
2161 if (rca_input) {
2162 for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
2163 if (rca_initdata[i][0])
2164 cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
2165 else
2166 cit_write_reg(gspca_dev, rca_initdata[i][1],
2167 rca_initdata[i][2]);
2168 }
2169 }
2170
2171 return 0;
2172}
2173
2174static int cit_start_model4(struct gspca_dev *gspca_dev)
2175{
2176 struct sd *sd = (struct sd *) gspca_dev;
2177
2178 cit_write_reg(gspca_dev, 0x0000, 0x0100);
2179 cit_write_reg(gspca_dev, 0x00c0, 0x0111);
2180 cit_write_reg(gspca_dev, 0x00bc, 0x012c);
2181 cit_write_reg(gspca_dev, 0x0080, 0x012b);
2182 cit_write_reg(gspca_dev, 0x0000, 0x0108);
2183 cit_write_reg(gspca_dev, 0x0001, 0x0133);
2184 cit_write_reg(gspca_dev, 0x009b, 0x010f);
2185 cit_write_reg(gspca_dev, 0x00bb, 0x010f);
2186 cit_model4_Packet1(gspca_dev, 0x0038, 0x0000);
2187 cit_model4_Packet1(gspca_dev, 0x000a, 0x005c);
2188
2189 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2190 cit_write_reg(gspca_dev, 0x0004, 0x012f);
2191 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2192 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2193 cit_write_reg(gspca_dev, 0x00fb, 0x012e);
2194 cit_write_reg(gspca_dev, 0x0000, 0x0130);
2195 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2196 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2197 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2198 cit_write_reg(gspca_dev, 0x000c, 0x0127);
2199 cit_write_reg(gspca_dev, 0x0009, 0x012e);
2200 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2201
2202 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2203 cit_write_reg(gspca_dev, 0x0012, 0x012f);
2204 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2205 cit_write_reg(gspca_dev, 0x0008, 0x0127);
2206 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2207 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2208 cit_write_reg(gspca_dev, 0x002a, 0x012d);
2209 cit_write_reg(gspca_dev, 0x0000, 0x012f);
2210 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2211 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2212 cit_model4_Packet1(gspca_dev, 0x0034, 0x0000);
2213
2214 switch (gspca_dev->width) {
2215 case 128: /* 128x96 */
2216 cit_write_reg(gspca_dev, 0x0070, 0x0119);
2217 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2218 cit_write_reg(gspca_dev, 0x0039, 0x010a);
2219 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2220 cit_write_reg(gspca_dev, 0x0028, 0x0103);
2221 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2222 cit_write_reg(gspca_dev, 0x001e, 0x0105);
2223 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2224 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2225 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2226 cit_write_reg(gspca_dev, 0x000a, 0x0127);
2227 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2228 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2229 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2230 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2231 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2232 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2233 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2234 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2235 cit_write_reg(gspca_dev, 0x005a, 0x012d);
2236 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2237 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2238 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2239 cit_write_reg(gspca_dev, 0x0043, 0x0130);
2240 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2241 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2242 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2243 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2244 cit_write_reg(gspca_dev, 0x00eb, 0x012e);
2245 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2246 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2247 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2248 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2249 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2250 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2251 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2252 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2253 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2254 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2255 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2256 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2257 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2258 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2259 cit_write_reg(gspca_dev, 0x0017, 0x0127);
2260 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2261 cit_write_reg(gspca_dev, 0x0031, 0x0130);
2262 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2263 cit_write_reg(gspca_dev, 0x0017, 0x012d);
2264 cit_write_reg(gspca_dev, 0x0078, 0x012f);
2265 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2266 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2267 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2268 sd->sof_len = 2;
2269 break;
2270 case 160: /* 160x120 */
2271 cit_write_reg(gspca_dev, 0x0038, 0x0119);
2272 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2273 cit_write_reg(gspca_dev, 0x00b9, 0x010a);
2274 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2275 cit_write_reg(gspca_dev, 0x0028, 0x0103);
2276 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2277 cit_write_reg(gspca_dev, 0x001e, 0x0105);
2278 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2279 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2280 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2281 cit_write_reg(gspca_dev, 0x000b, 0x0127);
2282 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2283 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2284 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2285 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2286 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2287 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2288 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2289 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2290 cit_write_reg(gspca_dev, 0x005a, 0x012d);
2291 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2292 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2293 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2294 cit_write_reg(gspca_dev, 0x0043, 0x0130);
2295 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2296 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2297 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2298 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2299 cit_write_reg(gspca_dev, 0x00c7, 0x012e);
2300 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2301 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2302 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2303 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2304 cit_write_reg(gspca_dev, 0x0025, 0x0127);
2305 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2306 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2307 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2308 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2309 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2310 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2311 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2312 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2313 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2314 cit_write_reg(gspca_dev, 0x0048, 0x0127);
2315 cit_write_reg(gspca_dev, 0x0035, 0x012e);
2316 cit_write_reg(gspca_dev, 0x00d0, 0x0130);
2317 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2318 cit_write_reg(gspca_dev, 0x0048, 0x012d);
2319 cit_write_reg(gspca_dev, 0x0090, 0x012f);
2320 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2321 cit_write_reg(gspca_dev, 0x0001, 0x0127);
2322 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2323 sd->sof_len = 2;
2324 break;
2325 case 176: /* 176x144 */
2326 cit_write_reg(gspca_dev, 0x0038, 0x0119);
2327 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2328 cit_write_reg(gspca_dev, 0x00b9, 0x010a);
2329 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2330 cit_write_reg(gspca_dev, 0x002c, 0x0103);
2331 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2332 cit_write_reg(gspca_dev, 0x0024, 0x0105);
2333 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2334 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2335 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2336 cit_write_reg(gspca_dev, 0x0007, 0x0127);
2337 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2338 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2339 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2340 cit_write_reg(gspca_dev, 0x0001, 0x012f);
2341 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2342 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2343 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2344 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2345 cit_write_reg(gspca_dev, 0x005e, 0x012d);
2346 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2347 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2348 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2349 cit_write_reg(gspca_dev, 0x0049, 0x0130);
2350 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2351 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2352 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2353 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2354 cit_write_reg(gspca_dev, 0x00c7, 0x012e);
2355 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2356 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2357 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2358 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2359 cit_write_reg(gspca_dev, 0x0028, 0x0127);
2360 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2361 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2362 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2363 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2364 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2365 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2366 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2367 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2368 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2369 cit_write_reg(gspca_dev, 0x0010, 0x0127);
2370 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2371 cit_write_reg(gspca_dev, 0x002a, 0x0130);
2372 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2373 cit_write_reg(gspca_dev, 0x0010, 0x012d);
2374 cit_write_reg(gspca_dev, 0x006d, 0x012f);
2375 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2376 cit_write_reg(gspca_dev, 0x0001, 0x0127);
2377 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2378 /* TESTME HDG: this does not seem right
2379 (it is 2 for all other resolutions) */
2380 sd->sof_len = 10;
2381 break;
2382 case 320: /* 320x240 */
2383 cit_write_reg(gspca_dev, 0x0070, 0x0119);
2384 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2385 cit_write_reg(gspca_dev, 0x0039, 0x010a);
2386 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2387 cit_write_reg(gspca_dev, 0x0028, 0x0103);
2388 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2389 cit_write_reg(gspca_dev, 0x001e, 0x0105);
2390 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2391 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2392 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2393 cit_write_reg(gspca_dev, 0x000a, 0x0127);
2394 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2395 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2396 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2397 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2398 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2399 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2400 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2401 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2402 cit_write_reg(gspca_dev, 0x005a, 0x012d);
2403 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2404 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2405 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2406 cit_write_reg(gspca_dev, 0x0043, 0x0130);
2407 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2408 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2409 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2410 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2411 cit_write_reg(gspca_dev, 0x00eb, 0x012e);
2412 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2413 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2414 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2415 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2416 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2417 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2418 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2419 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2420 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2421 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2422 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2423 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2424 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2425 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2426 cit_write_reg(gspca_dev, 0x0017, 0x0127);
2427 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2428 cit_write_reg(gspca_dev, 0x0031, 0x0130);
2429 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2430 cit_write_reg(gspca_dev, 0x0017, 0x012d);
2431 cit_write_reg(gspca_dev, 0x0078, 0x012f);
2432 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2433 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2434 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2435 sd->sof_len = 2;
2436 break;
2437 case 352: /* 352x288 */
2438 cit_write_reg(gspca_dev, 0x0070, 0x0119);
2439 cit_write_reg(gspca_dev, 0x00c0, 0x0111);
2440 cit_write_reg(gspca_dev, 0x0039, 0x010a);
2441 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2442 cit_write_reg(gspca_dev, 0x002c, 0x0103);
2443 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2444 cit_write_reg(gspca_dev, 0x0024, 0x0105);
2445 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2446 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2447 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2448 cit_write_reg(gspca_dev, 0x0006, 0x0127);
2449 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2450 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2451 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2452 cit_write_reg(gspca_dev, 0x0002, 0x012f);
2453 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2454 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2455 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2456 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2457 cit_write_reg(gspca_dev, 0x005e, 0x012d);
2458 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2459 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2460 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2461 cit_write_reg(gspca_dev, 0x0049, 0x0130);
2462 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2463 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2464 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2465 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2466 cit_write_reg(gspca_dev, 0x00cf, 0x012e);
2467 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2468 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2469 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2470 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2471 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2472 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2473 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2474 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2475 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2476 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2477 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2478 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2479 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2480 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2481 cit_write_reg(gspca_dev, 0x0010, 0x0127);
2482 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2483 cit_write_reg(gspca_dev, 0x0025, 0x0130);
2484 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2485 cit_write_reg(gspca_dev, 0x0010, 0x012d);
2486 cit_write_reg(gspca_dev, 0x0048, 0x012f);
2487 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2488 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2489 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2490 sd->sof_len = 2;
2491 break;
2492 }
2493
2494 cit_model4_Packet1(gspca_dev, 0x0038, 0x0004);
2495
2496 return 0;
2497}
2498
2499static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
2500{
2501 const unsigned short compression = 0; /* 0=none, 7=best frame rate */
2502 int i, clock_div;
2503
2504 clock_div = cit_get_clock_div(gspca_dev);
2505 if (clock_div < 0)
2506 return clock_div;
2507
2508 cit_write_reg(gspca_dev, 0x0003, 0x0133);
2509 cit_write_reg(gspca_dev, 0x0000, 0x0117);
2510 cit_write_reg(gspca_dev, 0x0008, 0x0123);
2511 cit_write_reg(gspca_dev, 0x0000, 0x0100);
2512 cit_write_reg(gspca_dev, 0x0060, 0x0116);
2513 /* cit_write_reg(gspca_dev, 0x0002, 0x0112); see sd_stop0 */
2514 cit_write_reg(gspca_dev, 0x0000, 0x0133);
2515 cit_write_reg(gspca_dev, 0x0000, 0x0123);
2516 cit_write_reg(gspca_dev, 0x0001, 0x0117);
2517 cit_write_reg(gspca_dev, 0x0040, 0x0108);
2518 cit_write_reg(gspca_dev, 0x0019, 0x012c);
2519 cit_write_reg(gspca_dev, 0x0060, 0x0116);
2520 /* cit_write_reg(gspca_dev, 0x000b, 0x0115); see sd_stop0 */
2521
2522 cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
2523
2524 cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
2525 cit_write_reg(gspca_dev, 0x003a, 0x0102); /* Hstart */
2526 cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
2527 cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
2528 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2529 cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
2530 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2531 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2532 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2533
2534 switch (gspca_dev->width) {
2535 case 160: /* 160x120 */
2536 cit_write_reg(gspca_dev, 0x0024, 0x010b);
2537 cit_write_reg(gspca_dev, 0x0089, 0x0119);
2538 cit_write_reg(gspca_dev, 0x000a, 0x011b);
2539 cit_write_reg(gspca_dev, 0x0003, 0x011e);
2540 cit_write_reg(gspca_dev, 0x0007, 0x0104);
2541 cit_write_reg(gspca_dev, 0x0009, 0x011a);
2542 cit_write_reg(gspca_dev, 0x008b, 0x011c);
2543 cit_write_reg(gspca_dev, 0x0008, 0x0118);
2544 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2545 break;
2546 case 320: /* 320x240 */
2547 cit_write_reg(gspca_dev, 0x0028, 0x010b);
2548 cit_write_reg(gspca_dev, 0x00d9, 0x0119);
2549 cit_write_reg(gspca_dev, 0x0006, 0x011b);
2550 cit_write_reg(gspca_dev, 0x0000, 0x011e);
2551 cit_write_reg(gspca_dev, 0x000e, 0x0104);
2552 cit_write_reg(gspca_dev, 0x0004, 0x011a);
2553 cit_write_reg(gspca_dev, 0x003f, 0x011c);
2554 cit_write_reg(gspca_dev, 0x000c, 0x0118);
2555 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2556 break;
2557 }
2558
2559 cit_model3_Packet1(gspca_dev, 0x0019, 0x0031);
2560 cit_model3_Packet1(gspca_dev, 0x001a, 0x0003);
2561 cit_model3_Packet1(gspca_dev, 0x001b, 0x0038);
2562 cit_model3_Packet1(gspca_dev, 0x001c, 0x0000);
2563 cit_model3_Packet1(gspca_dev, 0x0024, 0x0001);
2564 cit_model3_Packet1(gspca_dev, 0x0027, 0x0001);
2565 cit_model3_Packet1(gspca_dev, 0x002a, 0x0004);
2566 cit_model3_Packet1(gspca_dev, 0x0035, 0x000b);
2567 cit_model3_Packet1(gspca_dev, 0x003f, 0x0001);
2568 cit_model3_Packet1(gspca_dev, 0x0044, 0x0000);
2569 cit_model3_Packet1(gspca_dev, 0x0054, 0x0000);
2570 cit_model3_Packet1(gspca_dev, 0x00c4, 0x0000);
2571 cit_model3_Packet1(gspca_dev, 0x00e7, 0x0001);
2572 cit_model3_Packet1(gspca_dev, 0x00e9, 0x0001);
2573 cit_model3_Packet1(gspca_dev, 0x00ee, 0x0000);
2574 cit_model3_Packet1(gspca_dev, 0x00f3, 0x00c0);
2575
2576 cit_write_reg(gspca_dev, compression, 0x0109);
2577 cit_write_reg(gspca_dev, clock_div, 0x0111);
2578
2579/* if (sd->input_index) { */
2580 if (rca_input) {
2581 for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
2582 if (rca_initdata[i][0])
2583 cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
2584 else
2585 cit_write_reg(gspca_dev, rca_initdata[i][1],
2586 rca_initdata[i][2]);
2587 }
2588 }
2589
2590 return 0;
2591}
2592
2593/* -- start the camera -- */
2594static int sd_start(struct gspca_dev *gspca_dev)
2595{
2596 struct sd *sd = (struct sd *) gspca_dev;
2597 int packet_size;
2598
2599 packet_size = cit_get_packet_size(gspca_dev);
2600 if (packet_size < 0)
2601 return packet_size;
2602
2603 switch (sd->model) {
2604 case CIT_MODEL0:
2605 cit_start_model0(gspca_dev);
2606 break;
2607 case CIT_MODEL1:
2608 cit_start_model1(gspca_dev);
2609 break;
2610 case CIT_MODEL2:
2611 cit_start_model2(gspca_dev);
2612 break;
2613 case CIT_MODEL3:
2614 cit_start_model3(gspca_dev);
2615 break;
2616 case CIT_MODEL4:
2617 cit_start_model4(gspca_dev);
2618 break;
2619 case CIT_IBM_NETCAM_PRO:
2620 cit_start_ibm_netcam_pro(gspca_dev);
2621 break;
2622 }
2623
2624 /* Program max isoc packet size */
2625 cit_write_reg(gspca_dev, packet_size >> 8, 0x0106);
2626 cit_write_reg(gspca_dev, packet_size & 0xff, 0x0107);
2627
2628 cit_restart_stream(gspca_dev);
2629
2630 return 0;
2631}
2632
2633static int sd_isoc_init(struct gspca_dev *gspca_dev)
2634{
2635 struct usb_host_interface *alt;
2636 int max_packet_size;
2637
2638 switch (gspca_dev->width) {
2639 case 160:
2640 max_packet_size = 450;
2641 break;
2642 case 176:
2643 max_packet_size = 600;
2644 break;
2645 default:
2646 max_packet_size = 1022;
2647 break;
2648 }
2649
2650 /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
2651 alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
2652 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
2653
2654 return 0;
2655}
2656
2657static int sd_isoc_nego(struct gspca_dev *gspca_dev)
2658{
2659 int ret, packet_size, min_packet_size;
2660 struct usb_host_interface *alt;
2661
2662 switch (gspca_dev->width) {
2663 case 160:
2664 min_packet_size = 200;
2665 break;
2666 case 176:
2667 min_packet_size = 266;
2668 break;
2669 default:
2670 min_packet_size = 400;
2671 break;
2672 }
2673
2674 alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
2675 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
2676 if (packet_size <= min_packet_size)
2677 return -EIO;
2678
2679 packet_size -= 100;
2680 if (packet_size < min_packet_size)
2681 packet_size = min_packet_size;
2682 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
2683
2684 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
2685 if (ret < 0)
2686 pr_err("set alt 1 err %d\n", ret);
2687
2688 return ret;
2689}
2690
2691static void sd_stopN(struct gspca_dev *gspca_dev)
2692{
2693 cit_write_reg(gspca_dev, 0x0000, 0x010c);
2694}
2695
2696static void sd_stop0(struct gspca_dev *gspca_dev)
2697{
2698 struct sd *sd = (struct sd *) gspca_dev;
2699
2700 /* We cannot use gspca_dev->present here as that is not set when
2701 sd_init gets called and we get called from sd_init */
2702 if (!gspca_dev->dev)
2703 return;
2704
2705 switch (sd->model) {
2706 case CIT_MODEL0:
2707 /* HDG windows does this, but it causes the cams autogain to
2708 restart from a gain of 0, which does not look good when
2709 changing resolutions. */
2710 /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
2711 cit_write_reg(gspca_dev, 0x00c0, 0x0100); /* LED Off */
2712 break;
2713 case CIT_MODEL1:
2714 cit_send_FF_04_02(gspca_dev);
2715 cit_read_reg(gspca_dev, 0x0100, 0);
2716 cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
2717 break;
2718 case CIT_MODEL2:
2719 v4l2_ctrl_grab(sd->lighting, false);
2720 /* Fall through! */
2721 case CIT_MODEL4:
2722 cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
2723
2724 cit_write_reg(gspca_dev, 0x0080, 0x0100); /* LED Off */
2725 cit_write_reg(gspca_dev, 0x0020, 0x0111);
2726 cit_write_reg(gspca_dev, 0x00a0, 0x0111);
2727
2728 cit_model2_Packet1(gspca_dev, 0x0030, 0x0002);
2729
2730 cit_write_reg(gspca_dev, 0x0020, 0x0111);
2731 cit_write_reg(gspca_dev, 0x0000, 0x0112);
2732 break;
2733 case CIT_MODEL3:
2734 cit_write_reg(gspca_dev, 0x0006, 0x012c);
2735 cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
2736 cit_read_reg(gspca_dev, 0x0116, 0);
2737 cit_write_reg(gspca_dev, 0x0064, 0x0116);
2738 cit_read_reg(gspca_dev, 0x0115, 0);
2739 cit_write_reg(gspca_dev, 0x0003, 0x0115);
2740 cit_write_reg(gspca_dev, 0x0008, 0x0123);
2741 cit_write_reg(gspca_dev, 0x0000, 0x0117);
2742 cit_write_reg(gspca_dev, 0x0000, 0x0112);
2743 cit_write_reg(gspca_dev, 0x0080, 0x0100);
2744 break;
2745 case CIT_IBM_NETCAM_PRO:
2746 cit_model3_Packet1(gspca_dev, 0x0049, 0x00ff);
2747 cit_write_reg(gspca_dev, 0x0006, 0x012c);
2748 cit_write_reg(gspca_dev, 0x0000, 0x0116);
2749 /* HDG windows does this, but I cannot get the camera
2750 to restart with this without redoing the entire init
2751 sequence which makes switching modes really slow */
2752 /* cit_write_reg(gspca_dev, 0x0006, 0x0115); */
2753 cit_write_reg(gspca_dev, 0x0008, 0x0123);
2754 cit_write_reg(gspca_dev, 0x0000, 0x0117);
2755 cit_write_reg(gspca_dev, 0x0003, 0x0133);
2756 cit_write_reg(gspca_dev, 0x0000, 0x0111);
2757 /* HDG windows does this, but I get a green picture when
2758 restarting the stream after this */
2759 /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
2760 cit_write_reg(gspca_dev, 0x00c0, 0x0100);
2761 break;
2762 }
2763
2764#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2765 /* If the last button state is pressed, release it now! */
2766 if (sd->button_state) {
2767 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2768 input_sync(gspca_dev->input_dev);
2769 sd->button_state = 0;
2770 }
2771#endif
2772}
2773
2774static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
2775{
2776 struct sd *sd = (struct sd *) gspca_dev;
2777 u8 byte3 = 0, byte4 = 0;
2778 int i;
2779
2780 switch (sd->model) {
2781 case CIT_MODEL0:
2782 case CIT_MODEL1:
2783 case CIT_MODEL3:
2784 case CIT_IBM_NETCAM_PRO:
2785 switch (gspca_dev->width) {
2786 case 160: /* 160x120 */
2787 byte3 = 0x02;
2788 byte4 = 0x0a;
2789 break;
2790 case 176: /* 176x144 */
2791 byte3 = 0x02;
2792 byte4 = 0x0e;
2793 break;
2794 case 320: /* 320x240 */
2795 byte3 = 0x02;
2796 byte4 = 0x08;
2797 break;
2798 case 352: /* 352x288 */
2799 byte3 = 0x02;
2800 byte4 = 0x00;
2801 break;
2802 case 640:
2803 byte3 = 0x03;
2804 byte4 = 0x08;
2805 break;
2806 }
2807
2808 /* These have a different byte3 */
2809 if (sd->model <= CIT_MODEL1)
2810 byte3 = 0x00;
2811
2812 for (i = 0; i < len; i++) {
2813 /* For this model the SOF always starts at offset 0
2814 so no need to search the entire frame */
2815 if (sd->model == CIT_MODEL0 && sd->sof_read != i)
2816 break;
2817
2818 switch (sd->sof_read) {
2819 case 0:
2820 if (data[i] == 0x00)
2821 sd->sof_read++;
2822 break;
2823 case 1:
2824 if (data[i] == 0xff)
2825 sd->sof_read++;
2826 else if (data[i] == 0x00)
2827 sd->sof_read = 1;
2828 else
2829 sd->sof_read = 0;
2830 break;
2831 case 2:
2832 if (data[i] == byte3)
2833 sd->sof_read++;
2834 else if (data[i] == 0x00)
2835 sd->sof_read = 1;
2836 else
2837 sd->sof_read = 0;
2838 break;
2839 case 3:
2840 if (data[i] == byte4) {
2841 sd->sof_read = 0;
2842 return data + i + (sd->sof_len - 3);
2843 }
2844 if (byte3 == 0x00 && data[i] == 0xff)
2845 sd->sof_read = 2;
2846 else if (data[i] == 0x00)
2847 sd->sof_read = 1;
2848 else
2849 sd->sof_read = 0;
2850 break;
2851 }
2852 }
2853 break;
2854 case CIT_MODEL2:
2855 case CIT_MODEL4:
2856 /* TESTME we need to find a longer sof signature to avoid
2857 false positives */
2858 for (i = 0; i < len; i++) {
2859 switch (sd->sof_read) {
2860 case 0:
2861 if (data[i] == 0x00)
2862 sd->sof_read++;
2863 break;
2864 case 1:
2865 sd->sof_read = 0;
2866 if (data[i] == 0xff) {
2867 if (i >= 4)
2868 PDEBUG(D_FRAM,
2869 "header found at offset: %d: %02x %02x 00 %02x %02x %02x\n",
2870 i - 1,
2871 data[i - 4],
2872 data[i - 3],
2873 data[i],
2874 data[i + 1],
2875 data[i + 2]);
2876 else
2877 PDEBUG(D_FRAM,
2878 "header found at offset: %d: 00 %02x %02x %02x\n",
2879 i - 1,
2880 data[i],
2881 data[i + 1],
2882 data[i + 2]);
2883 return data + i + (sd->sof_len - 1);
2884 }
2885 break;
2886 }
2887 }
2888 break;
2889 }
2890 return NULL;
2891}
2892
2893static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2894 u8 *data, int len)
2895{
2896 struct sd *sd = (struct sd *) gspca_dev;
2897 unsigned char *sof;
2898
2899 sof = cit_find_sof(gspca_dev, data, len);
2900 if (sof) {
2901 int n;
2902
2903 /* finish decoding current frame */
2904 n = sof - data;
2905 if (n > sd->sof_len)
2906 n -= sd->sof_len;
2907 else
2908 n = 0;
2909 gspca_frame_add(gspca_dev, LAST_PACKET,
2910 data, n);
2911 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
2912 len -= sof - data;
2913 data = sof;
2914 }
2915
2916 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2917}
2918
2919#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2920static void cit_check_button(struct gspca_dev *gspca_dev)
2921{
2922 int new_button_state;
2923 struct sd *sd = (struct sd *)gspca_dev;
2924
2925 switch (sd->model) {
2926 case CIT_MODEL3:
2927 case CIT_IBM_NETCAM_PRO:
2928 break;
2929 default: /* TEST ME unknown if this works on other models too */
2930 return;
2931 }
2932
2933 /* Read the button state */
2934 cit_read_reg(gspca_dev, 0x0113, 0);
2935 new_button_state = !gspca_dev->usb_buf[0];
2936
2937 /* Tell the cam we've seen the button press, notice that this
2938 is a nop (iow the cam keeps reporting pressed) until the
2939 button is actually released. */
2940 if (new_button_state)
2941 cit_write_reg(gspca_dev, 0x01, 0x0113);
2942
2943 if (sd->button_state != new_button_state) {
2944 input_report_key(gspca_dev->input_dev, KEY_CAMERA,
2945 new_button_state);
2946 input_sync(gspca_dev->input_dev);
2947 sd->button_state = new_button_state;
2948 }
2949}
2950#endif
2951
2952static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
2953{
2954 struct gspca_dev *gspca_dev =
2955 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
2956 struct sd *sd = (struct sd *)gspca_dev;
2957
2958 gspca_dev->usb_err = 0;
2959
2960 if (!gspca_dev->streaming)
2961 return 0;
2962
2963 if (sd->stop_on_control_change)
2964 sd_stopN(gspca_dev);
2965 switch (ctrl->id) {
2966 case V4L2_CID_BRIGHTNESS:
2967 cit_set_brightness(gspca_dev, ctrl->val);
2968 break;
2969 case V4L2_CID_CONTRAST:
2970 cit_set_contrast(gspca_dev, ctrl->val);
2971 break;
2972 case V4L2_CID_HUE:
2973 cit_set_hue(gspca_dev, ctrl->val);
2974 break;
2975 case V4L2_CID_HFLIP:
2976 cit_set_hflip(gspca_dev, ctrl->val);
2977 break;
2978 case V4L2_CID_SHARPNESS:
2979 cit_set_sharpness(gspca_dev, ctrl->val);
2980 break;
2981 case V4L2_CID_BACKLIGHT_COMPENSATION:
2982 cit_set_lighting(gspca_dev, ctrl->val);
2983 break;
2984 }
2985 if (sd->stop_on_control_change)
2986 cit_restart_stream(gspca_dev);
2987 return gspca_dev->usb_err;
2988}
2989
2990static const struct v4l2_ctrl_ops sd_ctrl_ops = {
2991 .s_ctrl = sd_s_ctrl,
2992};
2993
2994static int sd_init_controls(struct gspca_dev *gspca_dev)
2995{
2996 struct sd *sd = (struct sd *)gspca_dev;
2997 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
2998 bool has_brightness;
2999 bool has_contrast;
3000 bool has_hue;
3001 bool has_sharpness;
3002 bool has_lighting;
3003 bool has_hflip;
3004
3005 has_brightness = has_contrast = has_hue =
3006 has_sharpness = has_hflip = has_lighting = false;
3007 switch (sd->model) {
3008 case CIT_MODEL0:
3009 has_contrast = has_hflip = true;
3010 break;
3011 case CIT_MODEL1:
3012 has_brightness = has_contrast =
3013 has_sharpness = has_lighting = true;
3014 break;
3015 case CIT_MODEL2:
3016 has_brightness = has_hue = has_lighting = true;
3017 break;
3018 case CIT_MODEL3:
3019 has_brightness = has_contrast = has_sharpness = true;
3020 break;
3021 case CIT_MODEL4:
3022 has_brightness = has_hue = true;
3023 break;
3024 case CIT_IBM_NETCAM_PRO:
3025 has_brightness = has_hue =
3026 has_sharpness = has_hflip = has_lighting = true;
3027 break;
3028 }
3029 gspca_dev->vdev.ctrl_handler = hdl;
3030 v4l2_ctrl_handler_init(hdl, 5);
3031 if (has_brightness)
3032 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3033 V4L2_CID_BRIGHTNESS, 0, 63, 1, 32);
3034 if (has_contrast)
3035 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3036 V4L2_CID_CONTRAST, 0, 20, 1, 10);
3037 if (has_hue)
3038 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3039 V4L2_CID_HUE, 0, 127, 1, 63);
3040 if (has_sharpness)
3041 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3042 V4L2_CID_SHARPNESS, 0, 6, 1, 3);
3043 if (has_lighting)
3044 sd->lighting = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3045 V4L2_CID_BACKLIGHT_COMPENSATION, 0, 2, 1, 1);
3046 if (has_hflip)
3047 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
3048 V4L2_CID_HFLIP, 0, 1, 1, 0);
3049
3050 if (hdl->error) {
3051 pr_err("Could not initialize controls\n");
3052 return hdl->error;
3053 }
3054 return 0;
3055}
3056
3057/* sub-driver description */
3058static const struct sd_desc sd_desc = {
3059 .name = MODULE_NAME,
3060 .config = sd_config,
3061 .init = sd_init,
3062 .init_controls = sd_init_controls,
3063 .start = sd_start,
3064 .stopN = sd_stopN,
3065 .stop0 = sd_stop0,
3066 .pkt_scan = sd_pkt_scan,
3067#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3068 .dq_callback = cit_check_button,
3069 .other_input = 1,
3070#endif
3071};
3072
3073static const struct sd_desc sd_desc_isoc_nego = {
3074 .name = MODULE_NAME,
3075 .config = sd_config,
3076 .init = sd_init,
3077 .init_controls = sd_init_controls,
3078 .start = sd_start,
3079 .isoc_init = sd_isoc_init,
3080 .isoc_nego = sd_isoc_nego,
3081 .stopN = sd_stopN,
3082 .stop0 = sd_stop0,
3083 .pkt_scan = sd_pkt_scan,
3084#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3085 .dq_callback = cit_check_button,
3086 .other_input = 1,
3087#endif
3088};
3089
3090/* -- module initialisation -- */
3091static const struct usb_device_id device_table[] = {
3092 { USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 },
3093 { USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 },
3094 { USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
3095 { USB_DEVICE_VER(0x0545, 0x8080, 0x0301, 0x0301), .driver_info = CIT_MODEL3 },
3096 { USB_DEVICE_VER(0x0545, 0x8002, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
3097 { USB_DEVICE_VER(0x0545, 0x800c, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
3098 { USB_DEVICE_VER(0x0545, 0x800d, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
3099 {}
3100};
3101MODULE_DEVICE_TABLE(usb, device_table);
3102
3103/* -- device connect -- */
3104static int sd_probe(struct usb_interface *intf,
3105 const struct usb_device_id *id)
3106{
3107 const struct sd_desc *desc = &sd_desc;
3108
3109 switch (id->driver_info) {
3110 case CIT_MODEL0:
3111 case CIT_MODEL1:
3112 if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
3113 return -ENODEV;
3114 break;
3115 case CIT_MODEL2:
3116 case CIT_MODEL4:
3117 if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
3118 return -ENODEV;
3119 break;
3120 case CIT_MODEL3:
3121 if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
3122 return -ENODEV;
3123 /* FIXME this likely applies to all model3 cams and probably
3124 to other models too. */
3125 if (ibm_netcam_pro)
3126 desc = &sd_desc_isoc_nego;
3127 break;
3128 }
3129
3130 return gspca_dev_probe2(intf, id, desc, sizeof(struct sd), THIS_MODULE);
3131}
3132
3133static struct usb_driver sd_driver = {
3134 .name = MODULE_NAME,
3135 .id_table = device_table,
3136 .probe = sd_probe,
3137 .disconnect = gspca_disconnect,
3138#ifdef CONFIG_PM
3139 .suspend = gspca_suspend,
3140 .resume = gspca_resume,
3141 .reset_resume = gspca_resume,
3142#endif
3143};
3144
3145module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/zc3xx-reg.h b/drivers/media/usb/gspca/zc3xx-reg.h
new file mode 100644
index 00000000000..a1bd94e8ce5
--- /dev/null
+++ b/drivers/media/usb/gspca/zc3xx-reg.h
@@ -0,0 +1,251 @@
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/* Matrixes */
164
165/* Color matrix is like :
166 R' = R * RGB00 + G * RGB01 + B * RGB02 + RGB03
167 G' = R * RGB10 + G * RGB11 + B * RGB22 + RGB13
168 B' = R * RGB20 + G * RGB21 + B * RGB12 + RGB23
169 */
170#define ZC3XX_R10A_RGB00 0x010a
171#define ZC3XX_R10B_RGB01 0x010b
172#define ZC3XX_R10C_RGB02 0x010c
173#define ZC3XX_R113_RGB03 0x0113
174#define ZC3XX_R10D_RGB10 0x010d
175#define ZC3XX_R10E_RGB11 0x010e
176#define ZC3XX_R10F_RGB12 0x010f
177#define ZC3XX_R114_RGB13 0x0114
178#define ZC3XX_R110_RGB20 0x0110
179#define ZC3XX_R111_RGB21 0x0111
180#define ZC3XX_R112_RGB22 0x0112
181#define ZC3XX_R115_RGB23 0x0115
182
183/* Gamma matrix */
184#define ZC3XX_R120_GAMMA00 0x0120
185#define ZC3XX_R121_GAMMA01 0x0121
186#define ZC3XX_R122_GAMMA02 0x0122
187#define ZC3XX_R123_GAMMA03 0x0123
188#define ZC3XX_R124_GAMMA04 0x0124
189#define ZC3XX_R125_GAMMA05 0x0125
190#define ZC3XX_R126_GAMMA06 0x0126
191#define ZC3XX_R127_GAMMA07 0x0127
192#define ZC3XX_R128_GAMMA08 0x0128
193#define ZC3XX_R129_GAMMA09 0x0129
194#define ZC3XX_R12A_GAMMA0A 0x012a
195#define ZC3XX_R12B_GAMMA0B 0x012b
196#define ZC3XX_R12C_GAMMA0C 0x012c
197#define ZC3XX_R12D_GAMMA0D 0x012d
198#define ZC3XX_R12E_GAMMA0E 0x012e
199#define ZC3XX_R12F_GAMMA0F 0x012f
200#define ZC3XX_R130_GAMMA10 0x0130
201#define ZC3XX_R131_GAMMA11 0x0131
202#define ZC3XX_R132_GAMMA12 0x0132
203#define ZC3XX_R133_GAMMA13 0x0133
204#define ZC3XX_R134_GAMMA14 0x0134
205#define ZC3XX_R135_GAMMA15 0x0135
206#define ZC3XX_R136_GAMMA16 0x0136
207#define ZC3XX_R137_GAMMA17 0x0137
208#define ZC3XX_R138_GAMMA18 0x0138
209#define ZC3XX_R139_GAMMA19 0x0139
210#define ZC3XX_R13A_GAMMA1A 0x013a
211#define ZC3XX_R13B_GAMMA1B 0x013b
212#define ZC3XX_R13C_GAMMA1C 0x013c
213#define ZC3XX_R13D_GAMMA1D 0x013d
214#define ZC3XX_R13E_GAMMA1E 0x013e
215#define ZC3XX_R13F_GAMMA1F 0x013f
216
217/* Luminance gamma */
218#define ZC3XX_R140_YGAMMA00 0x0140
219#define ZC3XX_R141_YGAMMA01 0x0141
220#define ZC3XX_R142_YGAMMA02 0x0142
221#define ZC3XX_R143_YGAMMA03 0x0143
222#define ZC3XX_R144_YGAMMA04 0x0144
223#define ZC3XX_R145_YGAMMA05 0x0145
224#define ZC3XX_R146_YGAMMA06 0x0146
225#define ZC3XX_R147_YGAMMA07 0x0147
226#define ZC3XX_R148_YGAMMA08 0x0148
227#define ZC3XX_R149_YGAMMA09 0x0149
228#define ZC3XX_R14A_YGAMMA0A 0x014a
229#define ZC3XX_R14B_YGAMMA0B 0x014b
230#define ZC3XX_R14C_YGAMMA0C 0x014c
231#define ZC3XX_R14D_YGAMMA0D 0x014d
232#define ZC3XX_R14E_YGAMMA0E 0x014e
233#define ZC3XX_R14F_YGAMMA0F 0x014f
234#define ZC3XX_R150_YGAMMA10 0x0150
235#define ZC3XX_R151_YGAMMA11 0x0151
236
237#define ZC3XX_R1C5_SHARPNESSMODE 0x01c5
238#define ZC3XX_R1C6_SHARPNESS00 0x01c6
239#define ZC3XX_R1C7_SHARPNESS01 0x01c7
240#define ZC3XX_R1C8_SHARPNESS02 0x01c8
241#define ZC3XX_R1C9_SHARPNESS03 0x01c9
242#define ZC3XX_R1CA_SHARPNESS04 0x01ca
243#define ZC3XX_R1CB_SHARPNESS05 0x01cb
244
245/* Dead pixels */
246#define ZC3XX_R250_DEADPIXELSMODE 0x0250
247
248/* EEPROM */
249#define ZC3XX_R300_EEPROMCONFIG 0x0300
250#define ZC3XX_R301_EEPROMACCESS 0x0301
251#define ZC3XX_R302_EEPROMSTATUS 0x0302
diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c
new file mode 100644
index 00000000000..f0bacee33ef
--- /dev/null
+++ b/drivers/media/usb/gspca/zc3xx.c
@@ -0,0 +1,7024 @@
1/*
2 * Z-Star/Vimicro zc301/zc302p/vc30x driver
3 *
4 * Copyright (C) 2009-2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.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 * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include <linux/input.h>
25#include "gspca.h"
26#include "jpeg.h"
27
28MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
29 "Serge A. Suchkov <Serge.A.S@tochka.ru>");
30MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33static int force_sensor = -1;
34
35#define REG08_DEF 3 /* default JPEG compression (75%) */
36#include "zc3xx-reg.h"
37
38/* specific webcam descriptor */
39struct sd {
40 struct gspca_dev gspca_dev; /* !! must be the first item */
41
42 struct { /* gamma/brightness/contrast control cluster */
43 struct v4l2_ctrl *gamma;
44 struct v4l2_ctrl *brightness;
45 struct v4l2_ctrl *contrast;
46 };
47 struct { /* autogain/exposure control cluster */
48 struct v4l2_ctrl *autogain;
49 struct v4l2_ctrl *exposure;
50 };
51 struct v4l2_ctrl *plfreq;
52 struct v4l2_ctrl *sharpness;
53 struct v4l2_ctrl *jpegqual;
54
55 struct work_struct work;
56 struct workqueue_struct *work_thread;
57
58 u8 reg08; /* webcam compression quality */
59
60 u8 bridge;
61 u8 sensor; /* Type of image sensor chip */
62 u16 chip_revision;
63
64 u8 jpeg_hdr[JPEG_HDR_SZ];
65};
66enum bridges {
67 BRIDGE_ZC301,
68 BRIDGE_ZC303,
69};
70enum sensors {
71 SENSOR_ADCM2700,
72 SENSOR_CS2102,
73 SENSOR_CS2102K,
74 SENSOR_GC0303,
75 SENSOR_GC0305,
76 SENSOR_HDCS2020,
77 SENSOR_HV7131B,
78 SENSOR_HV7131R,
79 SENSOR_ICM105A,
80 SENSOR_MC501CB,
81 SENSOR_MT9V111_1, /* (mi360soc) zc301 */
82 SENSOR_MT9V111_3, /* (mi360soc) zc303 */
83 SENSOR_OV7620, /* OV7648 - same values */
84 SENSOR_OV7630C,
85 SENSOR_PAS106,
86 SENSOR_PAS202B,
87 SENSOR_PB0330,
88 SENSOR_PO2030,
89 SENSOR_TAS5130C,
90 SENSOR_MAX
91};
92
93static const struct v4l2_pix_format vga_mode[] = {
94 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
95 .bytesperline = 320,
96 .sizeimage = 320 * 240 * 3 / 8 + 590,
97 .colorspace = V4L2_COLORSPACE_JPEG,
98 .priv = 1},
99 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
100 .bytesperline = 640,
101 .sizeimage = 640 * 480 * 3 / 8 + 590,
102 .colorspace = V4L2_COLORSPACE_JPEG,
103 .priv = 0},
104};
105
106static const struct v4l2_pix_format broken_vga_mode[] = {
107 {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
108 .bytesperline = 320,
109 .sizeimage = 320 * 232 * 4 / 8 + 590,
110 .colorspace = V4L2_COLORSPACE_JPEG,
111 .priv = 1},
112 {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
113 .bytesperline = 640,
114 .sizeimage = 640 * 472 * 3 / 8 + 590,
115 .colorspace = V4L2_COLORSPACE_JPEG,
116 .priv = 0},
117};
118
119static const struct v4l2_pix_format sif_mode[] = {
120 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
121 .bytesperline = 176,
122 .sizeimage = 176 * 144 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
124 .priv = 1},
125 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
126 .bytesperline = 352,
127 .sizeimage = 352 * 288 * 3 / 8 + 590,
128 .colorspace = V4L2_COLORSPACE_JPEG,
129 .priv = 0},
130};
131
132/*
133 * Bridge reg08 bits 1-2 -> JPEG quality conversion table. Note the highest
134 * quality setting is not usable as USB 1 does not have enough bandwidth.
135 */
136static u8 jpeg_qual[] = {50, 75, 87, /* 94 */};
137
138/* usb exchanges */
139struct usb_action {
140 u8 req;
141 u8 val;
142 u16 idx;
143};
144
145static const struct usb_action adcm2700_Initial[] = {
146 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
147 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
148 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
149 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
150 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
151 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
152 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
153 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
154 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
155 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
156 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
157 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
158 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
159 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
160 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
161 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
162 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
163 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
164 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
165 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
166 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
167 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
168 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
169 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
170 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
171 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
172 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
173 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
174 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
175 {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */
176 {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */
177 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
178 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
179 {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */
180 {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */
181 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
182 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
183 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
184 {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */
185 {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */
186 {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */
187 {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */
188 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
189 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
190 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
191 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
192 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
193 {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */
194 {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */
195 {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */
196 {0xbb, 0x86, 0x0002}, /* 00,86,02,bb */
197 {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */
198 {0xbb, 0x86, 0x0802}, /* 08,86,02,bb */
199 {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */
200 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
201 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
202 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
203 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
204 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
205 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
206 {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */
207/*mswin+*/
208 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
209 {0xaa, 0xfe, 0x0002},
210 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
211 {0xaa, 0xb4, 0xcd37},
212 {0xaa, 0xa4, 0x0004},
213 {0xaa, 0xa8, 0x0007},
214 {0xaa, 0xac, 0x0004},
215/*mswin-*/
216 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
217 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
218 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
219 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
220 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
221 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
222 {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */
223 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
224 {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */
225 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
226 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
227 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
228 {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */
229 {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */
230 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
231 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
232 {}
233};
234static const struct usb_action adcm2700_InitialScale[] = {
235 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
236 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
237 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
238 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
239 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
240 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
241 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
242 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
243 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
244 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
245 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
246 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
247 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
248 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
249 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
250 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
251 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
252 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
253 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
254 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
255 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
256 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
257 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
258 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
259 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
260 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
261 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
262 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
263 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
264 {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */
265 {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */
266 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
267 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
268 {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */
269 {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */
270 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
271 {0xdd, 0x00, 0x0050}, /* 00,00,50,dd */
272 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
273 {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */
274 {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */
275 {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */
276 {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */
277 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
278 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
279 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
280 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
281 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
282 {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */
283 {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */
284 {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */
285 {0xbb, 0x86, 0x0002}, /* 00,88,02,bb */
286 {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */
287 {0xbb, 0x86, 0x0802}, /* 08,88,02,bb */
288 {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */
289 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
290 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
291 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
292 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
293 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
294 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
295 {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */
296 /*******/
297 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
298 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
299 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
300 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
301 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
302 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
303 {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */
304 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
305 {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */
306 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
307 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
308 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
309 {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */
310 {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */
311 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
312 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
313 {}
314};
315static const struct usb_action adcm2700_50HZ[] = {
316 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
317 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
318 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
319 {0xbb, 0x05, 0x8400}, /* 84,05,00,bb */
320 {0xbb, 0xd0, 0xb007}, /* b0,d0,07,bb */
321 {0xbb, 0xa0, 0xb80f}, /* b8,a0,0f,bb */
322 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
323 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
324 {0xaa, 0x26, 0x00d0}, /* 00,26,d0,aa */
325 {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
326 {}
327};
328static const struct usb_action adcm2700_60HZ[] = {
329 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
330 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
331 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
332 {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */
333 {0xbb, 0x82, 0xb006}, /* b0,82,06,bb */
334 {0xbb, 0x04, 0xb80d}, /* b8,04,0d,bb */
335 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
336 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
337 {0xaa, 0x26, 0x0057}, /* 00,26,57,aa */
338 {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
339 {}
340};
341static const struct usb_action adcm2700_NoFliker[] = {
342 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
343 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
344 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
345 {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */
346 {0xbb, 0x05, 0xb000}, /* b0,05,00,bb */
347 {0xbb, 0xa0, 0xb801}, /* b8,a0,01,bb */
348 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
349 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
350 {}
351};
352static const struct usb_action cs2102_InitialScale[] = { /* 320x240 */
353 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
354 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
355 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
356 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
357 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
358 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
359 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
360 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
361 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
362 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
363 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
364 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
365 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
366 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
367 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
368 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
369 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
370 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
371 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
372 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
373 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
374 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
375 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
376 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
377 {0xaa, 0x02, 0x0008},
378 {0xaa, 0x03, 0x0000},
379 {0xaa, 0x11, 0x0000},
380 {0xaa, 0x12, 0x0089},
381 {0xaa, 0x13, 0x0000},
382 {0xaa, 0x14, 0x00e9},
383 {0xaa, 0x20, 0x0000},
384 {0xaa, 0x22, 0x0000},
385 {0xaa, 0x0b, 0x0004},
386 {0xaa, 0x30, 0x0030},
387 {0xaa, 0x31, 0x0030},
388 {0xaa, 0x32, 0x0030},
389 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
390 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
391 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
392 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
393 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
394 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
395 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
396 {0xa0, 0x10, 0x01ae},
397 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
398 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
399 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
400 {0xa0, 0x00, 0x01ad},
401 {}
402};
403
404static const struct usb_action cs2102_Initial[] = { /* 640x480 */
405 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
406 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
407 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
408 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
409 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
410 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
411 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
412 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
413 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
414 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
415 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
416 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
417 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
418 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
419 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
420 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
421 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
422 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
423 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
424 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
425 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
426 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
427 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
428 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
429 {0xaa, 0x02, 0x0008},
430 {0xaa, 0x03, 0x0000},
431 {0xaa, 0x11, 0x0001},
432 {0xaa, 0x12, 0x0087},
433 {0xaa, 0x13, 0x0001},
434 {0xaa, 0x14, 0x00e7},
435 {0xaa, 0x20, 0x0000},
436 {0xaa, 0x22, 0x0000},
437 {0xaa, 0x0b, 0x0004},
438 {0xaa, 0x30, 0x0030},
439 {0xaa, 0x31, 0x0030},
440 {0xaa, 0x32, 0x0030},
441 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
442 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
443 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
444 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
445 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
446 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
447 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
448 {0xa0, 0x15, 0x01ae},
449 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
450 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
451 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
452 {0xa0, 0x00, 0x01ad},
453 {}
454};
455static const struct usb_action cs2102_50HZScale[] = {
456 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
457 {0xaa, 0x23, 0x0001},
458 {0xaa, 0x24, 0x005f},
459 {0xaa, 0x25, 0x0090},
460 {0xaa, 0x21, 0x00dd},
461 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
462 {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
463 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
464 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
465 {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID},
466 {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW},
467 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
468 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
469 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
470 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
471 {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0},
472 {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1},
473 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
474 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
475 {}
476};
477static const struct usb_action cs2102_50HZ[] = {
478 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
479 {0xaa, 0x23, 0x0000},
480 {0xaa, 0x24, 0x00af},
481 {0xaa, 0x25, 0x00c8},
482 {0xaa, 0x21, 0x0068},
483 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
484 {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
485 {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW},
486 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
487 {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID},
488 {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW},
489 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
490 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
491 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
492 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
493 {0xa0, 0x68, ZC3XX_R01D_HSYNC_0},
494 {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1},
495 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
496 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
497 {}
498};
499static const struct usb_action cs2102_60HZScale[] = {
500 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
501 {0xaa, 0x23, 0x0001},
502 {0xaa, 0x24, 0x0055},
503 {0xaa, 0x25, 0x00cc},
504 {0xaa, 0x21, 0x003f},
505 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
506 {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID},
507 {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW},
508 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
509 {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID},
510 {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW},
511 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
512 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
513 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
514 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
515 {0xa0, 0x39, ZC3XX_R01D_HSYNC_0},
516 {0xa0, 0x70, ZC3XX_R01E_HSYNC_1},
517 {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2},
518 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
519 {}
520};
521static const struct usb_action cs2102_60HZ[] = {
522 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
523 {0xaa, 0x23, 0x0000},
524 {0xaa, 0x24, 0x00aa},
525 {0xaa, 0x25, 0x00e6},
526 {0xaa, 0x21, 0x003f},
527 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
528 {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID},
529 {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW},
530 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
531 {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID},
532 {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW},
533 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
534 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
535 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
536 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
537 {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0},
538 {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1},
539 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
540 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
541 {}
542};
543static const struct usb_action cs2102_NoFlikerScale[] = {
544 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
545 {0xaa, 0x23, 0x0001},
546 {0xaa, 0x24, 0x005f},
547 {0xaa, 0x25, 0x0000},
548 {0xaa, 0x21, 0x0001},
549 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
550 {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
551 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
552 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
553 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
554 {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
555 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
556 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
557 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
558 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
559 {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
560 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
561 {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
562 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
563 {}
564};
565static const struct usb_action cs2102_NoFliker[] = {
566 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
567 {0xaa, 0x23, 0x0000},
568 {0xaa, 0x24, 0x00af},
569 {0xaa, 0x25, 0x0080},
570 {0xaa, 0x21, 0x0001},
571 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
572 {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
573 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
574 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
575 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
576 {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
577 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
578 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
579 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
580 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
581 {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
582 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
583 {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
584 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
585 {}
586};
587
588/* CS2102_KOCOM */
589static const struct usb_action cs2102K_InitialScale[] = {
590 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
591 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
592 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
593 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
594 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
595 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
596 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
597 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
598 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
599 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
600 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
601 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
602 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
603 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
604 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
605 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
606 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
607 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
608 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
609 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
610 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
611 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
612 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
613 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
614 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
615 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
616 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
617 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
618 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
619 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
620 {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE},
621 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
622 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
623 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
624 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
625 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
626 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
627 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
628 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
629 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
630 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
631 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
632 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
633 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
634 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
635 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
636 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
637 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
638 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
639 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
640 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
641 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
642 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
643 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
644 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
645 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
646 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
647 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
648 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
649 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
650 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
651 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
652 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
653 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
654 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
655 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
656 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
657 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
658 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
659 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
660 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
661 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
662 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
663 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
664 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
665 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
666 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
667 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
668 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
669 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
670 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
671 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
672 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
673 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
674 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
675 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
676 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
677 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
678 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
679 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
680 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
681 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
682 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
683 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
684 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
685 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
686 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
687 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
688 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
689 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
690 {0xa0, 0x00, 0x01ad},
691 {0xa0, 0x01, 0x01b1},
692 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
693 {0xa0, 0x60, ZC3XX_R116_RGAIN},
694 {0xa0, 0x40, ZC3XX_R117_GGAIN},
695 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
696 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
697 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
698 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
699 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
700 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
701 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
702 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
703 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
704 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
705 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
706 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
707 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
708 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
709 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
710 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
711 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
712 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
713 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
714 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
715 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
716 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
717 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
718 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
719 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
720 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
721 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
722 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
723 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
724 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
725 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
726 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
727 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
728 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
729 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
730 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
731 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
732 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
733 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
734 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
735 {0xa0, 0x58, ZC3XX_R10E_RGB11},
736 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
737 {0xa0, 0xf4, ZC3XX_R110_RGB20},
738 {0xa0, 0xf4, ZC3XX_R111_RGB21},
739 {0xa0, 0x58, ZC3XX_R112_RGB22},
740 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
741 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
742 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
743 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
744 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
745 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
746 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
747 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
748 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
749 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
750 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
751 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
752 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
753 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
754 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
755 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
756 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
757 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
758 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
759 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
760 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
761 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
762 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
763 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
764 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
765 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
766 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
767 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
768 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
769 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
770 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
771 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
772 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
773 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
774 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
775 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
776 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
777 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
778 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
779 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
780 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
781 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
782 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
783 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
784 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
785 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
786 {0xa0, 0x60, ZC3XX_R116_RGAIN},
787 {0xa0, 0x40, ZC3XX_R117_GGAIN},
788 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
789 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
790 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
791 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
792 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
793 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
794 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
795 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
796 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
797 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
798 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
799 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
800 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
801 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
802 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
803 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
804 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
805 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
806 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
807 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
808 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
809 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
810 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
811 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
812 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
813 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
814 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
815 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
816 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
817 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
818 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
819 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
820 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
821 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
822 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
823 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
824 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
825 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
826 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
827 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
828 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
829 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
830 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
831 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
832 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
833 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
834 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
835 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
836 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
837 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
838 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
839 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
840 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
841 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
842 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
843 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
844 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
845 {}
846};
847
848static const struct usb_action cs2102K_Initial[] = {
849 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
850 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
851 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
852 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
853 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
854 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
855 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
856 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
857 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
858 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
859 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
860 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
861 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
862 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
863 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
864 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
865 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
866/*fixme: next sequence = i2c exchanges*/
867 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
868 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
869 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
870 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
871 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
872 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
873 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
874 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
875 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
876 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
877 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
878 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
879 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
880 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
881 {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
882 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
883 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
884 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
885 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
886 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
887 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
888 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
889 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
890 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
891 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
892 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
893 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
894 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
895 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
896 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
897 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
898 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
899 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
900 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
901 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
902 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
903 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
904 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
905 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
906 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
907 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
908 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
909 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
910 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
911 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
912 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
913 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
914 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
915 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
916 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
917 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
918 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
919 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
920 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
921 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
922 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
923 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
924 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
925 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
926 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
927 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
928 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
929 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
930 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
931 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
932 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
933 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
934 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
935 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
936 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
937 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
938 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
939 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
940 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
941 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
942 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
943 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
944 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
945 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
946 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
947 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
948 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
949 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
950 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
951 {0xa0, 0x00, 0x01ad},
952 {0xa0, 0x01, 0x01b1},
953 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
954 {0xa0, 0x60, ZC3XX_R116_RGAIN},
955 {0xa0, 0x40, ZC3XX_R117_GGAIN},
956 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
957 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
958 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
959 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
960 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
961 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
962 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
963 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
964 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
965 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
966 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
967 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
968 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
969 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
970 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
971 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
972 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
973 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
974 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
975 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
976 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
977 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
978 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
979 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
980 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
981 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
982 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
983 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
984 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
985 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
986 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
987 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
988 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
989 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
990 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
991 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
992 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
993 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
994 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
995 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
996 {0xa0, 0x58, ZC3XX_R10E_RGB11},
997 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
998 {0xa0, 0xf4, ZC3XX_R110_RGB20},
999 {0xa0, 0xf4, ZC3XX_R111_RGB21},
1000 {0xa0, 0x58, ZC3XX_R112_RGB22},
1001 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1002 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1003 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1004 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1005 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1006 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1007 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1008 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1009 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1010 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1011 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1012 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1013 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1014 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1015 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1016 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1017 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1018 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1019 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1020 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1021 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1022 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1023 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1024 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1025 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1026 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1027 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
1028 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
1029 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1030 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
1031 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
1032 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1033 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1034 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
1035 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1036 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1037 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1038 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1039 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1040 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
1041 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
1042 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
1043 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1044 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1045 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1046 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1047 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1048 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1049 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1050 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1051 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1052 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1053 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1054 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1055 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1056 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1057 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1058 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1059 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1060 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1061 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1062 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1063 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1064 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1065 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1066 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1067 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1068 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1069 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1070 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1071 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1072 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1073 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1074 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1075 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1076 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1077 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1078 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1079 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1080 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1081 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1082 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1083 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1084 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1085 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1086 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1087 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1088 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1089 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1090 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1091 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1092 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1093 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1094 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1095 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1096 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1097 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1098 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1099 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1100 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1101 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1102 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1103 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1104 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1105 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1106/*fixme:what does the next sequence?*/
1107 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1108 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1109 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1110 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1111 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1112 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1113 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1114 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1115 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1116 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1117 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1118 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1119 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1120 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1121 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1122 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1123 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1124 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1125 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1126 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1127 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1128 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1129 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1130 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1131 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1132 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1133 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1134 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1135 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
1136 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1137 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1138 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1139 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1140 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1141 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1142 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1143 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1144 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1145 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1146 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1147 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1148 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1149 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1150 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1151 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1152 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1153 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1154 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1155 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1156 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1157 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1158 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1159 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1160 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1161 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1162 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1163 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1164 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1165 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1166 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1167 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1168 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1169 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1170 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1171 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1172 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1173 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1174 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1175 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1176 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1177 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1178 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1179 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1180 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1181 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1182 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1183 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1184 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1185 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1186 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1187 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1188 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1189 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1190 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1191 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1192 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1193 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1194 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1195 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1196 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1197 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1198 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1199 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1200 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1201 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1202 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1203 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1204 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1205 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1206 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1207 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1208 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1209 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1210 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1211 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1212 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1213 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1214 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1215 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1216 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1217 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1218 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1219 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1220 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1221 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1222 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1223 {}
1224};
1225
1226static const struct usb_action gc0305_Initial[] = { /* 640x480 */
1227 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1228 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1229 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1230 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
1231 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1232 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1233 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1234 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1235 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1236 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1237 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1238 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1239 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1240 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1241 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1242 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
1243 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
1244 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1245 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa */
1246 {0xaa, 0x15, 0x0003}, /* 00,15,03,aa */
1247 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1248 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1249 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1250 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1251 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1252 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1253 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1254 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1255 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1256 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1257 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1258 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1259 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1260 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1261 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1262 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1263 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1264 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1265 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1266 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1267 {0xaa, 0x17, 0x00e6}, /* 00,17,e6,aa */
1268 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1269 {0xaa, 0x19, 0x0086}, /* 00,19,86,aa */
1270 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1271 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1272 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1273 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1274 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1275 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1276 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1277 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1278 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1279 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1280 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1281 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1282 {0xa0, 0x85, ZC3XX_R18D_YTARGET}, /* 01,8d,85,cc */
1283 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1284 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1285 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1286 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1287 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1288 {}
1289};
1290static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */
1291 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1292 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1293 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1294 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
1295 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1296 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1297 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1298 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1299 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1300 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1301 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1302 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1303 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1304 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1305 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1306 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
1307 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
1308 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1309 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
1310 {0xaa, 0x15, 0x0001}, /* 00,15,01,aa */
1311 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1312 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1313 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1314 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1315 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1316 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1317 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1318 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1319 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1320 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1321 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1322 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1323 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1324 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1325 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1326 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1327 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1328 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1329 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1330 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1331 {0xaa, 0x17, 0x00e8}, /* 00,17,e8,aa */
1332 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1333 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa */
1334 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1335 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1336 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1337 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1338 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1339 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1340 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1341 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1342 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1343 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1344 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1345 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1346 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1347 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1348 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1349 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1350 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1351 {}
1352};
1353static const struct usb_action gc0305_50HZ[] = {
1354 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1355 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
1356 {0xaa, 0x84, 0x0038}, /* 00,84,38,aa */ /* win: 00,84,ec */
1357 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1358 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1359 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
1360 /* win: 01,92,10 */
1361 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1362 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1363 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc */
1364 /* win: 01,97,ec */
1365 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1366 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1367 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1368 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1369 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1370 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1371 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1372 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1373 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1374 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1375/* {0xa0, 0x85, ZC3XX_R18D_YTARGET}, * 01,8d,85,cc *
1376 * if 640x480 */
1377 {}
1378};
1379static const struct usb_action gc0305_60HZ[] = {
1380 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1381 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1382 {0xaa, 0x84, 0x00ec}, /* 00,84,ec,aa */
1383 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1384 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1385 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
1386 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1387 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1388 {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,ec,cc */
1389 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1390 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1391 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1392 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1393 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1394 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1395 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1396 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1397 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1398 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1399 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1400 {}
1401};
1402
1403static const struct usb_action gc0305_NoFliker[] = {
1404 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
1405 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1406 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1407 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
1408 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1409 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,00,cc */
1410 {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,48,cc */
1411 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1412 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1413 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
1414 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1415 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1416 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1417 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1418 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1419 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1420 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1421 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
1422 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1423 {}
1424};
1425
1426static const struct usb_action hdcs2020_InitialScale[] = {
1427 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1428 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
1429 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */
1430 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1431 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1432 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1433 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1434 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1435 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1436 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1437 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1438 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1439 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1440 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1441 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1442 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1443 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1444 {0xaa, 0x1c, 0x0000},
1445 {0xaa, 0x0a, 0x0001},
1446 {0xaa, 0x0b, 0x0006},
1447 {0xaa, 0x0c, 0x007b},
1448 {0xaa, 0x0d, 0x00a7},
1449 {0xaa, 0x03, 0x00fb},
1450 {0xaa, 0x05, 0x0000},
1451 {0xaa, 0x06, 0x0003},
1452 {0xaa, 0x09, 0x0008},
1453
1454 {0xaa, 0x0f, 0x0018}, /* set sensor gain */
1455 {0xaa, 0x10, 0x0018},
1456 {0xaa, 0x11, 0x0018},
1457 {0xaa, 0x12, 0x0018},
1458
1459 {0xaa, 0x15, 0x004e},
1460 {0xaa, 0x1c, 0x0004},
1461 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
1462 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1463 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1464 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1465 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1466 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1467 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1468 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1469 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1470 {0xa1, 0x01, 0x0002},
1471 {0xa1, 0x01, 0x0008},
1472 {0xa1, 0x01, 0x0180},
1473 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1474 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1475 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1476 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1477 {0xa1, 0x01, 0x0008},
1478 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1479 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1480 {0xa1, 0x01, 0x01c8},
1481 {0xa1, 0x01, 0x01c9},
1482 {0xa1, 0x01, 0x01ca},
1483 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1484 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1485 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1486 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1487 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1488 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1489 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1490 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1491 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1492 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1493 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1494 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1495 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1496 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1497 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1498 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1499 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1500 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1501 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1502 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1503 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1504 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1505 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1506 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1507 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1508 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1509 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1510 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1511 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1512 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1513 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1514 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1515 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1516
1517 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
1518 {0xa0, 0xed, ZC3XX_R10B_RGB01},
1519 {0xa0, 0xed, ZC3XX_R10C_RGB02},
1520 {0xa0, 0xed, ZC3XX_R10D_RGB10},
1521 {0xa0, 0x66, ZC3XX_R10E_RGB11},
1522 {0xa0, 0xed, ZC3XX_R10F_RGB12},
1523 {0xa0, 0xed, ZC3XX_R110_RGB20},
1524 {0xa0, 0xed, ZC3XX_R111_RGB21},
1525 {0xa0, 0x66, ZC3XX_R112_RGB22},
1526
1527 {0xa1, 0x01, 0x0180},
1528 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1529 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1530 {0xaa, 0x13, 0x0031},
1531 {0xaa, 0x14, 0x0001},
1532 {0xaa, 0x0e, 0x0004},
1533 {0xaa, 0x19, 0x00cd},
1534 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1535 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1536 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
1537 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1538 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1539 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
1540 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1541 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1542
1543 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 0x14 */
1544 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1545 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1546 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
1547 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
1548 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
1549 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1550 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1551 {0xa1, 0x01, 0x0180},
1552 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1553 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1554 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1555 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1556 {}
1557};
1558static const struct usb_action hdcs2020_Initial[] = {
1559 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1560 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1561 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1562 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1563 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1564 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1565 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1566 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1567 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1568 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1569 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1570 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1571 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1572 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1573 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1574 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1575 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1576 {0xaa, 0x1c, 0x0000},
1577 {0xaa, 0x0a, 0x0001},
1578 {0xaa, 0x0b, 0x0006},
1579 {0xaa, 0x0c, 0x007a},
1580 {0xaa, 0x0d, 0x00a7},
1581 {0xaa, 0x03, 0x00fb},
1582 {0xaa, 0x05, 0x0000},
1583 {0xaa, 0x06, 0x0003},
1584 {0xaa, 0x09, 0x0008},
1585 {0xaa, 0x0f, 0x0018}, /* original setting */
1586 {0xaa, 0x10, 0x0018},
1587 {0xaa, 0x11, 0x0018},
1588 {0xaa, 0x12, 0x0018},
1589 {0xaa, 0x15, 0x004e},
1590 {0xaa, 0x1c, 0x0004},
1591 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
1592 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1593 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1594 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1595 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1596 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1597 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1598 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1599 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1600 {0xa1, 0x01, 0x0002},
1601 {0xa1, 0x01, 0x0008},
1602 {0xa1, 0x01, 0x0180},
1603 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1604 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1605 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1606 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1607 {0xa1, 0x01, 0x0008},
1608 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1609 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1610 {0xa1, 0x01, 0x01c8},
1611 {0xa1, 0x01, 0x01c9},
1612 {0xa1, 0x01, 0x01ca},
1613 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1614 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1615 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1616 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1617 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1618 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1619 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1620 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1621 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1622 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1623 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1624 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1625 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1626 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1627 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1628 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1629 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1630 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1631 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1632 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1633 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1634 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1635 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1636 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1637 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1638 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1639 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1640 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1641 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1642 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1643 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1644 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1645 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1646 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
1647 {0xa0, 0xed, ZC3XX_R10B_RGB01},
1648 {0xa0, 0xed, ZC3XX_R10C_RGB02},
1649 {0xa0, 0xed, ZC3XX_R10D_RGB10},
1650 {0xa0, 0x66, ZC3XX_R10E_RGB11},
1651 {0xa0, 0xed, ZC3XX_R10F_RGB12},
1652 {0xa0, 0xed, ZC3XX_R110_RGB20},
1653 {0xa0, 0xed, ZC3XX_R111_RGB21},
1654 {0xa0, 0x66, ZC3XX_R112_RGB22},
1655 {0xa1, 0x01, 0x0180},
1656 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1657 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1658 /**** set exposure ***/
1659 {0xaa, 0x13, 0x0031},
1660 {0xaa, 0x14, 0x0001},
1661 {0xaa, 0x0e, 0x0004},
1662 {0xaa, 0x19, 0x00cd},
1663 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1664 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1665 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
1666 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1667 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1668 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
1669 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1670 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1671 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1672 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1673 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1674 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
1675 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
1676 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
1677 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1678 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1679 {0xa1, 0x01, 0x0180},
1680 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1681 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1682 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1683 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1684 {}
1685};
1686static const struct usb_action hdcs2020_50HZ[] = {
1687 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1688 {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */
1689 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
1690 {0xaa, 0x0e, 0x0005}, /* 00,0e,05,aa */
1691 {0xaa, 0x19, 0x001f}, /* 00,19,1f,aa */
1692 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1693 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
1694 {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
1695 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1696 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1697 {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
1698 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1699 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1700 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
1701 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
1702 {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */
1703 {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */
1704 {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
1705 {}
1706};
1707static const struct usb_action hdcs2020_60HZ[] = {
1708 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1709 {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */
1710 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
1711 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
1712 {0xaa, 0x19, 0x00cd}, /* 00,19,cd,aa */
1713 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1714 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
1715 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
1716 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1717 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1718 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
1719 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1720 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1721 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
1722 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
1723 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
1724 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */
1725 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
1726 {}
1727};
1728static const struct usb_action hdcs2020_NoFliker[] = {
1729 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1730 {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
1731 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
1732 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
1733 {0xaa, 0x19, 0x0000}, /* 00,19,00,aa */
1734 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1735 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
1736 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
1737 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1738 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1739 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
1740 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1741 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1742 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
1743 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
1744 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
1745 {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */
1746 {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */
1747 {}
1748};
1749
1750static const struct usb_action hv7131b_InitialScale[] = { /* 320x240 */
1751 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1752 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
1753 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
1754 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1755 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
1756 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
1757 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1758 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1759 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1760 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1761 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1762 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1763 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1764 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1765 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1766 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1767 {0xaa, 0x30, 0x002d},
1768 {0xaa, 0x01, 0x0005},
1769 {0xaa, 0x11, 0x0000},
1770 {0xaa, 0x13, 0x0001}, /* {0xaa, 0x13, 0x0000}, */
1771 {0xaa, 0x14, 0x0001},
1772 {0xaa, 0x15, 0x00e8},
1773 {0xaa, 0x16, 0x0002},
1774 {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */
1775 {0xaa, 0x31, 0x0038},
1776 {0xaa, 0x32, 0x0038},
1777 {0xaa, 0x33, 0x0038},
1778 {0xaa, 0x5b, 0x0001},
1779 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1780 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1781 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1782 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
1783 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
1784 {0xa0, 0x00, 0x01ad},
1785 {0xa0, 0xc0, 0x019b},
1786 {0xa0, 0xa0, 0x019c},
1787 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
1788 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1789 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1790 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1791 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1792 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1793 {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */
1794 {}
1795};
1796
1797static const struct usb_action hv7131b_Initial[] = { /* 640x480*/
1798 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1799 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1800 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
1801 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1802 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
1803 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
1804 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1805 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1806 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1807 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1808 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1809 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1810 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1811 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1812 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1813 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1814 {0xaa, 0x30, 0x002d},
1815 {0xaa, 0x01, 0x0005},
1816 {0xaa, 0x11, 0x0001},
1817 {0xaa, 0x13, 0x0000}, /* {0xaa, 0x13, 0x0001}; */
1818 {0xaa, 0x14, 0x0001},
1819 {0xaa, 0x15, 0x00e6},
1820 {0xaa, 0x16, 0x0002},
1821 {0xaa, 0x17, 0x0086},
1822 {0xaa, 0x31, 0x0038},
1823 {0xaa, 0x32, 0x0038},
1824 {0xaa, 0x33, 0x0038},
1825 {0xaa, 0x5b, 0x0001},
1826 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1827 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1828 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1829 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1830 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
1831 {0xa0, 0x00, 0x01ad},
1832 {0xa0, 0xc0, 0x019b},
1833 {0xa0, 0xa0, 0x019c},
1834 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
1835 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1836 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1837 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1838 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1839 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1840 {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}, */
1841 {}
1842};
1843static const struct usb_action hv7131b_50HZ[] = { /* 640x480*/
1844 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1845 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1846 {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */
1847 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
1848 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1849 {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */
1850 {0xaa, 0x22, 0x001b}, /* 00,22,1b,aa */
1851 {0xaa, 0x23, 0x00fc}, /* 00,23,fc,aa */
1852 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1853 {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */
1854 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
1855 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1856 {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,ea,cc */
1857 {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,60,cc */
1858 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
1859 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
1860 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
1861 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1862 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1863 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
1864 {0xa0, 0x1b, ZC3XX_R01F_HSYNC_2}, /* 00,1f,1b,cc */
1865 {0xa0, 0xfc, ZC3XX_R020_HSYNC_3}, /* 00,20,fc,cc */
1866 {}
1867};
1868static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */
1869 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1870 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1871 {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */
1872 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
1873 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1874 {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */
1875 {0xaa, 0x22, 0x0012}, /* 00,22,12,aa */
1876 {0xaa, 0x23, 0x0080}, /* 00,23,80,aa */
1877 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1878 {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */
1879 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
1880 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */
1881 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,d4,cc */
1882 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,c0,cc */
1883 {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */
1884 {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */
1885 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
1886 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1887 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1888 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
1889 {0xa0, 0x12, ZC3XX_R01F_HSYNC_2}, /* 00,1f,12,cc */
1890 {0xa0, 0x80, ZC3XX_R020_HSYNC_3}, /* 00,20,80,cc */
1891 {}
1892};
1893static const struct usb_action hv7131b_60HZ[] = { /* 640x480*/
1894 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1895 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1896 {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */
1897 {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */
1898 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1899 {0xaa, 0x21, 0x0040}, /* 00,21,40,aa */
1900 {0xaa, 0x22, 0x0013}, /* 00,22,13,aa */
1901 {0xaa, 0x23, 0x004c}, /* 00,23,4c,aa */
1902 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1903 {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */
1904 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */
1905 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1906 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,c3,cc */
1907 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,50,cc */
1908 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
1909 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
1910 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
1911 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1912 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1913 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
1914 {0xa0, 0x13, ZC3XX_R01F_HSYNC_2}, /* 00,1f,13,cc */
1915 {0xa0, 0x4c, ZC3XX_R020_HSYNC_3}, /* 00,20,4c,cc */
1916 {}
1917};
1918static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
1919 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1920 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1921 {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */
1922 {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */
1923 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1924 {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */
1925 {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */
1926 {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */
1927 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1928 {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */
1929 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */
1930 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */
1931 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,86,cc */
1932 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,a0,cc */
1933 {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */
1934 {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */
1935 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
1936 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1937 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1938 {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */
1939 {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */
1940 {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
1941 {}
1942};
1943static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
1944 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1945 {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
1946 {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
1947 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
1948 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1949 {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */
1950 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
1951 {0xaa, 0x23, 0x0003}, /* 00,23,03,aa */
1952 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1953 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */
1954 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */
1955 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1956 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */
1957 {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */
1958 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1959 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1960 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
1961 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
1962 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1963 {0xa0, 0x10, ZC3XX_R01E_HSYNC_1}, /* 00,1e,10,cc */
1964 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, /* 00,1f,00,cc */
1965 {0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */
1966 {}
1967};
1968static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
1969 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1970 {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
1971 {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
1972 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
1973 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1974 {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */
1975 {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */
1976 {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */
1977 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1978 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */
1979 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */
1980 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1981 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */
1982 {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */
1983 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1984 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1985 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
1986 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
1987 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1988 {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */
1989 {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */
1990 {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
1991 {}
1992};
1993
1994/* from lPEPI264v.inf (hv7131b!) */
1995static const struct usb_action hv7131r_InitialScale[] = {
1996 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1997 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
1998 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
1999 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2000 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2001 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2002 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2003 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2004 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2005 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2006 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2007 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2008 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2009 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2010 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2011 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2012 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2013 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2014 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2015 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2016 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2017 {0xdd, 0x00, 0x0200},
2018 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2019 {0xaa, 0x01, 0x000c},
2020 {0xaa, 0x11, 0x0000},
2021 {0xaa, 0x13, 0x0000},
2022 {0xaa, 0x14, 0x0001},
2023 {0xaa, 0x15, 0x00e8},
2024 {0xaa, 0x16, 0x0002},
2025 {0xaa, 0x17, 0x0088},
2026 {0xaa, 0x30, 0x000b},
2027 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2028 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2029 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2030 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2031 {0xa0, 0x00, 0x01ad},
2032 {0xa0, 0xc0, 0x019b},
2033 {0xa0, 0xa0, 0x019c},
2034 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2035 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2036 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2037 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2038 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2039 {}
2040};
2041static const struct usb_action hv7131r_Initial[] = {
2042 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2043 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2044 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2045 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2046 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2047 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2048 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2049 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2050 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2051 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2052 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2053 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2054 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2055 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2056 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2057 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2058 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2059 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2060 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2061 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2062 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2063 {0xdd, 0x00, 0x0200},
2064 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2065 {0xaa, 0x01, 0x000c},
2066 {0xaa, 0x11, 0x0000},
2067 {0xaa, 0x13, 0x0000},
2068 {0xaa, 0x14, 0x0001},
2069 {0xaa, 0x15, 0x00e6},
2070 {0xaa, 0x16, 0x0002},
2071 {0xaa, 0x17, 0x0086},
2072 {0xaa, 0x30, 0x000b},
2073 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2074 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2075 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2076 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2077 {0xa0, 0x00, 0x01ad},
2078 {0xa0, 0xc0, 0x019b},
2079 {0xa0, 0xa0, 0x019c},
2080 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2081 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2082 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2083 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2084 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2085 {}
2086};
2087static const struct usb_action hv7131r_50HZ[] = {
2088 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2089 {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
2090 {0xa0, 0x68, ZC3XX_R191_EXPOSURELIMITMID},
2091 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
2092 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2093 {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},
2094 {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},
2095 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2096 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2097 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2098 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2099 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2100 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2101 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2102 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2103 {}
2104};
2105static const struct usb_action hv7131r_50HZScale[] = {
2106 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2107 {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
2108 {0xa0, 0xd1, ZC3XX_R191_EXPOSURELIMITMID},
2109 {0xa0, 0x40, ZC3XX_R192_EXPOSURELIMITLOW},
2110 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2111 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2112 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2113 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2114 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2115 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2116 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2117 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2118 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2119 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2120 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2121 {}
2122};
2123static const struct usb_action hv7131r_60HZ[] = {
2124 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2125 {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
2126 {0xa0, 0x1a, ZC3XX_R191_EXPOSURELIMITMID},
2127 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
2128 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2129 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
2130 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
2131 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2132 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2133 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2134 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2135 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2136 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2137 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2138 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2139 {}
2140};
2141static const struct usb_action hv7131r_60HZScale[] = {
2142 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2143 {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
2144 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID},
2145 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2146 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2147 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
2148 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
2149 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2150 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2151 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2152 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2153 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2154 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2155 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2156 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2157 {}
2158};
2159static const struct usb_action hv7131r_NoFliker[] = {
2160 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2161 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
2162 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
2163 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2164 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2165 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},
2166 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW},
2167 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2168 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2169 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
2170 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
2171 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2172 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2173 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2174 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2175 {}
2176};
2177static const struct usb_action hv7131r_NoFlikerScale[] = {
2178 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2179 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
2180 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
2181 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2182 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2183 {0xa0, 0x04, ZC3XX_R196_ANTIFLICKERMID},
2184 {0xa0, 0xb0, ZC3XX_R197_ANTIFLICKERLOW},
2185 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2186 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2187 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
2188 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
2189 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2190 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2191 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2192 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2193 {}
2194};
2195
2196static const struct usb_action icm105a_InitialScale[] = {
2197 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2198 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2199 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2200 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2201 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2202 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2203 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2204 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2205 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2206 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2207 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2208 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2209 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2210 {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW},
2211 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2212 {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW},
2213 {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW},
2214 {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW},
2215 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2216 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2217 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2218 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2219 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
2220 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2221 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2222 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2223 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2224 {0xaa, 0x01, 0x0010},
2225 {0xaa, 0x03, 0x0000},
2226 {0xaa, 0x04, 0x0001},
2227 {0xaa, 0x05, 0x0020},
2228 {0xaa, 0x06, 0x0001},
2229 {0xaa, 0x08, 0x0000},
2230 {0xaa, 0x03, 0x0001},
2231 {0xaa, 0x04, 0x0011},
2232 {0xaa, 0x05, 0x00a0},
2233 {0xaa, 0x06, 0x0001},
2234 {0xaa, 0x08, 0x0000},
2235 {0xaa, 0x03, 0x0002},
2236 {0xaa, 0x04, 0x0013},
2237 {0xaa, 0x05, 0x0020},
2238 {0xaa, 0x06, 0x0001},
2239 {0xaa, 0x08, 0x0000},
2240 {0xaa, 0x03, 0x0003},
2241 {0xaa, 0x04, 0x0015},
2242 {0xaa, 0x05, 0x0020},
2243 {0xaa, 0x06, 0x0005},
2244 {0xaa, 0x08, 0x0000},
2245 {0xaa, 0x03, 0x0004},
2246 {0xaa, 0x04, 0x0017},
2247 {0xaa, 0x05, 0x0020},
2248 {0xaa, 0x06, 0x000d},
2249 {0xaa, 0x08, 0x0000},
2250 {0xaa, 0x03, 0x0005},
2251 {0xaa, 0x04, 0x0019},
2252 {0xaa, 0x05, 0x0020},
2253 {0xaa, 0x06, 0x0005},
2254 {0xaa, 0x08, 0x0000},
2255 {0xaa, 0x03, 0x0006},
2256 {0xaa, 0x04, 0x0017},
2257 {0xaa, 0x05, 0x0026},
2258 {0xaa, 0x06, 0x0005},
2259 {0xaa, 0x08, 0x0000},
2260 {0xaa, 0x03, 0x0007},
2261 {0xaa, 0x04, 0x0019},
2262 {0xaa, 0x05, 0x0022},
2263 {0xaa, 0x06, 0x0005},
2264 {0xaa, 0x08, 0x0000},
2265 {0xaa, 0x03, 0x0008},
2266 {0xaa, 0x04, 0x0021},
2267 {0xaa, 0x05, 0x00aa},
2268 {0xaa, 0x06, 0x0005},
2269 {0xaa, 0x08, 0x0000},
2270 {0xaa, 0x03, 0x0009},
2271 {0xaa, 0x04, 0x0023},
2272 {0xaa, 0x05, 0x00aa},
2273 {0xaa, 0x06, 0x000d},
2274 {0xaa, 0x08, 0x0000},
2275 {0xaa, 0x03, 0x000a},
2276 {0xaa, 0x04, 0x0025},
2277 {0xaa, 0x05, 0x00aa},
2278 {0xaa, 0x06, 0x0005},
2279 {0xaa, 0x08, 0x0000},
2280 {0xaa, 0x03, 0x000b},
2281 {0xaa, 0x04, 0x00ec},
2282 {0xaa, 0x05, 0x002e},
2283 {0xaa, 0x06, 0x0005},
2284 {0xaa, 0x08, 0x0000},
2285 {0xaa, 0x03, 0x000c},
2286 {0xaa, 0x04, 0x00fa},
2287 {0xaa, 0x05, 0x002a},
2288 {0xaa, 0x06, 0x0005},
2289 {0xaa, 0x08, 0x0000},
2290 {0xaa, 0x07, 0x000d},
2291 {0xaa, 0x01, 0x0005},
2292 {0xaa, 0x94, 0x0002},
2293 {0xaa, 0x90, 0x0000},
2294 {0xaa, 0x91, 0x001f},
2295 {0xaa, 0x10, 0x0064},
2296 {0xaa, 0x9b, 0x00f0},
2297 {0xaa, 0x9c, 0x0002},
2298 {0xaa, 0x14, 0x001a},
2299 {0xaa, 0x20, 0x0080},
2300 {0xaa, 0x22, 0x0080},
2301 {0xaa, 0x24, 0x0080},
2302 {0xaa, 0x26, 0x0080},
2303 {0xaa, 0x00, 0x0084},
2304 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2305 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2306 {0xaa, 0xa8, 0x00c0},
2307 {0xa1, 0x01, 0x0002},
2308 {0xa1, 0x01, 0x0008},
2309 {0xa1, 0x01, 0x0180},
2310 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2311 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2312 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2313 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2314 {0xa1, 0x01, 0x0008},
2315
2316 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2317 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2318 {0xa1, 0x01, 0x01c8},
2319 {0xa1, 0x01, 0x01c9},
2320 {0xa1, 0x01, 0x01ca},
2321 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2322 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2323 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2324 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2325 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2326 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2327 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2328 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2329 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2330 {0xa0, 0x52, ZC3XX_R112_RGB22},
2331 {0xa1, 0x01, 0x0180},
2332 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2333 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2334 {0xaa, 0x0d, 0x0003},
2335 {0xaa, 0x0c, 0x008c},
2336 {0xaa, 0x0e, 0x0095},
2337 {0xaa, 0x0f, 0x0002},
2338 {0xaa, 0x1c, 0x0094},
2339 {0xaa, 0x1d, 0x0002},
2340 {0xaa, 0x20, 0x0080},
2341 {0xaa, 0x22, 0x0080},
2342 {0xaa, 0x24, 0x0080},
2343 {0xaa, 0x26, 0x0080},
2344 {0xaa, 0x00, 0x0084},
2345 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
2346 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW},
2347 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2348 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
2349 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
2350 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2351 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2352 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW},
2353 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2354 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2355 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2356 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
2357 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0},
2358 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1},
2359 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2},
2360 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
2361 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
2362 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN},
2363 {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN},
2364 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2365 {0xa1, 0x01, 0x0180},
2366 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2367 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2368 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2369 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2370 {}
2371};
2372
2373static const struct usb_action icm105a_Initial[] = {
2374 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2375 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2376 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2377 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2378 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2379 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2380 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2381 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2382 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2383 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2384 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2385 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2386 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2387 {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW},
2388 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2389 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
2390 {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW},
2391 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
2392 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2393 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2394 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2395 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2396 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2397 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2398 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2399 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2400 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2401 {0xaa, 0x01, 0x0010},
2402 {0xaa, 0x03, 0x0000},
2403 {0xaa, 0x04, 0x0001},
2404 {0xaa, 0x05, 0x0020},
2405 {0xaa, 0x06, 0x0001},
2406 {0xaa, 0x08, 0x0000},
2407 {0xaa, 0x03, 0x0001},
2408 {0xaa, 0x04, 0x0011},
2409 {0xaa, 0x05, 0x00a0},
2410 {0xaa, 0x06, 0x0001},
2411 {0xaa, 0x08, 0x0000},
2412 {0xaa, 0x03, 0x0002},
2413 {0xaa, 0x04, 0x0013},
2414 {0xaa, 0x05, 0x0020},
2415 {0xaa, 0x06, 0x0001},
2416 {0xaa, 0x08, 0x0000},
2417 {0xaa, 0x03, 0x0003},
2418 {0xaa, 0x04, 0x0015},
2419 {0xaa, 0x05, 0x0020},
2420 {0xaa, 0x06, 0x0005},
2421 {0xaa, 0x08, 0x0000},
2422 {0xaa, 0x03, 0x0004},
2423 {0xaa, 0x04, 0x0017},
2424 {0xaa, 0x05, 0x0020},
2425 {0xaa, 0x06, 0x000d},
2426 {0xaa, 0x08, 0x0000},
2427 {0xaa, 0x03, 0x0005},
2428 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
2429 {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE},
2430 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
2431 {0xa1, 0x01, 0x0091},
2432 {0xaa, 0x05, 0x0020},
2433 {0xaa, 0x06, 0x0005},
2434 {0xaa, 0x08, 0x0000},
2435 {0xaa, 0x03, 0x0006},
2436 {0xaa, 0x04, 0x0017},
2437 {0xaa, 0x05, 0x0026},
2438 {0xaa, 0x06, 0x0005},
2439 {0xaa, 0x08, 0x0000},
2440 {0xaa, 0x03, 0x0007},
2441 {0xaa, 0x04, 0x0019},
2442 {0xaa, 0x05, 0x0022},
2443 {0xaa, 0x06, 0x0005},
2444 {0xaa, 0x08, 0x0000},
2445 {0xaa, 0x03, 0x0008},
2446 {0xaa, 0x04, 0x0021},
2447 {0xaa, 0x05, 0x00aa},
2448 {0xaa, 0x06, 0x0005},
2449 {0xaa, 0x08, 0x0000},
2450 {0xaa, 0x03, 0x0009},
2451 {0xaa, 0x04, 0x0023},
2452 {0xaa, 0x05, 0x00aa},
2453 {0xaa, 0x06, 0x000d},
2454 {0xaa, 0x08, 0x0000},
2455 {0xaa, 0x03, 0x000a},
2456 {0xaa, 0x04, 0x0025},
2457 {0xaa, 0x05, 0x00aa},
2458 {0xaa, 0x06, 0x0005},
2459 {0xaa, 0x08, 0x0000},
2460 {0xaa, 0x03, 0x000b},
2461 {0xaa, 0x04, 0x00ec},
2462 {0xaa, 0x05, 0x002e},
2463 {0xaa, 0x06, 0x0005},
2464 {0xaa, 0x08, 0x0000},
2465 {0xaa, 0x03, 0x000c},
2466 {0xaa, 0x04, 0x00fa},
2467 {0xaa, 0x05, 0x002a},
2468 {0xaa, 0x06, 0x0005},
2469 {0xaa, 0x08, 0x0000},
2470 {0xaa, 0x07, 0x000d},
2471 {0xaa, 0x01, 0x0005},
2472 {0xaa, 0x94, 0x0002},
2473 {0xaa, 0x90, 0x0000},
2474 {0xaa, 0x91, 0x0010},
2475 {0xaa, 0x10, 0x0064},
2476 {0xaa, 0x9b, 0x00f0},
2477 {0xaa, 0x9c, 0x0002},
2478 {0xaa, 0x14, 0x001a},
2479 {0xaa, 0x20, 0x0080},
2480 {0xaa, 0x22, 0x0080},
2481 {0xaa, 0x24, 0x0080},
2482 {0xaa, 0x26, 0x0080},
2483 {0xaa, 0x00, 0x0084},
2484 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2485 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2486 {0xaa, 0xa8, 0x0080},
2487 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2488 {0xa1, 0x01, 0x0002},
2489 {0xa1, 0x01, 0x0008},
2490 {0xa1, 0x01, 0x0180},
2491 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2492 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2493 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2494 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2495 {0xa1, 0x01, 0x0008},
2496
2497 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2498 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2499 {0xa1, 0x01, 0x01c8},
2500 {0xa1, 0x01, 0x01c9},
2501 {0xa1, 0x01, 0x01ca},
2502 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2503
2504 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2505 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2506 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2507 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2508 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2509 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2510 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2511 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2512 {0xa0, 0x52, ZC3XX_R112_RGB22},
2513 {0xa1, 0x01, 0x0180},
2514 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2515 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2516 {0xaa, 0x0d, 0x0003},
2517 {0xaa, 0x0c, 0x0020},
2518 {0xaa, 0x0e, 0x000e},
2519 {0xaa, 0x0f, 0x0002},
2520 {0xaa, 0x1c, 0x000d},
2521 {0xaa, 0x1d, 0x0002},
2522 {0xaa, 0x20, 0x0080},
2523 {0xaa, 0x22, 0x0080},
2524 {0xaa, 0x24, 0x0080},
2525 {0xaa, 0x26, 0x0080},
2526 {0xaa, 0x00, 0x0084},
2527 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
2528 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW},
2529 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2530 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
2531 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW},
2532 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2533 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2534 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW},
2535 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2536 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2537 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2538 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
2539 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0},
2540 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1},
2541 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
2542 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
2543 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
2544 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2545 {0xa1, 0x01, 0x0180},
2546 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2547 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2548 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2549 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2550 {}
2551};
2552static const struct usb_action icm105a_50HZScale[] = {
2553 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2554 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2555 {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
2556 {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */
2557 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2558 {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */
2559 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2560 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2561 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2562 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2563 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2564 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2565 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2566 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */
2567 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2568 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2569 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */
2570 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2571 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2572 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */
2573 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2574 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2575 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2576 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2577 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
2578 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */
2579 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
2580 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2581 {}
2582};
2583static const struct usb_action icm105a_50HZ[] = {
2584 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2585 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2586 {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
2587 {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */
2588 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2589 {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */
2590 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2591 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2592 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2593 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2594 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2595 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2596 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2597 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */
2598 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2599 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2600 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
2601 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2602 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2603 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */
2604 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2605 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2606 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2607 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2608 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */
2609 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */
2610 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */
2611 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2612 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
2613 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
2614 {}
2615};
2616static const struct usb_action icm105a_60HZScale[] = {
2617 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2618 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2619 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
2620 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
2621 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2622 {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */
2623 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2624 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2625 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2626 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2627 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2628 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2629 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2630 {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */
2631 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2632 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2633 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
2634 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2635 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2636 {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */
2637 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2638 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2639 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2640 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2641 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
2642 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
2643 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
2644 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2645 {}
2646};
2647static const struct usb_action icm105a_60HZ[] = {
2648 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2649 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2650 {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
2651 {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */
2652 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2653 {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */
2654 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2655 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2656 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2657 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2658 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2659 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2660 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2661 {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */
2662 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2663 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2664 {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */
2665 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2666 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2667 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
2668 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2669 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2670 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2671 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2672 {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */
2673 {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */
2674 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
2675 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2676 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
2677 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
2678 {}
2679};
2680static const struct usb_action icm105a_NoFlikerScale[] = {
2681 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2682 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2683 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
2684 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
2685 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2686 {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */
2687 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2688 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2689 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2690 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2691 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2692 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2693 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2694 {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */
2695 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2696 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2697 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
2698 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2699 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2700 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
2701 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2702 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2703 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2704 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2705 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
2706 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
2707 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
2708 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2709 {}
2710};
2711static const struct usb_action icm105a_NoFliker[] = {
2712 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2713 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2714 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
2715 {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */
2716 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2717 {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */
2718 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2719 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2720 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2721 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2722 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2723 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2724 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2725 {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */
2726 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2727 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2728 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
2729 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2730 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2731 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
2732 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2733 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2734 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2735 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2736 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
2737 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
2738 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
2739 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2740 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
2741 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
2742 {}
2743};
2744
2745static const struct usb_action mc501cb_Initial[] = {
2746 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
2747 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
2748 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
2749 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
2750 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
2751 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
2752 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2753 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
2754 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
2755 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
2756 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
2757 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
2758 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
2759 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
2760 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
2761 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
2762 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
2763 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
2764 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
2765 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
2766 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
2767 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
2768 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
2769 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2770 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2771 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
2772 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2773 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
2774 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2775 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
2776 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
2777 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
2778 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
2779 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
2780 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
2781 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
2782 {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */
2783 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
2784 {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */
2785 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
2786 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
2787 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
2788 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
2789 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
2790 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
2791 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
2792 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
2793 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
2794 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
2795 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
2796 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
2797 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
2798 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
2799 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
2800 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
2801 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
2802 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
2803 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
2804 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
2805 {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
2806 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
2807 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
2808 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
2809 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
2810 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
2811 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
2812 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
2813 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
2814 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
2815 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
2816 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
2817 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
2818 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
2819 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
2820 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
2821 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
2822 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
2823 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
2824 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2825 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
2826 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
2827 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
2828 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2829 {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */
2830 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
2831 {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */
2832 {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */
2833 {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */
2834 {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */
2835 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
2836 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
2837 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2838 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
2839 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
2840 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
2841 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
2842 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
2843 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
2844 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
2845 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
2846 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
2847 {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */
2848 {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */
2849 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2850 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
2851 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
2852 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
2853 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
2854 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
2855 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
2856
2857 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2858 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
2859 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
2860 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
2861 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
2862 {}
2863};
2864
2865static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */
2866 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
2867 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
2868 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
2869 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
2870 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
2871 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
2872 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2873 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
2874 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
2875 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
2876 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
2877 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
2878 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
2879 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
2880 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
2881 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
2882 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
2883 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
2884 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
2885 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
2886 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
2887 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
2888 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
2889 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2890 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2891 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
2892 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2893 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
2894 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2895 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
2896 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
2897 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
2898 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
2899 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
2900 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
2901 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
2902 {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */
2903 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
2904 {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */
2905 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
2906 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
2907 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
2908 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
2909 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
2910 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
2911 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
2912 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
2913 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
2914 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
2915 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
2916 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
2917 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
2918 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
2919 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
2920 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
2921 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
2922 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
2923 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
2924 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
2925 {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
2926 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
2927 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
2928 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
2929 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
2930 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
2931 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
2932 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
2933 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
2934 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
2935 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
2936 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
2937 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
2938 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
2939 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
2940 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
2941 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
2942 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
2943 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
2944 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2945 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
2946 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
2947 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
2948 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2949 {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */
2950 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
2951 {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */
2952 {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */
2953 {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */
2954 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
2955 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
2956 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
2957 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2958 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
2959 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
2960 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
2961 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
2962 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
2963 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
2964 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
2965 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
2966 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
2967 {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */
2968 {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */
2969 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2970 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
2971 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
2972 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
2973 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
2974 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
2975 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
2976 {}
2977};
2978
2979static const struct usb_action mc501cb_50HZ[] = {
2980 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2981 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
2982 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
2983 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
2984 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
2985 {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */
2986 {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */
2987 {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */
2988 {}
2989};
2990
2991static const struct usb_action mc501cb_50HZScale[] = {
2992 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2993 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
2994 {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
2995 {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
2996 {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
2997 {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */
2998 {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */
2999 {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */
3000 {}
3001};
3002
3003static const struct usb_action mc501cb_60HZ[] = {
3004 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3005 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3006 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3007 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3008 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3009 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3010 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3011 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3012 {}
3013};
3014
3015static const struct usb_action mc501cb_60HZScale[] = {
3016 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3017 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3018 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3019 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3020 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3021 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3022 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3023 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3024 {}
3025};
3026
3027static const struct usb_action mc501cb_NoFliker[] = {
3028 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3029 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3030 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3031 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3032 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3033 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3034 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3035 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3036 {}
3037};
3038
3039static const struct usb_action mc501cb_NoFlikerScale[] = {
3040 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3041 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3042 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3043 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3044 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3045 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3046 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3047 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3048 {}
3049};
3050
3051/* from zs211.inf */
3052static const struct usb_action ov7620_Initial[] = { /* 640x480 */
3053 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3054 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
3055 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3056 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3057 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3058 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3059 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3060 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3061 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3062 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3063 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3064 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3065 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3066 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3067 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3068 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
3069 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3070 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3071 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3072 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3073 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3074 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3075 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
3076 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3077 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3078 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3079 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3080 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3081 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3082 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3083 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3084 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3085 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3086 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3087 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3088 {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */
3089 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3090 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3091 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3092 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3093 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3094 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3095 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3096 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3097 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3098 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3099 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3100 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3101 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3102 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3103 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3104 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3105 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3106 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3107 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3108 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3109 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3110 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3111 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3112 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3113 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3114 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3115 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3116 {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */
3117 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3118 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3119 {}
3120};
3121static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */
3122 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3123 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */
3124 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3125 /* mx change? */
3126 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3127 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3128 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3129 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3130 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3131 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3132 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3133 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3134 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3135 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3136 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3137 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3138 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
3139 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3140 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3141 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3142 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3143 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3144 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3145 {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d6,cc */
3146 /* OV7648 00,9c,d8,cc */
3147 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3148 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3149 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3150 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3151 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3152 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3153 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3154 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3155 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3156 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3157 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3158 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3159 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3160 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3161 {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */
3162 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3163 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3164 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3165 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3166 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3167 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3168 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3169 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3170 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3171 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3172 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3173 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3174 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3175 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3176 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3177 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3178 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3179 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3180 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3181 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3182 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3183 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3184 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3185 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3186 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3187 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,50,cc */
3188 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3189 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3190 {}
3191};
3192static const struct usb_action ov7620_50HZ[] = {
3193 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3194 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3195 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3196 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3197 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3198 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3199 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3200 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3201 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3202 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3203 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3204 {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */
3205 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3206/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3207 * if mode0 (640x480) */
3208 {}
3209};
3210static const struct usb_action ov7620_60HZ[] = {
3211 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3212 /* (bug in zs211.inf) */
3213 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3214 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3215 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3216 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3217 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3218 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3219 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3220 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3221 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3222 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3223 {0xaa, 0x10, 0x0020}, /* 00,10,20,aa */
3224 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3225/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3226 * if mode0 (640x480) */
3227/* ?? in gspca v1, it was
3228 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3229 {0xa1, 0x01, 0x0037}, */
3230 {}
3231};
3232static const struct usb_action ov7620_NoFliker[] = {
3233 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3234 /* (bug in zs211.inf) */
3235 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3236 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3237 {0xaa, 0x75, 0x008e}, /* 00,75,8e,aa */
3238 {0xaa, 0x2d, 0x0001}, /* 00,2d,01,aa */
3239 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3240 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3241 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3242 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3243 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3244 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
3245/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc
3246 * if mode1 (320x240) */
3247/* ?? was
3248 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3249 {0xa1, 0x01, 0x0037}, */
3250 {}
3251};
3252
3253static const struct usb_action ov7630c_InitialScale[] = {
3254 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3255 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3256 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3257 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3258 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3259 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3260 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3261 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3262 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3263 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3264 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3265 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3266 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3267 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3268 {0xaa, 0x12, 0x0080},
3269 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3270 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3271 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3272 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3273 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3274 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3275 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3276 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3277 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3278 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
3279 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
3280 {0xaa, 0x12, 0x0069},
3281 {0xaa, 0x04, 0x0020},
3282 {0xaa, 0x06, 0x0050},
3283 {0xaa, 0x13, 0x0083},
3284 {0xaa, 0x14, 0x0000},
3285 {0xaa, 0x15, 0x0024},
3286 {0xaa, 0x17, 0x0018},
3287 {0xaa, 0x18, 0x00ba},
3288 {0xaa, 0x19, 0x0002},
3289 {0xaa, 0x1a, 0x00f6},
3290 {0xaa, 0x1b, 0x0002},
3291 {0xaa, 0x20, 0x00c2},
3292 {0xaa, 0x24, 0x0060},
3293 {0xaa, 0x25, 0x0040},
3294 {0xaa, 0x26, 0x0030},
3295 {0xaa, 0x27, 0x00ea},
3296 {0xaa, 0x28, 0x00a0},
3297 {0xaa, 0x21, 0x0000},
3298 {0xaa, 0x2a, 0x0081},
3299 {0xaa, 0x2b, 0x0096},
3300 {0xaa, 0x2d, 0x0094},
3301 {0xaa, 0x2f, 0x003d},
3302 {0xaa, 0x30, 0x0024},
3303 {0xaa, 0x60, 0x0000},
3304 {0xaa, 0x61, 0x0040},
3305 {0xaa, 0x68, 0x007c},
3306 {0xaa, 0x6f, 0x0015},
3307 {0xaa, 0x75, 0x0088},
3308 {0xaa, 0x77, 0x00b5},
3309 {0xaa, 0x01, 0x0060},
3310 {0xaa, 0x02, 0x0060},
3311 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3312 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3313 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3314 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3315 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3316 {0xa0, 0x00, 0x01ad},
3317 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3318 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3319 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3320 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3321 {0xa0, 0x60, ZC3XX_R116_RGAIN},
3322 {0xa0, 0x46, ZC3XX_R118_BGAIN},
3323 {0xa0, 0x04, ZC3XX_R113_RGB03},
3324/* 0x10, */
3325 {0xa1, 0x01, 0x0002},
3326 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3327 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3328 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3329 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3330 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3331 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3332 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3333 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3334 {0xa0, 0x50, ZC3XX_R112_RGB22},
3335 {0xa1, 0x01, 0x0008},
3336 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3337 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
3338 {0xa1, 0x01, 0x01c8},
3339 {0xa1, 0x01, 0x01c9},
3340 {0xa1, 0x01, 0x01ca},
3341 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
3342 {0xa0, 0x01, ZC3XX_R120_GAMMA00}, /* gamma 2 ?*/
3343 {0xa0, 0x0c, ZC3XX_R121_GAMMA01},
3344 {0xa0, 0x1f, ZC3XX_R122_GAMMA02},
3345 {0xa0, 0x3a, ZC3XX_R123_GAMMA03},
3346 {0xa0, 0x53, ZC3XX_R124_GAMMA04},
3347 {0xa0, 0x6d, ZC3XX_R125_GAMMA05},
3348 {0xa0, 0x85, ZC3XX_R126_GAMMA06},
3349 {0xa0, 0x9c, ZC3XX_R127_GAMMA07},
3350 {0xa0, 0xb0, ZC3XX_R128_GAMMA08},
3351 {0xa0, 0xc2, ZC3XX_R129_GAMMA09},
3352 {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A},
3353 {0xa0, 0xde, ZC3XX_R12B_GAMMA0B},
3354 {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C},
3355 {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D},
3356 {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E},
3357 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
3358 {0xa0, 0x05, ZC3XX_R130_GAMMA10},
3359 {0xa0, 0x0f, ZC3XX_R131_GAMMA11},
3360 {0xa0, 0x16, ZC3XX_R132_GAMMA12},
3361 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
3362 {0xa0, 0x19, ZC3XX_R134_GAMMA14},
3363 {0xa0, 0x19, ZC3XX_R135_GAMMA15},
3364 {0xa0, 0x17, ZC3XX_R136_GAMMA16},
3365 {0xa0, 0x15, ZC3XX_R137_GAMMA17},
3366 {0xa0, 0x12, ZC3XX_R138_GAMMA18},
3367 {0xa0, 0x10, ZC3XX_R139_GAMMA19},
3368 {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A},
3369 {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B},
3370 {0xa0, 0x09, ZC3XX_R13C_GAMMA1C},
3371 {0xa0, 0x08, ZC3XX_R13D_GAMMA1D},
3372 {0xa0, 0x06, ZC3XX_R13E_GAMMA1E},
3373 {0xa0, 0x03, ZC3XX_R13F_GAMMA1F},
3374 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3375 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3376 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3377 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3378 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3379 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3380 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3381 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3382 {0xa0, 0x50, ZC3XX_R112_RGB22},
3383
3384 {0xa1, 0x01, 0x0180},
3385 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3386 {0xaa, 0x10, 0x001b},
3387 {0xaa, 0x76, 0x0002},
3388 {0xaa, 0x2a, 0x0081},
3389 {0xaa, 0x2b, 0x0000},
3390 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3391 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID},
3392 {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW},
3393 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3394 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3395 {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW},
3396 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3397 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3398 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3399 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3400 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
3401 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
3402 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3403 {0xaa, 0x13, 0x0083}, /* 40 */
3404 {0xa1, 0x01, 0x0180},
3405 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3406 {}
3407};
3408
3409static const struct usb_action ov7630c_Initial[] = {
3410 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3411 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
3412 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3413 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3414 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3415 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3416 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3417 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3418 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3419 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3420 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3421 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3422
3423 {0xaa, 0x12, 0x0080},
3424 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3425 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3426 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3427 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3428 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3429 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3430 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3431 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3432 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3433 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
3434 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
3435 {0xaa, 0x12, 0x0069}, /* i2c */
3436 {0xaa, 0x04, 0x0020},
3437 {0xaa, 0x06, 0x0050},
3438 {0xaa, 0x13, 0x00c3},
3439 {0xaa, 0x14, 0x0000},
3440 {0xaa, 0x15, 0x0024},
3441 {0xaa, 0x19, 0x0003},
3442 {0xaa, 0x1a, 0x00f6},
3443 {0xaa, 0x1b, 0x0002},
3444 {0xaa, 0x20, 0x00c2},
3445 {0xaa, 0x24, 0x0060},
3446 {0xaa, 0x25, 0x0040},
3447 {0xaa, 0x26, 0x0030},
3448 {0xaa, 0x27, 0x00ea},
3449 {0xaa, 0x28, 0x00a0},
3450 {0xaa, 0x21, 0x0000},
3451 {0xaa, 0x2a, 0x0081},
3452 {0xaa, 0x2b, 0x0096},
3453 {0xaa, 0x2d, 0x0084},
3454 {0xaa, 0x2f, 0x003d},
3455 {0xaa, 0x30, 0x0024},
3456 {0xaa, 0x60, 0x0000},
3457 {0xaa, 0x61, 0x0040},
3458 {0xaa, 0x68, 0x007c},
3459 {0xaa, 0x6f, 0x0015},
3460 {0xaa, 0x75, 0x0088},
3461 {0xaa, 0x77, 0x00b5},
3462 {0xaa, 0x01, 0x0060},
3463 {0xaa, 0x02, 0x0060},
3464 {0xaa, 0x17, 0x0018},
3465 {0xaa, 0x18, 0x00ba},
3466 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3467 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3468 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3469 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3470 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3471 {0xa0, 0x00, 0x01ad},
3472 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3473 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3474 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3475 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3476 {0xa0, 0x60, ZC3XX_R116_RGAIN},
3477 {0xa0, 0x46, ZC3XX_R118_BGAIN},
3478 {0xa0, 0x04, ZC3XX_R113_RGB03},
3479
3480 {0xa1, 0x01, 0x0002},
3481 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
3482 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
3483 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3484 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
3485 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
3486 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
3487 {0xa0, 0x00, ZC3XX_R110_RGB20},
3488 {0xa0, 0xf6, ZC3XX_R111_RGB21},
3489 {0xa0, 0x4a, ZC3XX_R112_RGB22},
3490
3491 {0xa1, 0x01, 0x0008},
3492 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3493 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
3494 {0xa1, 0x01, 0x01c8},
3495 {0xa1, 0x01, 0x01c9},
3496 {0xa1, 0x01, 0x01ca},
3497 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
3498 {0xa0, 0x16, ZC3XX_R120_GAMMA00}, /* gamma ~4 */
3499 {0xa0, 0x3a, ZC3XX_R121_GAMMA01},
3500 {0xa0, 0x5b, ZC3XX_R122_GAMMA02},
3501 {0xa0, 0x7c, ZC3XX_R123_GAMMA03},
3502 {0xa0, 0x94, ZC3XX_R124_GAMMA04},
3503 {0xa0, 0xa9, ZC3XX_R125_GAMMA05},
3504 {0xa0, 0xbb, ZC3XX_R126_GAMMA06},
3505 {0xa0, 0xca, ZC3XX_R127_GAMMA07},
3506 {0xa0, 0xd7, ZC3XX_R128_GAMMA08},
3507 {0xa0, 0xe1, ZC3XX_R129_GAMMA09},
3508 {0xa0, 0xea, ZC3XX_R12A_GAMMA0A},
3509 {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B},
3510 {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C},
3511 {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D},
3512 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
3513 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
3514 {0xa0, 0x20, ZC3XX_R130_GAMMA10},
3515 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
3516 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
3517 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
3518 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
3519 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
3520 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
3521 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
3522 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
3523 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
3524 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
3525 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
3526 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
3527 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
3528 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
3529 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
3530 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
3531 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
3532 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3533 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
3534 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
3535 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
3536 {0xa0, 0x00, ZC3XX_R110_RGB20},
3537 {0xa0, 0xf6, ZC3XX_R111_RGB21},
3538 {0xa0, 0x4a, ZC3XX_R112_RGB22},
3539
3540 {0xa1, 0x01, 0x0180},
3541 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3542 {0xaa, 0x10, 0x000d},
3543 {0xaa, 0x76, 0x0002},
3544 {0xaa, 0x2a, 0x0081},
3545 {0xaa, 0x2b, 0x0000},
3546 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3547 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
3548 {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW},
3549 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3550 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3551 {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW},
3552 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3553 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3554 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3555 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3556 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
3557 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
3558 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3559 {0xaa, 0x13, 0x00c3},
3560
3561 {0xa1, 0x01, 0x0180},
3562 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3563 {}
3564};
3565
3566static const struct usb_action pas106b_Initial_com[] = {
3567/* Sream and Sensor specific */
3568 {0xa1, 0x01, 0x0010}, /* CMOSSensorSelect */
3569/* System */
3570 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
3571 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
3572/* Picture size */
3573 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* ClockSelect */
3574 {0xa0, 0x03, 0x003a},
3575 {0xa0, 0x0c, 0x003b},
3576 {0xa0, 0x04, 0x0038},
3577 {}
3578};
3579
3580static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */
3581/* JPEG control */
3582 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3583/* Sream and Sensor specific */
3584 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
3585/* Picture size */
3586 {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH},
3587 {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW},
3588 {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH},
3589 {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW},
3590/* System */
3591 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3592/* Sream and Sensor specific */
3593 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
3594 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3595/* Sensor Interface */
3596 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3597/* Window inside sensor array */
3598 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
3599 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3600 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
3601 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
3602 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
3603/* Init the sensor */
3604 {0xaa, 0x02, 0x0004},
3605 {0xaa, 0x08, 0x0000},
3606 {0xaa, 0x09, 0x0005},
3607 {0xaa, 0x0a, 0x0002},
3608 {0xaa, 0x0b, 0x0002},
3609 {0xaa, 0x0c, 0x0005},
3610 {0xaa, 0x0d, 0x0000},
3611 {0xaa, 0x0e, 0x0002},
3612 {0xaa, 0x14, 0x0081},
3613/* Other registers */
3614 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
3615/* Frame retreiving */
3616 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
3617/* Gains */
3618 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
3619/* Unknown */
3620 {0xa0, 0x00, 0x01ad},
3621/* Sharpness */
3622 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3623 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3624/* Other registers */
3625 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3626/* Auto exposure and white balance */
3627 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3628/*Dead pixels */
3629 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3630/* EEPROM */
3631 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3632/* JPEG control */
3633 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3634 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3635 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3636/* Other registers */
3637 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3638/* Auto exposure and white balance */
3639 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3640/*Dead pixels */
3641 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3642/* EEPROM */
3643 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3644/* JPEG control */
3645 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3646 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3647 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3648
3649 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
3650 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
3651 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3652 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
3653 {0xa0, 0x58, ZC3XX_R10E_RGB11},
3654 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
3655 {0xa0, 0xf4, ZC3XX_R110_RGB20},
3656 {0xa0, 0xf4, ZC3XX_R111_RGB21},
3657 {0xa0, 0x58, ZC3XX_R112_RGB22},
3658/* Auto correction */
3659 {0xa0, 0x03, ZC3XX_R181_WINXSTART},
3660 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
3661 {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
3662 {0xa0, 0x03, ZC3XX_R184_WINYSTART},
3663 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
3664 {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
3665 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3666/* Auto exposure and white balance */
3667 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3668 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
3669 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
3670 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3671 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3672 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
3673 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
3674 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
3675/* sensor on */
3676 {0xaa, 0x07, 0x00b1},
3677 {0xaa, 0x05, 0x0003},
3678 {0xaa, 0x04, 0x0001},
3679 {0xaa, 0x03, 0x003b},
3680/* Gains */
3681 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
3682 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3683 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
3684 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
3685/* Auto correction */
3686 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3687 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
3688 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3689/* Gains */
3690 {0xa0, 0x40, ZC3XX_R116_RGAIN},
3691 {0xa0, 0x40, ZC3XX_R117_GGAIN},
3692 {0xa0, 0x40, ZC3XX_R118_BGAIN},
3693 {}
3694};
3695
3696static const struct usb_action pas106b_Initial[] = { /* 352x288 */
3697/* JPEG control */
3698 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3699/* Sream and Sensor specific */
3700 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
3701/* Picture size */
3702 {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH},
3703 {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW},
3704 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3705 {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW},
3706/* System */
3707 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3708/* Sream and Sensor specific */
3709 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
3710 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3711/* Sensor Interface */
3712 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3713/* Window inside sensor array */
3714 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
3715 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3716 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
3717 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
3718 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
3719/* Init the sensor */
3720 {0xaa, 0x02, 0x0004},
3721 {0xaa, 0x08, 0x0000},
3722 {0xaa, 0x09, 0x0005},
3723 {0xaa, 0x0a, 0x0002},
3724 {0xaa, 0x0b, 0x0002},
3725 {0xaa, 0x0c, 0x0005},
3726 {0xaa, 0x0d, 0x0000},
3727 {0xaa, 0x0e, 0x0002},
3728 {0xaa, 0x14, 0x0081},
3729/* Other registers */
3730 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
3731/* Frame retreiving */
3732 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
3733/* Gains */
3734 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
3735/* Unknown */
3736 {0xa0, 0x00, 0x01ad},
3737/* Sharpness */
3738 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3739 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3740/* Other registers */
3741 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3742/* Auto exposure and white balance */
3743 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3744 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
3745/*Dead pixels */
3746 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3747/* EEPROM */
3748 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3749/* JPEG control */
3750 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3751 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3752 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3753/* Other registers */
3754 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3755/* Auto exposure and white balance */
3756 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3757/*Dead pixels */
3758 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3759/* EEPROM */
3760 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3761/* JPEG control */
3762 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3763 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3764 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3765
3766 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
3767 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
3768 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3769 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
3770 {0xa0, 0x58, ZC3XX_R10E_RGB11},
3771 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
3772 {0xa0, 0xf4, ZC3XX_R110_RGB20},
3773 {0xa0, 0xf4, ZC3XX_R111_RGB21},
3774 {0xa0, 0x58, ZC3XX_R112_RGB22},
3775/* Auto correction */
3776 {0xa0, 0x03, ZC3XX_R181_WINXSTART},
3777 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
3778 {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
3779 {0xa0, 0x03, ZC3XX_R184_WINYSTART},
3780 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
3781 {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
3782 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3783
3784/* Auto exposure and white balance */
3785 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3786 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
3787 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
3788
3789 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3790 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3791 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
3792
3793 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3794 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3795/* sensor on */
3796 {0xaa, 0x07, 0x00b1},
3797 {0xaa, 0x05, 0x0003},
3798 {0xaa, 0x04, 0x0001},
3799 {0xaa, 0x03, 0x003b},
3800/* Gains */
3801 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
3802 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3803 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
3804/* Auto correction */
3805 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3806 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
3807 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3808/* Gains */
3809 {0xa0, 0x40, ZC3XX_R116_RGAIN},
3810 {0xa0, 0x40, ZC3XX_R117_GGAIN},
3811 {0xa0, 0x40, ZC3XX_R118_BGAIN},
3812
3813 {0xa0, 0x00, 0x0007}, /* AutoCorrectEnable */
3814 {0xa0, 0xff, ZC3XX_R018_FRAMELOST}, /* Frame adjust */
3815 {}
3816};
3817static const struct usb_action pas106b_50HZ[] = {
3818 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3819 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
3820 {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */
3821 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3822 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3823 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */
3824 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3825 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
3826 {0xaa, 0x03, 0x0021}, /* 00,03,21,aa */
3827 {0xaa, 0x04, 0x000c}, /* 00,04,0c,aa */
3828 {0xaa, 0x05, 0x0002}, /* 00,05,02,aa */
3829 {0xaa, 0x07, 0x001c}, /* 00,07,1c,aa */
3830 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
3831 {}
3832};
3833static const struct usb_action pas106b_60HZ[] = {
3834 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3835 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
3836 {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */
3837 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3838 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3839 {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */
3840 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3841 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
3842 {0xaa, 0x03, 0x001c}, /* 00,03,1c,aa */
3843 {0xaa, 0x04, 0x0004}, /* 00,04,04,aa */
3844 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
3845 {0xaa, 0x07, 0x00c4}, /* 00,07,c4,aa */
3846 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
3847 {}
3848};
3849static const struct usb_action pas106b_NoFliker[] = {
3850 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3851 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
3852 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
3853 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3854 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3855 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
3856 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3857 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3858 {0xaa, 0x03, 0x0013}, /* 00,03,13,aa */
3859 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3860 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
3861 {0xaa, 0x07, 0x0030}, /* 00,07,30,aa */
3862 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
3863 {}
3864};
3865
3866/* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */
3867static const struct usb_action pas202b_Initial[] = { /* 640x480 */
3868 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3869 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3870 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */
3871 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
3872 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3873 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3874 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3875 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
3876 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3877 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3878 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3879 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3880 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3881 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,03,cc */
3882 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3883 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,03,cc */
3884 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3885 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
3886 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3887 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3888 {0xaa, 0x02, 0x0002}, /* 00,02,04,aa --> 02 */
3889 {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */
3890 {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */
3891 {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */
3892 {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */
3893 {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */
3894 {0xaa, 0x0c, 0x0006},
3895 {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */
3896 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3897 {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */
3898 {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */
3899 {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */
3900 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
3901 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3902 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3903 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3904 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3905 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3906 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3907 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3908 {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */
3909 {}
3910};
3911static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */
3912 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3913 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3914 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */
3915 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
3916 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3917 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3918 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3919 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3920 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3921 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3922 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3923 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3924 {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,08,cc */
3925 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,02,cc */
3926 {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */
3927 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */
3928 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3929 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
3930 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3931 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3932 {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */
3933 {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */
3934 {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */
3935 {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */
3936 {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */
3937 {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */
3938 {0xaa, 0x0c, 0x0006},
3939 {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */
3940 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3941 {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */
3942 {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */
3943 {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */
3944 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
3945 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3946 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3947 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3948 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3949 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3950 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3951 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3952 {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */
3953 {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH},
3954 {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW},
3955 {}
3956};
3957static const struct usb_action pas202b_50HZ[] = {
3958 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3959 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
3960 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
3961 {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
3962 {0xaa, 0x21, 0x001b},
3963 {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */
3964 {0xaa, 0x04, 0x0008},
3965 {0xaa, 0x05, 0x001b},
3966 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
3967 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
3968 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
3969 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
3970 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3971 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
3972 {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
3973 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3974 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3975 {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */
3976 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
3977 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
3978 {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */
3979 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
3980 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */
3981 {0xa0, 0xeb, ZC3XX_R020_HSYNC_3}, /* 00,20,eb,cc */
3982 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
3983 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
3984 {}
3985};
3986static const struct usb_action pas202b_50HZScale[] = {
3987 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3988 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
3989 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
3990 {0xaa, 0x20, 0x0004},
3991 {0xaa, 0x21, 0x003d},
3992 {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */
3993 {0xaa, 0x04, 0x0010},
3994 {0xaa, 0x05, 0x003d},
3995 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
3996 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
3997 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
3998 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
3999 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4000 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
4001 {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
4002 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4003 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4004 {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */
4005 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4006 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4007 {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */
4008 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
4009 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */
4010 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4011 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4012 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4013 {}
4014};
4015static const struct usb_action pas202b_60HZ[] = {
4016 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4017 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4018 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4019 {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
4020 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
4021 {0xaa, 0x03, 0x0045}, /* 00,03,45,aa */
4022 {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
4023 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
4024 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4025 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4026 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
4027 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
4028 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4029 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
4030 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
4031 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4032 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4033 {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */
4034 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4035 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4036 {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */
4037 {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */
4038 {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */
4039 {0xa0, 0xf5, ZC3XX_R020_HSYNC_3}, /* 00,20,f5,cc */
4040 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4041 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4042 {}
4043};
4044static const struct usb_action pas202b_60HZScale[] = {
4045 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4046 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4047 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4048 {0xaa, 0x20, 0x0004},
4049 {0xaa, 0x21, 0x0008},
4050 {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */
4051 {0xaa, 0x04, 0x0010},
4052 {0xaa, 0x05, 0x0008},
4053 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4054 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4055 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
4056 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
4057 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4058 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
4059 {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW},
4060 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4061 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4062 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
4063 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4064 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4065 {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */
4066 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
4067 {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */
4068 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4069 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4070 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4071 {}
4072};
4073static const struct usb_action pas202b_NoFliker[] = {
4074 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4075 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4076 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4077 {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
4078 {0xaa, 0x21, 0x0006},
4079 {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */
4080 {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
4081 {0xaa, 0x05, 0x0006},
4082 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4083 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4084 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4085 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
4086 {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW},
4087 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4088 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4089 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
4090 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4091 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4092 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4093 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4094 {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */
4095 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */
4096 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4097 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4098 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4099 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4100 {}
4101};
4102static const struct usb_action pas202b_NoFlikerScale[] = {
4103 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4104 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4105 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4106 {0xaa, 0x20, 0x0004},
4107 {0xaa, 0x21, 0x000c},
4108 {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */
4109 {0xaa, 0x04, 0x0010},
4110 {0xaa, 0x05, 0x000c},
4111 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4112 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4113 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4114 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
4115 {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW},
4116 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4117 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4118 {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */
4119 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4120 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4121 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4122 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4123 {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */
4124 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */
4125 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4126 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4127 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4128 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4129 {}
4130};
4131
4132/* mt9v111 (mi0360soc) and pb0330 from vm30x.inf 0ac8:301b 07/02/13 */
4133static const struct usb_action mt9v111_1_Initial[] = { /* 640x480 */
4134 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4135 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4136 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4137 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4138 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4139 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4140 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4141 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4142 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4143 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4144 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4145 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4146 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4147 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4148 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4149 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4150 {0xdd, 0x00, 0x0200},
4151 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4152 {0xaa, 0x01, 0x0001},
4153 {0xaa, 0x06, 0x0000},
4154 {0xaa, 0x08, 0x0483},
4155 {0xaa, 0x01, 0x0004},
4156 {0xaa, 0x08, 0x0006},
4157 {0xaa, 0x02, 0x0011},
4158 {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/
4159 {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/
4160 {0xaa, 0x07, 0x3002},
4161 {0xaa, 0x20, 0x5100},
4162 {0xaa, 0x35, 0x507f},
4163 {0xaa, 0x30, 0x0005},
4164 {0xaa, 0x31, 0x0000},
4165 {0xaa, 0x58, 0x0078},
4166 {0xaa, 0x62, 0x0411},
4167 {0xaa, 0x2b, 0x007f},
4168 {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/
4169 {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/
4170 {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/
4171 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4172 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
4173 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4174 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4175 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4176 {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/
4177 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4178 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4179 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4180 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4181 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4182 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4183 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4184 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4185 {}
4186};
4187static const struct usb_action mt9v111_1_InitialScale[] = { /* 320x240 */
4188 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4189 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4190 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4191 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4192 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4193 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4194 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4195 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4196 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4197 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4198 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4199 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4200 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4201 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4202 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4203 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4204 {0xdd, 0x00, 0x0200},
4205 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4206 {0xaa, 0x01, 0x0001},
4207 {0xaa, 0x06, 0x0000},
4208 {0xaa, 0x08, 0x0483},
4209 {0xaa, 0x01, 0x0004},
4210 {0xaa, 0x08, 0x0006},
4211 {0xaa, 0x02, 0x0011},
4212 {0xaa, 0x03, 0x01e7},
4213 {0xaa, 0x04, 0x0287},
4214 {0xaa, 0x07, 0x3002},
4215 {0xaa, 0x20, 0x5100},
4216 {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/
4217 {0xaa, 0x30, 0x0005},
4218 {0xaa, 0x31, 0x0000},
4219 {0xaa, 0x58, 0x0078},
4220 {0xaa, 0x62, 0x0411},
4221 {0xaa, 0x2b, 0x007f}, /*jfm: was 28*/
4222 {0xaa, 0x2c, 0x007f}, /*jfm: was 30*/
4223 {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/
4224 {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/
4225 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4226 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
4227 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4228 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4229 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4230 {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/
4231 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4232 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4233 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4234 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4235 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4236 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4237 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4238 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4239 {}
4240};
4241static const struct usb_action mt9v111_1_AE50HZ[] = {
4242 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4243 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4244 {0xbb, 0x00, 0x0562},
4245 {0xbb, 0x01, 0x09aa},
4246 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4247 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
4248 {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
4249 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4250 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4251 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
4252 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4253 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4254 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4255 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4256 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
4257 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
4258 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
4259 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4260 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4261 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4262 {}
4263};
4264static const struct usb_action mt9v111_1_AE50HZScale[] = {
4265 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4266 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4267 {0xbb, 0x00, 0x0509},
4268 {0xbb, 0x01, 0x0934},
4269 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4270 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4271 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4272 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4273 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4274 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4275 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4276 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4277 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4278 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4279 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4280 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4281 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4282 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4283 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4284 {}
4285};
4286static const struct usb_action mt9v111_1_AE60HZ[] = {
4287 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4288 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4289 {0xaa, 0x05, 0x003d},
4290 {0xaa, 0x09, 0x016e},
4291 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4292 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4293 {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW},
4294 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4295 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4296 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
4297 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4298 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4299 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4300 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4301 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
4302 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
4303 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
4304 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4305 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4306 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4307 {}
4308};
4309static const struct usb_action mt9v111_1_AE60HZScale[] = {
4310 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4311 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4312 {0xbb, 0x00, 0x0509},
4313 {0xbb, 0x01, 0x0983},
4314 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4315 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4316 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4317 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4318 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4319 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4320 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4321 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4322 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4323 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4324 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4325 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4326 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4327 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4328 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4329 {}
4330};
4331static const struct usb_action mt9v111_1_AENoFliker[] = {
4332 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4333 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4334 {0xbb, 0x00, 0x0509},
4335 {0xbb, 0x01, 0x0960},
4336 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4337 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4338 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4339 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4340 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4341 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4342 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4343 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4344 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4345 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4346 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
4347 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
4348 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4349 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4350 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4351 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4352 {}
4353};
4354static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
4355 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4356 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4357 {0xbb, 0x00, 0x0534},
4358 {0xbb, 0x02, 0x0960},
4359 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4360 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4361 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4362 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4363 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4364 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4365 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4366 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4367 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4368 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4369 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4370 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4371 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4372 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4373 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4374 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4375 {}
4376};
4377/* from usbvm303.inf 0ac8:303b 07/03/25 (3 - tas5130c) */
4378static const struct usb_action mt9v111_3_Initial[] = {
4379 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4380 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4381 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4382 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4383 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4384 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4385 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4386 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4387 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4388 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4389 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4390 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4391 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4392 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4393 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4394 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4395 {0xdd, 0x00, 0x0200},
4396 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4397 {0xaa, 0x01, 0x0001}, /* select IFP/SOC registers */
4398 {0xaa, 0x06, 0x0000}, /* operating mode control */
4399 {0xaa, 0x08, 0x0483}, /* output format control */
4400 /* H red first, V red or blue first,
4401 * raw Bayer, auto flicker */
4402 {0xaa, 0x01, 0x0004}, /* select sensor core registers */
4403 {0xaa, 0x08, 0x0006}, /* row start */
4404 {0xaa, 0x02, 0x0011}, /* column start */
4405 {0xaa, 0x03, 0x01e5}, /* window height - 1 */
4406 {0xaa, 0x04, 0x0285}, /* window width - 1 */
4407 {0xaa, 0x07, 0x3002}, /* output control */
4408 {0xaa, 0x20, 0x1100}, /* read mode: bits 8 & 12 (?) */
4409 {0xaa, 0x35, 0x007f}, /* global gain */
4410 {0xaa, 0x30, 0x0005},
4411 {0xaa, 0x31, 0x0000},
4412 {0xaa, 0x58, 0x0078},
4413 {0xaa, 0x62, 0x0411},
4414 {0xaa, 0x2b, 0x007f}, /* green1 gain */
4415 {0xaa, 0x2c, 0x007f}, /* blue gain */
4416 {0xaa, 0x2d, 0x007f}, /* red gain */
4417 {0xaa, 0x2e, 0x007f}, /* green2 gain */
4418 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4419 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4420 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4421 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4422 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4423 {0xa0, 0x00, 0x01ad},
4424 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4425 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4426 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4427 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4428 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4429 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
4430 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4431 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4432 {}
4433};
4434static const struct usb_action mt9v111_3_InitialScale[] = {
4435 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4436 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4437 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4438 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4439 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4440 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4441 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4442 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4443 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4444 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4445 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4446 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4447 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4448 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4449 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4450 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4451 {0xdd, 0x00, 0x0200},
4452 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4453 {0xaa, 0x01, 0x0001},
4454 {0xaa, 0x06, 0x0000},
4455 {0xaa, 0x08, 0x0483},
4456 {0xaa, 0x01, 0x0004},
4457 {0xaa, 0x08, 0x0006},
4458 {0xaa, 0x02, 0x0011},
4459 {0xaa, 0x03, 0x01e7},
4460 {0xaa, 0x04, 0x0287},
4461 {0xaa, 0x07, 0x3002},
4462 {0xaa, 0x20, 0x1100},
4463 {0xaa, 0x35, 0x007f},
4464 {0xaa, 0x30, 0x0005},
4465 {0xaa, 0x31, 0x0000},
4466 {0xaa, 0x58, 0x0078},
4467 {0xaa, 0x62, 0x0411},
4468 {0xaa, 0x2b, 0x007f},
4469 {0xaa, 0x2c, 0x007f},
4470 {0xaa, 0x2d, 0x007f},
4471 {0xaa, 0x2e, 0x007f},
4472 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4473 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4474 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4475 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4476 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4477 {0xa0, 0x00, 0x01ad},
4478 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4479 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4480 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4481 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4482 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4483 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
4484 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4485 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4486 {}
4487};
4488static const struct usb_action mt9v111_3_AE50HZ[] = {
4489 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4490 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4491 {0xaa, 0x05, 0x0009}, /* horizontal blanking */
4492 {0xaa, 0x09, 0x01ce}, /* shutter width */
4493 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4494 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4495 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4496 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4497 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4498 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4499 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4500 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4501 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4502 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4503 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4504 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4505 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4506 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4507 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4508 {}
4509};
4510static const struct usb_action mt9v111_3_AE50HZScale[] = {
4511 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4512 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4513 {0xaa, 0x05, 0x0009},
4514 {0xaa, 0x09, 0x01ce},
4515 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4516 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4517 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4518 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4519 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4520 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4521 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4522 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4523 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4524 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4525 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4526 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4527 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4528 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4529 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4530 {}
4531};
4532static const struct usb_action mt9v111_3_AE60HZ[] = {
4533 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4534 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4535 {0xaa, 0x05, 0x0009},
4536 {0xaa, 0x09, 0x0083},
4537 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4538 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4539 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4540 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4541 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4542 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4543 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4544 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4545 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4546 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4547 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4548 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4549 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4550 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4551 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4552 {}
4553};
4554static const struct usb_action mt9v111_3_AE60HZScale[] = {
4555 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4556 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4557 {0xaa, 0x05, 0x0009},
4558 {0xaa, 0x09, 0x0083},
4559 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4560 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4561 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4562 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4563 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4564 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4565 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4566 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4567 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4568 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4569 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4570 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4571 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4572 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4573 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4574 {}
4575};
4576static const struct usb_action mt9v111_3_AENoFliker[] = {
4577 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4578 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4579 {0xaa, 0x05, 0x0034},
4580 {0xaa, 0x09, 0x0260},
4581 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4582 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4583 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4584 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4585 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4586 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4587 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4588 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4589 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4590 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4591 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4592 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4593 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4594 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4595 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4596 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4597 {}
4598};
4599static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
4600 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4601 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4602 {0xaa, 0x05, 0x0034},
4603 {0xaa, 0x09, 0x0260},
4604 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4605 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4606 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4607 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4608 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4609 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4610 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4611 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4612 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4613 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4614 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4615 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4616 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4617 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4618 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4619 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4620 {}
4621};
4622
4623static const struct usb_action pb0330_Initial[] = { /* 640x480 */
4624 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4625 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4626 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4627 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4628 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4629 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4630 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4631 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4632 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4633 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4634 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4635 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4636 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4637 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4638 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4639 {0xdd, 0x00, 0x0200},
4640 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4641 {0xaa, 0x01, 0x0006},
4642 {0xaa, 0x02, 0x0011},
4643 {0xaa, 0x03, 0x01e5}, /*jfm: was 1e7*/
4644 {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/
4645 {0xaa, 0x06, 0x0003},
4646 {0xaa, 0x07, 0x3002},
4647 {0xaa, 0x20, 0x1100},
4648 {0xaa, 0x2f, 0xf7b0},
4649 {0xaa, 0x30, 0x0005},
4650 {0xaa, 0x31, 0x0000},
4651 {0xaa, 0x34, 0x0100},
4652 {0xaa, 0x35, 0x0060},
4653 {0xaa, 0x3d, 0x068f},
4654 {0xaa, 0x40, 0x01e0},
4655 {0xaa, 0x58, 0x0078},
4656 {0xaa, 0x62, 0x0411},
4657 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4658 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4659 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4660 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4661 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4662 {0xa0, 0x09, 0x01ad}, /*jfm: was 00 */
4663 {0xa0, 0x15, 0x01ae},
4664 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4665 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4666 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4667 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4668 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4669 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/
4670 {}
4671};
4672static const struct usb_action pb0330_InitialScale[] = { /* 320x240 */
4673 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4674 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4675 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4676 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4677 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4678 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4679 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4680 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4681 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4682 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4683 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4684 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4685 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4686 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4687 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4688 {0xdd, 0x00, 0x0200},
4689 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4690 {0xaa, 0x01, 0x0006},
4691 {0xaa, 0x02, 0x0011},
4692 {0xaa, 0x03, 0x01e7},
4693 {0xaa, 0x04, 0x0287},
4694 {0xaa, 0x06, 0x0003},
4695 {0xaa, 0x07, 0x3002},
4696 {0xaa, 0x20, 0x1100},
4697 {0xaa, 0x2f, 0xf7b0},
4698 {0xaa, 0x30, 0x0005},
4699 {0xaa, 0x31, 0x0000},
4700 {0xaa, 0x34, 0x0100},
4701 {0xaa, 0x35, 0x0060},
4702 {0xaa, 0x3d, 0x068f},
4703 {0xaa, 0x40, 0x01e0},
4704 {0xaa, 0x58, 0x0078},
4705 {0xaa, 0x62, 0x0411},
4706 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4707 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4708 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4709 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4710 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4711 {0xa0, 0x09, 0x01ad},
4712 {0xa0, 0x15, 0x01ae},
4713 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4714 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4715 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4716 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4717 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4718 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/
4719 {}
4720};
4721static const struct usb_action pb0330_50HZ[] = {
4722 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4723 {0xbb, 0x00, 0x055c},
4724 {0xbb, 0x01, 0x09aa},
4725 {0xbb, 0x00, 0x1001},
4726 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4727 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4728 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4729 {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW},
4730 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4731 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4732 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
4733 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4734 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4735 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4736 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4737 {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0},
4738 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
4739 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
4740 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4741 {}
4742};
4743static const struct usb_action pb0330_50HZScale[] = {
4744 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4745 {0xbb, 0x00, 0x0566},
4746 {0xbb, 0x02, 0x09b2},
4747 {0xbb, 0x00, 0x1002},
4748 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4749 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4750 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4751 {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
4752 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4753 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4754 {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
4755 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4756 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4757 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4758 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4759 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4760 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
4761 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
4762 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4763 {}
4764};
4765static const struct usb_action pb0330_60HZ[] = {
4766 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4767 {0xbb, 0x00, 0x0535},
4768 {0xbb, 0x01, 0x0974},
4769 {0xbb, 0x00, 0x1001},
4770 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4771 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4772 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4773 {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
4774 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4775 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4776 {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW},
4777 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4778 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4779 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4780 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4781 {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
4782 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
4783 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4784 {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
4785 {}
4786};
4787static const struct usb_action pb0330_60HZScale[] = {
4788 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4789 {0xbb, 0x00, 0x0535},
4790 {0xbb, 0x02, 0x096c},
4791 {0xbb, 0x00, 0x1002},
4792 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4793 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4794 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4795 {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW},
4796 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4797 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4798 {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW},
4799 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4800 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4801 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4802 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4803 {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
4804 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
4805 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4806 {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
4807 {}
4808};
4809static const struct usb_action pb0330_NoFliker[] = {
4810 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4811 {0xbb, 0x00, 0x0509},
4812 {0xbb, 0x02, 0x0940},
4813 {0xbb, 0x00, 0x1002},
4814 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4815 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4816 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4817 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4818 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4819 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4820 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
4821 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4822 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4823 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4824 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4825 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
4826 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
4827 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4828 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4829 {}
4830};
4831static const struct usb_action pb0330_NoFlikerScale[] = {
4832 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4833 {0xbb, 0x00, 0x0535},
4834 {0xbb, 0x01, 0x0980},
4835 {0xbb, 0x00, 0x1001},
4836 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4837 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4838 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4839 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4840 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4841 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4842 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
4843 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4844 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4845 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4846 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4847 {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
4848 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4849 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4850 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4851 {}
4852};
4853
4854/* from oem9.inf */
4855static const struct usb_action po2030_Initial[] = { /* 640x480 */
4856 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
4857 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
4858 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
4859 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
4860 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
4861 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
4862 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
4863 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
4864 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
4865 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
4866 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
4867 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
4868 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
4869 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
4870 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
4871 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
4872 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
4873 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
4874 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
4875 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
4876 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
4877 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
4878 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
4879 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
4880 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
4881 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
4882 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
4883 {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */
4884 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
4885 {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */
4886 {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */
4887 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
4888 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
4889 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
4890 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
4891 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
4892 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
4893 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
4894 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
4895 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
4896 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
4897 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
4898 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
4899 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
4900 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
4901 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
4902 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
4903 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
4904 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
4905 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
4906 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
4907 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
4908 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
4909 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
4910 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
4911 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
4912 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
4913 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
4914 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
4915 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
4916 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
4917 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
4918 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
4919 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
4920 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
4921 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
4922 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
4923 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
4924 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
4925 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
4926 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
4927 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
4928 {}
4929};
4930
4931/* from oem9.inf */
4932static const struct usb_action po2030_InitialScale[] = { /* 320x240 */
4933 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
4934 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
4935 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
4936 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
4937 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
4938 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
4939 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
4940 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
4941 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
4942 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
4943 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
4944 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
4945 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
4946 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
4947 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
4948 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
4949 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
4950 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
4951 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
4952 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
4953 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
4954 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
4955 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
4956 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
4957 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
4958 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
4959 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
4960 {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */
4961 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
4962 {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */
4963 {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */
4964 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
4965 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
4966 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
4967 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
4968 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
4969 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
4970 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
4971 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
4972 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
4973 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
4974 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
4975 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
4976 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
4977 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
4978 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
4979 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
4980 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
4981 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
4982 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
4983 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
4984 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
4985 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
4986 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
4987 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
4988 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
4989 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
4990 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
4991 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
4992 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
4993 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
4994 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
4995 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
4996 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
4997 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
4998 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
4999 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5000 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5001 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5002 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5003 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5004 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5005 {}
5006};
5007
5008static const struct usb_action po2030_50HZ[] = {
5009 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5010 {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
5011 {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
5012 {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */
5013 {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */
5014 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */
5015 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
5016 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5017 {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */
5018 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */
5019 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5020 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5021 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5022 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5023 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5024 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5025 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5026 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5027 {}
5028};
5029
5030static const struct usb_action po2030_60HZ[] = {
5031 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5032 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5033 {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
5034 {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */
5035 {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */
5036 {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */
5037 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
5038 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5039 {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */
5040 {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */
5041 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5042 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5043 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5044 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5045 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5046 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5047 /* win: 01,8d,80 */
5048 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5049 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5050 {}
5051};
5052
5053static const struct usb_action po2030_NoFliker[] = {
5054 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
5055 {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
5056 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5057 {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */
5058 {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */
5059 {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */
5060 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
5061 {}
5062};
5063
5064static const struct usb_action tas5130c_InitialScale[] = { /* 320x240 */
5065 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5066 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
5067 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5068 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5069 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5070 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5071 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5072 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5073 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5074 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5075 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5076 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5077 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5078
5079 {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW},
5080 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5081 {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW},
5082 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5083 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
5084 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5085 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
5086 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5087 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
5088 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5089 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5090 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
5091 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
5092 {0xa0, 0x00, 0x01ad},
5093 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5094 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5095 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5096 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5097 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5098 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5099 {}
5100};
5101static const struct usb_action tas5130c_Initial[] = { /* 640x480 */
5102 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5103 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
5104 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},
5105 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5106 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5107 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5108 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5109 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5110 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5111 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5112 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5113 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5114 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5115 {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW},
5116 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5117 {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW},
5118 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5119 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
5120 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5121 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
5122 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5123 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
5124 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5125 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5126 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
5127 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
5128 {0xa0, 0x00, 0x01ad},
5129 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5130 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5131 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5132 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5133 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5134 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5135 {}
5136};
5137static const struct usb_action tas5130c_50HZ[] = {
5138 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5139 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5140 {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
5141 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5142 {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */
5143 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5144 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
5145 {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
5146 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5147 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5148 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */
5149 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5150 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5151 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5152 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5153 {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */
5154 {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */
5155 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
5156 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5157 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5158 {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW},
5159 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5160 {}
5161};
5162static const struct usb_action tas5130c_50HZScale[] = {
5163 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5164 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5165 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5166 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5167 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5168 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5169 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
5170 {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW},
5171 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5172 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5173 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5174 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5175 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5176 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5177 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5178 {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */
5179 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */
5180 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
5181 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5182 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5183 {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW},
5184 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5185 {}
5186};
5187static const struct usb_action tas5130c_60HZ[] = {
5188 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5189 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5190 {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
5191 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5192 {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */
5193 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5194 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
5195 {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW},
5196 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5197 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5198 {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */
5199 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5200 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5201 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5202 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5203 {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */
5204 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5205 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5206 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5207 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5208 {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW},
5209 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5210 {}
5211};
5212static const struct usb_action tas5130c_60HZScale[] = {
5213 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5214 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5215 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5216 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5217 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5218 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5219 {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID},
5220 {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW},
5221 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5222 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5223 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5224 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5225 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5226 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5227 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5228 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
5229 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5230 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5231 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5232 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5233 {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW},
5234 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5235 {}
5236};
5237static const struct usb_action tas5130c_NoFliker[] = {
5238 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5239 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5240 {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
5241 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5242 {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */
5243 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5244 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
5245 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
5246 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5247 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5248 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
5249 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5250 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5251 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5252 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5253 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5254 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5255 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5256 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5257 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5258 {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
5259 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5260 {}
5261};
5262
5263static const struct usb_action tas5130c_NoFlikerScale[] = {
5264 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5265 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5266 {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
5267 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5268 {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */
5269 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5270 {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID},
5271 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
5272 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5273 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5274 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
5275 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5276 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5277 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5278 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5279 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5280 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5281 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5282 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5283 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5284 {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
5285 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5286 {}
5287};
5288
5289/* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */
5290static const struct usb_action gc0303_Initial[] = {
5291 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
5292 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
5293 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
5294 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
5295 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
5296 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
5297 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
5298 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
5299 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5300 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
5301 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
5302 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
5303 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
5304 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
5305 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
5306 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
5307 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc,
5308 * 6<->8 */
5309 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc,
5310 * 6<->8 */
5311 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
5312 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5313 {0xaa, 0x01, 0x0000},
5314 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
5315 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
5316 {0xaa, 0x1b, 0x0000},
5317 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
5318 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
5319 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
5320 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
5321 {0xaa, 0x0a, 0x0002},
5322 {0xaa, 0x0b, 0x0000},
5323 {0xaa, 0x0c, 0x0002},
5324 {0xaa, 0x0d, 0x0000},
5325 {0xaa, 0x0e, 0x0002},
5326 {0xaa, 0x0f, 0x0000},
5327 {0xaa, 0x10, 0x0002},
5328 {0xaa, 0x11, 0x0000},
5329 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
5330 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */
5331 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
5332 {0xaa, 0x19, 0x0088}, /* 00,19,86,aa, */
5333 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
5334 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
5335 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
5336 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
5337 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
5338 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
5339 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
5340 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
5341 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
5342 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
5343 {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
5344 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
5345 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
5346 {0xaa, 0x1b, 0x0000},
5347 {}
5348};
5349
5350static const struct usb_action gc0303_InitialScale[] = {
5351 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
5352 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
5353 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
5354 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
5355 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
5356 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
5357 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
5358 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
5359 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5360 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
5361 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
5362 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
5363 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
5364 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
5365 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
5366 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
5367 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc,
5368 * 8<->6 */
5369 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc,
5370 * 8<->6 */
5371 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
5372 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5373 {0xaa, 0x01, 0x0000},
5374 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
5375 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
5376 {0xaa, 0x1b, 0x0000},
5377 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
5378 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
5379 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
5380 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
5381 {0xaa, 0x0a, 0x0001},
5382 {0xaa, 0x0b, 0x0000},
5383 {0xaa, 0x0c, 0x0001},
5384 {0xaa, 0x0d, 0x0000},
5385 {0xaa, 0x0e, 0x0001},
5386 {0xaa, 0x0f, 0x0000},
5387 {0xaa, 0x10, 0x0001},
5388 {0xaa, 0x11, 0x0000},
5389 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
5390 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */
5391 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
5392 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */
5393 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
5394 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
5395 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
5396 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
5397 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
5398 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
5399 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
5400 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
5401 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
5402 {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
5403 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
5404 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
5405 {0xaa, 0x1b, 0x0000},
5406 {}
5407};
5408static const struct usb_action gc0303_50HZ[] = {
5409 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5410 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
5411 {0xaa, 0x84, 0x0063},
5412 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5413 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
5414 {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
5415 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5416 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5417 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */
5418 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5419 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5420 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
5421 {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},
5422 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5423 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5424 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5425 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5426 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5427 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5428 {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
5429 {}
5430};
5431
5432static const struct usb_action gc0303_50HZScale[] = {
5433 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5434 {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */
5435 {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */
5436 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5437 {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
5438 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
5439 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5440 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5441 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc, */
5442 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5443 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5444 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
5445 {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
5446 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5447 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5448 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5449 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5450 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5451 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5452 {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
5453 {}
5454};
5455
5456static const struct usb_action gc0303_60HZ[] = {
5457 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5458 {0xaa, 0x83, 0x0000},
5459 {0xaa, 0x84, 0x003b},
5460 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5461 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
5462 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
5463 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5464 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5465 {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3b,cc, */
5466 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5467 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5468 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
5469 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
5470 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5471 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5472 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5473 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5474 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5475 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5476 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
5477 {}
5478};
5479
5480static const struct usb_action gc0303_60HZScale[] = {
5481 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5482 {0xaa, 0x83, 0x0000},
5483 {0xaa, 0x84, 0x0076},
5484 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5485 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */
5486 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */
5487 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,5,00,cc, */
5488 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,6,00,cc, */
5489 {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,7,76,cc, */
5490 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,c,0e,cc, */
5491 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,f,15,cc, */
5492 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,9,10,cc, */
5493 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,a,24,cc, */
5494 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,d,62,cc, */
5495 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,e,90,cc, */
5496 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,f,c8,cc, */
5497 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */
5498 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */
5499 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5500 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
5501 {}
5502};
5503
5504static const struct usb_action gc0303_NoFliker[] = {
5505 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
5506 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5507 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
5508 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
5509 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */
5510 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
5511 {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
5512 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5513 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5514 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
5515 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5516 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5517 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5518 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5519 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5520 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5521 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5522 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
5523 {}
5524};
5525
5526static const struct usb_action gc0303_NoFlikerScale[] = {
5527 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
5528 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5529 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
5530 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
5531 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5532 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
5533 {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
5534 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5535 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5536 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
5537 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5538 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5539 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5540 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5541 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5542 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5543 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5544 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
5545 {}
5546};
5547
5548static u8 reg_r(struct gspca_dev *gspca_dev,
5549 u16 index)
5550{
5551 int ret;
5552
5553 if (gspca_dev->usb_err < 0)
5554 return 0;
5555 ret = usb_control_msg(gspca_dev->dev,
5556 usb_rcvctrlpipe(gspca_dev->dev, 0),
5557 0xa1,
5558 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5559 0x01, /* value */
5560 index, gspca_dev->usb_buf, 1,
5561 500);
5562 if (ret < 0) {
5563 pr_err("reg_r err %d\n", ret);
5564 gspca_dev->usb_err = ret;
5565 return 0;
5566 }
5567 return gspca_dev->usb_buf[0];
5568}
5569
5570static void reg_w(struct gspca_dev *gspca_dev,
5571 u8 value,
5572 u16 index)
5573{
5574 int ret;
5575
5576 if (gspca_dev->usb_err < 0)
5577 return;
5578 ret = usb_control_msg(gspca_dev->dev,
5579 usb_sndctrlpipe(gspca_dev->dev, 0),
5580 0xa0,
5581 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5582 value, index, NULL, 0,
5583 500);
5584 if (ret < 0) {
5585 pr_err("reg_w_i err %d\n", ret);
5586 gspca_dev->usb_err = ret;
5587 }
5588}
5589
5590static u16 i2c_read(struct gspca_dev *gspca_dev,
5591 u8 reg)
5592{
5593 u8 retbyte;
5594 u16 retval;
5595
5596 if (gspca_dev->usb_err < 0)
5597 return 0;
5598 reg_w(gspca_dev, reg, 0x0092);
5599 reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */
5600 msleep(20);
5601 retbyte = reg_r(gspca_dev, 0x0091); /* read status */
5602 if (retbyte != 0x00)
5603 pr_err("i2c_r status error %02x\n", retbyte);
5604 retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */
5605 retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */
5606 return retval;
5607}
5608
5609static u8 i2c_write(struct gspca_dev *gspca_dev,
5610 u8 reg,
5611 u8 valL,
5612 u8 valH)
5613{
5614 u8 retbyte;
5615
5616 if (gspca_dev->usb_err < 0)
5617 return 0;
5618 reg_w(gspca_dev, reg, 0x92);
5619 reg_w(gspca_dev, valL, 0x93);
5620 reg_w(gspca_dev, valH, 0x94);
5621 reg_w(gspca_dev, 0x01, 0x90); /* <- write command */
5622 msleep(1);
5623 retbyte = reg_r(gspca_dev, 0x0091); /* read status */
5624 if (retbyte != 0x00)
5625 pr_err("i2c_w status error %02x\n", retbyte);
5626 return retbyte;
5627}
5628
5629static void usb_exchange(struct gspca_dev *gspca_dev,
5630 const struct usb_action *action)
5631{
5632 while (action->req) {
5633 switch (action->req) {
5634 case 0xa0: /* write register */
5635 reg_w(gspca_dev, action->val, action->idx);
5636 break;
5637 case 0xa1: /* read status */
5638 reg_r(gspca_dev, action->idx);
5639 break;
5640 case 0xaa:
5641 i2c_write(gspca_dev,
5642 action->val, /* reg */
5643 action->idx & 0xff, /* valL */
5644 action->idx >> 8); /* valH */
5645 break;
5646 case 0xbb:
5647 i2c_write(gspca_dev,
5648 action->idx >> 8, /* reg */
5649 action->idx & 0xff, /* valL */
5650 action->val); /* valH */
5651 break;
5652 default:
5653/* case 0xdd: * delay */
5654 msleep(action->idx);
5655 break;
5656 }
5657 action++;
5658 msleep(1);
5659 }
5660}
5661
5662static void setmatrix(struct gspca_dev *gspca_dev)
5663{
5664 struct sd *sd = (struct sd *) gspca_dev;
5665 int i;
5666 const u8 *matrix;
5667 static const u8 adcm2700_matrix[9] =
5668/* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */
5669/*ms-win*/
5670 {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74};
5671 static const u8 gc0305_matrix[9] =
5672 {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
5673 static const u8 ov7620_matrix[9] =
5674 {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
5675 static const u8 pas202b_matrix[9] =
5676 {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f};
5677 static const u8 po2030_matrix[9] =
5678 {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
5679 static const u8 tas5130c_matrix[9] =
5680 {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
5681 static const u8 gc0303_matrix[9] =
5682 {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c};
5683 static const u8 *matrix_tb[SENSOR_MAX] = {
5684 [SENSOR_ADCM2700] = adcm2700_matrix,
5685 [SENSOR_CS2102] = ov7620_matrix,
5686 [SENSOR_CS2102K] = NULL,
5687 [SENSOR_GC0303] = gc0303_matrix,
5688 [SENSOR_GC0305] = gc0305_matrix,
5689 [SENSOR_HDCS2020] = NULL,
5690 [SENSOR_HV7131B] = NULL,
5691 [SENSOR_HV7131R] = po2030_matrix,
5692 [SENSOR_ICM105A] = po2030_matrix,
5693 [SENSOR_MC501CB] = NULL,
5694 [SENSOR_MT9V111_1] = gc0305_matrix,
5695 [SENSOR_MT9V111_3] = gc0305_matrix,
5696 [SENSOR_OV7620] = ov7620_matrix,
5697 [SENSOR_OV7630C] = NULL,
5698 [SENSOR_PAS106] = NULL,
5699 [SENSOR_PAS202B] = pas202b_matrix,
5700 [SENSOR_PB0330] = gc0305_matrix,
5701 [SENSOR_PO2030] = po2030_matrix,
5702 [SENSOR_TAS5130C] = tas5130c_matrix,
5703 };
5704
5705 matrix = matrix_tb[sd->sensor];
5706 if (matrix == NULL)
5707 return; /* matrix already loaded */
5708 for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
5709 reg_w(gspca_dev, matrix[i], 0x010a + i);
5710}
5711
5712static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
5713{
5714 static const u8 sharpness_tb[][2] = {
5715 {0x02, 0x03},
5716 {0x04, 0x07},
5717 {0x08, 0x0f},
5718 {0x10, 0x1e}
5719 };
5720
5721 reg_w(gspca_dev, sharpness_tb[val][0], 0x01c6);
5722 reg_r(gspca_dev, 0x01c8);
5723 reg_r(gspca_dev, 0x01c9);
5724 reg_r(gspca_dev, 0x01ca);
5725 reg_w(gspca_dev, sharpness_tb[val][1], 0x01cb);
5726}
5727
5728static void setcontrast(struct gspca_dev *gspca_dev,
5729 s32 gamma, s32 brightness, s32 contrast)
5730{
5731 const u8 *Tgamma;
5732 int g, i, adj, gp1, gp2;
5733 u8 gr[16];
5734 static const u8 delta_b[16] = /* delta for brightness */
5735 {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
5736 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18};
5737 static const u8 delta_c[16] = /* delta for contrast */
5738 {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06,
5739 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02};
5740 static const u8 gamma_tb[6][16] = {
5741 {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
5742 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff},
5743 {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
5744 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff},
5745 {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
5746 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff},
5747 {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
5748 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff},
5749 {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
5750 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff},
5751 {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
5752 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
5753 };
5754
5755 Tgamma = gamma_tb[gamma - 1];
5756
5757 contrast -= 128; /* -128 / 127 */
5758 brightness -= 128; /* -128 / 92 */
5759 adj = 0;
5760 gp1 = gp2 = 0;
5761 for (i = 0; i < 16; i++) {
5762 g = Tgamma[i] + delta_b[i] * brightness / 256
5763 - delta_c[i] * contrast / 256 - adj / 2;
5764 if (g > 0xff)
5765 g = 0xff;
5766 else if (g < 0)
5767 g = 0;
5768 reg_w(gspca_dev, g, 0x0120 + i); /* gamma */
5769 if (contrast > 0)
5770 adj--;
5771 else if (contrast < 0)
5772 adj++;
5773 if (i > 1)
5774 gr[i - 1] = (g - gp2) / 2;
5775 else if (i != 0)
5776 gr[0] = gp1 == 0 ? 0 : (g - gp1);
5777 gp2 = gp1;
5778 gp1 = g;
5779 }
5780 gr[15] = (0xff - gp2) / 2;
5781 for (i = 0; i < 16; i++)
5782 reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */
5783}
5784
5785static s32 getexposure(struct gspca_dev *gspca_dev)
5786{
5787 return (i2c_read(gspca_dev, 0x25) << 9)
5788 | (i2c_read(gspca_dev, 0x26) << 1)
5789 | (i2c_read(gspca_dev, 0x27) >> 7);
5790}
5791
5792static void setexposure(struct gspca_dev *gspca_dev, s32 val)
5793{
5794 i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
5795 i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
5796 i2c_write(gspca_dev, 0x27, val << 7, 0x00);
5797}
5798
5799static void setquality(struct gspca_dev *gspca_dev)
5800{
5801 struct sd *sd = (struct sd *) gspca_dev;
5802 jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08 >> 1]);
5803 reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING);
5804}
5805
5806/* Matches the sensor's internal frame rate to the lighting frequency.
5807 * Valid frequencies are:
5808 * 50Hz, for European and Asian lighting (default)
5809 * 60Hz, for American lighting
5810 * 0 = No Fliker (for outdoore usage)
5811 */
5812static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
5813{
5814 struct sd *sd = (struct sd *) gspca_dev;
5815 int i, mode;
5816 const struct usb_action *zc3_freq;
5817 static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
5818 [SENSOR_ADCM2700] =
5819 {adcm2700_NoFliker, adcm2700_NoFliker,
5820 adcm2700_50HZ, adcm2700_50HZ,
5821 adcm2700_60HZ, adcm2700_60HZ},
5822 [SENSOR_CS2102] =
5823 {cs2102_NoFliker, cs2102_NoFlikerScale,
5824 cs2102_50HZ, cs2102_50HZScale,
5825 cs2102_60HZ, cs2102_60HZScale},
5826 [SENSOR_CS2102K] =
5827 {cs2102_NoFliker, cs2102_NoFlikerScale,
5828 NULL, NULL, /* currently disabled */
5829 NULL, NULL},
5830 [SENSOR_GC0303] =
5831 {gc0303_NoFliker, gc0303_NoFlikerScale,
5832 gc0303_50HZ, gc0303_50HZScale,
5833 gc0303_60HZ, gc0303_60HZScale},
5834 [SENSOR_GC0305] =
5835 {gc0305_NoFliker, gc0305_NoFliker,
5836 gc0305_50HZ, gc0305_50HZ,
5837 gc0305_60HZ, gc0305_60HZ},
5838 [SENSOR_HDCS2020] =
5839 {hdcs2020_NoFliker, hdcs2020_NoFliker,
5840 hdcs2020_50HZ, hdcs2020_50HZ,
5841 hdcs2020_60HZ, hdcs2020_60HZ},
5842 [SENSOR_HV7131B] =
5843 {hv7131b_NoFliker, hv7131b_NoFlikerScale,
5844 hv7131b_50HZ, hv7131b_50HZScale,
5845 hv7131b_60HZ, hv7131b_60HZScale},
5846 [SENSOR_HV7131R] =
5847 {hv7131r_NoFliker, hv7131r_NoFlikerScale,
5848 hv7131r_50HZ, hv7131r_50HZScale,
5849 hv7131r_60HZ, hv7131r_60HZScale},
5850 [SENSOR_ICM105A] =
5851 {icm105a_NoFliker, icm105a_NoFlikerScale,
5852 icm105a_50HZ, icm105a_50HZScale,
5853 icm105a_60HZ, icm105a_60HZScale},
5854 [SENSOR_MC501CB] =
5855 {mc501cb_NoFliker, mc501cb_NoFlikerScale,
5856 mc501cb_50HZ, mc501cb_50HZScale,
5857 mc501cb_60HZ, mc501cb_60HZScale},
5858 [SENSOR_MT9V111_1] =
5859 {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
5860 mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
5861 mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
5862 [SENSOR_MT9V111_3] =
5863 {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
5864 mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
5865 mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
5866 [SENSOR_OV7620] =
5867 {ov7620_NoFliker, ov7620_NoFliker,
5868 ov7620_50HZ, ov7620_50HZ,
5869 ov7620_60HZ, ov7620_60HZ},
5870 [SENSOR_OV7630C] =
5871 {NULL, NULL,
5872 NULL, NULL,
5873 NULL, NULL},
5874 [SENSOR_PAS106] =
5875 {pas106b_NoFliker, pas106b_NoFliker,
5876 pas106b_50HZ, pas106b_50HZ,
5877 pas106b_60HZ, pas106b_60HZ},
5878 [SENSOR_PAS202B] =
5879 {pas202b_NoFliker, pas202b_NoFlikerScale,
5880 pas202b_50HZ, pas202b_50HZScale,
5881 pas202b_60HZ, pas202b_60HZScale},
5882 [SENSOR_PB0330] =
5883 {pb0330_NoFliker, pb0330_NoFlikerScale,
5884 pb0330_50HZ, pb0330_50HZScale,
5885 pb0330_60HZ, pb0330_60HZScale},
5886 [SENSOR_PO2030] =
5887 {po2030_NoFliker, po2030_NoFliker,
5888 po2030_50HZ, po2030_50HZ,
5889 po2030_60HZ, po2030_60HZ},
5890 [SENSOR_TAS5130C] =
5891 {tas5130c_NoFliker, tas5130c_NoFlikerScale,
5892 tas5130c_50HZ, tas5130c_50HZScale,
5893 tas5130c_60HZ, tas5130c_60HZScale},
5894 };
5895
5896 i = val * 2;
5897 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
5898 if (mode)
5899 i++; /* 320x240 */
5900 zc3_freq = freq_tb[sd->sensor][i];
5901 if (zc3_freq == NULL)
5902 return;
5903 usb_exchange(gspca_dev, zc3_freq);
5904 switch (sd->sensor) {
5905 case SENSOR_GC0305:
5906 if (mode /* if 320x240 */
5907 && val == 1) /* and 50Hz */
5908 reg_w(gspca_dev, 0x85, 0x018d);
5909 /* win: 0x80, 0x018d */
5910 break;
5911 case SENSOR_OV7620:
5912 if (!mode) { /* if 640x480 */
5913 if (val != 0) /* and filter */
5914 reg_w(gspca_dev, 0x40, 0x0002);
5915 else
5916 reg_w(gspca_dev, 0x44, 0x0002);
5917 }
5918 break;
5919 case SENSOR_PAS202B:
5920 reg_w(gspca_dev, 0x00, 0x01a7);
5921 break;
5922 }
5923}
5924
5925static void setautogain(struct gspca_dev *gspca_dev, s32 val)
5926{
5927 reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180);
5928}
5929
5930/*
5931 * Update the transfer parameters.
5932 * This function is executed from a work queue.
5933 */
5934static void transfer_update(struct work_struct *work)
5935{
5936 struct sd *sd = container_of(work, struct sd, work);
5937 struct gspca_dev *gspca_dev = &sd->gspca_dev;
5938 int change, good;
5939 u8 reg07, reg11;
5940
5941 /* reg07 gets set to 0 by sd_start before starting us */
5942 reg07 = 0;
5943
5944 good = 0;
5945 for (;;) {
5946 msleep(100);
5947
5948 mutex_lock(&gspca_dev->usb_lock);
5949#ifdef CONFIG_PM
5950 if (gspca_dev->frozen)
5951 goto err;
5952#endif
5953 if (!gspca_dev->dev || !gspca_dev->streaming)
5954 goto err;
5955
5956 /* Bit 0 of register 11 indicates FIFO overflow */
5957 gspca_dev->usb_err = 0;
5958 reg11 = reg_r(gspca_dev, 0x0011);
5959 if (gspca_dev->usb_err)
5960 goto err;
5961
5962 change = reg11 & 0x01;
5963 if (change) { /* overflow */
5964 good = 0;
5965
5966 if (reg07 == 0) /* Bit Rate Control not enabled? */
5967 reg07 = 0x32; /* Allow 98 bytes / unit */
5968 else if (reg07 > 2)
5969 reg07 -= 2; /* Decrease allowed bytes / unit */
5970 else
5971 change = 0;
5972 } else { /* no overflow */
5973 good++;
5974 if (good >= 10) {
5975 good = 0;
5976 if (reg07) { /* BRC enabled? */
5977 change = 1;
5978 if (reg07 < 0x32)
5979 reg07 += 2;
5980 else
5981 reg07 = 0;
5982 }
5983 }
5984 }
5985 if (change) {
5986 gspca_dev->usb_err = 0;
5987 reg_w(gspca_dev, reg07, 0x0007);
5988 if (gspca_dev->usb_err)
5989 goto err;
5990 }
5991 mutex_unlock(&gspca_dev->usb_lock);
5992 }
5993 return;
5994err:
5995 mutex_unlock(&gspca_dev->usb_lock);
5996}
5997
5998static void send_unknown(struct gspca_dev *gspca_dev, int sensor)
5999{
6000 reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */
6001 switch (sensor) {
6002 case SENSOR_PAS106:
6003 reg_w(gspca_dev, 0x03, 0x003a);
6004 reg_w(gspca_dev, 0x0c, 0x003b);
6005 reg_w(gspca_dev, 0x08, 0x0038);
6006 break;
6007 case SENSOR_ADCM2700:
6008 case SENSOR_GC0305:
6009 case SENSOR_OV7620:
6010 case SENSOR_MT9V111_1:
6011 case SENSOR_MT9V111_3:
6012 case SENSOR_PB0330:
6013 case SENSOR_PO2030:
6014 reg_w(gspca_dev, 0x0d, 0x003a);
6015 reg_w(gspca_dev, 0x02, 0x003b);
6016 reg_w(gspca_dev, 0x00, 0x0038);
6017 break;
6018 case SENSOR_HV7131R:
6019 case SENSOR_PAS202B:
6020 reg_w(gspca_dev, 0x03, 0x003b);
6021 reg_w(gspca_dev, 0x0c, 0x003a);
6022 reg_w(gspca_dev, 0x0b, 0x0039);
6023 if (sensor == SENSOR_PAS202B)
6024 reg_w(gspca_dev, 0x0b, 0x0038);
6025 break;
6026 }
6027}
6028
6029/* start probe 2 wires */
6030static void start_2wr_probe(struct gspca_dev *gspca_dev, int sensor)
6031{
6032 reg_w(gspca_dev, 0x01, 0x0000);
6033 reg_w(gspca_dev, sensor, 0x0010);
6034 reg_w(gspca_dev, 0x01, 0x0001);
6035 reg_w(gspca_dev, 0x03, 0x0012);
6036 reg_w(gspca_dev, 0x01, 0x0012);
6037/* msleep(2); */
6038}
6039
6040static int sif_probe(struct gspca_dev *gspca_dev)
6041{
6042 u16 checkword;
6043
6044 start_2wr_probe(gspca_dev, 0x0f); /* PAS106 */
6045 reg_w(gspca_dev, 0x08, 0x008d);
6046 msleep(150);
6047 checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
6048 | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
6049 PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
6050 if (checkword == 0x0007) {
6051 send_unknown(gspca_dev, SENSOR_PAS106);
6052 return 0x0f; /* PAS106 */
6053 }
6054 return -1;
6055}
6056
6057static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6058{
6059 u16 retword;
6060
6061 start_2wr_probe(gspca_dev, 0x00); /* HV7131B */
6062 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6063 retword = i2c_read(gspca_dev, 0x01);
6064 if (retword != 0)
6065 return 0x00; /* HV7131B */
6066
6067 start_2wr_probe(gspca_dev, 0x04); /* CS2102 */
6068 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6069 retword = i2c_read(gspca_dev, 0x01);
6070 if (retword != 0)
6071 return 0x04; /* CS2102 */
6072
6073 start_2wr_probe(gspca_dev, 0x06); /* OmniVision */
6074 reg_w(gspca_dev, 0x08, 0x008d);
6075 i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
6076 retword = i2c_read(gspca_dev, 0x11);
6077 if (retword != 0) {
6078 /* (should have returned 0xaa) --> Omnivision? */
6079 /* reg_r 0x10 -> 0x06 --> */
6080 goto ov_check;
6081 }
6082
6083 start_2wr_probe(gspca_dev, 0x08); /* HDCS2020 */
6084 i2c_write(gspca_dev, 0x1c, 0x00, 0x00);
6085 i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
6086 retword = i2c_read(gspca_dev, 0x15);
6087 if (retword != 0)
6088 return 0x08; /* HDCS2020 */
6089
6090 start_2wr_probe(gspca_dev, 0x0a); /* PB0330 */
6091 i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
6092 retword = i2c_read(gspca_dev, 0x07);
6093 if (retword != 0)
6094 return 0x0a; /* PB0330 */
6095 retword = i2c_read(gspca_dev, 0x03);
6096 if (retword != 0)
6097 return 0x0a; /* PB0330 ?? */
6098 retword = i2c_read(gspca_dev, 0x04);
6099 if (retword != 0)
6100 return 0x0a; /* PB0330 ?? */
6101
6102 start_2wr_probe(gspca_dev, 0x0c); /* ICM105A */
6103 i2c_write(gspca_dev, 0x01, 0x11, 0x00);
6104 retword = i2c_read(gspca_dev, 0x01);
6105 if (retword != 0)
6106 return 0x0c; /* ICM105A */
6107
6108 start_2wr_probe(gspca_dev, 0x0e); /* PAS202BCB */
6109 reg_w(gspca_dev, 0x08, 0x008d);
6110 i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
6111 msleep(50);
6112 retword = i2c_read(gspca_dev, 0x03);
6113 if (retword != 0) {
6114 send_unknown(gspca_dev, SENSOR_PAS202B);
6115 return 0x0e; /* PAS202BCB */
6116 }
6117
6118 start_2wr_probe(gspca_dev, 0x02); /* TAS5130C */
6119 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6120 retword = i2c_read(gspca_dev, 0x01);
6121 if (retword != 0)
6122 return 0x02; /* TAS5130C */
6123ov_check:
6124 reg_r(gspca_dev, 0x0010); /* ?? */
6125 reg_r(gspca_dev, 0x0010);
6126
6127 reg_w(gspca_dev, 0x01, 0x0000);
6128 reg_w(gspca_dev, 0x01, 0x0001);
6129 reg_w(gspca_dev, 0x06, 0x0010); /* OmniVision */
6130 reg_w(gspca_dev, 0xa1, 0x008b);
6131 reg_w(gspca_dev, 0x08, 0x008d);
6132 msleep(500);
6133 reg_w(gspca_dev, 0x01, 0x0012);
6134 i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
6135 retword = i2c_read(gspca_dev, 0x0a) << 8;
6136 retword |= i2c_read(gspca_dev, 0x0b);
6137 PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword);
6138 switch (retword) {
6139 case 0x7631: /* OV7630C */
6140 reg_w(gspca_dev, 0x06, 0x0010);
6141 break;
6142 case 0x7620: /* OV7620 */
6143 case 0x7648: /* OV7648 */
6144 break;
6145 default:
6146 return -1; /* not OmniVision */
6147 }
6148 return retword;
6149}
6150
6151struct sensor_by_chipset_revision {
6152 u16 revision;
6153 u8 internal_sensor_id;
6154};
6155static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
6156 {0xc000, 0x12}, /* TAS5130C */
6157 {0xc001, 0x13}, /* MT9V111 */
6158 {0xe001, 0x13},
6159 {0x8001, 0x13},
6160 {0x8000, 0x14}, /* CS2102K */
6161 {0x8400, 0x15}, /* MT9V111 */
6162 {0xe400, 0x15},
6163};
6164
6165static int vga_3wr_probe(struct gspca_dev *gspca_dev)
6166{
6167 struct sd *sd = (struct sd *) gspca_dev;
6168 int i;
6169 u16 retword;
6170
6171/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
6172 reg_w(gspca_dev, 0x02, 0x0010);
6173 reg_r(gspca_dev, 0x0010);
6174 reg_w(gspca_dev, 0x01, 0x0000);
6175 reg_w(gspca_dev, 0x00, 0x0010);
6176 reg_w(gspca_dev, 0x01, 0x0001);
6177 reg_w(gspca_dev, 0x91, 0x008b);
6178 reg_w(gspca_dev, 0x03, 0x0012);
6179 reg_w(gspca_dev, 0x01, 0x0012);
6180 reg_w(gspca_dev, 0x05, 0x0012);
6181 retword = i2c_read(gspca_dev, 0x14);
6182 if (retword != 0)
6183 return 0x11; /* HV7131R */
6184 retword = i2c_read(gspca_dev, 0x15);
6185 if (retword != 0)
6186 return 0x11; /* HV7131R */
6187 retword = i2c_read(gspca_dev, 0x16);
6188 if (retword != 0)
6189 return 0x11; /* HV7131R */
6190
6191 reg_w(gspca_dev, 0x02, 0x0010);
6192 retword = reg_r(gspca_dev, 0x000b) << 8;
6193 retword |= reg_r(gspca_dev, 0x000a);
6194 PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
6195 reg_r(gspca_dev, 0x0010);
6196 if ((retword & 0xff00) == 0x6400)
6197 return 0x02; /* TAS5130C */
6198 for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
6199 if (chipset_revision_sensor[i].revision == retword) {
6200 sd->chip_revision = retword;
6201 send_unknown(gspca_dev, SENSOR_PB0330);
6202 return chipset_revision_sensor[i].internal_sensor_id;
6203 }
6204 }
6205
6206 reg_w(gspca_dev, 0x01, 0x0000); /* check PB0330 */
6207 reg_w(gspca_dev, 0x01, 0x0001);
6208 reg_w(gspca_dev, 0xdd, 0x008b);
6209 reg_w(gspca_dev, 0x0a, 0x0010);
6210 reg_w(gspca_dev, 0x03, 0x0012);
6211 reg_w(gspca_dev, 0x01, 0x0012);
6212 retword = i2c_read(gspca_dev, 0x00);
6213 if (retword != 0) {
6214 PDEBUG(D_PROBE, "probe 3wr vga type 0a");
6215 return 0x0a; /* PB0330 */
6216 }
6217
6218 /* probe gc0303 / gc0305 */
6219 reg_w(gspca_dev, 0x01, 0x0000);
6220 reg_w(gspca_dev, 0x01, 0x0001);
6221 reg_w(gspca_dev, 0x98, 0x008b);
6222 reg_w(gspca_dev, 0x01, 0x0010);
6223 reg_w(gspca_dev, 0x03, 0x0012);
6224 msleep(2);
6225 reg_w(gspca_dev, 0x01, 0x0012);
6226 retword = i2c_read(gspca_dev, 0x00);
6227 if (retword != 0) {
6228 PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
6229 if (retword == 0x0011) /* gc0303 */
6230 return 0x0303;
6231 if (retword == 0x0029) /* gc0305 */
6232 send_unknown(gspca_dev, SENSOR_GC0305);
6233 return retword;
6234 }
6235
6236 reg_w(gspca_dev, 0x01, 0x0000); /* check OmniVision */
6237 reg_w(gspca_dev, 0x01, 0x0001);
6238 reg_w(gspca_dev, 0xa1, 0x008b);
6239 reg_w(gspca_dev, 0x08, 0x008d);
6240 reg_w(gspca_dev, 0x06, 0x0010);
6241 reg_w(gspca_dev, 0x01, 0x0012);
6242 reg_w(gspca_dev, 0x05, 0x0012);
6243 if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */
6244 && i2c_read(gspca_dev, 0x1d) == 0x00a2) {
6245 send_unknown(gspca_dev, SENSOR_OV7620);
6246 return 0x06; /* OmniVision confirm ? */
6247 }
6248
6249 reg_w(gspca_dev, 0x01, 0x0000);
6250 reg_w(gspca_dev, 0x00, 0x0002);
6251 reg_w(gspca_dev, 0x01, 0x0010);
6252 reg_w(gspca_dev, 0x01, 0x0001);
6253 reg_w(gspca_dev, 0xee, 0x008b);
6254 reg_w(gspca_dev, 0x03, 0x0012);
6255 reg_w(gspca_dev, 0x01, 0x0012);
6256 reg_w(gspca_dev, 0x05, 0x0012);
6257 retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */
6258 retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */
6259 PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
6260 if (retword == 0x2030) {
6261#ifdef GSPCA_DEBUG
6262 u8 retbyte;
6263
6264 retbyte = i2c_read(gspca_dev, 0x02); /* revision number */
6265 PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
6266#endif
6267 send_unknown(gspca_dev, SENSOR_PO2030);
6268 return retword;
6269 }
6270
6271 reg_w(gspca_dev, 0x01, 0x0000);
6272 reg_w(gspca_dev, 0x0a, 0x0010);
6273 reg_w(gspca_dev, 0xd3, 0x008b);
6274 reg_w(gspca_dev, 0x01, 0x0001);
6275 reg_w(gspca_dev, 0x03, 0x0012);
6276 reg_w(gspca_dev, 0x01, 0x0012);
6277 reg_w(gspca_dev, 0x05, 0x0012);
6278 reg_w(gspca_dev, 0xd3, 0x008b);
6279 retword = i2c_read(gspca_dev, 0x01);
6280 if (retword != 0) {
6281 PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
6282 return 0x16; /* adcm2700 (6100/6200) */
6283 }
6284 return -1;
6285}
6286
6287static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
6288{
6289 struct sd *sd = (struct sd *) gspca_dev;
6290 int sensor;
6291
6292 switch (sd->sensor) {
6293 case SENSOR_MC501CB:
6294 return -1; /* don't probe */
6295 case SENSOR_GC0303:
6296 /* may probe but with no write in reg 0x0010 */
6297 return -1; /* don't probe */
6298 case SENSOR_PAS106:
6299 sensor = sif_probe(gspca_dev);
6300 if (sensor >= 0)
6301 return sensor;
6302 break;
6303 }
6304 sensor = vga_2wr_probe(gspca_dev);
6305 if (sensor >= 0)
6306 return sensor;
6307 return vga_3wr_probe(gspca_dev);
6308}
6309
6310/* this function is called at probe time */
6311static int sd_config(struct gspca_dev *gspca_dev,
6312 const struct usb_device_id *id)
6313{
6314 struct sd *sd = (struct sd *) gspca_dev;
6315
6316 if (id->idProduct == 0x301b)
6317 sd->bridge = BRIDGE_ZC301;
6318 else
6319 sd->bridge = BRIDGE_ZC303;
6320
6321 /* define some sensors from the vendor/product */
6322 sd->sensor = id->driver_info;
6323
6324 sd->reg08 = REG08_DEF;
6325
6326 INIT_WORK(&sd->work, transfer_update);
6327
6328 return 0;
6329}
6330
6331static int zcxx_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
6332{
6333 struct gspca_dev *gspca_dev =
6334 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
6335 struct sd *sd = (struct sd *)gspca_dev;
6336
6337 switch (ctrl->id) {
6338 case V4L2_CID_AUTOGAIN:
6339 gspca_dev->usb_err = 0;
6340 if (ctrl->val && sd->exposure && gspca_dev->streaming)
6341 sd->exposure->val = getexposure(gspca_dev);
6342 return gspca_dev->usb_err;
6343 }
6344 return -EINVAL;
6345}
6346
6347static int zcxx_s_ctrl(struct v4l2_ctrl *ctrl)
6348{
6349 struct gspca_dev *gspca_dev =
6350 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
6351 struct sd *sd = (struct sd *)gspca_dev;
6352 int i, qual;
6353
6354 gspca_dev->usb_err = 0;
6355
6356 if (ctrl->id == V4L2_CID_JPEG_COMPRESSION_QUALITY) {
6357 qual = sd->reg08 >> 1;
6358
6359 for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) {
6360 if (ctrl->val <= jpeg_qual[i])
6361 break;
6362 }
6363 if (i > 0 && i == qual && ctrl->val < jpeg_qual[i])
6364 i--;
6365
6366 /* With high quality settings we need max bandwidth */
6367 if (i >= 2 && gspca_dev->streaming &&
6368 !gspca_dev->cam.needs_full_bandwidth)
6369 return -EBUSY;
6370
6371 sd->reg08 = (i << 1) | 1;
6372 ctrl->val = jpeg_qual[i];
6373 }
6374
6375 if (!gspca_dev->streaming)
6376 return 0;
6377
6378 switch (ctrl->id) {
6379 /* gamma/brightness/contrast cluster */
6380 case V4L2_CID_GAMMA:
6381 setcontrast(gspca_dev, sd->gamma->val,
6382 sd->brightness->val, sd->contrast->val);
6383 break;
6384 /* autogain/exposure cluster */
6385 case V4L2_CID_AUTOGAIN:
6386 setautogain(gspca_dev, ctrl->val);
6387 if (!gspca_dev->usb_err && !ctrl->val && sd->exposure)
6388 setexposure(gspca_dev, sd->exposure->val);
6389 break;
6390 case V4L2_CID_POWER_LINE_FREQUENCY:
6391 setlightfreq(gspca_dev, ctrl->val);
6392 break;
6393 case V4L2_CID_SHARPNESS:
6394 setsharpness(gspca_dev, ctrl->val);
6395 break;
6396 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
6397 setquality(gspca_dev);
6398 break;
6399 }
6400 return gspca_dev->usb_err;
6401}
6402
6403static const struct v4l2_ctrl_ops zcxx_ctrl_ops = {
6404 .g_volatile_ctrl = zcxx_g_volatile_ctrl,
6405 .s_ctrl = zcxx_s_ctrl,
6406};
6407
6408static int sd_init_controls(struct gspca_dev *gspca_dev)
6409{
6410 struct sd *sd = (struct sd *)gspca_dev;
6411 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
6412 static const u8 gamma[SENSOR_MAX] = {
6413 [SENSOR_ADCM2700] = 4,
6414 [SENSOR_CS2102] = 4,
6415 [SENSOR_CS2102K] = 5,
6416 [SENSOR_GC0303] = 3,
6417 [SENSOR_GC0305] = 4,
6418 [SENSOR_HDCS2020] = 4,
6419 [SENSOR_HV7131B] = 4,
6420 [SENSOR_HV7131R] = 4,
6421 [SENSOR_ICM105A] = 4,
6422 [SENSOR_MC501CB] = 4,
6423 [SENSOR_MT9V111_1] = 4,
6424 [SENSOR_MT9V111_3] = 4,
6425 [SENSOR_OV7620] = 3,
6426 [SENSOR_OV7630C] = 4,
6427 [SENSOR_PAS106] = 4,
6428 [SENSOR_PAS202B] = 4,
6429 [SENSOR_PB0330] = 4,
6430 [SENSOR_PO2030] = 4,
6431 [SENSOR_TAS5130C] = 3,
6432 };
6433
6434 gspca_dev->vdev.ctrl_handler = hdl;
6435 v4l2_ctrl_handler_init(hdl, 8);
6436 sd->brightness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6437 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
6438 sd->contrast = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6439 V4L2_CID_CONTRAST, 0, 255, 1, 128);
6440 sd->gamma = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6441 V4L2_CID_GAMMA, 1, 6, 1, gamma[sd->sensor]);
6442 if (sd->sensor == SENSOR_HV7131R)
6443 sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6444 V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927);
6445 sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6446 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
6447 if (sd->sensor != SENSOR_OV7630C)
6448 sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &zcxx_ctrl_ops,
6449 V4L2_CID_POWER_LINE_FREQUENCY,
6450 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
6451 V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
6452 sd->sharpness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6453 V4L2_CID_SHARPNESS, 0, 3, 1,
6454 sd->sensor == SENSOR_PO2030 ? 0 : 2);
6455 sd->jpegqual = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
6456 V4L2_CID_JPEG_COMPRESSION_QUALITY,
6457 jpeg_qual[0], jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1], 1,
6458 jpeg_qual[REG08_DEF >> 1]);
6459 if (hdl->error) {
6460 pr_err("Could not initialize controls\n");
6461 return hdl->error;
6462 }
6463 v4l2_ctrl_cluster(3, &sd->gamma);
6464 if (sd->sensor == SENSOR_HV7131R)
6465 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
6466 return 0;
6467}
6468
6469/* this function is called at probe and resume time */
6470static int sd_init(struct gspca_dev *gspca_dev)
6471{
6472 struct sd *sd = (struct sd *) gspca_dev;
6473 struct cam *cam;
6474 int sensor;
6475 static const u8 mode_tb[SENSOR_MAX] = {
6476 [SENSOR_ADCM2700] = 2,
6477 [SENSOR_CS2102] = 1,
6478 [SENSOR_CS2102K] = 1,
6479 [SENSOR_GC0303] = 1,
6480 [SENSOR_GC0305] = 1,
6481 [SENSOR_HDCS2020] = 1,
6482 [SENSOR_HV7131B] = 1,
6483 [SENSOR_HV7131R] = 1,
6484 [SENSOR_ICM105A] = 1,
6485 [SENSOR_MC501CB] = 2,
6486 [SENSOR_MT9V111_1] = 1,
6487 [SENSOR_MT9V111_3] = 1,
6488 [SENSOR_OV7620] = 2,
6489 [SENSOR_OV7630C] = 1,
6490 [SENSOR_PAS106] = 0,
6491 [SENSOR_PAS202B] = 1,
6492 [SENSOR_PB0330] = 1,
6493 [SENSOR_PO2030] = 1,
6494 [SENSOR_TAS5130C] = 1,
6495 };
6496
6497 sensor = zcxx_probeSensor(gspca_dev);
6498 if (sensor >= 0)
6499 PDEBUG(D_PROBE, "probe sensor -> %04x", sensor);
6500 if ((unsigned) force_sensor < SENSOR_MAX) {
6501 sd->sensor = force_sensor;
6502 PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
6503 } else {
6504 switch (sensor) {
6505 case -1:
6506 switch (sd->sensor) {
6507 case SENSOR_MC501CB:
6508 PDEBUG(D_PROBE, "Sensor MC501CB");
6509 break;
6510 case SENSOR_GC0303:
6511 PDEBUG(D_PROBE, "Sensor GC0303");
6512 break;
6513 default:
6514 pr_warn("Unknown sensor - set to TAS5130C\n");
6515 sd->sensor = SENSOR_TAS5130C;
6516 }
6517 break;
6518 case 0:
6519 /* check the sensor type */
6520 sensor = i2c_read(gspca_dev, 0x00);
6521 PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor);
6522 switch (sensor) {
6523 case 0: /* hv7131b */
6524 case 1: /* hv7131e */
6525 PDEBUG(D_PROBE, "Find Sensor HV7131B");
6526 sd->sensor = SENSOR_HV7131B;
6527 break;
6528 default:
6529/* case 2: * hv7131r */
6530 PDEBUG(D_PROBE, "Find Sensor HV7131R");
6531 sd->sensor = SENSOR_HV7131R;
6532 break;
6533 }
6534 break;
6535 case 0x02:
6536 PDEBUG(D_PROBE, "Sensor TAS5130C");
6537 sd->sensor = SENSOR_TAS5130C;
6538 break;
6539 case 0x04:
6540 PDEBUG(D_PROBE, "Find Sensor CS2102");
6541 sd->sensor = SENSOR_CS2102;
6542 break;
6543 case 0x08:
6544 PDEBUG(D_PROBE, "Find Sensor HDCS2020");
6545 sd->sensor = SENSOR_HDCS2020;
6546 break;
6547 case 0x0a:
6548 PDEBUG(D_PROBE,
6549 "Find Sensor PB0330. Chip revision %x",
6550 sd->chip_revision);
6551 sd->sensor = SENSOR_PB0330;
6552 break;
6553 case 0x0c:
6554 PDEBUG(D_PROBE, "Find Sensor ICM105A");
6555 sd->sensor = SENSOR_ICM105A;
6556 break;
6557 case 0x0e:
6558 PDEBUG(D_PROBE, "Find Sensor PAS202B");
6559 sd->sensor = SENSOR_PAS202B;
6560 break;
6561 case 0x0f:
6562 PDEBUG(D_PROBE, "Find Sensor PAS106");
6563 sd->sensor = SENSOR_PAS106;
6564 break;
6565 case 0x10:
6566 case 0x12:
6567 PDEBUG(D_PROBE, "Find Sensor TAS5130C");
6568 sd->sensor = SENSOR_TAS5130C;
6569 break;
6570 case 0x11:
6571 PDEBUG(D_PROBE, "Find Sensor HV7131R");
6572 sd->sensor = SENSOR_HV7131R;
6573 break;
6574 case 0x13:
6575 case 0x15:
6576 PDEBUG(D_PROBE,
6577 "Sensor MT9V111. Chip revision %04x",
6578 sd->chip_revision);
6579 sd->sensor = sd->bridge == BRIDGE_ZC301
6580 ? SENSOR_MT9V111_1
6581 : SENSOR_MT9V111_3;
6582 break;
6583 case 0x14:
6584 PDEBUG(D_PROBE,
6585 "Find Sensor CS2102K?. Chip revision %x",
6586 sd->chip_revision);
6587 sd->sensor = SENSOR_CS2102K;
6588 break;
6589 case 0x16:
6590 PDEBUG(D_PROBE, "Find Sensor ADCM2700");
6591 sd->sensor = SENSOR_ADCM2700;
6592 break;
6593 case 0x29:
6594 PDEBUG(D_PROBE, "Find Sensor GC0305");
6595 sd->sensor = SENSOR_GC0305;
6596 break;
6597 case 0x0303:
6598 PDEBUG(D_PROBE, "Sensor GC0303");
6599 sd->sensor = SENSOR_GC0303;
6600 break;
6601 case 0x2030:
6602 PDEBUG(D_PROBE, "Find Sensor PO2030");
6603 sd->sensor = SENSOR_PO2030;
6604 break;
6605 case 0x7620:
6606 PDEBUG(D_PROBE, "Find Sensor OV7620");
6607 sd->sensor = SENSOR_OV7620;
6608 break;
6609 case 0x7631:
6610 PDEBUG(D_PROBE, "Find Sensor OV7630C");
6611 sd->sensor = SENSOR_OV7630C;
6612 break;
6613 case 0x7648:
6614 PDEBUG(D_PROBE, "Find Sensor OV7648");
6615 sd->sensor = SENSOR_OV7620; /* same sensor (?) */
6616 break;
6617 default:
6618 pr_err("Unknown sensor %04x\n", sensor);
6619 return -EINVAL;
6620 }
6621 }
6622 if (sensor < 0x20) {
6623 if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
6624 reg_w(gspca_dev, 0x02, 0x0010);
6625 reg_r(gspca_dev, 0x0010);
6626 }
6627
6628 cam = &gspca_dev->cam;
6629 switch (mode_tb[sd->sensor]) {
6630 case 0:
6631 cam->cam_mode = sif_mode;
6632 cam->nmodes = ARRAY_SIZE(sif_mode);
6633 break;
6634 case 1:
6635 cam->cam_mode = vga_mode;
6636 cam->nmodes = ARRAY_SIZE(vga_mode);
6637 break;
6638 default:
6639/* case 2: */
6640 cam->cam_mode = broken_vga_mode;
6641 cam->nmodes = ARRAY_SIZE(broken_vga_mode);
6642 break;
6643 }
6644
6645 /* switch off the led */
6646 reg_w(gspca_dev, 0x01, 0x0000);
6647 return gspca_dev->usb_err;
6648}
6649
6650static int sd_pre_start(struct gspca_dev *gspca_dev)
6651{
6652 struct sd *sd = (struct sd *) gspca_dev;
6653 gspca_dev->cam.needs_full_bandwidth = (sd->reg08 >= 4) ? 1 : 0;
6654 return 0;
6655}
6656
6657static int sd_start(struct gspca_dev *gspca_dev)
6658{
6659 struct sd *sd = (struct sd *) gspca_dev;
6660 int mode;
6661 static const struct usb_action *init_tb[SENSOR_MAX][2] = {
6662 [SENSOR_ADCM2700] =
6663 {adcm2700_Initial, adcm2700_InitialScale},
6664 [SENSOR_CS2102] =
6665 {cs2102_Initial, cs2102_InitialScale},
6666 [SENSOR_CS2102K] =
6667 {cs2102K_Initial, cs2102K_InitialScale},
6668 [SENSOR_GC0303] =
6669 {gc0303_Initial, gc0303_InitialScale},
6670 [SENSOR_GC0305] =
6671 {gc0305_Initial, gc0305_InitialScale},
6672 [SENSOR_HDCS2020] =
6673 {hdcs2020_Initial, hdcs2020_InitialScale},
6674 [SENSOR_HV7131B] =
6675 {hv7131b_Initial, hv7131b_InitialScale},
6676 [SENSOR_HV7131R] =
6677 {hv7131r_Initial, hv7131r_InitialScale},
6678 [SENSOR_ICM105A] =
6679 {icm105a_Initial, icm105a_InitialScale},
6680 [SENSOR_MC501CB] =
6681 {mc501cb_Initial, mc501cb_InitialScale},
6682 [SENSOR_MT9V111_1] =
6683 {mt9v111_1_Initial, mt9v111_1_InitialScale},
6684 [SENSOR_MT9V111_3] =
6685 {mt9v111_3_Initial, mt9v111_3_InitialScale},
6686 [SENSOR_OV7620] =
6687 {ov7620_Initial, ov7620_InitialScale},
6688 [SENSOR_OV7630C] =
6689 {ov7630c_Initial, ov7630c_InitialScale},
6690 [SENSOR_PAS106] =
6691 {pas106b_Initial, pas106b_InitialScale},
6692 [SENSOR_PAS202B] =
6693 {pas202b_Initial, pas202b_InitialScale},
6694 [SENSOR_PB0330] =
6695 {pb0330_Initial, pb0330_InitialScale},
6696 [SENSOR_PO2030] =
6697 {po2030_Initial, po2030_InitialScale},
6698 [SENSOR_TAS5130C] =
6699 {tas5130c_Initial, tas5130c_InitialScale},
6700 };
6701
6702 /* create the JPEG header */
6703 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
6704 0x21); /* JPEG 422 */
6705
6706 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
6707 switch (sd->sensor) {
6708 case SENSOR_HV7131R:
6709 zcxx_probeSensor(gspca_dev);
6710 break;
6711 case SENSOR_PAS106:
6712 usb_exchange(gspca_dev, pas106b_Initial_com);
6713 break;
6714 }
6715 usb_exchange(gspca_dev, init_tb[sd->sensor][mode]);
6716
6717 switch (sd->sensor) {
6718 case SENSOR_ADCM2700:
6719 case SENSOR_GC0305:
6720 case SENSOR_OV7620:
6721 case SENSOR_PO2030:
6722 case SENSOR_TAS5130C:
6723 case SENSOR_GC0303:
6724/* msleep(100); * ?? */
6725 reg_r(gspca_dev, 0x0002); /* --> 0x40 */
6726 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6727 reg_w(gspca_dev, 0x15, 0x01ae);
6728 if (sd->sensor == SENSOR_TAS5130C)
6729 break;
6730 reg_w(gspca_dev, 0x0d, 0x003a);
6731 reg_w(gspca_dev, 0x02, 0x003b);
6732 reg_w(gspca_dev, 0x00, 0x0038);
6733 break;
6734 case SENSOR_HV7131R:
6735 case SENSOR_PAS202B:
6736 reg_w(gspca_dev, 0x03, 0x003b);
6737 reg_w(gspca_dev, 0x0c, 0x003a);
6738 reg_w(gspca_dev, 0x0b, 0x0039);
6739 if (sd->sensor == SENSOR_HV7131R)
6740 reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN);
6741 break;
6742 }
6743
6744 setmatrix(gspca_dev);
6745 switch (sd->sensor) {
6746 case SENSOR_ADCM2700:
6747 case SENSOR_OV7620:
6748 reg_r(gspca_dev, 0x0008);
6749 reg_w(gspca_dev, 0x00, 0x0008);
6750 break;
6751 case SENSOR_PAS202B:
6752 case SENSOR_GC0305:
6753 case SENSOR_HV7131R:
6754 case SENSOR_TAS5130C:
6755 reg_r(gspca_dev, 0x0008);
6756 /* fall thru */
6757 case SENSOR_PO2030:
6758 reg_w(gspca_dev, 0x03, 0x0008);
6759 break;
6760 }
6761 setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
6762
6763 /* set the gamma tables when not set */
6764 switch (sd->sensor) {
6765 case SENSOR_CS2102K: /* gamma set in xxx_Initial */
6766 case SENSOR_HDCS2020:
6767 case SENSOR_OV7630C:
6768 break;
6769 default:
6770 setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma),
6771 v4l2_ctrl_g_ctrl(sd->brightness),
6772 v4l2_ctrl_g_ctrl(sd->contrast));
6773 break;
6774 }
6775 setmatrix(gspca_dev); /* one more time? */
6776 switch (sd->sensor) {
6777 case SENSOR_OV7620:
6778 case SENSOR_PAS202B:
6779 reg_r(gspca_dev, 0x0180); /* from win */
6780 reg_w(gspca_dev, 0x00, 0x0180);
6781 break;
6782 }
6783 setquality(gspca_dev);
6784 /* Start with BRC disabled, transfer_update will enable it if needed */
6785 reg_w(gspca_dev, 0x00, 0x0007);
6786 if (sd->plfreq)
6787 setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
6788
6789 switch (sd->sensor) {
6790 case SENSOR_ADCM2700:
6791 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6792 reg_w(gspca_dev, 0x15, 0x01ae);
6793 reg_w(gspca_dev, 0x02, 0x0180);
6794 /* ms-win + */
6795 reg_w(gspca_dev, 0x40, 0x0117);
6796 break;
6797 case SENSOR_HV7131R:
6798 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
6799 reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
6800 break;
6801 case SENSOR_GC0305:
6802 case SENSOR_TAS5130C:
6803 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6804 reg_w(gspca_dev, 0x15, 0x01ae);
6805 /* fall thru */
6806 case SENSOR_PAS202B:
6807 case SENSOR_PO2030:
6808/* reg_w(gspca_dev, 0x40, ZC3XX_R117_GGAIN); in win traces */
6809 reg_r(gspca_dev, 0x0180);
6810 break;
6811 case SENSOR_OV7620:
6812 reg_w(gspca_dev, 0x09, 0x01ad);
6813 reg_w(gspca_dev, 0x15, 0x01ae);
6814 i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */
6815 i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
6816 /*fixme: returned value to send? */
6817 reg_w(gspca_dev, 0x40, 0x0117);
6818 reg_r(gspca_dev, 0x0180);
6819 break;
6820 }
6821
6822 setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
6823
6824 if (gspca_dev->usb_err < 0)
6825 return gspca_dev->usb_err;
6826
6827 /* Start the transfer parameters update thread */
6828 sd->work_thread = create_singlethread_workqueue(KBUILD_MODNAME);
6829 queue_work(sd->work_thread, &sd->work);
6830
6831 return 0;
6832}
6833
6834/* called on streamoff with alt 0 and on disconnect */
6835static void sd_stop0(struct gspca_dev *gspca_dev)
6836{
6837 struct sd *sd = (struct sd *) gspca_dev;
6838
6839 if (sd->work_thread != NULL) {
6840 mutex_unlock(&gspca_dev->usb_lock);
6841 destroy_workqueue(sd->work_thread);
6842 mutex_lock(&gspca_dev->usb_lock);
6843 sd->work_thread = NULL;
6844 }
6845 if (!gspca_dev->dev)
6846 return;
6847 send_unknown(gspca_dev, sd->sensor);
6848}
6849
6850static void sd_pkt_scan(struct gspca_dev *gspca_dev,
6851 u8 *data,
6852 int len)
6853{
6854 struct sd *sd = (struct sd *) gspca_dev;
6855
6856 /* check the JPEG end of frame */
6857 if (len >= 3
6858 && data[len - 3] == 0xff && data[len - 2] == 0xd9) {
6859/*fixme: what does the last byte mean?*/
6860 gspca_frame_add(gspca_dev, LAST_PACKET,
6861 data, len - 1);
6862 return;
6863 }
6864
6865 /* check the JPEG start of a frame */
6866 if (data[0] == 0xff && data[1] == 0xd8) {
6867 /* put the JPEG header in the new frame */
6868 gspca_frame_add(gspca_dev, FIRST_PACKET,
6869 sd->jpeg_hdr, JPEG_HDR_SZ);
6870
6871 /* remove the webcam's header:
6872 * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
6873 * - 'ss ss' is the frame sequence number (BE)
6874 * - 'ww ww' and 'hh hh' are the window dimensions (BE)
6875 * - 'pp pp' is the packet sequence number (BE)
6876 */
6877 data += 18;
6878 len -= 18;
6879 }
6880 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6881}
6882
6883static int sd_set_jcomp(struct gspca_dev *gspca_dev,
6884 struct v4l2_jpegcompression *jcomp)
6885{
6886 struct sd *sd = (struct sd *) gspca_dev;
6887 int ret;
6888
6889 ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
6890 if (ret)
6891 return ret;
6892 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
6893 return 0;
6894}
6895
6896static int sd_get_jcomp(struct gspca_dev *gspca_dev,
6897 struct v4l2_jpegcompression *jcomp)
6898{
6899 struct sd *sd = (struct sd *) gspca_dev;
6900
6901 memset(jcomp, 0, sizeof *jcomp);
6902 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
6903 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
6904 | V4L2_JPEG_MARKER_DQT;
6905 return 0;
6906}
6907
6908#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
6909static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
6910 u8 *data, /* interrupt packet data */
6911 int len) /* interrput packet length */
6912{
6913 if (len == 8 && data[4] == 1) {
6914 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
6915 input_sync(gspca_dev->input_dev);
6916 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
6917 input_sync(gspca_dev->input_dev);
6918 }
6919
6920 return 0;
6921}
6922#endif
6923
6924static const struct sd_desc sd_desc = {
6925 .name = KBUILD_MODNAME,
6926 .config = sd_config,
6927 .init = sd_init,
6928 .init_controls = sd_init_controls,
6929 .isoc_init = sd_pre_start,
6930 .start = sd_start,
6931 .stop0 = sd_stop0,
6932 .pkt_scan = sd_pkt_scan,
6933 .get_jcomp = sd_get_jcomp,
6934 .set_jcomp = sd_set_jcomp,
6935#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
6936 .int_pkt_scan = sd_int_pkt_scan,
6937#endif
6938};
6939
6940static const struct usb_device_id device_table[] = {
6941 {USB_DEVICE(0x03f0, 0x1b07)},
6942 {USB_DEVICE(0x041e, 0x041e)},
6943 {USB_DEVICE(0x041e, 0x4017)},
6944 {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
6945 {USB_DEVICE(0x041e, 0x401e)},
6946 {USB_DEVICE(0x041e, 0x401f)},
6947 {USB_DEVICE(0x041e, 0x4022)},
6948 {USB_DEVICE(0x041e, 0x4029)},
6949 {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
6950 {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
6951 {USB_DEVICE(0x041e, 0x4036)},
6952 {USB_DEVICE(0x041e, 0x403a)},
6953 {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303},
6954 {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303},
6955 {USB_DEVICE(0x0458, 0x7007)},
6956 {USB_DEVICE(0x0458, 0x700c)},
6957 {USB_DEVICE(0x0458, 0x700f)},
6958 {USB_DEVICE(0x0461, 0x0a00)},
6959 {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB},
6960 {USB_DEVICE(0x046d, 0x08a0)},
6961 {USB_DEVICE(0x046d, 0x08a1)},
6962 {USB_DEVICE(0x046d, 0x08a2)},
6963 {USB_DEVICE(0x046d, 0x08a3)},
6964 {USB_DEVICE(0x046d, 0x08a6)},
6965 {USB_DEVICE(0x046d, 0x08a7)},
6966 {USB_DEVICE(0x046d, 0x08a9)},
6967 {USB_DEVICE(0x046d, 0x08aa)},
6968 {USB_DEVICE(0x046d, 0x08ac)},
6969 {USB_DEVICE(0x046d, 0x08ad)},
6970 {USB_DEVICE(0x046d, 0x08ae)},
6971 {USB_DEVICE(0x046d, 0x08af)},
6972 {USB_DEVICE(0x046d, 0x08b9)},
6973 {USB_DEVICE(0x046d, 0x08d7)},
6974 {USB_DEVICE(0x046d, 0x08d8)},
6975 {USB_DEVICE(0x046d, 0x08d9)},
6976 {USB_DEVICE(0x046d, 0x08da)},
6977 {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
6978 {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
6979 {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
6980 {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
6981 {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
6982 {USB_DEVICE(0x055f, 0xc005)},
6983 {USB_DEVICE(0x055f, 0xd003)},
6984 {USB_DEVICE(0x055f, 0xd004)},
6985 {USB_DEVICE(0x0698, 0x2003)},
6986 {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
6987 {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106},
6988 {USB_DEVICE(0x0ac8, 0x301b)},
6989 {USB_DEVICE(0x0ac8, 0x303b)},
6990 {USB_DEVICE(0x0ac8, 0x305b)},
6991 {USB_DEVICE(0x0ac8, 0x307b)},
6992 {USB_DEVICE(0x10fd, 0x0128)},
6993 {USB_DEVICE(0x10fd, 0x804d)},
6994 {USB_DEVICE(0x10fd, 0x8050)},
6995 {} /* end of entry */
6996};
6997MODULE_DEVICE_TABLE(usb, device_table);
6998
6999/* -- device connect -- */
7000static int sd_probe(struct usb_interface *intf,
7001 const struct usb_device_id *id)
7002{
7003 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
7004 THIS_MODULE);
7005}
7006
7007/* USB driver */
7008static struct usb_driver sd_driver = {
7009 .name = KBUILD_MODNAME,
7010 .id_table = device_table,
7011 .probe = sd_probe,
7012 .disconnect = gspca_disconnect,
7013#ifdef CONFIG_PM
7014 .suspend = gspca_suspend,
7015 .resume = gspca_resume,
7016 .reset_resume = gspca_resume,
7017#endif
7018};
7019
7020module_usb_driver(sd_driver);
7021
7022module_param(force_sensor, int, 0644);
7023MODULE_PARM_DESC(force_sensor,
7024 "Force sensor. Only for experts!!!");