aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r--drivers/media/video/gspca/Kconfig405
-rw-r--r--drivers/media/video/gspca/Makefile89
-rw-r--r--drivers/media/video/gspca/autogain_functions.h179
-rw-r--r--drivers/media/video/gspca/benq.c315
-rw-r--r--drivers/media/video/gspca/conex.c1079
-rw-r--r--drivers/media/video/gspca/cpia1.c2145
-rw-r--r--drivers/media/video/gspca/etoms.c908
-rw-r--r--drivers/media/video/gspca/finepix.c303
-rw-r--r--drivers/media/video/gspca/gl860/Kconfig8
-rw-r--r--drivers/media/video/gspca/gl860/Makefile10
-rw-r--r--drivers/media/video/gspca/gl860/gl860-mi1320.c536
-rw-r--r--drivers/media/video/gspca/gl860/gl860-mi2020.c733
-rw-r--r--drivers/media/video/gspca/gl860/gl860-ov2640.c489
-rw-r--r--drivers/media/video/gspca/gl860/gl860-ov9655.c336
-rw-r--r--drivers/media/video/gspca/gl860/gl860.c735
-rw-r--r--drivers/media/video/gspca/gl860/gl860.h105
-rw-r--r--drivers/media/video/gspca/gspca.c2499
-rw-r--r--drivers/media/video/gspca/gspca.h244
-rw-r--r--drivers/media/video/gspca/jeilinj.c601
-rw-r--r--drivers/media/video/gspca/jpeg.h168
-rw-r--r--drivers/media/video/gspca/kinect.c429
-rw-r--r--drivers/media/video/gspca/konica.c646
-rw-r--r--drivers/media/video/gspca/m5602/Kconfig11
-rw-r--r--drivers/media/video/gspca/m5602/Makefile11
-rw-r--r--drivers/media/video/gspca/m5602/m5602_bridge.h163
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c434
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.c645
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.h271
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.c487
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.h260
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.c880
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h307
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.c762
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.h272
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c721
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.h283
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c601
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.h193
-rw-r--r--drivers/media/video/gspca/m5602/m5602_sensor.h70
-rw-r--r--drivers/media/video/gspca/mars.c529
-rw-r--r--drivers/media/video/gspca/mr97310a.c1271
-rw-r--r--drivers/media/video/gspca/nw80x.c2145
-rw-r--r--drivers/media/video/gspca/ov519.c5072
-rw-r--r--drivers/media/video/gspca/ov534.c1546
-rw-r--r--drivers/media/video/gspca/ov534_9.c1469
-rw-r--r--drivers/media/video/gspca/pac207.c581
-rw-r--r--drivers/media/video/gspca/pac7302.c1233
-rw-r--r--drivers/media/video/gspca/pac7311.c881
-rw-r--r--drivers/media/video/gspca/pac_common.h134
-rw-r--r--drivers/media/video/gspca/se401.c774
-rw-r--r--drivers/media/video/gspca/se401.h90
-rw-r--r--drivers/media/video/gspca/sn9c2028.c750
-rw-r--r--drivers/media/video/gspca/sn9c2028.h51
-rw-r--r--drivers/media/video/gspca/sn9c20x.c2566
-rw-r--r--drivers/media/video/gspca/sonixb.c1541
-rw-r--r--drivers/media/video/gspca/sonixj.c3119
-rw-r--r--drivers/media/video/gspca/spca1528.c598
-rw-r--r--drivers/media/video/gspca/spca500.c1104
-rw-r--r--drivers/media/video/gspca/spca501.c2200
-rw-r--r--drivers/media/video/gspca/spca505.c827
-rw-r--r--drivers/media/video/gspca/spca506.c734
-rw-r--r--drivers/media/video/gspca/spca508.c1556
-rw-r--r--drivers/media/video/gspca/spca561.c1118
-rw-r--r--drivers/media/video/gspca/sq905.c448
-rw-r--r--drivers/media/video/gspca/sq905c.c354
-rw-r--r--drivers/media/video/gspca/sq930x.c1208
-rw-r--r--drivers/media/video/gspca/stk014.c531
-rw-r--r--drivers/media/video/gspca/stv0680.c367
-rw-r--r--drivers/media/video/gspca/stv06xx/Kconfig9
-rw-r--r--drivers/media/video/gspca/stv06xx/Makefile10
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.c630
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.h115
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c611
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h207
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c573
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h152
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_sensor.h87
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_st6422.c401
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_st6422.h52
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c392
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h259
-rw-r--r--drivers/media/video/gspca/sunplus.c1223
-rw-r--r--drivers/media/video/gspca/t613.c1450
-rw-r--r--drivers/media/video/gspca/tv8532.c433
-rw-r--r--drivers/media/video/gspca/vc032x.c4243
-rw-r--r--drivers/media/video/gspca/vicam.c381
-rw-r--r--drivers/media/video/gspca/w996Xcf.c558
-rw-r--r--drivers/media/video/gspca/xirlink_cit.c3337
-rw-r--r--drivers/media/video/gspca/zc3xx-reg.h251
-rw-r--r--drivers/media/video/gspca/zc3xx.c7065
90 files changed, 76569 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
new file mode 100644
index 00000000000..43d9a20caeb
--- /dev/null
+++ b/drivers/media/video/gspca/Kconfig
@@ -0,0 +1,405 @@
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/video/gspca/m5602/Kconfig"
21source "drivers/media/video/gspca/stv06xx/Kconfig"
22source "drivers/media/video/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_KINECT
81 tristate "Kinect sensor device USB Camera Driver"
82 depends on VIDEO_V4L2 && USB_GSPCA
83 help
84 Say Y here if you want support for the Microsoft Kinect sensor device.
85
86 To compile this driver as a module, choose M here: the
87 module will be called gspca_kinect.
88
89config USB_GSPCA_KONICA
90 tristate "Konica USB Camera V4L2 driver"
91 depends on VIDEO_V4L2 && USB_GSPCA
92 help
93 Say Y here if you want support for cameras based on the Konica chip.
94
95 To compile this driver as a module, choose M here: the
96 module will be called gspca_konica.
97
98config USB_GSPCA_MARS
99 tristate "Mars USB Camera Driver"
100 depends on VIDEO_V4L2 && USB_GSPCA
101 help
102 Say Y here if you want support for cameras based on the Mars chip.
103
104 To compile this driver as a module, choose M here: the
105 module will be called gspca_mars.
106
107config USB_GSPCA_MR97310A
108 tristate "Mars-Semi MR97310A USB Camera Driver"
109 depends on VIDEO_V4L2 && USB_GSPCA
110 help
111 Say Y here if you want support for cameras based on the MR97310A chip.
112
113 To compile this driver as a module, choose M here: the
114 module will be called gspca_mr97310a.
115
116config USB_GSPCA_NW80X
117 tristate "Divio based (NW80x) USB Camera Driver"
118 depends on VIDEO_V4L2 && USB_GSPCA
119 help
120 Say Y here if you want support for cameras based on the NW80x chips.
121
122 To compile this driver as a module, choose M here: the
123 module will be called gspca_nw80x.
124
125config USB_GSPCA_OV519
126 tristate "OV51x / OVFX2 / W996xCF USB Camera Driver"
127 depends on VIDEO_V4L2 && USB_GSPCA
128 help
129 Say Y here if you want support for cameras based on one of these:
130 OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF
131
132 To compile this driver as a module, choose M here: the
133 module will be called gspca_ov519.
134
135config USB_GSPCA_OV534
136 tristate "OV534 OV772x USB Camera Driver"
137 depends on VIDEO_V4L2 && USB_GSPCA
138 help
139 Say Y here if you want support for cameras based on the OV534 chip
140 and sensor OV772x (e.g. Sony Playstation EYE)
141
142 To compile this driver as a module, choose M here: the
143 module will be called gspca_ov534.
144
145config USB_GSPCA_OV534_9
146 tristate "OV534 OV965x 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 OV965x (e.g. Hercules Dualpix)
151
152 To compile this driver as a module, choose M here: the
153 module will be called gspca_ov534_9.
154
155config USB_GSPCA_PAC207
156 tristate "Pixart PAC207 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 PAC207 chip.
160
161 To compile this driver as a module, choose M here: the
162 module will be called gspca_pac207.
163
164config USB_GSPCA_PAC7302
165 tristate "Pixart PAC7302 USB Camera Driver"
166 depends on VIDEO_V4L2 && USB_GSPCA
167 help
168 Say Y here if you want support for cameras based on the PAC7302 chip.
169
170 To compile this driver as a module, choose M here: the
171 module will be called gspca_pac7302.
172
173config USB_GSPCA_PAC7311
174 tristate "Pixart PAC7311 USB Camera Driver"
175 depends on VIDEO_V4L2 && USB_GSPCA
176 help
177 Say Y here if you want support for cameras based on the PAC7311 chip.
178
179 To compile this driver as a module, choose M here: the
180 module will be called gspca_pac7311.
181
182config USB_GSPCA_SE401
183 tristate "SE401 USB Camera Driver"
184 depends on VIDEO_V4L2 && USB_GSPCA
185 help
186 Say Y here if you want support for cameras based on the
187 Endpoints (formerly known as AOX) se401 chip.
188
189 To compile this driver as a module, choose M here: the
190 module will be called gspca_se401.
191
192config USB_GSPCA_SN9C2028
193 tristate "SONIX Dual-Mode USB Camera Driver"
194 depends on VIDEO_V4L2 && USB_GSPCA
195 help
196 Say Y here if you want streaming support for Sonix SN9C2028 cameras.
197 These are supported as stillcams in libgphoto2/camlibs/sonix.
198
199 To compile this driver as a module, choose M here: the
200 module will be called gspca_sn9c2028.
201
202config USB_GSPCA_SN9C20X
203 tristate "SN9C20X USB Camera Driver"
204 depends on VIDEO_V4L2 && USB_GSPCA
205 help
206 Say Y here if you want support for cameras based on the
207 sn9c20x chips (SN9C201 and SN9C202).
208
209 To compile this driver as a module, choose M here: the
210 module will be called gspca_sn9c20x.
211
212config USB_GSPCA_SONIXB
213 tristate "SONIX Bayer 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 Sonix
217 chips with Bayer format (SN9C101, SN9C102 and SN9C103).
218
219 To compile this driver as a module, choose M here: the
220 module will be called gspca_sonixb.
221
222config USB_GSPCA_SONIXJ
223 tristate "SONIX JPEG 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 JPEG format (SN9C102P, SN9C105 and >= SN9C110).
228
229 To compile this driver as a module, choose M here: the
230 module will be called gspca_sonixj
231
232config USB_GSPCA_SPCA500
233 tristate "SPCA500 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 SPCA500 chip.
237
238 To compile this driver as a module, choose M here: the
239 module will be called gspca_spca500.
240
241config USB_GSPCA_SPCA501
242 tristate "SPCA501 USB Camera Driver"
243 depends on VIDEO_V4L2 && USB_GSPCA
244 help
245 Say Y here if you want support for cameras based on the SPCA501 chip.
246
247 To compile this driver as a module, choose M here: the
248 module will be called gspca_spca501.
249
250config USB_GSPCA_SPCA505
251 tristate "SPCA505 USB Camera Driver"
252 depends on VIDEO_V4L2 && USB_GSPCA
253 help
254 Say Y here if you want support for cameras based on the SPCA505 chip.
255
256 To compile this driver as a module, choose M here: the
257 module will be called gspca_spca505.
258
259config USB_GSPCA_SPCA506
260 tristate "SPCA506 USB Camera Driver"
261 depends on VIDEO_V4L2 && USB_GSPCA
262 help
263 Say Y here if you want support for cameras based on the SPCA506 chip.
264
265 To compile this driver as a module, choose M here: the
266 module will be called gspca_spca506.
267
268config USB_GSPCA_SPCA508
269 tristate "SPCA508 USB Camera Driver"
270 depends on VIDEO_V4L2 && USB_GSPCA
271 help
272 Say Y here if you want support for cameras based on the SPCA508 chip.
273
274 To compile this driver as a module, choose M here: the
275 module will be called gspca_spca508.
276
277config USB_GSPCA_SPCA561
278 tristate "SPCA561 USB Camera Driver"
279 depends on VIDEO_V4L2 && USB_GSPCA
280 help
281 Say Y here if you want support for cameras based on the SPCA561 chip.
282
283 To compile this driver as a module, choose M here: the
284 module will be called gspca_spca561.
285
286config USB_GSPCA_SPCA1528
287 tristate "SPCA1528 USB Camera Driver"
288 depends on VIDEO_V4L2 && USB_GSPCA
289 help
290 Say Y here if you want support for cameras based on the SPCA1528 chip.
291
292 To compile this driver as a module, choose M here: the
293 module will be called gspca_spca1528.
294
295config USB_GSPCA_SQ905
296 tristate "SQ Technologies SQ905 based USB Camera Driver"
297 depends on VIDEO_V4L2 && USB_GSPCA
298 help
299 Say Y here if you want support for cameras based on the SQ905 chip.
300
301 To compile this driver as a module, choose M here: the
302 module will be called gspca_sq905.
303
304config USB_GSPCA_SQ905C
305 tristate "SQ Technologies SQ905C based USB Camera Driver"
306 depends on VIDEO_V4L2 && USB_GSPCA
307 help
308 Say Y here if you want support for cameras based on the SQ905C chip.
309
310 To compile this driver as a module, choose M here: the
311 module will be called gspca_sq905c.
312
313config USB_GSPCA_SQ930X
314 tristate "SQ Technologies SQ930X based USB Camera Driver"
315 depends on VIDEO_V4L2 && USB_GSPCA
316 help
317 Say Y here if you want support for cameras based on the SQ930X chip.
318
319 To compile this driver as a module, choose M here: the
320 module will be called gspca_sq930x.
321
322config USB_GSPCA_STK014
323 tristate "Syntek DV4000 (STK014) USB Camera Driver"
324 depends on VIDEO_V4L2 && USB_GSPCA
325 help
326 Say Y here if you want support for cameras based on the STK014 chip.
327
328 To compile this driver as a module, choose M here: the
329 module will be called gspca_stk014.
330
331config USB_GSPCA_STV0680
332 tristate "STV0680 USB Camera Driver"
333 depends on VIDEO_V4L2 && USB_GSPCA
334 help
335 Say Y here if you want support for cameras based on the STV0680 chip.
336
337 To compile this driver as a module, choose M here: the
338 module will be called gspca_stv0680.
339
340config USB_GSPCA_SUNPLUS
341 tristate "SUNPLUS USB Camera Driver"
342 depends on VIDEO_V4L2 && USB_GSPCA
343 help
344 Say Y here if you want support for cameras based on the Sunplus
345 SPCA504(abc) SPCA533 SPCA536 chips.
346
347 To compile this driver as a module, choose M here: the
348 module will be called gspca_sunplus.
349
350config USB_GSPCA_T613
351 tristate "T613 (JPEG Compliance) 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 T613 chip.
355
356 To compile this driver as a module, choose M here: the
357 module will be called gspca_t613.
358
359config USB_GSPCA_TV8532
360 tristate "TV8532 USB Camera Driver"
361 depends on VIDEO_V4L2 && USB_GSPCA
362 help
363 Say Y here if you want support for cameras based on the TV8531 chip.
364
365 To compile this driver as a module, choose M here: the
366 module will be called gspca_tv8532.
367
368config USB_GSPCA_VC032X
369 tristate "VC032X USB Camera Driver"
370 depends on VIDEO_V4L2 && USB_GSPCA
371 help
372 Say Y here if you want support for cameras based on the VC032X chip.
373
374 To compile this driver as a module, choose M here: the
375 module will be called gspca_vc032x.
376
377config USB_GSPCA_VICAM
378 tristate "ViCam USB Camera Driver"
379 depends on VIDEO_V4L2 && USB_GSPCA
380 help
381 Say Y here if you want support for the 3com homeconnect camera
382 (vicam).
383
384 To compile this driver as a module, choose M here: the
385 module will be called gspca_vicam.
386
387config USB_GSPCA_XIRLINK_CIT
388 tristate "Xirlink C-It USB Camera Driver"
389 depends on VIDEO_V4L2 && USB_GSPCA
390 help
391 Say Y here if you want support for Xirlink C-It bases cameras.
392
393 To compile this driver as a module, choose M here: the
394 module will be called gspca_xirlink_cit.
395
396config USB_GSPCA_ZC3XX
397 tristate "ZC3XX USB Camera Driver"
398 depends on VIDEO_V4L2 && USB_GSPCA
399 help
400 Say Y here if you want support for cameras based on the ZC3XX chip.
401
402 To compile this driver as a module, choose M here: the
403 module will be called gspca_zc3xx.
404
405endif
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
new file mode 100644
index 00000000000..d6364a86333
--- /dev/null
+++ b/drivers/media/video/gspca/Makefile
@@ -0,0 +1,89 @@
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_KINECT) += gspca_kinect.o
9obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o
10obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
11obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
12obj-$(CONFIG_USB_GSPCA_NW80X) += gspca_nw80x.o
13obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
14obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o
15obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o
16obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
17obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o
18obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
19obj-$(CONFIG_USB_GSPCA_SE401) += gspca_se401.o
20obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
21obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
22obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
23obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
24obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
25obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o
26obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o
27obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
28obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
29obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
30obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o
31obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o
32obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o
33obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o
34obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
35obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
36obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o
37obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
38obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o
39obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
40obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o
41obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o
42obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o
43
44gspca_main-objs := gspca.o
45gspca_benq-objs := benq.o
46gspca_conex-objs := conex.o
47gspca_cpia1-objs := cpia1.o
48gspca_etoms-objs := etoms.o
49gspca_finepix-objs := finepix.o
50gspca_jeilinj-objs := jeilinj.o
51gspca_kinect-objs := kinect.o
52gspca_konica-objs := konica.o
53gspca_mars-objs := mars.o
54gspca_mr97310a-objs := mr97310a.o
55gspca_nw80x-objs := nw80x.o
56gspca_ov519-objs := ov519.o
57gspca_ov534-objs := ov534.o
58gspca_ov534_9-objs := ov534_9.o
59gspca_pac207-objs := pac207.o
60gspca_pac7302-objs := pac7302.o
61gspca_pac7311-objs := pac7311.o
62gspca_se401-objs := se401.o
63gspca_sn9c2028-objs := sn9c2028.o
64gspca_sn9c20x-objs := sn9c20x.o
65gspca_sonixb-objs := sonixb.o
66gspca_sonixj-objs := sonixj.o
67gspca_spca500-objs := spca500.o
68gspca_spca501-objs := spca501.o
69gspca_spca505-objs := spca505.o
70gspca_spca506-objs := spca506.o
71gspca_spca508-objs := spca508.o
72gspca_spca561-objs := spca561.o
73gspca_spca1528-objs := spca1528.o
74gspca_sq905-objs := sq905.o
75gspca_sq905c-objs := sq905c.o
76gspca_sq930x-objs := sq930x.o
77gspca_stk014-objs := stk014.o
78gspca_stv0680-objs := stv0680.o
79gspca_sunplus-objs := sunplus.o
80gspca_t613-objs := t613.o
81gspca_tv8532-objs := tv8532.o
82gspca_vc032x-objs := vc032x.o
83gspca_vicam-objs := vicam.o
84gspca_xirlink_cit-objs := xirlink_cit.o
85gspca_zc3xx-objs := zc3xx.o
86
87obj-$(CONFIG_USB_M5602) += m5602/
88obj-$(CONFIG_USB_STV06XX) += stv06xx/
89obj-$(CONFIG_USB_GL860) += gl860/
diff --git a/drivers/media/video/gspca/autogain_functions.h b/drivers/media/video/gspca/autogain_functions.h
new file mode 100644
index 00000000000..46777eee678
--- /dev/null
+++ b/drivers/media/video/gspca/autogain_functions.h
@@ -0,0 +1,179 @@
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/* auto gain and exposure algorithm based on the knee algorithm described here:
22 http://ytse.tricolour.net/docs/LowLightOptimization.html
23
24 Returns 0 if no changes were made, 1 if the gain and or exposure settings
25 where changed. */
26static inline int auto_gain_n_exposure(
27 struct gspca_dev *gspca_dev,
28 int avg_lum,
29 int desired_avg_lum,
30 int deadzone,
31 int gain_knee,
32 int exposure_knee)
33{
34 struct sd *sd = (struct sd *) gspca_dev;
35 int i, steps, gain, orig_gain, exposure, orig_exposure;
36 int retval = 0;
37
38 orig_gain = gain = sd->ctrls[GAIN].val;
39 orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
40
41 /* If we are of a multiple of deadzone, do multiple steps to reach the
42 desired lumination fast (with the risc of a slight overshoot) */
43 steps = abs(desired_avg_lum - avg_lum) / deadzone;
44
45 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
46 avg_lum, desired_avg_lum, steps);
47
48 for (i = 0; i < steps; i++) {
49 if (avg_lum > desired_avg_lum) {
50 if (gain > gain_knee)
51 gain--;
52 else if (exposure > exposure_knee)
53 exposure--;
54 else if (gain > sd->ctrls[GAIN].def)
55 gain--;
56 else if (exposure > sd->ctrls[EXPOSURE].min)
57 exposure--;
58 else if (gain > sd->ctrls[GAIN].min)
59 gain--;
60 else
61 break;
62 } else {
63 if (gain < sd->ctrls[GAIN].def)
64 gain++;
65 else if (exposure < exposure_knee)
66 exposure++;
67 else if (gain < gain_knee)
68 gain++;
69 else if (exposure < sd->ctrls[EXPOSURE].max)
70 exposure++;
71 else if (gain < sd->ctrls[GAIN].max)
72 gain++;
73 else
74 break;
75 }
76 }
77
78 if (gain != orig_gain) {
79 sd->ctrls[GAIN].val = gain;
80 setgain(gspca_dev);
81 retval = 1;
82 }
83 if (exposure != orig_exposure) {
84 sd->ctrls[EXPOSURE].val = exposure;
85 setexposure(gspca_dev);
86 retval = 1;
87 }
88
89 if (retval)
90 PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
91 gain, exposure);
92 return retval;
93}
94
95/* Autogain + exposure algorithm for cameras with a coarse exposure control
96 (usually this means we can only control the clockdiv to change exposure)
97 As changing the clockdiv so that the fps drops from 30 to 15 fps for
98 example, will lead to a huge exposure change (it effectively doubles),
99 this algorithm normally tries to only adjust the gain (between 40 and
100 80 %) and if that does not help, only then changes exposure. This leads
101 to a much more stable image then using the knee algorithm which at
102 certain points of the knee graph will only try to adjust exposure,
103 which leads to oscilating as one exposure step is huge.
104
105 Note this assumes that the sd struct for the cam in question has
106 exp_too_high_cnt and exp_too_high_cnt int members for use by this function.
107
108 Returns 0 if no changes were made, 1 if the gain and or exposure settings
109 where changed. */
110static inline int coarse_grained_expo_autogain(
111 struct gspca_dev *gspca_dev,
112 int avg_lum,
113 int desired_avg_lum,
114 int deadzone)
115{
116 struct sd *sd = (struct sd *) gspca_dev;
117 int steps, gain, orig_gain, exposure, orig_exposure;
118 int gain_low, gain_high;
119 int retval = 0;
120
121 orig_gain = gain = sd->ctrls[GAIN].val;
122 orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
123
124 gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2;
125 gain_low += sd->ctrls[GAIN].min;
126 gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4;
127 gain_high += sd->ctrls[GAIN].min;
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 < sd->ctrls[EXPOSURE].max) {
138 gain = gain_high;
139 sd->exp_too_low_cnt++;
140 sd->exp_too_high_cnt = 0;
141 } else if ((gain + steps) < gain_low &&
142 exposure > sd->ctrls[EXPOSURE].min) {
143 gain = gain_low;
144 sd->exp_too_high_cnt++;
145 sd->exp_too_low_cnt = 0;
146 } else {
147 gain += steps;
148 if (gain > sd->ctrls[GAIN].max)
149 gain = sd->ctrls[GAIN].max;
150 else if (gain < sd->ctrls[GAIN].min)
151 gain = sd->ctrls[GAIN].min;
152 sd->exp_too_high_cnt = 0;
153 sd->exp_too_low_cnt = 0;
154 }
155
156 if (sd->exp_too_high_cnt > 3) {
157 exposure--;
158 sd->exp_too_high_cnt = 0;
159 } else if (sd->exp_too_low_cnt > 3) {
160 exposure++;
161 sd->exp_too_low_cnt = 0;
162 }
163
164 if (gain != orig_gain) {
165 sd->ctrls[GAIN].val = gain;
166 setgain(gspca_dev);
167 retval = 1;
168 }
169 if (exposure != orig_exposure) {
170 sd->ctrls[EXPOSURE].val = exposure;
171 setexposure(gspca_dev);
172 retval = 1;
173 }
174
175 if (retval)
176 PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
177 gain, exposure);
178 return retval;
179}
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c
new file mode 100644
index 00000000000..a09c4709d61
--- /dev/null
+++ b/drivers/media/video/gspca/benq.c
@@ -0,0 +1,315 @@
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 MODULE_NAME "benq"
22
23#include "gspca.h"
24
25MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
26MODULE_DESCRIPTION("Benq DC E300 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
34/* V4L2 controls supported by the driver */
35static const struct ctrl sd_ctrls[] = {
36};
37
38static const struct v4l2_pix_format vga_mode[] = {
39 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
40 .bytesperline = 320,
41 .sizeimage = 320 * 240 * 3 / 8 + 590,
42 .colorspace = V4L2_COLORSPACE_JPEG},
43};
44
45static void sd_isoc_irq(struct urb *urb);
46
47/* -- write a register -- */
48static void reg_w(struct gspca_dev *gspca_dev,
49 u16 value, u16 index)
50{
51 struct usb_device *dev = gspca_dev->dev;
52 int ret;
53
54 if (gspca_dev->usb_err < 0)
55 return;
56 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
57 0x02,
58 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
59 value,
60 index,
61 NULL,
62 0,
63 500);
64 if (ret < 0) {
65 err("reg_w err %d", ret);
66 gspca_dev->usb_err = ret;
67 }
68}
69
70/* this function is called at probe time */
71static int sd_config(struct gspca_dev *gspca_dev,
72 const struct usb_device_id *id)
73{
74 gspca_dev->cam.cam_mode = vga_mode;
75 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
76 gspca_dev->cam.no_urb_create = 1;
77 gspca_dev->cam.reverse_alts = 1;
78 return 0;
79}
80
81/* this function is called at probe and resume time */
82static int sd_init(struct gspca_dev *gspca_dev)
83{
84 return 0;
85}
86
87static int sd_isoc_init(struct gspca_dev *gspca_dev)
88{
89 int ret;
90
91 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface,
92 gspca_dev->nbalt - 1);
93 if (ret < 0) {
94 err("usb_set_interface failed");
95 return ret;
96 }
97/* reg_w(gspca_dev, 0x0003, 0x0002); */
98 return 0;
99}
100
101/* -- start the camera -- */
102static int sd_start(struct gspca_dev *gspca_dev)
103{
104 struct urb *urb;
105 int i, n;
106
107 /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
108#if MAX_NURBS < 4
109#error "Not enough URBs in the gspca table"
110#endif
111#define SD_PKT_SZ 64
112#define SD_NPKT 32
113 for (n = 0; n < 4; n++) {
114 urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
115 if (!urb) {
116 err("usb_alloc_urb failed");
117 return -ENOMEM;
118 }
119 gspca_dev->urb[n] = urb;
120 urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
121 SD_PKT_SZ * SD_NPKT,
122 GFP_KERNEL,
123 &urb->transfer_dma);
124
125 if (urb->transfer_buffer == NULL) {
126 err("usb_alloc_coherent failed");
127 return -ENOMEM;
128 }
129 urb->dev = gspca_dev->dev;
130 urb->context = gspca_dev;
131 urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;
132 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
133 n & 1 ? 0x82 : 0x83);
134 urb->transfer_flags = URB_ISO_ASAP
135 | URB_NO_TRANSFER_DMA_MAP;
136 urb->interval = 1;
137 urb->complete = sd_isoc_irq;
138 urb->number_of_packets = SD_NPKT;
139 for (i = 0; i < SD_NPKT; i++) {
140 urb->iso_frame_desc[i].length = SD_PKT_SZ;
141 urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;
142 }
143 }
144
145 return gspca_dev->usb_err;
146}
147
148static void sd_stopN(struct gspca_dev *gspca_dev)
149{
150 reg_w(gspca_dev, 0x003c, 0x0003);
151 reg_w(gspca_dev, 0x003c, 0x0004);
152 reg_w(gspca_dev, 0x003c, 0x0005);
153 reg_w(gspca_dev, 0x003c, 0x0006);
154 reg_w(gspca_dev, 0x003c, 0x0007);
155 usb_set_interface(gspca_dev->dev, gspca_dev->iface,
156 gspca_dev->nbalt - 1);
157}
158
159static void sd_pkt_scan(struct gspca_dev *gspca_dev,
160 u8 *data, /* isoc packet */
161 int len) /* iso packet length */
162{
163 /* unused */
164}
165
166/* reception of an URB */
167static void sd_isoc_irq(struct urb *urb)
168{
169 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
170 struct urb *urb0;
171 u8 *data;
172 int i, st;
173
174 PDEBUG(D_PACK, "sd isoc irq");
175 if (!gspca_dev->streaming)
176 return;
177 if (urb->status != 0) {
178 if (urb->status == -ESHUTDOWN)
179 return; /* disconnection */
180#ifdef CONFIG_PM
181 if (gspca_dev->frozen)
182 return;
183#endif
184 err("urb status: %d", urb->status);
185 return;
186 }
187
188 /* if this is a control URN (ep 0x83), wait */
189 if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])
190 return;
191
192 /* scan both received URBs */
193 if (urb == gspca_dev->urb[1])
194 urb0 = gspca_dev->urb[0];
195 else
196 urb0 = gspca_dev->urb[2];
197 for (i = 0; i < urb->number_of_packets; i++) {
198
199 /* check the packet status and length */
200 if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
201 || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
202 PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
203 urb0->iso_frame_desc[i].actual_length,
204 urb->iso_frame_desc[i].actual_length);
205 gspca_dev->last_packet_type = DISCARD_PACKET;
206 continue;
207 }
208 st = urb0->iso_frame_desc[i].status;
209 if (st == 0)
210 st = urb->iso_frame_desc[i].status;
211 if (st) {
212 err("ISOC data error: [%d] status=%d",
213 i, st);
214 gspca_dev->last_packet_type = DISCARD_PACKET;
215 continue;
216 }
217
218 /*
219 * The images are received in URBs of different endpoints
220 * (0x83 and 0x82).
221 * Image pieces in URBs of ep 0x83 are continuated in URBs of
222 * ep 0x82 of the same index.
223 * The packets in the URBs of endpoint 0x83 start with:
224 * - 80 ba/bb 00 00 = start of image followed by 'ff d8'
225 * - 04 ba/bb oo oo = image piece
226 * where 'oo oo' is the image offset
227 (not cheked)
228 * - (other -> bad frame)
229 * The images are JPEG encoded with full header and
230 * normal ff escape.
231 * The end of image ('ff d9') may occur in any URB.
232 * (not cheked)
233 */
234 data = (u8 *) urb0->transfer_buffer
235 + urb0->iso_frame_desc[i].offset;
236 if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {
237
238 /* new image */
239 gspca_frame_add(gspca_dev, LAST_PACKET,
240 NULL, 0);
241 gspca_frame_add(gspca_dev, FIRST_PACKET,
242 data + 4, SD_PKT_SZ - 4);
243 } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {
244 gspca_frame_add(gspca_dev, INTER_PACKET,
245 data + 4, SD_PKT_SZ - 4);
246 } else {
247 gspca_dev->last_packet_type = DISCARD_PACKET;
248 continue;
249 }
250 data = (u8 *) urb->transfer_buffer
251 + urb->iso_frame_desc[i].offset;
252 gspca_frame_add(gspca_dev, INTER_PACKET,
253 data, SD_PKT_SZ);
254 }
255
256 /* resubmit the URBs */
257 st = usb_submit_urb(urb0, GFP_ATOMIC);
258 if (st < 0)
259 err("usb_submit_urb(0) ret %d", st);
260 st = usb_submit_urb(urb, GFP_ATOMIC);
261 if (st < 0)
262 err("usb_submit_urb() ret %d", st);
263}
264
265/* sub-driver description */
266static const struct sd_desc sd_desc = {
267 .name = MODULE_NAME,
268 .ctrls = sd_ctrls,
269 .nctrls = ARRAY_SIZE(sd_ctrls),
270 .config = sd_config,
271 .init = sd_init,
272 .isoc_init = sd_isoc_init,
273 .start = sd_start,
274 .stopN = sd_stopN,
275 .pkt_scan = sd_pkt_scan,
276};
277
278/* -- module initialisation -- */
279static const struct usb_device_id device_table[] = {
280 {USB_DEVICE(0x04a5, 0x3035)},
281 {}
282};
283MODULE_DEVICE_TABLE(usb, device_table);
284
285/* -- device connect -- */
286static int sd_probe(struct usb_interface *intf,
287 const struct usb_device_id *id)
288{
289 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
290 THIS_MODULE);
291}
292
293static struct usb_driver sd_driver = {
294 .name = MODULE_NAME,
295 .id_table = device_table,
296 .probe = sd_probe,
297 .disconnect = gspca_disconnect,
298#ifdef CONFIG_PM
299 .suspend = gspca_suspend,
300 .resume = gspca_resume,
301#endif
302};
303
304/* -- module insert / remove -- */
305static int __init sd_mod_init(void)
306{
307 return usb_register(&sd_driver);
308}
309static void __exit sd_mod_exit(void)
310{
311 usb_deregister(&sd_driver);
312}
313
314module_init(sd_mod_init);
315module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
new file mode 100644
index 00000000000..8b398493f96
--- /dev/null
+++ b/drivers/media/video/gspca/conex.c
@@ -0,0 +1,1079 @@
1/*
2 * Connexant Cx11646 library
3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "conex"
23
24#include "gspca.h"
25#define CONEX_CAM 1 /* special JPEG header */
26#include "jpeg.h"
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 unsigned char brightness;
37 unsigned char contrast;
38 unsigned char colors;
39 u8 quality;
40#define QUALITY_MIN 30
41#define QUALITY_MAX 60
42#define QUALITY_DEF 40
43
44 u8 jpeg_hdr[JPEG_HDR_SZ];
45};
46
47/* V4L2 controls supported by the driver */
48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
54
55static const struct ctrl sd_ctrls[] = {
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 0,
62 .maximum = 255,
63 .step = 1,
64#define BRIGHTNESS_DEF 0xd4
65 .default_value = BRIGHTNESS_DEF,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70 {
71 {
72 .id = V4L2_CID_CONTRAST,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Contrast",
75 .minimum = 0x0a,
76 .maximum = 0x1f,
77 .step = 1,
78#define CONTRAST_DEF 0x0c
79 .default_value = CONTRAST_DEF,
80 },
81 .set = sd_setcontrast,
82 .get = sd_getcontrast,
83 },
84 {
85 {
86 .id = V4L2_CID_SATURATION,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Color",
89 .minimum = 0,
90 .maximum = 7,
91 .step = 1,
92#define COLOR_DEF 3
93 .default_value = COLOR_DEF,
94 },
95 .set = sd_setcolors,
96 .get = sd_getcolors,
97 },
98};
99
100static const struct v4l2_pix_format vga_mode[] = {
101 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
102 .bytesperline = 176,
103 .sizeimage = 176 * 144 * 3 / 8 + 590,
104 .colorspace = V4L2_COLORSPACE_JPEG,
105 .priv = 3},
106 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
107 .bytesperline = 320,
108 .sizeimage = 320 * 240 * 3 / 8 + 590,
109 .colorspace = V4L2_COLORSPACE_JPEG,
110 .priv = 2},
111 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
112 .bytesperline = 352,
113 .sizeimage = 352 * 288 * 3 / 8 + 590,
114 .colorspace = V4L2_COLORSPACE_JPEG,
115 .priv = 1},
116 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117 .bytesperline = 640,
118 .sizeimage = 640 * 480 * 3 / 8 + 590,
119 .colorspace = V4L2_COLORSPACE_JPEG,
120 .priv = 0},
121};
122
123/* the read bytes are found in gspca_dev->usb_buf */
124static void reg_r(struct gspca_dev *gspca_dev,
125 __u16 index,
126 __u16 len)
127{
128 struct usb_device *dev = gspca_dev->dev;
129
130#ifdef GSPCA_DEBUG
131 if (len > USB_BUF_SZ) {
132 err("reg_r: buffer overflow");
133 return;
134 }
135#endif
136 usb_control_msg(dev,
137 usb_rcvctrlpipe(dev, 0),
138 0,
139 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
140 0,
141 index, gspca_dev->usb_buf, len,
142 500);
143 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
144 index, gspca_dev->usb_buf[0]);
145}
146
147/* the bytes to write are in gspca_dev->usb_buf */
148static void reg_w_val(struct gspca_dev *gspca_dev,
149 __u16 index,
150 __u8 val)
151{
152 struct usb_device *dev = gspca_dev->dev;
153
154 gspca_dev->usb_buf[0] = val;
155 usb_control_msg(dev,
156 usb_sndctrlpipe(dev, 0),
157 0,
158 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159 0,
160 index, gspca_dev->usb_buf, 1, 500);
161}
162
163static void reg_w(struct gspca_dev *gspca_dev,
164 __u16 index,
165 const __u8 *buffer,
166 __u16 len)
167{
168 struct usb_device *dev = gspca_dev->dev;
169
170#ifdef GSPCA_DEBUG
171 if (len > USB_BUF_SZ) {
172 err("reg_w: buffer overflow");
173 return;
174 }
175 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
176#endif
177 memcpy(gspca_dev->usb_buf, buffer, len);
178 usb_control_msg(dev,
179 usb_sndctrlpipe(dev, 0),
180 0,
181 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
182 0,
183 index, gspca_dev->usb_buf, len, 500);
184}
185
186static const __u8 cx_sensor_init[][4] = {
187 {0x88, 0x11, 0x01, 0x01},
188 {0x88, 0x12, 0x70, 0x01},
189 {0x88, 0x0f, 0x00, 0x01},
190 {0x88, 0x05, 0x01, 0x01},
191 {}
192};
193
194static const __u8 cx11646_fw1[][3] = {
195 {0x00, 0x02, 0x00},
196 {0x01, 0x43, 0x00},
197 {0x02, 0xA7, 0x00},
198 {0x03, 0x8B, 0x01},
199 {0x04, 0xE9, 0x02},
200 {0x05, 0x08, 0x04},
201 {0x06, 0x08, 0x05},
202 {0x07, 0x07, 0x06},
203 {0x08, 0xE7, 0x06},
204 {0x09, 0xC6, 0x07},
205 {0x0A, 0x86, 0x08},
206 {0x0B, 0x46, 0x09},
207 {0x0C, 0x05, 0x0A},
208 {0x0D, 0xA5, 0x0A},
209 {0x0E, 0x45, 0x0B},
210 {0x0F, 0xE5, 0x0B},
211 {0x10, 0x85, 0x0C},
212 {0x11, 0x25, 0x0D},
213 {0x12, 0xC4, 0x0D},
214 {0x13, 0x45, 0x0E},
215 {0x14, 0xE4, 0x0E},
216 {0x15, 0x64, 0x0F},
217 {0x16, 0xE4, 0x0F},
218 {0x17, 0x64, 0x10},
219 {0x18, 0xE4, 0x10},
220 {0x19, 0x64, 0x11},
221 {0x1A, 0xE4, 0x11},
222 {0x1B, 0x64, 0x12},
223 {0x1C, 0xE3, 0x12},
224 {0x1D, 0x44, 0x13},
225 {0x1E, 0xC3, 0x13},
226 {0x1F, 0x24, 0x14},
227 {0x20, 0xA3, 0x14},
228 {0x21, 0x04, 0x15},
229 {0x22, 0x83, 0x15},
230 {0x23, 0xE3, 0x15},
231 {0x24, 0x43, 0x16},
232 {0x25, 0xA4, 0x16},
233 {0x26, 0x23, 0x17},
234 {0x27, 0x83, 0x17},
235 {0x28, 0xE3, 0x17},
236 {0x29, 0x43, 0x18},
237 {0x2A, 0xA3, 0x18},
238 {0x2B, 0x03, 0x19},
239 {0x2C, 0x63, 0x19},
240 {0x2D, 0xC3, 0x19},
241 {0x2E, 0x22, 0x1A},
242 {0x2F, 0x63, 0x1A},
243 {0x30, 0xC3, 0x1A},
244 {0x31, 0x23, 0x1B},
245 {0x32, 0x83, 0x1B},
246 {0x33, 0xE2, 0x1B},
247 {0x34, 0x23, 0x1C},
248 {0x35, 0x83, 0x1C},
249 {0x36, 0xE2, 0x1C},
250 {0x37, 0x23, 0x1D},
251 {0x38, 0x83, 0x1D},
252 {0x39, 0xE2, 0x1D},
253 {0x3A, 0x23, 0x1E},
254 {0x3B, 0x82, 0x1E},
255 {0x3C, 0xC3, 0x1E},
256 {0x3D, 0x22, 0x1F},
257 {0x3E, 0x63, 0x1F},
258 {0x3F, 0xC1, 0x1F},
259 {}
260};
261static void cx11646_fw(struct gspca_dev*gspca_dev)
262{
263 int i = 0;
264
265 reg_w_val(gspca_dev, 0x006a, 0x02);
266 while (cx11646_fw1[i][1]) {
267 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
268 i++;
269 }
270 reg_w_val(gspca_dev, 0x006a, 0x00);
271}
272
273static const __u8 cxsensor[] = {
274 0x88, 0x12, 0x70, 0x01,
275 0x88, 0x0d, 0x02, 0x01,
276 0x88, 0x0f, 0x00, 0x01,
277 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
278 0x88, 0x02, 0x10, 0x01,
279 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
280 0x88, 0x0B, 0x00, 0x01,
281 0x88, 0x0A, 0x0A, 0x01,
282 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
283 0x88, 0x05, 0x01, 0x01,
284 0xA1, 0x18, 0x00, 0x01,
285 0x00
286};
287
288static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
289static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
290static const __u8 reg10[] = { 0xb1, 0xb1 };
291static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
292static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
293 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
294static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
295 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
296static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
297static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
298
299static void cx_sensor(struct gspca_dev*gspca_dev)
300{
301 int i = 0;
302 int length;
303 const __u8 *ptsensor = cxsensor;
304
305 reg_w(gspca_dev, 0x0020, reg20, 8);
306 reg_w(gspca_dev, 0x0028, reg28, 8);
307 reg_w(gspca_dev, 0x0010, reg10, 8);
308 reg_w_val(gspca_dev, 0x0092, 0x03);
309
310 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
311 case 0:
312 reg_w(gspca_dev, 0x0071, reg71a, 4);
313 break;
314 case 1:
315 reg_w(gspca_dev, 0x0071, reg71b, 4);
316 break;
317 default:
318/* case 2: */
319 reg_w(gspca_dev, 0x0071, reg71c, 4);
320 break;
321 case 3:
322 reg_w(gspca_dev, 0x0071, reg71d, 4);
323 break;
324 }
325 reg_w(gspca_dev, 0x007b, reg7b, 6);
326 reg_w_val(gspca_dev, 0x00f8, 0x00);
327 reg_w(gspca_dev, 0x0010, reg10, 8);
328 reg_w_val(gspca_dev, 0x0098, 0x41);
329 for (i = 0; i < 11; i++) {
330 if (i == 3 || i == 5 || i == 8)
331 length = 8;
332 else
333 length = 4;
334 reg_w(gspca_dev, 0x00e5, ptsensor, length);
335 if (length == 4)
336 reg_r(gspca_dev, 0x00e8, 1);
337 else
338 reg_r(gspca_dev, 0x00e8, length);
339 ptsensor += length;
340 }
341 reg_r(gspca_dev, 0x00e7, 8);
342}
343
344static const __u8 cx_inits_176[] = {
345 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
346 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
347 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
348 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
349 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
350 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
351 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
352};
353static const __u8 cx_inits_320[] = {
354 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
355 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
356 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
357 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
358 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
359 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
360 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
361};
362static const __u8 cx_inits_352[] = {
363 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
364 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
365 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
366 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
367 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
368 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
369 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
370};
371static const __u8 cx_inits_640[] = {
372 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
373 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
374 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
375 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
376 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
377 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
378 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
379};
380
381static void cx11646_initsize(struct gspca_dev *gspca_dev)
382{
383 const __u8 *cxinit;
384 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
385 static const __u8 reg17[] =
386 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
387
388 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
389 case 0:
390 cxinit = cx_inits_640;
391 break;
392 case 1:
393 cxinit = cx_inits_352;
394 break;
395 default:
396/* case 2: */
397 cxinit = cx_inits_320;
398 break;
399 case 3:
400 cxinit = cx_inits_176;
401 break;
402 }
403 reg_w_val(gspca_dev, 0x009a, 0x01);
404 reg_w_val(gspca_dev, 0x0010, 0x10);
405 reg_w(gspca_dev, 0x0012, reg12, 5);
406 reg_w(gspca_dev, 0x0017, reg17, 8);
407 reg_w_val(gspca_dev, 0x00c0, 0x00);
408 reg_w_val(gspca_dev, 0x00c1, 0x04);
409 reg_w_val(gspca_dev, 0x00c2, 0x04);
410
411 reg_w(gspca_dev, 0x0061, cxinit, 8);
412 cxinit += 8;
413 reg_w(gspca_dev, 0x00ca, cxinit, 8);
414 cxinit += 8;
415 reg_w(gspca_dev, 0x00d2, cxinit, 8);
416 cxinit += 8;
417 reg_w(gspca_dev, 0x00da, cxinit, 6);
418 cxinit += 8;
419 reg_w(gspca_dev, 0x0041, cxinit, 8);
420 cxinit += 8;
421 reg_w(gspca_dev, 0x0049, cxinit, 8);
422 cxinit += 8;
423 reg_w(gspca_dev, 0x0051, cxinit, 2);
424
425 reg_r(gspca_dev, 0x0010, 1);
426}
427
428static const __u8 cx_jpeg_init[][8] = {
429 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
430 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
431 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
432 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
433 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
434 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
435 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
436 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
437 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
438 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
439 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
440 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
441 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
442 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
443 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
444 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
445 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
446 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
447 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
448 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
449 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
450 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
451 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
452 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
453 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
454 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
455 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
456 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
457 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
458 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
459 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
460 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
461 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
462 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
463 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
464 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
465 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
466 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
467 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
468 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
469 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
470 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
471 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
472 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
473 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
474 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
475 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
476 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
477 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
478 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
479 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
480 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
481 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
482 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
483 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
484 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
485 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
486 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
487 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
488 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
489 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
490 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
491 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
492 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
493 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
494 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
495 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
496 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
497 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
498 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
499 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
500 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
501 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
502 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
503 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
504 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
505 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
506 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
507 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
508};
509
510
511static const __u8 cxjpeg_640[][8] = {
512 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
513 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
514 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
515 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
516 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
517 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
518 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
519 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
520 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
521 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
522 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
523 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
524 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
525 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
526 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
527 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
528 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
529 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
530 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
531 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
532 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
533 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
534 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
535 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
536 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
537 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
538 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
539};
540static const __u8 cxjpeg_352[][8] = {
541 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
542 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
543 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
544 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
545 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
546 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
547 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
548 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
549 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
550 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
551 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
552 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
553 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
554 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
555 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
556 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
557 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
558 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
559 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
560 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
561 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
562 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
563 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
564 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
565 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
566 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
567 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
568};
569static const __u8 cxjpeg_320[][8] = {
570 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
571 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
572 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
573 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
574 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
575 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
576 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
577 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
578 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
579 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
580 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
581 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
582 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
583 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
584 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
585 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
586 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
587 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
588 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
589 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
590 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
591 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
592 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
593 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
594 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
595 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
596 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
597};
598static const __u8 cxjpeg_176[][8] = {
599 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
600 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
601 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
602 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
603 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
604 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
605 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
606 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
607 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
608 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
609 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
610 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
611 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
612 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
613 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
614 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
615 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
616 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
617 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
618 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
619 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
620 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
621 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
622 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
623 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
624 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
625 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
626};
627/* 640 take with the zcx30x part */
628static const __u8 cxjpeg_qtable[][8] = {
629 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
630 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
631 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
632 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
633 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
634 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
635 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
636 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
637 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
638 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
639 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
640 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
641 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
642 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
644 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
645 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
646 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
647};
648
649
650static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
651{
652 int i;
653 int length;
654
655 reg_w_val(gspca_dev, 0x00c0, 0x01);
656 reg_w_val(gspca_dev, 0x00c3, 0x00);
657 reg_w_val(gspca_dev, 0x00c0, 0x00);
658 reg_r(gspca_dev, 0x0001, 1);
659 length = 8;
660 for (i = 0; i < 79; i++) {
661 if (i == 78)
662 length = 6;
663 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
664 }
665 reg_r(gspca_dev, 0x0002, 1);
666 reg_w_val(gspca_dev, 0x0055, 0x14);
667}
668
669static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
670static const __u8 regE5_8[] =
671 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
672static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
673static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
674static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
675static const __u8 reg51[] = { 0x77, 0x03 };
676#define reg70 0x03
677
678static void cx11646_jpeg(struct gspca_dev*gspca_dev)
679{
680 int i;
681 int length;
682 __u8 Reg55;
683 int retry;
684
685 reg_w_val(gspca_dev, 0x00c0, 0x01);
686 reg_w_val(gspca_dev, 0x00c3, 0x00);
687 reg_w_val(gspca_dev, 0x00c0, 0x00);
688 reg_r(gspca_dev, 0x0001, 1);
689 length = 8;
690 switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
691 case 0:
692 for (i = 0; i < 27; i++) {
693 if (i == 26)
694 length = 2;
695 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
696 }
697 Reg55 = 0x28;
698 break;
699 case 1:
700 for (i = 0; i < 27; i++) {
701 if (i == 26)
702 length = 2;
703 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
704 }
705 Reg55 = 0x16;
706 break;
707 default:
708/* case 2: */
709 for (i = 0; i < 27; i++) {
710 if (i == 26)
711 length = 2;
712 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
713 }
714 Reg55 = 0x14;
715 break;
716 case 3:
717 for (i = 0; i < 27; i++) {
718 if (i == 26)
719 length = 2;
720 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
721 }
722 Reg55 = 0x0B;
723 break;
724 }
725
726 reg_r(gspca_dev, 0x0002, 1);
727 reg_w_val(gspca_dev, 0x0055, Reg55);
728 reg_r(gspca_dev, 0x0002, 1);
729 reg_w(gspca_dev, 0x0010, reg10, 2);
730 reg_w_val(gspca_dev, 0x0054, 0x02);
731 reg_w_val(gspca_dev, 0x0054, 0x01);
732 reg_w_val(gspca_dev, 0x0000, 0x94);
733 reg_w_val(gspca_dev, 0x0053, 0xc0);
734 reg_w_val(gspca_dev, 0x00fc, 0xe1);
735 reg_w_val(gspca_dev, 0x0000, 0x00);
736 /* wait for completion */
737 retry = 50;
738 do {
739 reg_r(gspca_dev, 0x0002, 1);
740 /* 0x07 until 0x00 */
741 if (gspca_dev->usb_buf[0] == 0x00)
742 break;
743 reg_w_val(gspca_dev, 0x0053, 0x00);
744 } while (--retry);
745 if (retry == 0)
746 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
747 /* send the qtable now */
748 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
749 length = 8;
750 for (i = 0; i < 18; i++) {
751 if (i == 17)
752 length = 2;
753 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
754
755 }
756 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
757 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
758 reg_w_val(gspca_dev, 0x0054, 0x02);
759 reg_w_val(gspca_dev, 0x0054, 0x01);
760 reg_w_val(gspca_dev, 0x0000, 0x94);
761 reg_w_val(gspca_dev, 0x0053, 0xc0);
762
763 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
764 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
765 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
766 reg_w(gspca_dev, 0x0012, reg12, 5);
767 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
768 reg_r(gspca_dev, 0x00e8, 8);
769 reg_w(gspca_dev, 0x00e5, regE5a, 4);
770 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
771 reg_w_val(gspca_dev, 0x009a, 0x01);
772 reg_w(gspca_dev, 0x00e5, regE5b, 4);
773 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
774 reg_w(gspca_dev, 0x00e5, regE5c, 4);
775 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
776
777 reg_w(gspca_dev, 0x0051, reg51, 2);
778 reg_w(gspca_dev, 0x0010, reg10, 2);
779 reg_w_val(gspca_dev, 0x0070, reg70);
780}
781
782static void cx11646_init1(struct gspca_dev *gspca_dev)
783{
784 int i = 0;
785
786 reg_w_val(gspca_dev, 0x0010, 0x00);
787 reg_w_val(gspca_dev, 0x0053, 0x00);
788 reg_w_val(gspca_dev, 0x0052, 0x00);
789 reg_w_val(gspca_dev, 0x009b, 0x2f);
790 reg_w_val(gspca_dev, 0x009c, 0x10);
791 reg_r(gspca_dev, 0x0098, 1);
792 reg_w_val(gspca_dev, 0x0098, 0x40);
793 reg_r(gspca_dev, 0x0099, 1);
794 reg_w_val(gspca_dev, 0x0099, 0x07);
795 reg_w_val(gspca_dev, 0x0039, 0x40);
796 reg_w_val(gspca_dev, 0x003c, 0xff);
797 reg_w_val(gspca_dev, 0x003f, 0x1f);
798 reg_w_val(gspca_dev, 0x003d, 0x40);
799/* reg_w_val(gspca_dev, 0x003d, 0x60); */
800 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
801
802 while (cx_sensor_init[i][0]) {
803 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
804 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
805 if (i == 1) {
806 reg_w_val(gspca_dev, 0x00ed, 0x01);
807 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
808 }
809 i++;
810 }
811 reg_w_val(gspca_dev, 0x00c3, 0x00);
812}
813
814/* this function is called at probe time */
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;
820
821 cam = &gspca_dev->cam;
822 cam->cam_mode = vga_mode;
823 cam->nmodes = ARRAY_SIZE(vga_mode);
824
825 sd->brightness = BRIGHTNESS_DEF;
826 sd->contrast = CONTRAST_DEF;
827 sd->colors = COLOR_DEF;
828 sd->quality = QUALITY_DEF;
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 cx11646_init1(gspca_dev);
836 cx11646_initsize(gspca_dev);
837 cx11646_fw(gspca_dev);
838 cx_sensor(gspca_dev);
839 cx11646_jpegInit(gspca_dev);
840 return 0;
841}
842
843static int sd_start(struct gspca_dev *gspca_dev)
844{
845 struct sd *sd = (struct sd *) gspca_dev;
846
847 /* create the JPEG header */
848 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
849 0x22); /* JPEG 411 */
850 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
851
852 cx11646_initsize(gspca_dev);
853 cx11646_fw(gspca_dev);
854 cx_sensor(gspca_dev);
855 cx11646_jpeg(gspca_dev);
856 return 0;
857}
858
859/* called on streamoff with alt 0 and on disconnect */
860static void sd_stop0(struct gspca_dev *gspca_dev)
861{
862 int retry = 50;
863
864 if (!gspca_dev->present)
865 return;
866 reg_w_val(gspca_dev, 0x0000, 0x00);
867 reg_r(gspca_dev, 0x0002, 1);
868 reg_w_val(gspca_dev, 0x0053, 0x00);
869
870 while (retry--) {
871/* reg_r(gspca_dev, 0x0002, 1);*/
872 reg_r(gspca_dev, 0x0053, 1);
873 if (gspca_dev->usb_buf[0] == 0)
874 break;
875 }
876 reg_w_val(gspca_dev, 0x0000, 0x00);
877 reg_r(gspca_dev, 0x0002, 1);
878
879 reg_w_val(gspca_dev, 0x0010, 0x00);
880 reg_r(gspca_dev, 0x0033, 1);
881 reg_w_val(gspca_dev, 0x00fc, 0xe0);
882}
883
884static void sd_pkt_scan(struct gspca_dev *gspca_dev,
885 u8 *data, /* isoc packet */
886 int len) /* iso packet length */
887{
888 struct sd *sd = (struct sd *) gspca_dev;
889
890 if (data[0] == 0xff && data[1] == 0xd8) {
891
892 /* start of frame */
893 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
894
895 /* put the JPEG header in the new frame */
896 gspca_frame_add(gspca_dev, FIRST_PACKET,
897 sd->jpeg_hdr, JPEG_HDR_SZ);
898 data += 2;
899 len -= 2;
900 }
901 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
902}
903
904static void setbrightness(struct gspca_dev *gspca_dev)
905{
906 struct sd *sd = (struct sd *) gspca_dev;
907 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
908 __u8 reg51c[2];
909 __u8 bright;
910 __u8 colors;
911
912 bright = sd->brightness;
913 regE5cbx[2] = bright;
914 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
915 reg_r(gspca_dev, 0x00e8, 8);
916 reg_w(gspca_dev, 0x00e5, regE5c, 4);
917 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
918
919 colors = sd->colors;
920 reg51c[0] = 0x77;
921 reg51c[1] = colors;
922 reg_w(gspca_dev, 0x0051, reg51c, 2);
923 reg_w(gspca_dev, 0x0010, reg10, 2);
924 reg_w_val(gspca_dev, 0x0070, reg70);
925}
926
927static void setcontrast(struct gspca_dev *gspca_dev)
928{
929 struct sd *sd = (struct sd *) gspca_dev;
930 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
931/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
932 __u8 reg51c[2];
933
934 regE5acx[2] = sd->contrast;
935 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
936 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
937 reg51c[0] = 0x77;
938 reg51c[1] = sd->colors;
939 reg_w(gspca_dev, 0x0051, reg51c, 2);
940 reg_w(gspca_dev, 0x0010, reg10, 2);
941 reg_w_val(gspca_dev, 0x0070, reg70);
942}
943
944static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
945{
946 struct sd *sd = (struct sd *) gspca_dev;
947
948 sd->brightness = val;
949 if (gspca_dev->streaming)
950 setbrightness(gspca_dev);
951 return 0;
952}
953
954static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
955{
956 struct sd *sd = (struct sd *) gspca_dev;
957
958 *val = sd->brightness;
959 return 0;
960}
961
962static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
963{
964 struct sd *sd = (struct sd *) gspca_dev;
965
966 sd->contrast = val;
967 if (gspca_dev->streaming)
968 setcontrast(gspca_dev);
969 return 0;
970}
971
972static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
975
976 *val = sd->contrast;
977 return 0;
978}
979
980static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
981{
982 struct sd *sd = (struct sd *) gspca_dev;
983
984 sd->colors = val;
985 if (gspca_dev->streaming) {
986 setbrightness(gspca_dev);
987 setcontrast(gspca_dev);
988 }
989 return 0;
990}
991
992static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
993{
994 struct sd *sd = (struct sd *) gspca_dev;
995
996 *val = sd->colors;
997 return 0;
998}
999
1000static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1001 struct v4l2_jpegcompression *jcomp)
1002{
1003 struct sd *sd = (struct sd *) gspca_dev;
1004
1005 if (jcomp->quality < QUALITY_MIN)
1006 sd->quality = QUALITY_MIN;
1007 else if (jcomp->quality > QUALITY_MAX)
1008 sd->quality = QUALITY_MAX;
1009 else
1010 sd->quality = jcomp->quality;
1011 if (gspca_dev->streaming)
1012 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1013 return 0;
1014}
1015
1016static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1017 struct v4l2_jpegcompression *jcomp)
1018{
1019 struct sd *sd = (struct sd *) gspca_dev;
1020
1021 memset(jcomp, 0, sizeof *jcomp);
1022 jcomp->quality = sd->quality;
1023 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1024 | V4L2_JPEG_MARKER_DQT;
1025 return 0;
1026}
1027
1028/* sub-driver description */
1029static const struct sd_desc sd_desc = {
1030 .name = MODULE_NAME,
1031 .ctrls = sd_ctrls,
1032 .nctrls = ARRAY_SIZE(sd_ctrls),
1033 .config = sd_config,
1034 .init = sd_init,
1035 .start = sd_start,
1036 .stop0 = sd_stop0,
1037 .pkt_scan = sd_pkt_scan,
1038 .get_jcomp = sd_get_jcomp,
1039 .set_jcomp = sd_set_jcomp,
1040};
1041
1042/* -- module initialisation -- */
1043static const struct usb_device_id device_table[] = {
1044 {USB_DEVICE(0x0572, 0x0041)},
1045 {}
1046};
1047MODULE_DEVICE_TABLE(usb, device_table);
1048
1049/* -- device connect -- */
1050static int sd_probe(struct usb_interface *intf,
1051 const struct usb_device_id *id)
1052{
1053 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1054 THIS_MODULE);
1055}
1056
1057static struct usb_driver sd_driver = {
1058 .name = MODULE_NAME,
1059 .id_table = device_table,
1060 .probe = sd_probe,
1061 .disconnect = gspca_disconnect,
1062#ifdef CONFIG_PM
1063 .suspend = gspca_suspend,
1064 .resume = gspca_resume,
1065#endif
1066};
1067
1068/* -- module insert / remove -- */
1069static int __init sd_mod_init(void)
1070{
1071 return usb_register(&sd_driver);
1072}
1073static void __exit sd_mod_exit(void)
1074{
1075 usb_deregister(&sd_driver);
1076}
1077
1078module_init(sd_mod_init);
1079module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c
new file mode 100644
index 00000000000..f2a9451eea1
--- /dev/null
+++ b/drivers/media/video/gspca/cpia1.c
@@ -0,0 +1,2145 @@
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 MODULE_NAME "cpia1"
30
31#include <linux/input.h>
32#include "gspca.h"
33
34MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
35MODULE_DESCRIPTION("Vision CPiA");
36MODULE_LICENSE("GPL");
37
38/* constant value's */
39#define MAGIC_0 0x19
40#define MAGIC_1 0x68
41#define DATA_IN 0xc0
42#define DATA_OUT 0x40
43#define VIDEOSIZE_QCIF 0 /* 176x144 */
44#define VIDEOSIZE_CIF 1 /* 352x288 */
45#define SUBSAMPLE_420 0
46#define SUBSAMPLE_422 1
47#define YUVORDER_YUYV 0
48#define YUVORDER_UYVY 1
49#define NOT_COMPRESSED 0
50#define COMPRESSED 1
51#define NO_DECIMATION 0
52#define DECIMATION_ENAB 1
53#define EOI 0xff /* End Of Image */
54#define EOL 0xfd /* End Of Line */
55#define FRAME_HEADER_SIZE 64
56
57/* Image grab modes */
58#define CPIA_GRAB_SINGLE 0
59#define CPIA_GRAB_CONTINEOUS 1
60
61/* Compression parameters */
62#define CPIA_COMPRESSION_NONE 0
63#define CPIA_COMPRESSION_AUTO 1
64#define CPIA_COMPRESSION_MANUAL 2
65#define CPIA_COMPRESSION_TARGET_QUALITY 0
66#define CPIA_COMPRESSION_TARGET_FRAMERATE 1
67
68/* Return offsets for GetCameraState */
69#define SYSTEMSTATE 0
70#define GRABSTATE 1
71#define STREAMSTATE 2
72#define FATALERROR 3
73#define CMDERROR 4
74#define DEBUGFLAGS 5
75#define VPSTATUS 6
76#define ERRORCODE 7
77
78/* SystemState */
79#define UNINITIALISED_STATE 0
80#define PASS_THROUGH_STATE 1
81#define LO_POWER_STATE 2
82#define HI_POWER_STATE 3
83#define WARM_BOOT_STATE 4
84
85/* GrabState */
86#define GRAB_IDLE 0
87#define GRAB_ACTIVE 1
88#define GRAB_DONE 2
89
90/* StreamState */
91#define STREAM_NOT_READY 0
92#define STREAM_READY 1
93#define STREAM_OPEN 2
94#define STREAM_PAUSED 3
95#define STREAM_FINISHED 4
96
97/* Fatal Error, CmdError, and DebugFlags */
98#define CPIA_FLAG 1
99#define SYSTEM_FLAG 2
100#define INT_CTRL_FLAG 4
101#define PROCESS_FLAG 8
102#define COM_FLAG 16
103#define VP_CTRL_FLAG 32
104#define CAPTURE_FLAG 64
105#define DEBUG_FLAG 128
106
107/* VPStatus */
108#define VP_STATE_OK 0x00
109
110#define VP_STATE_FAILED_VIDEOINIT 0x01
111#define VP_STATE_FAILED_AECACBINIT 0x02
112#define VP_STATE_AEC_MAX 0x04
113#define VP_STATE_ACB_BMAX 0x08
114
115#define VP_STATE_ACB_RMIN 0x10
116#define VP_STATE_ACB_GMIN 0x20
117#define VP_STATE_ACB_RMAX 0x40
118#define VP_STATE_ACB_GMAX 0x80
119
120/* default (minimum) compensation values */
121#define COMP_RED 220
122#define COMP_GREEN1 214
123#define COMP_GREEN2 COMP_GREEN1
124#define COMP_BLUE 230
125
126/* exposure status */
127#define EXPOSURE_VERY_LIGHT 0
128#define EXPOSURE_LIGHT 1
129#define EXPOSURE_NORMAL 2
130#define EXPOSURE_DARK 3
131#define EXPOSURE_VERY_DARK 4
132
133#define CPIA_MODULE_CPIA (0 << 5)
134#define CPIA_MODULE_SYSTEM (1 << 5)
135#define CPIA_MODULE_VP_CTRL (5 << 5)
136#define CPIA_MODULE_CAPTURE (6 << 5)
137#define CPIA_MODULE_DEBUG (7 << 5)
138
139#define INPUT (DATA_IN << 8)
140#define OUTPUT (DATA_OUT << 8)
141
142#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
143#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
144#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
145#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
146#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
147#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
148#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
149#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
150
151#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
152#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
153#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
154#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
155#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
156#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
157#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
158#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
159#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
160#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
161#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
162#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
163#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
164
165#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
166#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
167#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
168#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
169#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
170#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
171#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
172#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
173#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
174#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
175#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
176#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
177#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
178#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
179#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
180#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
181#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
182
183#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
184#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
185#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
186#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
187#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
188#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
189#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
190#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
191#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
192#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
193#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
194#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
195#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
196#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
197#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)
198
199#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
200#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
201#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
202#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
203#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
204#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
205#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
206#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)
207
208#define ROUND_UP_EXP_FOR_FLICKER 15
209
210/* Constants for automatic frame rate adjustment */
211#define MAX_EXP 302
212#define MAX_EXP_102 255
213#define LOW_EXP 140
214#define VERY_LOW_EXP 70
215#define TC 94
216#define EXP_ACC_DARK 50
217#define EXP_ACC_LIGHT 90
218#define HIGH_COMP_102 160
219#define MAX_COMP 239
220#define DARK_TIME 3
221#define LIGHT_TIME 3
222
223#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
224 sd->params.version.firmwareRevision == (y))
225
226/* Developer's Guide Table 5 p 3-34
227 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
228static u8 flicker_jumps[2][2][4] =
229{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
230 { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
231};
232
233struct cam_params {
234 struct {
235 u8 firmwareVersion;
236 u8 firmwareRevision;
237 u8 vcVersion;
238 u8 vcRevision;
239 } version;
240 struct {
241 u16 vendor;
242 u16 product;
243 u16 deviceRevision;
244 } pnpID;
245 struct {
246 u8 vpVersion;
247 u8 vpRevision;
248 u16 cameraHeadID;
249 } vpVersion;
250 struct {
251 u8 systemState;
252 u8 grabState;
253 u8 streamState;
254 u8 fatalError;
255 u8 cmdError;
256 u8 debugFlags;
257 u8 vpStatus;
258 u8 errorCode;
259 } status;
260 struct {
261 u8 brightness;
262 u8 contrast;
263 u8 saturation;
264 } colourParams;
265 struct {
266 u8 gainMode;
267 u8 expMode;
268 u8 compMode;
269 u8 centreWeight;
270 u8 gain;
271 u8 fineExp;
272 u8 coarseExpLo;
273 u8 coarseExpHi;
274 u8 redComp;
275 u8 green1Comp;
276 u8 green2Comp;
277 u8 blueComp;
278 } exposure;
279 struct {
280 u8 balanceMode;
281 u8 redGain;
282 u8 greenGain;
283 u8 blueGain;
284 } colourBalance;
285 struct {
286 u8 divisor;
287 u8 baserate;
288 } sensorFps;
289 struct {
290 u8 gain1;
291 u8 gain2;
292 u8 gain4;
293 u8 gain8;
294 } apcor;
295 struct {
296 u8 disabled;
297 u8 flickerMode;
298 u8 coarseJump;
299 u8 allowableOverExposure;
300 } flickerControl;
301 struct {
302 u8 gain1;
303 u8 gain2;
304 u8 gain4;
305 u8 gain8;
306 } vlOffset;
307 struct {
308 u8 mode;
309 u8 decimation;
310 } compression;
311 struct {
312 u8 frTargeting;
313 u8 targetFR;
314 u8 targetQ;
315 } compressionTarget;
316 struct {
317 u8 yThreshold;
318 u8 uvThreshold;
319 } yuvThreshold;
320 struct {
321 u8 hysteresis;
322 u8 threshMax;
323 u8 smallStep;
324 u8 largeStep;
325 u8 decimationHysteresis;
326 u8 frDiffStepThresh;
327 u8 qDiffStepThresh;
328 u8 decimationThreshMod;
329 } compressionParams;
330 struct {
331 u8 videoSize; /* CIF/QCIF */
332 u8 subSample;
333 u8 yuvOrder;
334 } format;
335 struct { /* Intel QX3 specific data */
336 u8 qx3_detected; /* a QX3 is present */
337 u8 toplight; /* top light lit , R/W */
338 u8 bottomlight; /* bottom light lit, R/W */
339 u8 button; /* snapshot button pressed (R/O) */
340 u8 cradled; /* microscope is in cradle (R/O) */
341 } qx3;
342 struct {
343 u8 colStart; /* skip first 8*colStart pixels */
344 u8 colEnd; /* finish at 8*colEnd pixels */
345 u8 rowStart; /* skip first 4*rowStart lines */
346 u8 rowEnd; /* finish at 4*rowEnd lines */
347 } roi;
348 u8 ecpTiming;
349 u8 streamStartLine;
350};
351
352/* specific webcam descriptor */
353struct sd {
354 struct gspca_dev gspca_dev; /* !! must be the first item */
355 struct cam_params params; /* camera settings */
356
357 atomic_t cam_exposure;
358 atomic_t fps;
359 int exposure_count;
360 u8 exposure_status;
361 u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */
362 u8 first_frame;
363 u8 freq;
364};
365
366/* V4L2 controls supported by the driver */
367static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
368static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
369static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
370static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
371static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
372static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
373static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
374static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
375static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val);
376static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val);
377static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val);
378static int sd_getilluminator1(struct gspca_dev *gspca_dev, __s32 *val);
379static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val);
380static int sd_getilluminator2(struct gspca_dev *gspca_dev, __s32 *val);
381
382static const struct ctrl sd_ctrls[] = {
383 {
384#define BRIGHTNESS_IDX 0
385 {
386 .id = V4L2_CID_BRIGHTNESS,
387 .type = V4L2_CTRL_TYPE_INTEGER,
388 .name = "Brightness",
389 .minimum = 0,
390 .maximum = 100,
391 .step = 1,
392#define BRIGHTNESS_DEF 50
393 .default_value = BRIGHTNESS_DEF,
394 .flags = 0,
395 },
396 .set = sd_setbrightness,
397 .get = sd_getbrightness,
398 },
399#define CONTRAST_IDX 1
400 {
401 {
402 .id = V4L2_CID_CONTRAST,
403 .type = V4L2_CTRL_TYPE_INTEGER,
404 .name = "Contrast",
405 .minimum = 0,
406 .maximum = 96,
407 .step = 8,
408#define CONTRAST_DEF 48
409 .default_value = CONTRAST_DEF,
410 },
411 .set = sd_setcontrast,
412 .get = sd_getcontrast,
413 },
414#define SATURATION_IDX 2
415 {
416 {
417 .id = V4L2_CID_SATURATION,
418 .type = V4L2_CTRL_TYPE_INTEGER,
419 .name = "Saturation",
420 .minimum = 0,
421 .maximum = 100,
422 .step = 1,
423#define SATURATION_DEF 50
424 .default_value = SATURATION_DEF,
425 },
426 .set = sd_setsaturation,
427 .get = sd_getsaturation,
428 },
429#define POWER_LINE_FREQUENCY_IDX 3
430 {
431 {
432 .id = V4L2_CID_POWER_LINE_FREQUENCY,
433 .type = V4L2_CTRL_TYPE_MENU,
434 .name = "Light frequency filter",
435 .minimum = 0,
436 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
437 .step = 1,
438#define FREQ_DEF 1
439 .default_value = FREQ_DEF,
440 },
441 .set = sd_setfreq,
442 .get = sd_getfreq,
443 },
444#define ILLUMINATORS_1_IDX 4
445 {
446 {
447 .id = V4L2_CID_ILLUMINATORS_1,
448 .type = V4L2_CTRL_TYPE_BOOLEAN,
449 .name = "Illuminator 1",
450 .minimum = 0,
451 .maximum = 1,
452 .step = 1,
453#define ILLUMINATORS_1_DEF 0
454 .default_value = ILLUMINATORS_1_DEF,
455 },
456 .set = sd_setilluminator1,
457 .get = sd_getilluminator1,
458 },
459#define ILLUMINATORS_2_IDX 5
460 {
461 {
462 .id = V4L2_CID_ILLUMINATORS_2,
463 .type = V4L2_CTRL_TYPE_BOOLEAN,
464 .name = "Illuminator 2",
465 .minimum = 0,
466 .maximum = 1,
467 .step = 1,
468#define ILLUMINATORS_2_DEF 0
469 .default_value = ILLUMINATORS_2_DEF,
470 },
471 .set = sd_setilluminator2,
472 .get = sd_getilluminator2,
473 },
474#define COMP_TARGET_IDX 6
475 {
476 {
477#define V4L2_CID_COMP_TARGET V4L2_CID_PRIVATE_BASE
478 .id = V4L2_CID_COMP_TARGET,
479 .type = V4L2_CTRL_TYPE_MENU,
480 .name = "Compression Target",
481 .minimum = 0,
482 .maximum = 1,
483 .step = 1,
484#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
485 .default_value = COMP_TARGET_DEF,
486 },
487 .set = sd_setcomptarget,
488 .get = sd_getcomptarget,
489 },
490};
491
492static const struct v4l2_pix_format mode[] = {
493 {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
494 /* The sizeimage is trial and error, as with low framerates
495 the camera will pad out usb frames, making the image
496 data larger then strictly necessary */
497 .bytesperline = 160,
498 .sizeimage = 65536,
499 .colorspace = V4L2_COLORSPACE_SRGB,
500 .priv = 3},
501 {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
502 .bytesperline = 172,
503 .sizeimage = 65536,
504 .colorspace = V4L2_COLORSPACE_SRGB,
505 .priv = 2},
506 {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
507 .bytesperline = 320,
508 .sizeimage = 262144,
509 .colorspace = V4L2_COLORSPACE_SRGB,
510 .priv = 1},
511 {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
512 .bytesperline = 352,
513 .sizeimage = 262144,
514 .colorspace = V4L2_COLORSPACE_SRGB,
515 .priv = 0},
516};
517
518/**********************************************************************
519 *
520 * General functions
521 *
522 **********************************************************************/
523
524static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
525{
526 u8 requesttype;
527 unsigned int pipe;
528 int ret, databytes = command[6] | (command[7] << 8);
529 /* Sometimes we see spurious EPIPE errors */
530 int retries = 3;
531
532 if (command[0] == DATA_IN) {
533 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
534 requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
535 } else if (command[0] == DATA_OUT) {
536 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
537 requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
538 } else {
539 PDEBUG(D_ERR, "Unexpected first byte of command: %x",
540 command[0]);
541 return -EINVAL;
542 }
543
544retry:
545 ret = usb_control_msg(gspca_dev->dev, pipe,
546 command[1],
547 requesttype,
548 command[2] | (command[3] << 8),
549 command[4] | (command[5] << 8),
550 gspca_dev->usb_buf, databytes, 1000);
551
552 if (ret < 0)
553 err("usb_control_msg %02x, error %d", command[1],
554 ret);
555
556 if (ret == -EPIPE && retries > 0) {
557 retries--;
558 goto retry;
559 }
560
561 return (ret < 0) ? ret : 0;
562}
563
564/* send an arbitrary command to the camera */
565static int do_command(struct gspca_dev *gspca_dev, u16 command,
566 u8 a, u8 b, u8 c, u8 d)
567{
568 struct sd *sd = (struct sd *) gspca_dev;
569 int ret, datasize;
570 u8 cmd[8];
571
572 switch (command) {
573 case CPIA_COMMAND_GetCPIAVersion:
574 case CPIA_COMMAND_GetPnPID:
575 case CPIA_COMMAND_GetCameraStatus:
576 case CPIA_COMMAND_GetVPVersion:
577 case CPIA_COMMAND_GetColourParams:
578 case CPIA_COMMAND_GetColourBalance:
579 case CPIA_COMMAND_GetExposure:
580 datasize = 8;
581 break;
582 case CPIA_COMMAND_ReadMCPorts:
583 case CPIA_COMMAND_ReadVCRegs:
584 datasize = 4;
585 break;
586 default:
587 datasize = 0;
588 break;
589 }
590
591 cmd[0] = command >> 8;
592 cmd[1] = command & 0xff;
593 cmd[2] = a;
594 cmd[3] = b;
595 cmd[4] = c;
596 cmd[5] = d;
597 cmd[6] = datasize;
598 cmd[7] = 0;
599
600 ret = cpia_usb_transferCmd(gspca_dev, cmd);
601 if (ret)
602 return ret;
603
604 switch (command) {
605 case CPIA_COMMAND_GetCPIAVersion:
606 sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
607 sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
608 sd->params.version.vcVersion = gspca_dev->usb_buf[2];
609 sd->params.version.vcRevision = gspca_dev->usb_buf[3];
610 break;
611 case CPIA_COMMAND_GetPnPID:
612 sd->params.pnpID.vendor =
613 gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
614 sd->params.pnpID.product =
615 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
616 sd->params.pnpID.deviceRevision =
617 gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
618 break;
619 case CPIA_COMMAND_GetCameraStatus:
620 sd->params.status.systemState = gspca_dev->usb_buf[0];
621 sd->params.status.grabState = gspca_dev->usb_buf[1];
622 sd->params.status.streamState = gspca_dev->usb_buf[2];
623 sd->params.status.fatalError = gspca_dev->usb_buf[3];
624 sd->params.status.cmdError = gspca_dev->usb_buf[4];
625 sd->params.status.debugFlags = gspca_dev->usb_buf[5];
626 sd->params.status.vpStatus = gspca_dev->usb_buf[6];
627 sd->params.status.errorCode = gspca_dev->usb_buf[7];
628 break;
629 case CPIA_COMMAND_GetVPVersion:
630 sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
631 sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
632 sd->params.vpVersion.cameraHeadID =
633 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
634 break;
635 case CPIA_COMMAND_GetColourParams:
636 sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
637 sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
638 sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
639 break;
640 case CPIA_COMMAND_GetColourBalance:
641 sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
642 sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
643 sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
644 break;
645 case CPIA_COMMAND_GetExposure:
646 sd->params.exposure.gain = gspca_dev->usb_buf[0];
647 sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
648 sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
649 sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
650 sd->params.exposure.redComp = gspca_dev->usb_buf[4];
651 sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
652 sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
653 sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
654 break;
655
656 case CPIA_COMMAND_ReadMCPorts:
657 /* test button press */
658 a = ((gspca_dev->usb_buf[1] & 0x02) == 0);
659 if (a != sd->params.qx3.button) {
660#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
661 input_report_key(gspca_dev->input_dev, KEY_CAMERA, a);
662 input_sync(gspca_dev->input_dev);
663#endif
664 sd->params.qx3.button = a;
665 }
666 if (sd->params.qx3.button) {
667 /* button pressed - unlock the latch */
668 do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
669 3, 0xdf, 0xdf, 0);
670 do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
671 3, 0xff, 0xff, 0);
672 }
673
674 /* test whether microscope is cradled */
675 sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
676 break;
677 }
678
679 return 0;
680}
681
682/* send a command to the camera with an additional data transaction */
683static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
684 u8 a, u8 b, u8 c, u8 d,
685 u8 e, u8 f, u8 g, u8 h,
686 u8 i, u8 j, u8 k, u8 l)
687{
688 u8 cmd[8];
689
690 cmd[0] = command >> 8;
691 cmd[1] = command & 0xff;
692 cmd[2] = a;
693 cmd[3] = b;
694 cmd[4] = c;
695 cmd[5] = d;
696 cmd[6] = 8;
697 cmd[7] = 0;
698 gspca_dev->usb_buf[0] = e;
699 gspca_dev->usb_buf[1] = f;
700 gspca_dev->usb_buf[2] = g;
701 gspca_dev->usb_buf[3] = h;
702 gspca_dev->usb_buf[4] = i;
703 gspca_dev->usb_buf[5] = j;
704 gspca_dev->usb_buf[6] = k;
705 gspca_dev->usb_buf[7] = l;
706
707 return cpia_usb_transferCmd(gspca_dev, cmd);
708}
709
710/* find_over_exposure
711 * Finds a suitable value of OverExposure for use with SetFlickerCtrl
712 * Some calculation is required because this value changes with the brightness
713 * set with SetColourParameters
714 *
715 * Parameters: Brightness - last brightness value set with SetColourParameters
716 *
717 * Returns: OverExposure value to use with SetFlickerCtrl
718 */
719#define FLICKER_MAX_EXPOSURE 250
720#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146
721#define FLICKER_BRIGHTNESS_CONSTANT 59
722static int find_over_exposure(int brightness)
723{
724 int MaxAllowableOverExposure, OverExposure;
725
726 MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
727 FLICKER_BRIGHTNESS_CONSTANT;
728
729 if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
730 OverExposure = MaxAllowableOverExposure;
731 else
732 OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
733
734 return OverExposure;
735}
736#undef FLICKER_MAX_EXPOSURE
737#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
738#undef FLICKER_BRIGHTNESS_CONSTANT
739
740/* initialise cam_data structure */
741static void reset_camera_params(struct gspca_dev *gspca_dev)
742{
743 struct sd *sd = (struct sd *) gspca_dev;
744 struct cam_params *params = &sd->params;
745
746 /* The following parameter values are the defaults from
747 * "Software Developer's Guide for CPiA Cameras". Any changes
748 * to the defaults are noted in comments. */
749 params->colourParams.brightness = BRIGHTNESS_DEF;
750 params->colourParams.contrast = CONTRAST_DEF;
751 params->colourParams.saturation = SATURATION_DEF;
752 params->exposure.gainMode = 4;
753 params->exposure.expMode = 2; /* AEC */
754 params->exposure.compMode = 1;
755 params->exposure.centreWeight = 1;
756 params->exposure.gain = 0;
757 params->exposure.fineExp = 0;
758 params->exposure.coarseExpLo = 185;
759 params->exposure.coarseExpHi = 0;
760 params->exposure.redComp = COMP_RED;
761 params->exposure.green1Comp = COMP_GREEN1;
762 params->exposure.green2Comp = COMP_GREEN2;
763 params->exposure.blueComp = COMP_BLUE;
764 params->colourBalance.balanceMode = 2; /* ACB */
765 params->colourBalance.redGain = 32;
766 params->colourBalance.greenGain = 6;
767 params->colourBalance.blueGain = 92;
768 params->apcor.gain1 = 0x18;
769 params->apcor.gain2 = 0x16;
770 params->apcor.gain4 = 0x24;
771 params->apcor.gain8 = 0x34;
772 params->flickerControl.flickerMode = 0;
773 params->flickerControl.disabled = 1;
774
775 params->flickerControl.coarseJump =
776 flicker_jumps[sd->mainsFreq]
777 [params->sensorFps.baserate]
778 [params->sensorFps.divisor];
779 params->flickerControl.allowableOverExposure =
780 find_over_exposure(params->colourParams.brightness);
781 params->vlOffset.gain1 = 20;
782 params->vlOffset.gain2 = 24;
783 params->vlOffset.gain4 = 26;
784 params->vlOffset.gain8 = 26;
785 params->compressionParams.hysteresis = 3;
786 params->compressionParams.threshMax = 11;
787 params->compressionParams.smallStep = 1;
788 params->compressionParams.largeStep = 3;
789 params->compressionParams.decimationHysteresis = 2;
790 params->compressionParams.frDiffStepThresh = 5;
791 params->compressionParams.qDiffStepThresh = 3;
792 params->compressionParams.decimationThreshMod = 2;
793 /* End of default values from Software Developer's Guide */
794
795 /* Set Sensor FPS to 15fps. This seems better than 30fps
796 * for indoor lighting. */
797 params->sensorFps.divisor = 1;
798 params->sensorFps.baserate = 1;
799
800 params->yuvThreshold.yThreshold = 6; /* From windows driver */
801 params->yuvThreshold.uvThreshold = 6; /* From windows driver */
802
803 params->format.subSample = SUBSAMPLE_420;
804 params->format.yuvOrder = YUVORDER_YUYV;
805
806 params->compression.mode = CPIA_COMPRESSION_AUTO;
807 params->compression.decimation = NO_DECIMATION;
808
809 params->compressionTarget.frTargeting = COMP_TARGET_DEF;
810 params->compressionTarget.targetFR = 15; /* From windows driver */
811 params->compressionTarget.targetQ = 5; /* From windows driver */
812
813 params->qx3.qx3_detected = 0;
814 params->qx3.toplight = 0;
815 params->qx3.bottomlight = 0;
816 params->qx3.button = 0;
817 params->qx3.cradled = 0;
818}
819
820static void printstatus(struct cam_params *params)
821{
822 PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
823 params->status.systemState, params->status.grabState,
824 params->status.streamState, params->status.fatalError,
825 params->status.cmdError, params->status.debugFlags,
826 params->status.vpStatus, params->status.errorCode);
827}
828
829static int goto_low_power(struct gspca_dev *gspca_dev)
830{
831 struct sd *sd = (struct sd *) gspca_dev;
832 int ret;
833
834 ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
835 if (ret)
836 return ret;
837
838 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
839 if (ret)
840 return ret;
841
842 if (sd->params.status.systemState != LO_POWER_STATE) {
843 if (sd->params.status.systemState != WARM_BOOT_STATE) {
844 PDEBUG(D_ERR,
845 "unexpected state after lo power cmd: %02x",
846 sd->params.status.systemState);
847 printstatus(&sd->params);
848 }
849 return -EIO;
850 }
851
852 PDEBUG(D_CONF, "camera now in LOW power state");
853 return 0;
854}
855
856static int goto_high_power(struct gspca_dev *gspca_dev)
857{
858 struct sd *sd = (struct sd *) gspca_dev;
859 int ret;
860
861 ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
862 if (ret)
863 return ret;
864
865 msleep_interruptible(40); /* windows driver does it too */
866
867 if (signal_pending(current))
868 return -EINTR;
869
870 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
871 if (ret)
872 return ret;
873
874 if (sd->params.status.systemState != HI_POWER_STATE) {
875 PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
876 sd->params.status.systemState);
877 printstatus(&sd->params);
878 return -EIO;
879 }
880
881 PDEBUG(D_CONF, "camera now in HIGH power state");
882 return 0;
883}
884
885static int get_version_information(struct gspca_dev *gspca_dev)
886{
887 int ret;
888
889 /* GetCPIAVersion */
890 ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
891 if (ret)
892 return ret;
893
894 /* GetPnPID */
895 return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
896}
897
898static int save_camera_state(struct gspca_dev *gspca_dev)
899{
900 int ret;
901
902 ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
903 if (ret)
904 return ret;
905
906 return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
907}
908
909static int command_setformat(struct gspca_dev *gspca_dev)
910{
911 struct sd *sd = (struct sd *) gspca_dev;
912 int ret;
913
914 ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
915 sd->params.format.videoSize,
916 sd->params.format.subSample,
917 sd->params.format.yuvOrder, 0);
918 if (ret)
919 return ret;
920
921 return do_command(gspca_dev, CPIA_COMMAND_SetROI,
922 sd->params.roi.colStart, sd->params.roi.colEnd,
923 sd->params.roi.rowStart, sd->params.roi.rowEnd);
924}
925
926static int command_setcolourparams(struct gspca_dev *gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929 return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
930 sd->params.colourParams.brightness,
931 sd->params.colourParams.contrast,
932 sd->params.colourParams.saturation, 0);
933}
934
935static int command_setapcor(struct gspca_dev *gspca_dev)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
938 return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
939 sd->params.apcor.gain1,
940 sd->params.apcor.gain2,
941 sd->params.apcor.gain4,
942 sd->params.apcor.gain8);
943}
944
945static int command_setvloffset(struct gspca_dev *gspca_dev)
946{
947 struct sd *sd = (struct sd *) gspca_dev;
948 return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
949 sd->params.vlOffset.gain1,
950 sd->params.vlOffset.gain2,
951 sd->params.vlOffset.gain4,
952 sd->params.vlOffset.gain8);
953}
954
955static int command_setexposure(struct gspca_dev *gspca_dev)
956{
957 struct sd *sd = (struct sd *) gspca_dev;
958 int ret;
959
960 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
961 sd->params.exposure.gainMode,
962 1,
963 sd->params.exposure.compMode,
964 sd->params.exposure.centreWeight,
965 sd->params.exposure.gain,
966 sd->params.exposure.fineExp,
967 sd->params.exposure.coarseExpLo,
968 sd->params.exposure.coarseExpHi,
969 sd->params.exposure.redComp,
970 sd->params.exposure.green1Comp,
971 sd->params.exposure.green2Comp,
972 sd->params.exposure.blueComp);
973 if (ret)
974 return ret;
975
976 if (sd->params.exposure.expMode != 1) {
977 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
978 0,
979 sd->params.exposure.expMode,
980 0, 0,
981 sd->params.exposure.gain,
982 sd->params.exposure.fineExp,
983 sd->params.exposure.coarseExpLo,
984 sd->params.exposure.coarseExpHi,
985 0, 0, 0, 0);
986 }
987
988 return ret;
989}
990
991static int command_setcolourbalance(struct gspca_dev *gspca_dev)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 if (sd->params.colourBalance.balanceMode == 1) {
996 int ret;
997
998 ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
999 1,
1000 sd->params.colourBalance.redGain,
1001 sd->params.colourBalance.greenGain,
1002 sd->params.colourBalance.blueGain);
1003 if (ret)
1004 return ret;
1005
1006 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
1007 3, 0, 0, 0);
1008 }
1009 if (sd->params.colourBalance.balanceMode == 2) {
1010 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
1011 2, 0, 0, 0);
1012 }
1013 if (sd->params.colourBalance.balanceMode == 3) {
1014 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
1015 3, 0, 0, 0);
1016 }
1017
1018 return -EINVAL;
1019}
1020
1021static int command_setcompressiontarget(struct gspca_dev *gspca_dev)
1022{
1023 struct sd *sd = (struct sd *) gspca_dev;
1024
1025 return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
1026 sd->params.compressionTarget.frTargeting,
1027 sd->params.compressionTarget.targetFR,
1028 sd->params.compressionTarget.targetQ, 0);
1029}
1030
1031static int command_setyuvtresh(struct gspca_dev *gspca_dev)
1032{
1033 struct sd *sd = (struct sd *) gspca_dev;
1034
1035 return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
1036 sd->params.yuvThreshold.yThreshold,
1037 sd->params.yuvThreshold.uvThreshold, 0, 0);
1038}
1039
1040static int command_setcompressionparams(struct gspca_dev *gspca_dev)
1041{
1042 struct sd *sd = (struct sd *) gspca_dev;
1043
1044 return do_command_extended(gspca_dev,
1045 CPIA_COMMAND_SetCompressionParams,
1046 0, 0, 0, 0,
1047 sd->params.compressionParams.hysteresis,
1048 sd->params.compressionParams.threshMax,
1049 sd->params.compressionParams.smallStep,
1050 sd->params.compressionParams.largeStep,
1051 sd->params.compressionParams.decimationHysteresis,
1052 sd->params.compressionParams.frDiffStepThresh,
1053 sd->params.compressionParams.qDiffStepThresh,
1054 sd->params.compressionParams.decimationThreshMod);
1055}
1056
1057static int command_setcompression(struct gspca_dev *gspca_dev)
1058{
1059 struct sd *sd = (struct sd *) gspca_dev;
1060
1061 return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
1062 sd->params.compression.mode,
1063 sd->params.compression.decimation, 0, 0);
1064}
1065
1066static int command_setsensorfps(struct gspca_dev *gspca_dev)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069
1070 return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
1071 sd->params.sensorFps.divisor,
1072 sd->params.sensorFps.baserate, 0, 0);
1073}
1074
1075static int command_setflickerctrl(struct gspca_dev *gspca_dev)
1076{
1077 struct sd *sd = (struct sd *) gspca_dev;
1078
1079 return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
1080 sd->params.flickerControl.flickerMode,
1081 sd->params.flickerControl.coarseJump,
1082 sd->params.flickerControl.allowableOverExposure,
1083 0);
1084}
1085
1086static int command_setecptiming(struct gspca_dev *gspca_dev)
1087{
1088 struct sd *sd = (struct sd *) gspca_dev;
1089
1090 return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
1091 sd->params.ecpTiming, 0, 0, 0);
1092}
1093
1094static int command_pause(struct gspca_dev *gspca_dev)
1095{
1096 return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
1097}
1098
1099static int command_resume(struct gspca_dev *gspca_dev)
1100{
1101 struct sd *sd = (struct sd *) gspca_dev;
1102
1103 return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
1104 0, sd->params.streamStartLine, 0, 0);
1105}
1106
1107static int command_setlights(struct gspca_dev *gspca_dev)
1108{
1109 struct sd *sd = (struct sd *) gspca_dev;
1110 int ret, p1, p2;
1111
1112 if (!sd->params.qx3.qx3_detected)
1113 return 0;
1114
1115 p1 = (sd->params.qx3.bottomlight == 0) << 1;
1116 p2 = (sd->params.qx3.toplight == 0) << 3;
1117
1118 ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
1119 0x90, 0x8f, 0x50, 0);
1120 if (ret)
1121 return ret;
1122
1123 return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
1124 p1 | p2 | 0xe0, 0);
1125}
1126
1127static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
1128{
1129 /* Everything in here is from the Windows driver */
1130/* define for compgain calculation */
1131#if 0
1132#define COMPGAIN(base, curexp, newexp) \
1133 (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
1134#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
1135 (u16)((float)curexp * (float)(u8)(curcomp + 128) / \
1136 (float)(u8)(basecomp - 128))
1137#else
1138 /* equivalent functions without floating point math */
1139#define COMPGAIN(base, curexp, newexp) \
1140 (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
1141#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
1142 (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
1143#endif
1144
1145 struct sd *sd = (struct sd *) gspca_dev;
1146 int currentexp = sd->params.exposure.coarseExpLo +
1147 sd->params.exposure.coarseExpHi * 256;
1148 int ret, startexp;
1149
1150 if (on) {
1151 int cj = sd->params.flickerControl.coarseJump;
1152 sd->params.flickerControl.flickerMode = 1;
1153 sd->params.flickerControl.disabled = 0;
1154 if (sd->params.exposure.expMode != 2) {
1155 sd->params.exposure.expMode = 2;
1156 sd->exposure_status = EXPOSURE_NORMAL;
1157 }
1158 currentexp = currentexp << sd->params.exposure.gain;
1159 sd->params.exposure.gain = 0;
1160 /* round down current exposure to nearest value */
1161 startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
1162 if (startexp < 1)
1163 startexp = 1;
1164 startexp = (startexp * cj) - 1;
1165 if (FIRMWARE_VERSION(1, 2))
1166 while (startexp > MAX_EXP_102)
1167 startexp -= cj;
1168 else
1169 while (startexp > MAX_EXP)
1170 startexp -= cj;
1171 sd->params.exposure.coarseExpLo = startexp & 0xff;
1172 sd->params.exposure.coarseExpHi = startexp >> 8;
1173 if (currentexp > startexp) {
1174 if (currentexp > (2 * startexp))
1175 currentexp = 2 * startexp;
1176 sd->params.exposure.redComp =
1177 COMPGAIN(COMP_RED, currentexp, startexp);
1178 sd->params.exposure.green1Comp =
1179 COMPGAIN(COMP_GREEN1, currentexp, startexp);
1180 sd->params.exposure.green2Comp =
1181 COMPGAIN(COMP_GREEN2, currentexp, startexp);
1182 sd->params.exposure.blueComp =
1183 COMPGAIN(COMP_BLUE, currentexp, startexp);
1184 } else {
1185 sd->params.exposure.redComp = COMP_RED;
1186 sd->params.exposure.green1Comp = COMP_GREEN1;
1187 sd->params.exposure.green2Comp = COMP_GREEN2;
1188 sd->params.exposure.blueComp = COMP_BLUE;
1189 }
1190 if (FIRMWARE_VERSION(1, 2))
1191 sd->params.exposure.compMode = 0;
1192 else
1193 sd->params.exposure.compMode = 1;
1194
1195 sd->params.apcor.gain1 = 0x18;
1196 sd->params.apcor.gain2 = 0x18;
1197 sd->params.apcor.gain4 = 0x16;
1198 sd->params.apcor.gain8 = 0x14;
1199 } else {
1200 sd->params.flickerControl.flickerMode = 0;
1201 sd->params.flickerControl.disabled = 1;
1202 /* Average equivalent coarse for each comp channel */
1203 startexp = EXP_FROM_COMP(COMP_RED,
1204 sd->params.exposure.redComp, currentexp);
1205 startexp += EXP_FROM_COMP(COMP_GREEN1,
1206 sd->params.exposure.green1Comp, currentexp);
1207 startexp += EXP_FROM_COMP(COMP_GREEN2,
1208 sd->params.exposure.green2Comp, currentexp);
1209 startexp += EXP_FROM_COMP(COMP_BLUE,
1210 sd->params.exposure.blueComp, currentexp);
1211 startexp = startexp >> 2;
1212 while (startexp > MAX_EXP && sd->params.exposure.gain <
1213 sd->params.exposure.gainMode - 1) {
1214 startexp = startexp >> 1;
1215 ++sd->params.exposure.gain;
1216 }
1217 if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
1218 startexp = MAX_EXP_102;
1219 if (startexp > MAX_EXP)
1220 startexp = MAX_EXP;
1221 sd->params.exposure.coarseExpLo = startexp & 0xff;
1222 sd->params.exposure.coarseExpHi = startexp >> 8;
1223 sd->params.exposure.redComp = COMP_RED;
1224 sd->params.exposure.green1Comp = COMP_GREEN1;
1225 sd->params.exposure.green2Comp = COMP_GREEN2;
1226 sd->params.exposure.blueComp = COMP_BLUE;
1227 sd->params.exposure.compMode = 1;
1228 sd->params.apcor.gain1 = 0x18;
1229 sd->params.apcor.gain2 = 0x16;
1230 sd->params.apcor.gain4 = 0x24;
1231 sd->params.apcor.gain8 = 0x34;
1232 }
1233 sd->params.vlOffset.gain1 = 20;
1234 sd->params.vlOffset.gain2 = 24;
1235 sd->params.vlOffset.gain4 = 26;
1236 sd->params.vlOffset.gain8 = 26;
1237
1238 if (apply) {
1239 ret = command_setexposure(gspca_dev);
1240 if (ret)
1241 return ret;
1242
1243 ret = command_setapcor(gspca_dev);
1244 if (ret)
1245 return ret;
1246
1247 ret = command_setvloffset(gspca_dev);
1248 if (ret)
1249 return ret;
1250
1251 ret = command_setflickerctrl(gspca_dev);
1252 if (ret)
1253 return ret;
1254 }
1255
1256 return 0;
1257#undef EXP_FROM_COMP
1258#undef COMPGAIN
1259}
1260
1261/* monitor the exposure and adjust the sensor frame rate if needed */
1262static void monitor_exposure(struct gspca_dev *gspca_dev)
1263{
1264 struct sd *sd = (struct sd *) gspca_dev;
1265 u8 exp_acc, bcomp, cmd[8];
1266 int ret, light_exp, dark_exp, very_dark_exp;
1267 int old_exposure, new_exposure, framerate;
1268 int setfps = 0, setexp = 0, setflicker = 0;
1269
1270 /* get necessary stats and register settings from camera */
1271 /* do_command can't handle this, so do it ourselves */
1272 cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
1273 cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
1274 cmd[2] = 30;
1275 cmd[3] = 4;
1276 cmd[4] = 9;
1277 cmd[5] = 8;
1278 cmd[6] = 8;
1279 cmd[7] = 0;
1280 ret = cpia_usb_transferCmd(gspca_dev, cmd);
1281 if (ret) {
1282 err("ReadVPRegs(30,4,9,8) - failed: %d", ret);
1283 return;
1284 }
1285 exp_acc = gspca_dev->usb_buf[0];
1286 bcomp = gspca_dev->usb_buf[1];
1287
1288 light_exp = sd->params.colourParams.brightness +
1289 TC - 50 + EXP_ACC_LIGHT;
1290 if (light_exp > 255)
1291 light_exp = 255;
1292 dark_exp = sd->params.colourParams.brightness +
1293 TC - 50 - EXP_ACC_DARK;
1294 if (dark_exp < 0)
1295 dark_exp = 0;
1296 very_dark_exp = dark_exp / 2;
1297
1298 old_exposure = sd->params.exposure.coarseExpHi * 256 +
1299 sd->params.exposure.coarseExpLo;
1300
1301 if (!sd->params.flickerControl.disabled) {
1302 /* Flicker control on */
1303 int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
1304 HIGH_COMP_102;
1305 bcomp += 128; /* decode */
1306 if (bcomp >= max_comp && exp_acc < dark_exp) {
1307 /* dark */
1308 if (exp_acc < very_dark_exp) {
1309 /* very dark */
1310 if (sd->exposure_status == EXPOSURE_VERY_DARK)
1311 ++sd->exposure_count;
1312 else {
1313 sd->exposure_status =
1314 EXPOSURE_VERY_DARK;
1315 sd->exposure_count = 1;
1316 }
1317 } else {
1318 /* just dark */
1319 if (sd->exposure_status == EXPOSURE_DARK)
1320 ++sd->exposure_count;
1321 else {
1322 sd->exposure_status = EXPOSURE_DARK;
1323 sd->exposure_count = 1;
1324 }
1325 }
1326 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
1327 /* light */
1328 if (old_exposure <= VERY_LOW_EXP) {
1329 /* very light */
1330 if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
1331 ++sd->exposure_count;
1332 else {
1333 sd->exposure_status =
1334 EXPOSURE_VERY_LIGHT;
1335 sd->exposure_count = 1;
1336 }
1337 } else {
1338 /* just light */
1339 if (sd->exposure_status == EXPOSURE_LIGHT)
1340 ++sd->exposure_count;
1341 else {
1342 sd->exposure_status = EXPOSURE_LIGHT;
1343 sd->exposure_count = 1;
1344 }
1345 }
1346 } else {
1347 /* not dark or light */
1348 sd->exposure_status = EXPOSURE_NORMAL;
1349 }
1350 } else {
1351 /* Flicker control off */
1352 if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
1353 /* dark */
1354 if (exp_acc < very_dark_exp) {
1355 /* very dark */
1356 if (sd->exposure_status == EXPOSURE_VERY_DARK)
1357 ++sd->exposure_count;
1358 else {
1359 sd->exposure_status =
1360 EXPOSURE_VERY_DARK;
1361 sd->exposure_count = 1;
1362 }
1363 } else {
1364 /* just dark */
1365 if (sd->exposure_status == EXPOSURE_DARK)
1366 ++sd->exposure_count;
1367 else {
1368 sd->exposure_status = EXPOSURE_DARK;
1369 sd->exposure_count = 1;
1370 }
1371 }
1372 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
1373 /* light */
1374 if (old_exposure <= VERY_LOW_EXP) {
1375 /* very light */
1376 if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
1377 ++sd->exposure_count;
1378 else {
1379 sd->exposure_status =
1380 EXPOSURE_VERY_LIGHT;
1381 sd->exposure_count = 1;
1382 }
1383 } else {
1384 /* just light */
1385 if (sd->exposure_status == EXPOSURE_LIGHT)
1386 ++sd->exposure_count;
1387 else {
1388 sd->exposure_status = EXPOSURE_LIGHT;
1389 sd->exposure_count = 1;
1390 }
1391 }
1392 } else {
1393 /* not dark or light */
1394 sd->exposure_status = EXPOSURE_NORMAL;
1395 }
1396 }
1397
1398 framerate = atomic_read(&sd->fps);
1399 if (framerate > 30 || framerate < 1)
1400 framerate = 1;
1401
1402 if (!sd->params.flickerControl.disabled) {
1403 /* Flicker control on */
1404 if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
1405 sd->exposure_status == EXPOSURE_DARK) &&
1406 sd->exposure_count >= DARK_TIME * framerate &&
1407 sd->params.sensorFps.divisor < 2) {
1408
1409 /* dark for too long */
1410 ++sd->params.sensorFps.divisor;
1411 setfps = 1;
1412
1413 sd->params.flickerControl.coarseJump =
1414 flicker_jumps[sd->mainsFreq]
1415 [sd->params.sensorFps.baserate]
1416 [sd->params.sensorFps.divisor];
1417 setflicker = 1;
1418
1419 new_exposure = sd->params.flickerControl.coarseJump-1;
1420 while (new_exposure < old_exposure / 2)
1421 new_exposure +=
1422 sd->params.flickerControl.coarseJump;
1423 sd->params.exposure.coarseExpLo = new_exposure & 0xff;
1424 sd->params.exposure.coarseExpHi = new_exposure >> 8;
1425 setexp = 1;
1426 sd->exposure_status = EXPOSURE_NORMAL;
1427 PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
1428
1429 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
1430 sd->exposure_status == EXPOSURE_LIGHT) &&
1431 sd->exposure_count >= LIGHT_TIME * framerate &&
1432 sd->params.sensorFps.divisor > 0) {
1433
1434 /* light for too long */
1435 int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
1436 MAX_EXP;
1437 --sd->params.sensorFps.divisor;
1438 setfps = 1;
1439
1440 sd->params.flickerControl.coarseJump =
1441 flicker_jumps[sd->mainsFreq]
1442 [sd->params.sensorFps.baserate]
1443 [sd->params.sensorFps.divisor];
1444 setflicker = 1;
1445
1446 new_exposure = sd->params.flickerControl.coarseJump-1;
1447 while (new_exposure < 2 * old_exposure &&
1448 new_exposure +
1449 sd->params.flickerControl.coarseJump < max_exp)
1450 new_exposure +=
1451 sd->params.flickerControl.coarseJump;
1452 sd->params.exposure.coarseExpLo = new_exposure & 0xff;
1453 sd->params.exposure.coarseExpHi = new_exposure >> 8;
1454 setexp = 1;
1455 sd->exposure_status = EXPOSURE_NORMAL;
1456 PDEBUG(D_CONF, "Automatically increasing sensor_fps");
1457 }
1458 } else {
1459 /* Flicker control off */
1460 if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
1461 sd->exposure_status == EXPOSURE_DARK) &&
1462 sd->exposure_count >= DARK_TIME * framerate &&
1463 sd->params.sensorFps.divisor < 2) {
1464
1465 /* dark for too long */
1466 ++sd->params.sensorFps.divisor;
1467 setfps = 1;
1468
1469 if (sd->params.exposure.gain > 0) {
1470 --sd->params.exposure.gain;
1471 setexp = 1;
1472 }
1473 sd->exposure_status = EXPOSURE_NORMAL;
1474 PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
1475
1476 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
1477 sd->exposure_status == EXPOSURE_LIGHT) &&
1478 sd->exposure_count >= LIGHT_TIME * framerate &&
1479 sd->params.sensorFps.divisor > 0) {
1480
1481 /* light for too long */
1482 --sd->params.sensorFps.divisor;
1483 setfps = 1;
1484
1485 if (sd->params.exposure.gain <
1486 sd->params.exposure.gainMode - 1) {
1487 ++sd->params.exposure.gain;
1488 setexp = 1;
1489 }
1490 sd->exposure_status = EXPOSURE_NORMAL;
1491 PDEBUG(D_CONF, "Automatically increasing sensor_fps");
1492 }
1493 }
1494
1495 if (setexp)
1496 command_setexposure(gspca_dev);
1497
1498 if (setfps)
1499 command_setsensorfps(gspca_dev);
1500
1501 if (setflicker)
1502 command_setflickerctrl(gspca_dev);
1503}
1504
1505/*-----------------------------------------------------------------*/
1506/* if flicker is switched off, this function switches it back on.It checks,
1507 however, that conditions are suitable before restarting it.
1508 This should only be called for firmware version 1.2.
1509
1510 It also adjust the colour balance when an exposure step is detected - as
1511 long as flicker is running
1512*/
1513static void restart_flicker(struct gspca_dev *gspca_dev)
1514{
1515 struct sd *sd = (struct sd *) gspca_dev;
1516 int cam_exposure, old_exp;
1517
1518 if (!FIRMWARE_VERSION(1, 2))
1519 return;
1520
1521 cam_exposure = atomic_read(&sd->cam_exposure);
1522
1523 if (sd->params.flickerControl.flickerMode == 0 ||
1524 cam_exposure == 0)
1525 return;
1526
1527 old_exp = sd->params.exposure.coarseExpLo +
1528 sd->params.exposure.coarseExpHi*256;
1529 /*
1530 see how far away camera exposure is from a valid
1531 flicker exposure value
1532 */
1533 cam_exposure %= sd->params.flickerControl.coarseJump;
1534 if (!sd->params.flickerControl.disabled &&
1535 cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
1536 /* Flicker control auto-disabled */
1537 sd->params.flickerControl.disabled = 1;
1538 }
1539
1540 if (sd->params.flickerControl.disabled &&
1541 old_exp > sd->params.flickerControl.coarseJump +
1542 ROUND_UP_EXP_FOR_FLICKER) {
1543 /* exposure is now high enough to switch
1544 flicker control back on */
1545 set_flicker(gspca_dev, 1, 1);
1546 }
1547}
1548
1549/* this function is called at probe time */
1550static int sd_config(struct gspca_dev *gspca_dev,
1551 const struct usb_device_id *id)
1552{
1553 struct cam *cam;
1554
1555 reset_camera_params(gspca_dev);
1556
1557 PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)",
1558 id->idVendor, id->idProduct);
1559
1560 cam = &gspca_dev->cam;
1561 cam->cam_mode = mode;
1562 cam->nmodes = ARRAY_SIZE(mode);
1563
1564 sd_setfreq(gspca_dev, FREQ_DEF);
1565
1566 return 0;
1567}
1568
1569/* -- start the camera -- */
1570static int sd_start(struct gspca_dev *gspca_dev)
1571{
1572 struct sd *sd = (struct sd *) gspca_dev;
1573 int priv, ret;
1574
1575 /* Start the camera in low power mode */
1576 if (goto_low_power(gspca_dev)) {
1577 if (sd->params.status.systemState != WARM_BOOT_STATE) {
1578 PDEBUG(D_ERR, "unexpected systemstate: %02x",
1579 sd->params.status.systemState);
1580 printstatus(&sd->params);
1581 return -ENODEV;
1582 }
1583
1584 /* FIXME: this is just dirty trial and error */
1585 ret = goto_high_power(gspca_dev);
1586 if (ret)
1587 return ret;
1588
1589 ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
1590 0, 0, 0, 0);
1591 if (ret)
1592 return ret;
1593
1594 ret = goto_low_power(gspca_dev);
1595 if (ret)
1596 return ret;
1597 }
1598
1599 /* procedure described in developer's guide p3-28 */
1600
1601 /* Check the firmware version. */
1602 sd->params.version.firmwareVersion = 0;
1603 get_version_information(gspca_dev);
1604 if (sd->params.version.firmwareVersion != 1) {
1605 PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
1606 sd->params.version.firmwareVersion);
1607 return -ENODEV;
1608 }
1609
1610 /* A bug in firmware 1-02 limits gainMode to 2 */
1611 if (sd->params.version.firmwareRevision <= 2 &&
1612 sd->params.exposure.gainMode > 2) {
1613 sd->params.exposure.gainMode = 2;
1614 }
1615
1616 /* set QX3 detected flag */
1617 sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
1618 sd->params.pnpID.product == 0x0001);
1619
1620 /* The fatal error checking should be done after
1621 * the camera powers up (developer's guide p 3-38) */
1622
1623 /* Set streamState before transition to high power to avoid bug
1624 * in firmware 1-02 */
1625 ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
1626 STREAMSTATE, 0, STREAM_NOT_READY, 0);
1627 if (ret)
1628 return ret;
1629
1630 /* GotoHiPower */
1631 ret = goto_high_power(gspca_dev);
1632 if (ret)
1633 return ret;
1634
1635 /* Check the camera status */
1636 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
1637 if (ret)
1638 return ret;
1639
1640 if (sd->params.status.fatalError) {
1641 PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
1642 sd->params.status.fatalError,
1643 sd->params.status.vpStatus);
1644 return -EIO;
1645 }
1646
1647 /* VPVersion can't be retrieved before the camera is in HiPower,
1648 * so get it here instead of in get_version_information. */
1649 ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
1650 if (ret)
1651 return ret;
1652
1653 /* Determine video mode settings */
1654 sd->params.streamStartLine = 120;
1655
1656 priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1657 if (priv & 0x01) { /* crop */
1658 sd->params.roi.colStart = 2;
1659 sd->params.roi.rowStart = 6;
1660 } else {
1661 sd->params.roi.colStart = 0;
1662 sd->params.roi.rowStart = 0;
1663 }
1664
1665 if (priv & 0x02) { /* quarter */
1666 sd->params.format.videoSize = VIDEOSIZE_QCIF;
1667 sd->params.roi.colStart /= 2;
1668 sd->params.roi.rowStart /= 2;
1669 sd->params.streamStartLine /= 2;
1670 } else
1671 sd->params.format.videoSize = VIDEOSIZE_CIF;
1672
1673 sd->params.roi.colEnd = sd->params.roi.colStart +
1674 (gspca_dev->width >> 3);
1675 sd->params.roi.rowEnd = sd->params.roi.rowStart +
1676 (gspca_dev->height >> 2);
1677
1678 /* And now set the camera to a known state */
1679 ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
1680 CPIA_GRAB_CONTINEOUS, 0, 0, 0);
1681 if (ret)
1682 return ret;
1683 /* We start with compression disabled, as we need one uncompressed
1684 frame to handle later compressed frames */
1685 ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
1686 CPIA_COMPRESSION_NONE,
1687 NO_DECIMATION, 0, 0);
1688 if (ret)
1689 return ret;
1690 ret = command_setcompressiontarget(gspca_dev);
1691 if (ret)
1692 return ret;
1693 ret = command_setcolourparams(gspca_dev);
1694 if (ret)
1695 return ret;
1696 ret = command_setformat(gspca_dev);
1697 if (ret)
1698 return ret;
1699 ret = command_setyuvtresh(gspca_dev);
1700 if (ret)
1701 return ret;
1702 ret = command_setecptiming(gspca_dev);
1703 if (ret)
1704 return ret;
1705 ret = command_setcompressionparams(gspca_dev);
1706 if (ret)
1707 return ret;
1708 ret = command_setexposure(gspca_dev);
1709 if (ret)
1710 return ret;
1711 ret = command_setcolourbalance(gspca_dev);
1712 if (ret)
1713 return ret;
1714 ret = command_setsensorfps(gspca_dev);
1715 if (ret)
1716 return ret;
1717 ret = command_setapcor(gspca_dev);
1718 if (ret)
1719 return ret;
1720 ret = command_setflickerctrl(gspca_dev);
1721 if (ret)
1722 return ret;
1723 ret = command_setvloffset(gspca_dev);
1724 if (ret)
1725 return ret;
1726
1727 /* Start stream */
1728 ret = command_resume(gspca_dev);
1729 if (ret)
1730 return ret;
1731
1732 /* Wait 6 frames before turning compression on for the sensor to get
1733 all settings and AEC/ACB to settle */
1734 sd->first_frame = 6;
1735 sd->exposure_status = EXPOSURE_NORMAL;
1736 sd->exposure_count = 0;
1737 atomic_set(&sd->cam_exposure, 0);
1738 atomic_set(&sd->fps, 0);
1739
1740 return 0;
1741}
1742
1743static void sd_stopN(struct gspca_dev *gspca_dev)
1744{
1745 struct sd *sd = (struct sd *) gspca_dev;
1746
1747 command_pause(gspca_dev);
1748
1749 /* save camera state for later open (developers guide ch 3.5.3) */
1750 save_camera_state(gspca_dev);
1751
1752 /* GotoLoPower */
1753 goto_low_power(gspca_dev);
1754
1755 /* Update the camera status */
1756 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
1757
1758#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1759 /* If the last button state is pressed, release it now! */
1760 if (sd->params.qx3.button) {
1761 /* The camera latch will hold the pressed state until we reset
1762 the latch, so we do not reset sd->params.qx3.button now, to
1763 avoid a false keypress being reported the next sd_start */
1764 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1765 input_sync(gspca_dev->input_dev);
1766 }
1767#endif
1768}
1769
1770/* this function is called at probe and resume time */
1771static int sd_init(struct gspca_dev *gspca_dev)
1772{
1773 struct sd *sd = (struct sd *) gspca_dev;
1774 int ret;
1775
1776 /* Start / Stop the camera to make sure we are talking to
1777 a supported camera, and to get some information from it
1778 to print. */
1779 ret = sd_start(gspca_dev);
1780 if (ret)
1781 return ret;
1782
1783 /* Ensure the QX3 illuminators' states are restored upon resume,
1784 or disable the illuminator controls, if this isn't a QX3 */
1785 if (sd->params.qx3.qx3_detected)
1786 command_setlights(gspca_dev);
1787 else
1788 gspca_dev->ctrl_dis |=
1789 ((1 << ILLUMINATORS_1_IDX) | (1 << ILLUMINATORS_2_IDX));
1790
1791 sd_stopN(gspca_dev);
1792
1793 PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)",
1794 sd->params.version.firmwareVersion,
1795 sd->params.version.firmwareRevision,
1796 sd->params.version.vcVersion,
1797 sd->params.version.vcRevision);
1798 PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x",
1799 sd->params.pnpID.vendor, sd->params.pnpID.product,
1800 sd->params.pnpID.deviceRevision);
1801 PDEBUG(D_PROBE, "VP-Version: %d.%d %04x",
1802 sd->params.vpVersion.vpVersion,
1803 sd->params.vpVersion.vpRevision,
1804 sd->params.vpVersion.cameraHeadID);
1805
1806 return 0;
1807}
1808
1809static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1810 u8 *data,
1811 int len)
1812{
1813 struct sd *sd = (struct sd *) gspca_dev;
1814
1815 /* Check for SOF */
1816 if (len >= 64 &&
1817 data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
1818 data[16] == sd->params.format.videoSize &&
1819 data[17] == sd->params.format.subSample &&
1820 data[18] == sd->params.format.yuvOrder &&
1821 data[24] == sd->params.roi.colStart &&
1822 data[25] == sd->params.roi.colEnd &&
1823 data[26] == sd->params.roi.rowStart &&
1824 data[27] == sd->params.roi.rowEnd) {
1825 u8 *image;
1826
1827 atomic_set(&sd->cam_exposure, data[39] * 2);
1828 atomic_set(&sd->fps, data[41]);
1829
1830 /* Check for proper EOF for last frame */
1831 image = gspca_dev->image;
1832 if (image != NULL &&
1833 gspca_dev->image_len > 4 &&
1834 image[gspca_dev->image_len - 4] == 0xff &&
1835 image[gspca_dev->image_len - 3] == 0xff &&
1836 image[gspca_dev->image_len - 2] == 0xff &&
1837 image[gspca_dev->image_len - 1] == 0xff)
1838 gspca_frame_add(gspca_dev, LAST_PACKET,
1839 NULL, 0);
1840
1841 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1842 return;
1843 }
1844
1845 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1846}
1847
1848static void sd_dq_callback(struct gspca_dev *gspca_dev)
1849{
1850 struct sd *sd = (struct sd *) gspca_dev;
1851
1852 /* Set the normal compression settings once we have captured a
1853 few uncompressed frames (and AEC has hopefully settled) */
1854 if (sd->first_frame) {
1855 sd->first_frame--;
1856 if (sd->first_frame == 0)
1857 command_setcompression(gspca_dev);
1858 }
1859
1860 /* Switch flicker control back on if it got turned off */
1861 restart_flicker(gspca_dev);
1862
1863 /* If AEC is enabled, monitor the exposure and
1864 adjust the sensor frame rate if needed */
1865 if (sd->params.exposure.expMode == 2)
1866 monitor_exposure(gspca_dev);
1867
1868 /* Update our knowledge of the camera state */
1869 do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
1870 do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
1871}
1872
1873static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1874{
1875 struct sd *sd = (struct sd *) gspca_dev;
1876 int ret;
1877
1878 sd->params.colourParams.brightness = val;
1879 sd->params.flickerControl.allowableOverExposure =
1880 find_over_exposure(sd->params.colourParams.brightness);
1881 if (gspca_dev->streaming) {
1882 ret = command_setcolourparams(gspca_dev);
1883 if (ret)
1884 return ret;
1885 return command_setflickerctrl(gspca_dev);
1886 }
1887 return 0;
1888}
1889
1890static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1891{
1892 struct sd *sd = (struct sd *) gspca_dev;
1893
1894 *val = sd->params.colourParams.brightness;
1895 return 0;
1896}
1897
1898static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1899{
1900 struct sd *sd = (struct sd *) gspca_dev;
1901
1902 sd->params.colourParams.contrast = val;
1903 if (gspca_dev->streaming)
1904 return command_setcolourparams(gspca_dev);
1905
1906 return 0;
1907}
1908
1909static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1910{
1911 struct sd *sd = (struct sd *) gspca_dev;
1912
1913 *val = sd->params.colourParams.contrast;
1914 return 0;
1915}
1916
1917static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
1918{
1919 struct sd *sd = (struct sd *) gspca_dev;
1920
1921 sd->params.colourParams.saturation = val;
1922 if (gspca_dev->streaming)
1923 return command_setcolourparams(gspca_dev);
1924
1925 return 0;
1926}
1927
1928static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
1929{
1930 struct sd *sd = (struct sd *) gspca_dev;
1931
1932 *val = sd->params.colourParams.saturation;
1933 return 0;
1934}
1935
1936static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1937{
1938 struct sd *sd = (struct sd *) gspca_dev;
1939 int on;
1940
1941 switch (val) {
1942 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1943 on = 0;
1944 break;
1945 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1946 on = 1;
1947 sd->mainsFreq = 0;
1948 break;
1949 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1950 on = 1;
1951 sd->mainsFreq = 1;
1952 break;
1953 default:
1954 return -EINVAL;
1955 }
1956
1957 sd->freq = val;
1958 sd->params.flickerControl.coarseJump =
1959 flicker_jumps[sd->mainsFreq]
1960 [sd->params.sensorFps.baserate]
1961 [sd->params.sensorFps.divisor];
1962
1963 return set_flicker(gspca_dev, on, gspca_dev->streaming);
1964}
1965
1966static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1967{
1968 struct sd *sd = (struct sd *) gspca_dev;
1969
1970 *val = sd->freq;
1971 return 0;
1972}
1973
1974static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val)
1975{
1976 struct sd *sd = (struct sd *) gspca_dev;
1977
1978 sd->params.compressionTarget.frTargeting = val;
1979 if (gspca_dev->streaming)
1980 return command_setcompressiontarget(gspca_dev);
1981
1982 return 0;
1983}
1984
1985static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val)
1986{
1987 struct sd *sd = (struct sd *) gspca_dev;
1988
1989 *val = sd->params.compressionTarget.frTargeting;
1990 return 0;
1991}
1992
1993static int sd_setilluminator(struct gspca_dev *gspca_dev, __s32 val, int n)
1994{
1995 struct sd *sd = (struct sd *) gspca_dev;
1996 int ret;
1997
1998 if (!sd->params.qx3.qx3_detected)
1999 return -EINVAL;
2000
2001 switch (n) {
2002 case 1:
2003 sd->params.qx3.bottomlight = val ? 1 : 0;
2004 break;
2005 case 2:
2006 sd->params.qx3.toplight = val ? 1 : 0;
2007 break;
2008 default:
2009 return -EINVAL;
2010 }
2011
2012 ret = command_setlights(gspca_dev);
2013 if (ret && ret != -EINVAL)
2014 ret = -EBUSY;
2015
2016 return ret;
2017}
2018
2019static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val)
2020{
2021 return sd_setilluminator(gspca_dev, val, 1);
2022}
2023
2024static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val)
2025{
2026 return sd_setilluminator(gspca_dev, val, 2);
2027}
2028
2029static int sd_getilluminator(struct gspca_dev *gspca_dev, __s32 *val, int n)
2030{
2031 struct sd *sd = (struct sd *) gspca_dev;
2032
2033 if (!sd->params.qx3.qx3_detected)
2034 return -EINVAL;
2035
2036 switch (n) {
2037 case 1:
2038 *val = sd->params.qx3.bottomlight;
2039 break;
2040 case 2:
2041 *val = sd->params.qx3.toplight;
2042 break;
2043 default:
2044 return -EINVAL;
2045 }
2046 return 0;
2047}
2048
2049static int sd_getilluminator1(struct gspca_dev *gspca_dev, __s32 *val)
2050{
2051 return sd_getilluminator(gspca_dev, val, 1);
2052}
2053
2054static int sd_getilluminator2(struct gspca_dev *gspca_dev, __s32 *val)
2055{
2056 return sd_getilluminator(gspca_dev, val, 2);
2057}
2058
2059static int sd_querymenu(struct gspca_dev *gspca_dev,
2060 struct v4l2_querymenu *menu)
2061{
2062 switch (menu->id) {
2063 case V4L2_CID_POWER_LINE_FREQUENCY:
2064 switch (menu->index) {
2065 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
2066 strcpy((char *) menu->name, "NoFliker");
2067 return 0;
2068 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
2069 strcpy((char *) menu->name, "50 Hz");
2070 return 0;
2071 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
2072 strcpy((char *) menu->name, "60 Hz");
2073 return 0;
2074 }
2075 break;
2076 case V4L2_CID_COMP_TARGET:
2077 switch (menu->index) {
2078 case CPIA_COMPRESSION_TARGET_QUALITY:
2079 strcpy((char *) menu->name, "Quality");
2080 return 0;
2081 case CPIA_COMPRESSION_TARGET_FRAMERATE:
2082 strcpy((char *) menu->name, "Framerate");
2083 return 0;
2084 }
2085 break;
2086 }
2087 return -EINVAL;
2088}
2089
2090/* sub-driver description */
2091static const struct sd_desc sd_desc = {
2092 .name = MODULE_NAME,
2093 .ctrls = sd_ctrls,
2094 .nctrls = ARRAY_SIZE(sd_ctrls),
2095 .config = sd_config,
2096 .init = sd_init,
2097 .start = sd_start,
2098 .stopN = sd_stopN,
2099 .dq_callback = sd_dq_callback,
2100 .pkt_scan = sd_pkt_scan,
2101 .querymenu = sd_querymenu,
2102#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2103 .other_input = 1,
2104#endif
2105};
2106
2107/* -- module initialisation -- */
2108static const struct usb_device_id device_table[] = {
2109 {USB_DEVICE(0x0553, 0x0002)},
2110 {USB_DEVICE(0x0813, 0x0001)},
2111 {}
2112};
2113MODULE_DEVICE_TABLE(usb, device_table);
2114
2115/* -- device connect -- */
2116static int sd_probe(struct usb_interface *intf,
2117 const struct usb_device_id *id)
2118{
2119 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2120 THIS_MODULE);
2121}
2122
2123static struct usb_driver sd_driver = {
2124 .name = MODULE_NAME,
2125 .id_table = device_table,
2126 .probe = sd_probe,
2127 .disconnect = gspca_disconnect,
2128#ifdef CONFIG_PM
2129 .suspend = gspca_suspend,
2130 .resume = gspca_resume,
2131#endif
2132};
2133
2134/* -- module insert / remove -- */
2135static int __init sd_mod_init(void)
2136{
2137 return usb_register(&sd_driver);
2138}
2139static void __exit sd_mod_exit(void)
2140{
2141 usb_deregister(&sd_driver);
2142}
2143
2144module_init(sd_mod_init);
2145module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
new file mode 100644
index 00000000000..4b2c483fce6
--- /dev/null
+++ b/drivers/media/video/gspca/etoms.c
@@ -0,0 +1,908 @@
1/*
2 * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004)
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "etoms"
22
23#include "gspca.h"
24
25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26MODULE_DESCRIPTION("Etoms 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 unsigned char brightness;
34 unsigned char contrast;
35 unsigned char colors;
36 unsigned char autogain;
37
38 char sensor;
39#define SENSOR_PAS106 0
40#define SENSOR_TAS5130CXX 1
41 signed char ag_cnt;
42#define AG_CNT_START 13
43};
44
45/* V4L2 controls supported by the driver */
46static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
47static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
48static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
54
55static const struct ctrl sd_ctrls[] = {
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 1,
62 .maximum = 127,
63 .step = 1,
64#define BRIGHTNESS_DEF 63
65 .default_value = BRIGHTNESS_DEF,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70 {
71 {
72 .id = V4L2_CID_CONTRAST,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Contrast",
75 .minimum = 0,
76 .maximum = 255,
77 .step = 1,
78#define CONTRAST_DEF 127
79 .default_value = CONTRAST_DEF,
80 },
81 .set = sd_setcontrast,
82 .get = sd_getcontrast,
83 },
84#define COLOR_IDX 2
85 {
86 {
87 .id = V4L2_CID_SATURATION,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Color",
90 .minimum = 0,
91 .maximum = 15,
92 .step = 1,
93#define COLOR_DEF 7
94 .default_value = COLOR_DEF,
95 },
96 .set = sd_setcolors,
97 .get = sd_getcolors,
98 },
99 {
100 {
101 .id = V4L2_CID_AUTOGAIN,
102 .type = V4L2_CTRL_TYPE_BOOLEAN,
103 .name = "Auto Gain",
104 .minimum = 0,
105 .maximum = 1,
106 .step = 1,
107#define AUTOGAIN_DEF 1
108 .default_value = AUTOGAIN_DEF,
109 },
110 .set = sd_setautogain,
111 .get = sd_getautogain,
112 },
113};
114
115static const struct v4l2_pix_format vga_mode[] = {
116 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
117 .bytesperline = 320,
118 .sizeimage = 320 * 240,
119 .colorspace = V4L2_COLORSPACE_SRGB,
120 .priv = 1},
121/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
122 .bytesperline = 640,
123 .sizeimage = 640 * 480,
124 .colorspace = V4L2_COLORSPACE_SRGB,
125 .priv = 0}, */
126};
127
128static const struct v4l2_pix_format sif_mode[] = {
129 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
130 .bytesperline = 176,
131 .sizeimage = 176 * 144,
132 .colorspace = V4L2_COLORSPACE_SRGB,
133 .priv = 1},
134 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
135 .bytesperline = 352,
136 .sizeimage = 352 * 288,
137 .colorspace = V4L2_COLORSPACE_SRGB,
138 .priv = 0},
139};
140
141#define ETOMS_ALT_SIZE_1000 12
142
143#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */
144#define ET_GPIO_OUT 0x05 /* Only IO data */
145#define ET_GPIO_IN 0x06 /* Read Only IO data */
146#define ET_RESET_ALL 0x03
147#define ET_ClCK 0x01
148#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */
149
150#define ET_COMP 0x12 /* Compression register */
151#define ET_MAXQt 0x13
152#define ET_MINQt 0x14
153#define ET_COMP_VAL0 0x02
154#define ET_COMP_VAL1 0x03
155
156#define ET_REG1d 0x1d
157#define ET_REG1e 0x1e
158#define ET_REG1f 0x1f
159#define ET_REG20 0x20
160#define ET_REG21 0x21
161#define ET_REG22 0x22
162#define ET_REG23 0x23
163#define ET_REG24 0x24
164#define ET_REG25 0x25
165/* base registers for luma calculation */
166#define ET_LUMA_CENTER 0x39
167
168#define ET_G_RED 0x4d
169#define ET_G_GREEN1 0x4e
170#define ET_G_BLUE 0x4f
171#define ET_G_GREEN2 0x50
172#define ET_G_GR_H 0x51
173#define ET_G_GB_H 0x52
174
175#define ET_O_RED 0x34
176#define ET_O_GREEN1 0x35
177#define ET_O_BLUE 0x36
178#define ET_O_GREEN2 0x37
179
180#define ET_SYNCHRO 0x68
181#define ET_STARTX 0x69
182#define ET_STARTY 0x6a
183#define ET_WIDTH_LOW 0x6b
184#define ET_HEIGTH_LOW 0x6c
185#define ET_W_H_HEIGTH 0x6d
186
187#define ET_REG6e 0x6e /* OBW */
188#define ET_REG6f 0x6f /* OBW */
189#define ET_REG70 0x70 /* OBW_AWB */
190#define ET_REG71 0x71 /* OBW_AWB */
191#define ET_REG72 0x72 /* OBW_AWB */
192#define ET_REG73 0x73 /* Clkdelay ns */
193#define ET_REG74 0x74 /* test pattern */
194#define ET_REG75 0x75 /* test pattern */
195
196#define ET_I2C_CLK 0x8c
197#define ET_PXL_CLK 0x60
198
199#define ET_I2C_BASE 0x89
200#define ET_I2C_COUNT 0x8a
201#define ET_I2C_PREFETCH 0x8b
202#define ET_I2C_REG 0x88
203#define ET_I2C_DATA7 0x87
204#define ET_I2C_DATA6 0x86
205#define ET_I2C_DATA5 0x85
206#define ET_I2C_DATA4 0x84
207#define ET_I2C_DATA3 0x83
208#define ET_I2C_DATA2 0x82
209#define ET_I2C_DATA1 0x81
210#define ET_I2C_DATA0 0x80
211
212#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */
213#define PAS106_REG3 0x03 /* line/frame H [11..4] */
214#define PAS106_REG4 0x04 /* line/frame L [3..0] */
215#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */
216#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */
217#define PAS106_REG7 0x07 /* signbit Dac (default 0) */
218#define PAS106_REG9 0x09
219#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */
220#define PAS106_REG13 0x13 /* end i2c write */
221
222static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
223
224static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };
225
226static const __u8 I2c3[] = { 0x12, 0x05 };
227
228static const __u8 I2c4[] = { 0x41, 0x08 };
229
230/* read 'len' bytes to gspca_dev->usb_buf */
231static void reg_r(struct gspca_dev *gspca_dev,
232 __u16 index,
233 __u16 len)
234{
235 struct usb_device *dev = gspca_dev->dev;
236
237#ifdef GSPCA_DEBUG
238 if (len > USB_BUF_SZ) {
239 err("reg_r: buffer overflow");
240 return;
241 }
242#endif
243 usb_control_msg(dev,
244 usb_rcvctrlpipe(dev, 0),
245 0,
246 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
247 0,
248 index, gspca_dev->usb_buf, len, 500);
249 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
250 index, gspca_dev->usb_buf[0]);
251}
252
253static void reg_w_val(struct gspca_dev *gspca_dev,
254 __u16 index,
255 __u8 val)
256{
257 struct usb_device *dev = gspca_dev->dev;
258
259 gspca_dev->usb_buf[0] = val;
260 usb_control_msg(dev,
261 usb_sndctrlpipe(dev, 0),
262 0,
263 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
264 0,
265 index, gspca_dev->usb_buf, 1, 500);
266}
267
268static void reg_w(struct gspca_dev *gspca_dev,
269 __u16 index,
270 const __u8 *buffer,
271 __u16 len)
272{
273 struct usb_device *dev = gspca_dev->dev;
274
275#ifdef GSPCA_DEBUG
276 if (len > USB_BUF_SZ) {
277 err("reg_w: buffer overflow");
278 return;
279 }
280 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
281#endif
282 memcpy(gspca_dev->usb_buf, buffer, len);
283 usb_control_msg(dev,
284 usb_sndctrlpipe(dev, 0),
285 0,
286 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
287 0, index, gspca_dev->usb_buf, len, 500);
288}
289
290static int i2c_w(struct gspca_dev *gspca_dev,
291 __u8 reg,
292 const __u8 *buffer,
293 int len, __u8 mode)
294{
295 /* buffer should be [D0..D7] */
296 __u8 ptchcount;
297
298 /* set the base address */
299 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
300 /* sensor base for the pas106 */
301 /* set count and prefetch */
302 ptchcount = ((len & 0x07) << 4) | (mode & 0x03);
303 reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount);
304 /* set the register base */
305 reg_w_val(gspca_dev, ET_I2C_REG, reg);
306 while (--len >= 0)
307 reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]);
308 return 0;
309}
310
311static int i2c_r(struct gspca_dev *gspca_dev,
312 __u8 reg)
313{
314 /* set the base address */
315 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
316 /* sensor base for the pas106 */
317 /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */
318 reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11);
319 reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */
320 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */
321 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00);
322 reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */
323 return 0;
324}
325
326static int Et_WaitStatus(struct gspca_dev *gspca_dev)
327{
328 int retry = 10;
329
330 while (retry--) {
331 reg_r(gspca_dev, ET_ClCK, 1);
332 if (gspca_dev->usb_buf[0] != 0)
333 return 1;
334 }
335 return 0;
336}
337
338static int et_video(struct gspca_dev *gspca_dev,
339 int on)
340{
341 int ret;
342
343 reg_w_val(gspca_dev, ET_GPIO_OUT,
344 on ? 0x10 /* startvideo - set Bit5 */
345 : 0); /* stopvideo */
346 ret = Et_WaitStatus(gspca_dev);
347 if (ret != 0)
348 PDEBUG(D_ERR, "timeout video on/off");
349 return ret;
350}
351
352static void Et_init2(struct gspca_dev *gspca_dev)
353{
354 __u8 value;
355 static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 };
356
357 PDEBUG(D_STREAM, "Open Init2 ET");
358 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f);
359 reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10);
360 reg_r(gspca_dev, ET_GPIO_IN, 1);
361 reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */
362 reg_w_val(gspca_dev, ET_CTRL, 0x1b);
363
364 /* compression et subsampling */
365 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
366 value = ET_COMP_VAL1; /* 320 */
367 else
368 value = ET_COMP_VAL0; /* 640 */
369 reg_w_val(gspca_dev, ET_COMP, value);
370 reg_w_val(gspca_dev, ET_MAXQt, 0x1f);
371 reg_w_val(gspca_dev, ET_MINQt, 0x04);
372 /* undocumented registers */
373 reg_w_val(gspca_dev, ET_REG1d, 0xff);
374 reg_w_val(gspca_dev, ET_REG1e, 0xff);
375 reg_w_val(gspca_dev, ET_REG1f, 0xff);
376 reg_w_val(gspca_dev, ET_REG20, 0x35);
377 reg_w_val(gspca_dev, ET_REG21, 0x01);
378 reg_w_val(gspca_dev, ET_REG22, 0x00);
379 reg_w_val(gspca_dev, ET_REG23, 0xff);
380 reg_w_val(gspca_dev, ET_REG24, 0xff);
381 reg_w_val(gspca_dev, ET_REG25, 0x0f);
382 /* colors setting */
383 reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */
384 reg_w_val(gspca_dev, 0x31, 0x40);
385 reg_w_val(gspca_dev, 0x32, 0x00);
386 reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */
387 reg_w_val(gspca_dev, ET_O_GREEN1, 0x00);
388 reg_w_val(gspca_dev, ET_O_BLUE, 0x00);
389 reg_w_val(gspca_dev, ET_O_GREEN2, 0x00);
390 /*************/
391 reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */
392 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
393 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
394 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
395 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
396 reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */
397 /* Window control registers */
398 reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */
399 reg_w_val(gspca_dev, 0x62, 0x02);
400 reg_w_val(gspca_dev, 0x63, 0x03);
401 reg_w_val(gspca_dev, 0x64, 0x14);
402 reg_w_val(gspca_dev, 0x65, 0x0e);
403 reg_w_val(gspca_dev, 0x66, 0x02);
404 reg_w_val(gspca_dev, 0x67, 0x02);
405
406 /**************************************/
407 reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */
408 reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */
409 reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */
410 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80);
411 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0);
412 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */
413 reg_w_val(gspca_dev, ET_REG6e, 0x86);
414 reg_w_val(gspca_dev, ET_REG6f, 0x01);
415 reg_w_val(gspca_dev, ET_REG70, 0x26);
416 reg_w_val(gspca_dev, ET_REG71, 0x7a);
417 reg_w_val(gspca_dev, ET_REG72, 0x01);
418 /* Clock Pattern registers ***************** */
419 reg_w_val(gspca_dev, ET_REG73, 0x00);
420 reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */
421 reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */
422 /**********************************************/
423 reg_w_val(gspca_dev, 0x8a, 0x20);
424 reg_w_val(gspca_dev, 0x8d, 0x0f);
425 reg_w_val(gspca_dev, 0x8e, 0x08);
426 /**************************************/
427 reg_w_val(gspca_dev, 0x03, 0x08);
428 reg_w_val(gspca_dev, ET_PXL_CLK, 0x03);
429 reg_w_val(gspca_dev, 0x81, 0xff);
430 reg_w_val(gspca_dev, 0x80, 0x00);
431 reg_w_val(gspca_dev, 0x81, 0xff);
432 reg_w_val(gspca_dev, 0x80, 0x20);
433 reg_w_val(gspca_dev, 0x03, 0x01);
434 reg_w_val(gspca_dev, 0x03, 0x00);
435 reg_w_val(gspca_dev, 0x03, 0x08);
436 /********************************************/
437
438/* reg_r(gspca_dev, ET_I2C_BASE, 1);
439 always 0x40 as the pas106 ??? */
440 /* set the sensor */
441 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
442 value = 0x04; /* 320 */
443 else /* 640 */
444 value = 0x1e; /* 0x17 * setting PixelClock
445 * 0x03 mean 24/(3+1) = 6 Mhz
446 * 0x05 -> 24/(5+1) = 4 Mhz
447 * 0x0b -> 24/(11+1) = 2 Mhz
448 * 0x17 -> 24/(23+1) = 1 Mhz
449 */
450 reg_w_val(gspca_dev, ET_PXL_CLK, value);
451 /* now set by fifo the FormatLine setting */
452 reg_w(gspca_dev, 0x62, FormLine, 6);
453
454 /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */
455 reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */
456 reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */
457 /* Pedro change */
458 /* Brightness change Brith+ decrease value */
459 /* Brigth- increase value */
460 /* original value = 0x70; */
461 reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */
462 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */
463}
464
465static void setbrightness(struct gspca_dev *gspca_dev)
466{
467 struct sd *sd = (struct sd *) gspca_dev;
468 int i;
469 __u8 brightness = sd->brightness;
470
471 for (i = 0; i < 4; i++)
472 reg_w_val(gspca_dev, ET_O_RED + i, brightness);
473}
474
475static void setcontrast(struct gspca_dev *gspca_dev)
476{
477 struct sd *sd = (struct sd *) gspca_dev;
478 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
479 __u8 contrast = sd->contrast;
480
481 memset(RGBG, contrast, sizeof(RGBG) - 2);
482 reg_w(gspca_dev, ET_G_RED, RGBG, 6);
483}
484
485static void setcolors(struct gspca_dev *gspca_dev)
486{
487 struct sd *sd = (struct sd *) gspca_dev;
488 __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d };
489 __u8 i2cflags = 0x01;
490 /* __u8 green = 0; */
491 __u8 colors = sd->colors;
492
493 I2cc[3] = colors; /* red */
494 I2cc[0] = 15 - colors; /* blue */
495 /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */
496 /* I2cc[1] = I2cc[2] = green; */
497 if (sd->sensor == SENSOR_PAS106) {
498 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
499 i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1);
500 }
501/* PDEBUG(D_CONF , "Etoms red %d blue %d green %d",
502 I2cc[3], I2cc[0], green); */
503}
504
505static void getcolors(struct gspca_dev *gspca_dev)
506{
507 struct sd *sd = (struct sd *) gspca_dev;
508
509 if (sd->sensor == SENSOR_PAS106) {
510/* i2c_r(gspca_dev, PAS106_REG9); * blue */
511 i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */
512 sd->colors = gspca_dev->usb_buf[0] & 0x0f;
513 }
514}
515
516static void setautogain(struct gspca_dev *gspca_dev)
517{
518 struct sd *sd = (struct sd *) gspca_dev;
519
520 if (sd->autogain)
521 sd->ag_cnt = AG_CNT_START;
522 else
523 sd->ag_cnt = -1;
524}
525
526static void Et_init1(struct gspca_dev *gspca_dev)
527{
528 __u8 value;
529/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */
530 __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 };
531 /* try 1/120 0x6d 0xcd 0x40 */
532/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00};
533 * 1/60000 hmm ?? */
534
535 PDEBUG(D_STREAM, "Open Init1 ET");
536 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7);
537 reg_r(gspca_dev, ET_GPIO_IN, 1);
538 reg_w_val(gspca_dev, ET_RESET_ALL, 1);
539 reg_w_val(gspca_dev, ET_RESET_ALL, 0);
540 reg_w_val(gspca_dev, ET_ClCK, 0x10);
541 reg_w_val(gspca_dev, ET_CTRL, 0x19);
542 /* compression et subsampling */
543 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
544 value = ET_COMP_VAL1;
545 else
546 value = ET_COMP_VAL0;
547 PDEBUG(D_STREAM, "Open mode %d Compression %d",
548 gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv,
549 value);
550 reg_w_val(gspca_dev, ET_COMP, value);
551 reg_w_val(gspca_dev, ET_MAXQt, 0x1d);
552 reg_w_val(gspca_dev, ET_MINQt, 0x02);
553 /* undocumented registers */
554 reg_w_val(gspca_dev, ET_REG1d, 0xff);
555 reg_w_val(gspca_dev, ET_REG1e, 0xff);
556 reg_w_val(gspca_dev, ET_REG1f, 0xff);
557 reg_w_val(gspca_dev, ET_REG20, 0x35);
558 reg_w_val(gspca_dev, ET_REG21, 0x01);
559 reg_w_val(gspca_dev, ET_REG22, 0x00);
560 reg_w_val(gspca_dev, ET_REG23, 0xf7);
561 reg_w_val(gspca_dev, ET_REG24, 0xff);
562 reg_w_val(gspca_dev, ET_REG25, 0x07);
563 /* colors setting */
564 reg_w_val(gspca_dev, ET_G_RED, 0x80);
565 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
566 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
567 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
568 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
569 reg_w_val(gspca_dev, ET_G_GB_H, 0x00);
570 /* Window control registers */
571 reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0);
572 reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */
573 reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */
574 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60);
575 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20);
576 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50);
577 reg_w_val(gspca_dev, ET_REG6e, 0x86);
578 reg_w_val(gspca_dev, ET_REG6f, 0x01);
579 reg_w_val(gspca_dev, ET_REG70, 0x86);
580 reg_w_val(gspca_dev, ET_REG71, 0x14);
581 reg_w_val(gspca_dev, ET_REG72, 0x00);
582 /* Clock Pattern registers */
583 reg_w_val(gspca_dev, ET_REG73, 0x00);
584 reg_w_val(gspca_dev, ET_REG74, 0x00);
585 reg_w_val(gspca_dev, ET_REG75, 0x0a);
586 reg_w_val(gspca_dev, ET_I2C_CLK, 0x04);
587 reg_w_val(gspca_dev, ET_PXL_CLK, 0x01);
588 /* set the sensor */
589 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
590 I2c0[0] = 0x06;
591 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
592 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
593 value = 0x06;
594 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
595 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
596 /* value = 0x1f; */
597 value = 0x04;
598 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
599 } else {
600 I2c0[0] = 0x0a;
601
602 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
603 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
604 value = 0x0a;
605 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
606 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
607 value = 0x04;
608 /* value = 0x10; */
609 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
610 /* bit 2 enable bit 1:2 select 0 1 2 3
611 value = 0x07; * curve 0 *
612 i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1);
613 */
614 }
615
616/* value = 0x01; */
617/* value = 0x22; */
618/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */
619 /* magnetude and sign bit for DAC */
620 i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1);
621 /* now set by fifo the whole colors setting */
622 reg_w(gspca_dev, ET_G_RED, GainRGBG, 6);
623 getcolors(gspca_dev);
624 setcolors(gspca_dev);
625}
626
627/* this function is called at probe time */
628static int sd_config(struct gspca_dev *gspca_dev,
629 const struct usb_device_id *id)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
632 struct cam *cam;
633
634 cam = &gspca_dev->cam;
635 sd->sensor = id->driver_info;
636 if (sd->sensor == SENSOR_PAS106) {
637 cam->cam_mode = sif_mode;
638 cam->nmodes = ARRAY_SIZE(sif_mode);
639 } else {
640 cam->cam_mode = vga_mode;
641 cam->nmodes = ARRAY_SIZE(vga_mode);
642 gspca_dev->ctrl_dis = (1 << COLOR_IDX);
643 }
644 sd->brightness = BRIGHTNESS_DEF;
645 sd->contrast = CONTRAST_DEF;
646 sd->colors = COLOR_DEF;
647 sd->autogain = AUTOGAIN_DEF;
648 sd->ag_cnt = -1;
649 return 0;
650}
651
652/* this function is called at probe and resume time */
653static int sd_init(struct gspca_dev *gspca_dev)
654{
655 struct sd *sd = (struct sd *) gspca_dev;
656
657 if (sd->sensor == SENSOR_PAS106)
658 Et_init1(gspca_dev);
659 else
660 Et_init2(gspca_dev);
661 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
662 et_video(gspca_dev, 0); /* video off */
663 return 0;
664}
665
666/* -- start the camera -- */
667static int sd_start(struct gspca_dev *gspca_dev)
668{
669 struct sd *sd = (struct sd *) gspca_dev;
670
671 if (sd->sensor == SENSOR_PAS106)
672 Et_init1(gspca_dev);
673 else
674 Et_init2(gspca_dev);
675
676 setautogain(gspca_dev);
677
678 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
679 et_video(gspca_dev, 1); /* video on */
680 return 0;
681}
682
683static void sd_stopN(struct gspca_dev *gspca_dev)
684{
685 et_video(gspca_dev, 0); /* video off */
686}
687
688static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691
692 if (sd->sensor == SENSOR_PAS106) {
693 i2c_r(gspca_dev, PAS106_REG0e);
694 PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]);
695 return gspca_dev->usb_buf[0];
696 }
697 return 0x1f;
698}
699
700static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
701{
702 struct sd *sd = (struct sd *) gspca_dev;
703
704 if (sd->sensor == SENSOR_PAS106) {
705 __u8 i2cflags = 0x01;
706
707 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
708 i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
709 }
710}
711
712#define BLIMIT(bright) \
713 (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright))
714#define LIMIT(color) \
715 (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color))
716
717static void do_autogain(struct gspca_dev *gspca_dev)
718{
719 struct sd *sd = (struct sd *) gspca_dev;
720 __u8 luma;
721 __u8 luma_mean = 128;
722 __u8 luma_delta = 20;
723 __u8 spring = 4;
724 int Gbright;
725 __u8 r, g, b;
726
727 if (sd->ag_cnt < 0)
728 return;
729 if (--sd->ag_cnt >= 0)
730 return;
731 sd->ag_cnt = AG_CNT_START;
732
733 Gbright = Et_getgainG(gspca_dev);
734 reg_r(gspca_dev, ET_LUMA_CENTER, 4);
735 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
736 r = gspca_dev->usb_buf[1];
737 b = gspca_dev->usb_buf[2];
738 r = ((r << 8) - (r << 4) - (r << 3)) >> 10;
739 b = ((b << 7) >> 10);
740 g = ((g << 9) + (g << 7) + (g << 5)) >> 10;
741 luma = LIMIT(r + g + b);
742 PDEBUG(D_FRAM, "Etoms luma G %d", luma);
743 if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) {
744 Gbright += (luma_mean - luma) >> spring;
745 Gbright = BLIMIT(Gbright);
746 PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright);
747 Et_setgainG(gspca_dev, (__u8) Gbright);
748 }
749}
750
751#undef BLIMIT
752#undef LIMIT
753
754static void sd_pkt_scan(struct gspca_dev *gspca_dev,
755 u8 *data, /* isoc packet */
756 int len) /* iso packet length */
757{
758 int seqframe;
759
760 seqframe = data[0] & 0x3f;
761 len = (int) (((data[0] & 0xc0) << 2) | data[1]);
762 if (seqframe == 0x3f) {
763 PDEBUG(D_FRAM,
764 "header packet found datalength %d !!", len);
765 PDEBUG(D_FRAM, "G %d R %d G %d B %d",
766 data[2], data[3], data[4], data[5]);
767 data += 30;
768 /* don't change datalength as the chips provided it */
769 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
770 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
771 return;
772 }
773 if (len) {
774 data += 8;
775 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
776 } else { /* Drop Packet */
777 gspca_dev->last_packet_type = DISCARD_PACKET;
778 }
779}
780
781static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
782{
783 struct sd *sd = (struct sd *) gspca_dev;
784
785 sd->brightness = val;
786 if (gspca_dev->streaming)
787 setbrightness(gspca_dev);
788 return 0;
789}
790
791static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794
795 *val = sd->brightness;
796 return 0;
797}
798
799static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
800{
801 struct sd *sd = (struct sd *) gspca_dev;
802
803 sd->contrast = val;
804 if (gspca_dev->streaming)
805 setcontrast(gspca_dev);
806 return 0;
807}
808
809static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
810{
811 struct sd *sd = (struct sd *) gspca_dev;
812
813 *val = sd->contrast;
814 return 0;
815}
816
817static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
818{
819 struct sd *sd = (struct sd *) gspca_dev;
820
821 sd->colors = val;
822 if (gspca_dev->streaming)
823 setcolors(gspca_dev);
824 return 0;
825}
826
827static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
828{
829 struct sd *sd = (struct sd *) gspca_dev;
830
831 *val = sd->colors;
832 return 0;
833}
834
835static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
836{
837 struct sd *sd = (struct sd *) gspca_dev;
838
839 sd->autogain = val;
840 if (gspca_dev->streaming)
841 setautogain(gspca_dev);
842 return 0;
843}
844
845static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
846{
847 struct sd *sd = (struct sd *) gspca_dev;
848
849 *val = sd->autogain;
850 return 0;
851}
852
853/* sub-driver description */
854static const struct sd_desc sd_desc = {
855 .name = MODULE_NAME,
856 .ctrls = sd_ctrls,
857 .nctrls = ARRAY_SIZE(sd_ctrls),
858 .config = sd_config,
859 .init = sd_init,
860 .start = sd_start,
861 .stopN = sd_stopN,
862 .pkt_scan = sd_pkt_scan,
863 .dq_callback = do_autogain,
864};
865
866/* -- module initialisation -- */
867static const struct usb_device_id device_table[] = {
868 {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
869#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
870 {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
871#endif
872 {}
873};
874
875MODULE_DEVICE_TABLE(usb, device_table);
876
877/* -- device connect -- */
878static int sd_probe(struct usb_interface *intf,
879 const struct usb_device_id *id)
880{
881 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
882 THIS_MODULE);
883}
884
885static struct usb_driver sd_driver = {
886 .name = MODULE_NAME,
887 .id_table = device_table,
888 .probe = sd_probe,
889 .disconnect = gspca_disconnect,
890#ifdef CONFIG_PM
891 .suspend = gspca_suspend,
892 .resume = gspca_resume,
893#endif
894};
895
896/* -- module insert / remove -- */
897static int __init sd_mod_init(void)
898{
899 return usb_register(&sd_driver);
900}
901
902static void __exit sd_mod_exit(void)
903{
904 usb_deregister(&sd_driver);
905}
906
907module_init(sd_mod_init);
908module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
new file mode 100644
index 00000000000..987b4b69d7a
--- /dev/null
+++ b/drivers/media/video/gspca/finepix.c
@@ -0,0 +1,303 @@
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 MODULE_NAME "finepix"
22
23#include "gspca.h"
24
25MODULE_AUTHOR("Frank Zago <frank@zago.net>");
26MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
27MODULE_LICENSE("GPL");
28
29/* Default timeout, in ms */
30#define FPIX_TIMEOUT 250
31
32/* Maximum transfer size to use. The windows driver reads by chunks of
33 * 0x2000 bytes, so do the same. Note: reading more seems to work
34 * too. */
35#define FPIX_MAX_TRANSFER 0x2000
36
37/* Structure to hold all of our device specific stuff */
38struct usb_fpix {
39 struct gspca_dev gspca_dev; /* !! must be the first item */
40
41 struct work_struct work_struct;
42 struct workqueue_struct *work_thread;
43};
44
45/* Delay after which claim the next frame. If the delay is too small,
46 * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
47 * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
48 * 30ms is bad while 35ms is perfect. */
49#define NEXT_FRAME_DELAY 35
50
51/* These cameras only support 320x200. */
52static const struct v4l2_pix_format fpix_mode[1] = {
53 { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
54 .bytesperline = 320,
55 .sizeimage = 320 * 240 * 3 / 8 + 590,
56 .colorspace = V4L2_COLORSPACE_SRGB,
57 .priv = 0}
58};
59
60/* send a command to the webcam */
61static int command(struct gspca_dev *gspca_dev,
62 int order) /* 0: reset, 1: frame request */
63{
64 static u8 order_values[2][12] = {
65 {0xc6, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0}, /* reset */
66 {0xd3, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0}, /* fr req */
67 };
68
69 memcpy(gspca_dev->usb_buf, order_values[order], 12);
70 return usb_control_msg(gspca_dev->dev,
71 usb_sndctrlpipe(gspca_dev->dev, 0),
72 USB_REQ_GET_STATUS,
73 USB_DIR_OUT | USB_TYPE_CLASS |
74 USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
75 12, FPIX_TIMEOUT);
76}
77
78/* workqueue */
79static void dostream(struct work_struct *work)
80{
81 struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
82 struct gspca_dev *gspca_dev = &dev->gspca_dev;
83 struct urb *urb = gspca_dev->urb[0];
84 u8 *data = urb->transfer_buffer;
85 int ret = 0;
86 int len;
87
88 /* synchronize with the main driver */
89 mutex_lock(&gspca_dev->usb_lock);
90 mutex_unlock(&gspca_dev->usb_lock);
91 PDEBUG(D_STREAM, "dostream started");
92
93 /* loop reading a frame */
94again:
95 while (gspca_dev->present && gspca_dev->streaming) {
96
97 /* request a frame */
98 mutex_lock(&gspca_dev->usb_lock);
99 ret = command(gspca_dev, 1);
100 mutex_unlock(&gspca_dev->usb_lock);
101 if (ret < 0)
102 break;
103 if (!gspca_dev->present || !gspca_dev->streaming)
104 break;
105
106 /* the frame comes in parts */
107 for (;;) {
108 ret = usb_bulk_msg(gspca_dev->dev,
109 urb->pipe,
110 data,
111 FPIX_MAX_TRANSFER,
112 &len, FPIX_TIMEOUT);
113 if (ret < 0) {
114 /* Most of the time we get a timeout
115 * error. Just restart. */
116 goto again;
117 }
118 if (!gspca_dev->present || !gspca_dev->streaming)
119 goto out;
120 if (len < FPIX_MAX_TRANSFER ||
121 (data[len - 2] == 0xff &&
122 data[len - 1] == 0xd9)) {
123
124 /* If the result is less than what was asked
125 * for, then it's the end of the
126 * frame. Sometimes the jpeg is not complete,
127 * but there's nothing we can do. We also end
128 * here if the the jpeg ends right at the end
129 * of the frame. */
130 gspca_frame_add(gspca_dev, LAST_PACKET,
131 data, len);
132 break;
133 }
134
135 /* got a partial image */
136 gspca_frame_add(gspca_dev,
137 gspca_dev->last_packet_type
138 == LAST_PACKET
139 ? FIRST_PACKET : INTER_PACKET,
140 data, len);
141 }
142
143 /* We must wait before trying reading the next
144 * frame. If we don't, or if the delay is too short,
145 * the camera will disconnect. */
146 msleep(NEXT_FRAME_DELAY);
147 }
148
149out:
150 PDEBUG(D_STREAM, "dostream stopped");
151}
152
153/* this function is called at probe time */
154static int sd_config(struct gspca_dev *gspca_dev,
155 const struct usb_device_id *id)
156{
157 struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
158 struct cam *cam = &gspca_dev->cam;
159
160 cam->cam_mode = fpix_mode;
161 cam->nmodes = 1;
162 cam->bulk = 1;
163 cam->bulk_size = FPIX_MAX_TRANSFER;
164
165 INIT_WORK(&dev->work_struct, dostream);
166
167 return 0;
168}
169
170/* this function is called at probe and resume time */
171static int sd_init(struct gspca_dev *gspca_dev)
172{
173 return 0;
174}
175
176/* start the camera */
177static int sd_start(struct gspca_dev *gspca_dev)
178{
179 struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
180 int ret, len;
181
182 /* Init the device */
183 ret = command(gspca_dev, 0);
184 if (ret < 0) {
185 err("init failed %d", ret);
186 return ret;
187 }
188
189 /* Read the result of the command. Ignore the result, for it
190 * varies with the device. */
191 ret = usb_bulk_msg(gspca_dev->dev,
192 gspca_dev->urb[0]->pipe,
193 gspca_dev->urb[0]->transfer_buffer,
194 FPIX_MAX_TRANSFER, &len,
195 FPIX_TIMEOUT);
196 if (ret < 0) {
197 err("usb_bulk_msg failed %d", ret);
198 return ret;
199 }
200
201 /* Request a frame, but don't read it */
202 ret = command(gspca_dev, 1);
203 if (ret < 0) {
204 err("frame request failed %d", ret);
205 return ret;
206 }
207
208 /* Again, reset bulk in endpoint */
209 usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
210
211 /* Start the workqueue function to do the streaming */
212 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
213 queue_work(dev->work_thread, &dev->work_struct);
214
215 return 0;
216}
217
218/* called on streamoff with alt==0 and on disconnect */
219/* the usb_lock is held at entry - restore on exit */
220static void sd_stop0(struct gspca_dev *gspca_dev)
221{
222 struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
223
224 /* wait for the work queue to terminate */
225 mutex_unlock(&gspca_dev->usb_lock);
226 destroy_workqueue(dev->work_thread);
227 mutex_lock(&gspca_dev->usb_lock);
228 dev->work_thread = NULL;
229}
230
231/* Table of supported USB devices */
232static const struct usb_device_id device_table[] = {
233 {USB_DEVICE(0x04cb, 0x0104)},
234 {USB_DEVICE(0x04cb, 0x0109)},
235 {USB_DEVICE(0x04cb, 0x010b)},
236 {USB_DEVICE(0x04cb, 0x010f)},
237 {USB_DEVICE(0x04cb, 0x0111)},
238 {USB_DEVICE(0x04cb, 0x0113)},
239 {USB_DEVICE(0x04cb, 0x0115)},
240 {USB_DEVICE(0x04cb, 0x0117)},
241 {USB_DEVICE(0x04cb, 0x0119)},
242 {USB_DEVICE(0x04cb, 0x011b)},
243 {USB_DEVICE(0x04cb, 0x011d)},
244 {USB_DEVICE(0x04cb, 0x0121)},
245 {USB_DEVICE(0x04cb, 0x0123)},
246 {USB_DEVICE(0x04cb, 0x0125)},
247 {USB_DEVICE(0x04cb, 0x0127)},
248 {USB_DEVICE(0x04cb, 0x0129)},
249 {USB_DEVICE(0x04cb, 0x012b)},
250 {USB_DEVICE(0x04cb, 0x012d)},
251 {USB_DEVICE(0x04cb, 0x012f)},
252 {USB_DEVICE(0x04cb, 0x0131)},
253 {USB_DEVICE(0x04cb, 0x013b)},
254 {USB_DEVICE(0x04cb, 0x013d)},
255 {USB_DEVICE(0x04cb, 0x013f)},
256 {}
257};
258
259MODULE_DEVICE_TABLE(usb, device_table);
260
261/* sub-driver description */
262static const struct sd_desc sd_desc = {
263 .name = MODULE_NAME,
264 .config = sd_config,
265 .init = sd_init,
266 .start = sd_start,
267 .stop0 = sd_stop0,
268};
269
270/* -- device connect -- */
271static int sd_probe(struct usb_interface *intf,
272 const struct usb_device_id *id)
273{
274 return gspca_dev_probe(intf, id,
275 &sd_desc,
276 sizeof(struct usb_fpix),
277 THIS_MODULE);
278}
279
280static struct usb_driver sd_driver = {
281 .name = MODULE_NAME,
282 .id_table = device_table,
283 .probe = sd_probe,
284 .disconnect = gspca_disconnect,
285#ifdef CONFIG_PM
286 .suspend = gspca_suspend,
287 .resume = gspca_resume,
288#endif
289};
290
291/* -- module insert / remove -- */
292static int __init sd_mod_init(void)
293{
294 return usb_register(&sd_driver);
295}
296
297static void __exit sd_mod_exit(void)
298{
299 usb_deregister(&sd_driver);
300}
301
302module_init(sd_mod_init);
303module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/gl860/Kconfig b/drivers/media/video/gspca/gl860/Kconfig
new file mode 100644
index 00000000000..22772f53ec7
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/gl860/Makefile b/drivers/media/video/gspca/gl860/Makefile
new file mode 100644
index 00000000000..13c9403cc87
--- /dev/null
+++ b/drivers/media/video/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
9EXTRA_CFLAGS += -Idrivers/media/video/gspca
10
diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c
new file mode 100644
index 00000000000..b57160e0486
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c
new file mode 100644
index 00000000000..2edda6b7d65
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c
new file mode 100644
index 00000000000..768cac5cd72
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/gl860/gl860-ov9655.c b/drivers/media/video/gspca/gl860/gl860-ov9655.c
new file mode 100644
index 00000000000..5ae9619d72a
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
new file mode 100644
index 00000000000..e8e071aa212
--- /dev/null
+++ b/drivers/media/video/gspca/gl860/gl860.c
@@ -0,0 +1,735 @@
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#include "gspca.h"
22#include "gl860.h"
23
24MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>");
25MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver");
26MODULE_LICENSE("GPL");
27
28/*======================== static function declarations ====================*/
29
30static void (*dev_init_settings)(struct gspca_dev *gspca_dev);
31
32static int sd_config(struct gspca_dev *gspca_dev,
33 const struct usb_device_id *id);
34static int sd_init(struct gspca_dev *gspca_dev);
35static int sd_isoc_init(struct gspca_dev *gspca_dev);
36static int sd_start(struct gspca_dev *gspca_dev);
37static void sd_stop0(struct gspca_dev *gspca_dev);
38static void sd_pkt_scan(struct gspca_dev *gspca_dev,
39 u8 *data, int len);
40static void sd_callback(struct gspca_dev *gspca_dev);
41
42static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
43 u16 vendor_id, u16 product_id);
44
45/*============================ driver options ==============================*/
46
47static s32 AC50Hz = 0xff;
48module_param(AC50Hz, int, 0644);
49MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)");
50
51static char sensor[7];
52module_param_string(sensor, sensor, sizeof(sensor), 0644);
53MODULE_PARM_DESC(sensor,
54 " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')");
55
56/*============================ webcam controls =============================*/
57
58/* Functions to get and set a control value */
59#define SD_SETGET(thename) \
60static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\
61{\
62 struct sd *sd = (struct sd *) gspca_dev;\
63\
64 sd->vcur.thename = val;\
65 if (gspca_dev->streaming)\
66 sd->waitSet = 1;\
67 return 0;\
68} \
69static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\
70{\
71 struct sd *sd = (struct sd *) gspca_dev;\
72\
73 *val = sd->vcur.thename;\
74 return 0;\
75}
76
77SD_SETGET(mirror)
78SD_SETGET(flip)
79SD_SETGET(AC50Hz)
80SD_SETGET(backlight)
81SD_SETGET(brightness)
82SD_SETGET(gamma)
83SD_SETGET(hue)
84SD_SETGET(saturation)
85SD_SETGET(sharpness)
86SD_SETGET(whitebal)
87SD_SETGET(contrast)
88
89#define GL860_NCTRLS 11
90
91/* control table */
92static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS];
93static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS];
94static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS];
95static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS];
96
97#define SET_MY_CTRL(theid, \
98 thetype, thelabel, thename) \
99 if (sd->vmax.thename != 0) {\
100 sd_ctrls[nCtrls].qctrl.id = theid;\
101 sd_ctrls[nCtrls].qctrl.type = thetype;\
102 strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\
103 sd_ctrls[nCtrls].qctrl.minimum = 0;\
104 sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\
105 sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\
106 sd_ctrls[nCtrls].qctrl.step = \
107 (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\
108 sd_ctrls[nCtrls].set = sd_set_##thename;\
109 sd_ctrls[nCtrls].get = sd_get_##thename;\
110 nCtrls++;\
111 }
112
113static int gl860_build_control_table(struct gspca_dev *gspca_dev)
114{
115 struct sd *sd = (struct sd *) gspca_dev;
116 struct ctrl *sd_ctrls;
117 int nCtrls = 0;
118
119 if (_MI1320_)
120 sd_ctrls = sd_ctrls_mi1320;
121 else if (_MI2020_)
122 sd_ctrls = sd_ctrls_mi2020;
123 else if (_OV2640_)
124 sd_ctrls = sd_ctrls_ov2640;
125 else if (_OV9655_)
126 sd_ctrls = sd_ctrls_ov9655;
127 else
128 return 0;
129
130 memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl));
131
132 SET_MY_CTRL(V4L2_CID_BRIGHTNESS,
133 V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness)
134 SET_MY_CTRL(V4L2_CID_SHARPNESS,
135 V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness)
136 SET_MY_CTRL(V4L2_CID_CONTRAST,
137 V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast)
138 SET_MY_CTRL(V4L2_CID_GAMMA,
139 V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma)
140 SET_MY_CTRL(V4L2_CID_HUE,
141 V4L2_CTRL_TYPE_INTEGER, "Palette", hue)
142 SET_MY_CTRL(V4L2_CID_SATURATION,
143 V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation)
144 SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE,
145 V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal)
146 SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION,
147 V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight)
148
149 SET_MY_CTRL(V4L2_CID_HFLIP,
150 V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror)
151 SET_MY_CTRL(V4L2_CID_VFLIP,
152 V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip)
153 SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY,
154 V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz)
155
156 return nCtrls;
157}
158
159/*==================== sud-driver structure initialisation =================*/
160
161static const struct sd_desc sd_desc_mi1320 = {
162 .name = MODULE_NAME,
163 .ctrls = sd_ctrls_mi1320,
164 .nctrls = GL860_NCTRLS,
165 .config = sd_config,
166 .init = sd_init,
167 .isoc_init = sd_isoc_init,
168 .start = sd_start,
169 .stop0 = sd_stop0,
170 .pkt_scan = sd_pkt_scan,
171 .dq_callback = sd_callback,
172};
173
174static const struct sd_desc sd_desc_mi2020 = {
175 .name = MODULE_NAME,
176 .ctrls = sd_ctrls_mi2020,
177 .nctrls = GL860_NCTRLS,
178 .config = sd_config,
179 .init = sd_init,
180 .isoc_init = sd_isoc_init,
181 .start = sd_start,
182 .stop0 = sd_stop0,
183 .pkt_scan = sd_pkt_scan,
184 .dq_callback = sd_callback,
185};
186
187static const struct sd_desc sd_desc_ov2640 = {
188 .name = MODULE_NAME,
189 .ctrls = sd_ctrls_ov2640,
190 .nctrls = GL860_NCTRLS,
191 .config = sd_config,
192 .init = sd_init,
193 .isoc_init = sd_isoc_init,
194 .start = sd_start,
195 .stop0 = sd_stop0,
196 .pkt_scan = sd_pkt_scan,
197 .dq_callback = sd_callback,
198};
199
200static const struct sd_desc sd_desc_ov9655 = {
201 .name = MODULE_NAME,
202 .ctrls = sd_ctrls_ov9655,
203 .nctrls = GL860_NCTRLS,
204 .config = sd_config,
205 .init = sd_init,
206 .isoc_init = sd_isoc_init,
207 .start = sd_start,
208 .stop0 = sd_stop0,
209 .pkt_scan = sd_pkt_scan,
210 .dq_callback = sd_callback,
211};
212
213/*=========================== sub-driver image sizes =======================*/
214
215static struct v4l2_pix_format mi2020_mode[] = {
216 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
217 .bytesperline = 640,
218 .sizeimage = 640 * 480,
219 .colorspace = V4L2_COLORSPACE_SRGB,
220 .priv = 0
221 },
222 { 800, 598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
223 .bytesperline = 800,
224 .sizeimage = 800 * 598,
225 .colorspace = V4L2_COLORSPACE_SRGB,
226 .priv = 1
227 },
228 {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
229 .bytesperline = 1280,
230 .sizeimage = 1280 * 1024,
231 .colorspace = V4L2_COLORSPACE_SRGB,
232 .priv = 2
233 },
234 {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
235 .bytesperline = 1600,
236 .sizeimage = 1600 * 1198,
237 .colorspace = V4L2_COLORSPACE_SRGB,
238 .priv = 3
239 },
240};
241
242static struct v4l2_pix_format ov2640_mode[] = {
243 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
244 .bytesperline = 640,
245 .sizeimage = 640 * 480,
246 .colorspace = V4L2_COLORSPACE_SRGB,
247 .priv = 0
248 },
249 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
250 .bytesperline = 800,
251 .sizeimage = 800 * 600,
252 .colorspace = V4L2_COLORSPACE_SRGB,
253 .priv = 1
254 },
255 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
256 .bytesperline = 1280,
257 .sizeimage = 1280 * 960,
258 .colorspace = V4L2_COLORSPACE_SRGB,
259 .priv = 2
260 },
261 {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
262 .bytesperline = 1600,
263 .sizeimage = 1600 * 1200,
264 .colorspace = V4L2_COLORSPACE_SRGB,
265 .priv = 3
266 },
267};
268
269static struct v4l2_pix_format mi1320_mode[] = {
270 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
271 .bytesperline = 640,
272 .sizeimage = 640 * 480,
273 .colorspace = V4L2_COLORSPACE_SRGB,
274 .priv = 0
275 },
276 { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
277 .bytesperline = 800,
278 .sizeimage = 800 * 600,
279 .colorspace = V4L2_COLORSPACE_SRGB,
280 .priv = 1
281 },
282 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
283 .bytesperline = 1280,
284 .sizeimage = 1280 * 960,
285 .colorspace = V4L2_COLORSPACE_SRGB,
286 .priv = 2
287 },
288};
289
290static struct v4l2_pix_format ov9655_mode[] = {
291 { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
292 .bytesperline = 640,
293 .sizeimage = 640 * 480,
294 .colorspace = V4L2_COLORSPACE_SRGB,
295 .priv = 0
296 },
297 {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
298 .bytesperline = 1280,
299 .sizeimage = 1280 * 960,
300 .colorspace = V4L2_COLORSPACE_SRGB,
301 .priv = 1
302 },
303};
304
305/*========================= sud-driver functions ===========================*/
306
307/* This function is called at probe time */
308static int sd_config(struct gspca_dev *gspca_dev,
309 const struct usb_device_id *id)
310{
311 struct sd *sd = (struct sd *) gspca_dev;
312 struct cam *cam;
313 u16 vendor_id, product_id;
314
315 /* Get USB VendorID and ProductID */
316 vendor_id = id->idVendor;
317 product_id = id->idProduct;
318
319 sd->nbRightUp = 1;
320 sd->nbIm = -1;
321
322 sd->sensor = 0xff;
323 if (strcmp(sensor, "MI1320") == 0)
324 sd->sensor = ID_MI1320;
325 else if (strcmp(sensor, "OV2640") == 0)
326 sd->sensor = ID_OV2640;
327 else if (strcmp(sensor, "OV9655") == 0)
328 sd->sensor = ID_OV9655;
329 else if (strcmp(sensor, "MI2020") == 0)
330 sd->sensor = ID_MI2020;
331
332 /* Get sensor and set the suitable init/start/../stop functions */
333 if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1)
334 return -1;
335
336 cam = &gspca_dev->cam;
337 gspca_dev->nbalt = 4;
338
339 switch (sd->sensor) {
340 case ID_MI1320:
341 gspca_dev->sd_desc = &sd_desc_mi1320;
342 cam->cam_mode = mi1320_mode;
343 cam->nmodes = ARRAY_SIZE(mi1320_mode);
344 dev_init_settings = mi1320_init_settings;
345 break;
346
347 case ID_MI2020:
348 gspca_dev->sd_desc = &sd_desc_mi2020;
349 cam->cam_mode = mi2020_mode;
350 cam->nmodes = ARRAY_SIZE(mi2020_mode);
351 dev_init_settings = mi2020_init_settings;
352 break;
353
354 case ID_OV2640:
355 gspca_dev->sd_desc = &sd_desc_ov2640;
356 cam->cam_mode = ov2640_mode;
357 cam->nmodes = ARRAY_SIZE(ov2640_mode);
358 dev_init_settings = ov2640_init_settings;
359 break;
360
361 case ID_OV9655:
362 gspca_dev->sd_desc = &sd_desc_ov9655;
363 cam->cam_mode = ov9655_mode;
364 cam->nmodes = ARRAY_SIZE(ov9655_mode);
365 dev_init_settings = ov9655_init_settings;
366 break;
367 }
368
369 dev_init_settings(gspca_dev);
370 if (AC50Hz != 0xff)
371 ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
372 gl860_build_control_table(gspca_dev);
373
374 return 0;
375}
376
377/* This function is called at probe time after sd_config */
378static int sd_init(struct gspca_dev *gspca_dev)
379{
380 struct sd *sd = (struct sd *) gspca_dev;
381
382 return sd->dev_init_at_startup(gspca_dev);
383}
384
385/* This function is called before to choose the alt setting */
386static int sd_isoc_init(struct gspca_dev *gspca_dev)
387{
388 struct sd *sd = (struct sd *) gspca_dev;
389
390 return sd->dev_configure_alt(gspca_dev);
391}
392
393/* This function is called to start the webcam */
394static int sd_start(struct gspca_dev *gspca_dev)
395{
396 struct sd *sd = (struct sd *) gspca_dev;
397
398 return sd->dev_init_pre_alt(gspca_dev);
399}
400
401/* This function is called to stop the webcam */
402static void sd_stop0(struct gspca_dev *gspca_dev)
403{
404 struct sd *sd = (struct sd *) gspca_dev;
405
406 return sd->dev_post_unset_alt(gspca_dev);
407}
408
409/* This function is called when an image is being received */
410static void sd_pkt_scan(struct gspca_dev *gspca_dev,
411 u8 *data, int len)
412{
413 struct sd *sd = (struct sd *) gspca_dev;
414 static s32 nSkipped;
415
416 s32 mode = (s32) gspca_dev->curr_mode;
417 s32 nToSkip =
418 sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
419
420 /* Test only against 0202h, so endianess does not matter */
421 switch (*(s16 *) data) {
422 case 0x0202: /* End of frame, start a new one */
423 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
424 nSkipped = 0;
425 if (sd->nbIm >= 0 && sd->nbIm < 10)
426 sd->nbIm++;
427 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
428 break;
429
430 default:
431 data += 2;
432 len -= 2;
433 if (nSkipped + len <= nToSkip)
434 nSkipped += len;
435 else {
436 if (nSkipped < nToSkip && nSkipped + len > nToSkip) {
437 data += nToSkip - nSkipped;
438 len -= nToSkip - nSkipped;
439 nSkipped = nToSkip + 1;
440 }
441 gspca_frame_add(gspca_dev,
442 INTER_PACKET, data, len);
443 }
444 break;
445 }
446}
447
448/* This function is called when an image has been read */
449/* This function is used to monitor webcam orientation */
450static void sd_callback(struct gspca_dev *gspca_dev)
451{
452 struct sd *sd = (struct sd *) gspca_dev;
453
454 if (!_OV9655_) {
455 u8 state;
456 u8 upsideDown;
457
458 /* Probe sensor orientation */
459 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);
460
461 /* C8/40 means upside-down (looking backwards) */
462 /* D8/50 means right-up (looking onwards) */
463 upsideDown = (state == 0xc8 || state == 0x40);
464
465 if (upsideDown && sd->nbRightUp > -4) {
466 if (sd->nbRightUp > 0)
467 sd->nbRightUp = 0;
468 if (sd->nbRightUp == -3) {
469 sd->mirrorMask = 1;
470 sd->waitSet = 1;
471 }
472 sd->nbRightUp--;
473 }
474 if (!upsideDown && sd->nbRightUp < 4) {
475 if (sd->nbRightUp < 0)
476 sd->nbRightUp = 0;
477 if (sd->nbRightUp == 3) {
478 sd->mirrorMask = 0;
479 sd->waitSet = 1;
480 }
481 sd->nbRightUp++;
482 }
483 }
484
485 if (sd->waitSet)
486 sd->dev_camera_settings(gspca_dev);
487}
488
489/*=================== USB driver structure initialisation ==================*/
490
491static const struct usb_device_id device_table[] = {
492 {USB_DEVICE(0x05e3, 0x0503)},
493 {USB_DEVICE(0x05e3, 0xf191)},
494 {}
495};
496
497MODULE_DEVICE_TABLE(usb, device_table);
498
499static int sd_probe(struct usb_interface *intf,
500 const struct usb_device_id *id)
501{
502 return gspca_dev_probe(intf, id,
503 &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE);
504}
505
506static void sd_disconnect(struct usb_interface *intf)
507{
508 gspca_disconnect(intf);
509}
510
511static struct usb_driver sd_driver = {
512 .name = MODULE_NAME,
513 .id_table = device_table,
514 .probe = sd_probe,
515 .disconnect = sd_disconnect,
516#ifdef CONFIG_PM
517 .suspend = gspca_suspend,
518 .resume = gspca_resume,
519#endif
520};
521
522/*====================== Init and Exit module functions ====================*/
523
524static int __init sd_mod_init(void)
525{
526 PDEBUG(D_PROBE, "driver startup - version %s", DRIVER_VERSION);
527
528 if (usb_register(&sd_driver) < 0)
529 return -1;
530 return 0;
531}
532
533static void __exit sd_mod_exit(void)
534{
535 usb_deregister(&sd_driver);
536}
537
538module_init(sd_mod_init);
539module_exit(sd_mod_exit);
540
541/*==========================================================================*/
542
543int gl860_RTx(struct gspca_dev *gspca_dev,
544 unsigned char pref, u32 req, u16 val, u16 index,
545 s32 len, void *pdata)
546{
547 struct usb_device *udev = gspca_dev->dev;
548 s32 r = 0;
549
550 if (pref == 0x40) { /* Send */
551 if (len > 0) {
552 memcpy(gspca_dev->usb_buf, pdata, len);
553 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
554 req, pref, val, index,
555 gspca_dev->usb_buf,
556 len, 400 + 200 * (len > 1));
557 } else {
558 r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
559 req, pref, val, index, NULL, len, 400);
560 }
561 } else { /* Receive */
562 if (len > 0) {
563 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
564 req, pref, val, index,
565 gspca_dev->usb_buf,
566 len, 400 + 200 * (len > 1));
567 memcpy(pdata, gspca_dev->usb_buf, len);
568 } else {
569 r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
570 req, pref, val, index, NULL, len, 400);
571 }
572 }
573
574 if (r < 0)
575 err("ctrl transfer failed %4d "
576 "[p%02x r%d v%04x i%04x len%d]",
577 r, pref, req, val, index, len);
578 else if (len > 1 && r < len)
579 PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
580
581 msleep(1);
582
583 return r;
584}
585
586int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len)
587{
588 int n;
589
590 for (n = 0; n < len; n++) {
591 if (tbl[n].idx != 0xffff)
592 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val,
593 tbl[n].idx, 0, NULL);
594 else if (tbl[n].val == 0xffff)
595 break;
596 else
597 msleep(tbl[n].val);
598 }
599 return n;
600}
601
602int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
603 int len, int n)
604{
605 while (++n < len) {
606 if (tbl[n].idx != 0xffff)
607 ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx,
608 0, NULL);
609 else if (tbl[n].val == 0xffff)
610 break;
611 else
612 msleep(tbl[n].val);
613 }
614 return n;
615}
616
617void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len)
618{
619 int n;
620
621 for (n = 0; n < len; n++) {
622 if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0)
623 ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx,
624 3, tbl[n].data);
625 else
626 msleep(tbl[n].idx);
627 }
628}
629
630static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
631 u16 vendor_id, u16 product_id)
632{
633 struct sd *sd = (struct sd *) gspca_dev;
634 u8 probe, nb26, nb96, nOV, ntry;
635
636 if (product_id == 0xf191)
637 sd->sensor = ID_MI1320;
638
639 if (sd->sensor == 0xff) {
640 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
641 ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
642
643 ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
644 msleep(3);
645 ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
646 msleep(3);
647 ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
648 msleep(3);
649 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
650 msleep(3);
651 ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
652 msleep(3);
653 ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
654 msleep(3);
655 ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
656 msleep(56);
657
658 PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX");
659 nOV = 0;
660 for (ntry = 0; ntry < 4; ntry++) {
661 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
662 msleep(3);
663 ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
664 msleep(3);
665 ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
666 msleep(10);
667 ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
668 PDEBUG(D_PROBE, "probe=0x%02x", probe);
669 if (probe == 0xff)
670 nOV++;
671 }
672
673 if (nOV) {
674 PDEBUG(D_PROBE, "0xff -> OVXXXX");
675 PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655");
676
677 nb26 = nb96 = 0;
678 for (ntry = 0; ntry < 4; ntry++) {
679 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
680 0, NULL);
681 msleep(3);
682 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
683 0, NULL);
684 msleep(10);
685
686 /* Wait for 26(OV2640) or 96(OV9655) */
687 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
688 1, &probe);
689
690 if (probe == 0x26 || probe == 0x40) {
691 PDEBUG(D_PROBE,
692 "probe=0x%02x -> OV2640",
693 probe);
694 sd->sensor = ID_OV2640;
695 nb26 += 4;
696 break;
697 }
698 if (probe == 0x96 || probe == 0x55) {
699 PDEBUG(D_PROBE,
700 "probe=0x%02x -> OV9655",
701 probe);
702 sd->sensor = ID_OV9655;
703 nb96 += 4;
704 break;
705 }
706 PDEBUG(D_PROBE, "probe=0x%02x", probe);
707 if (probe == 0x00)
708 nb26++;
709 if (probe == 0xff)
710 nb96++;
711 msleep(3);
712 }
713 if (nb26 < 4 && nb96 < 4)
714 return -1;
715 } else {
716 PDEBUG(D_PROBE, "Not any 0xff -> MI2020");
717 sd->sensor = ID_MI2020;
718 }
719 }
720
721 if (_MI1320_) {
722 PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)");
723 } else if (_MI2020_) {
724 PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)");
725 } else if (_OV9655_) {
726 PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)");
727 } else if (_OV2640_) {
728 PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)");
729 } else {
730 PDEBUG(D_PROBE, "***** Unknown sensor *****");
731 return -1;
732 }
733
734 return 0;
735}
diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h
new file mode 100644
index 00000000000..0330a0293b9
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
new file mode 100644
index 00000000000..5da4879f47f
--- /dev/null
+++ b/drivers/media/video/gspca/gspca.c
@@ -0,0 +1,2499 @@
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 MODULE_NAME "gspca"
25
26#include <linux/init.h>
27#include <linux/fs.h>
28#include <linux/vmalloc.h>
29#include <linux/sched.h>
30#include <linux/slab.h>
31#include <linux/mm.h>
32#include <linux/string.h>
33#include <linux/pagemap.h>
34#include <linux/io.h>
35#include <asm/page.h>
36#include <linux/uaccess.h>
37#include <linux/ktime.h>
38#include <media/v4l2-ioctl.h>
39
40#include "gspca.h"
41
42#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
43#include <linux/input.h>
44#include <linux/usb/input.h>
45#endif
46
47/* global values */
48#define DEF_NURBS 3 /* default number of URBs */
49#if DEF_NURBS > MAX_NURBS
50#error "DEF_NURBS too big"
51#endif
52
53#define DRIVER_VERSION_NUMBER "2.13.0"
54
55MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
56MODULE_DESCRIPTION("GSPCA USB Camera Driver");
57MODULE_LICENSE("GPL");
58MODULE_VERSION(DRIVER_VERSION_NUMBER);
59
60#ifdef GSPCA_DEBUG
61int gspca_debug = D_ERR | D_PROBE;
62EXPORT_SYMBOL(gspca_debug);
63
64static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
65{
66 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
67 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
68 txt,
69 pixfmt & 0xff,
70 (pixfmt >> 8) & 0xff,
71 (pixfmt >> 16) & 0xff,
72 pixfmt >> 24,
73 w, h);
74 } else {
75 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
76 txt,
77 pixfmt,
78 w, h);
79 }
80}
81#else
82#define PDEBUG_MODE(txt, pixfmt, w, h)
83#endif
84
85/* specific memory types - !! should be different from V4L2_MEMORY_xxx */
86#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
87#define GSPCA_MEMORY_READ 7
88
89#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
90
91/*
92 * VMA operations.
93 */
94static void gspca_vm_open(struct vm_area_struct *vma)
95{
96 struct gspca_frame *frame = vma->vm_private_data;
97
98 frame->vma_use_count++;
99 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
100}
101
102static void gspca_vm_close(struct vm_area_struct *vma)
103{
104 struct gspca_frame *frame = vma->vm_private_data;
105
106 if (--frame->vma_use_count <= 0)
107 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
108}
109
110static const struct vm_operations_struct gspca_vm_ops = {
111 .open = gspca_vm_open,
112 .close = gspca_vm_close,
113};
114
115/*
116 * Input and interrupt endpoint handling functions
117 */
118#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
119static void int_irq(struct urb *urb)
120{
121 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
122 int ret;
123
124 ret = urb->status;
125 switch (ret) {
126 case 0:
127 if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
128 urb->transfer_buffer, urb->actual_length) < 0) {
129 PDEBUG(D_ERR, "Unknown packet received");
130 }
131 break;
132
133 case -ENOENT:
134 case -ECONNRESET:
135 case -ENODEV:
136 case -ESHUTDOWN:
137 /* Stop is requested either by software or hardware is gone,
138 * keep the ret value non-zero and don't resubmit later.
139 */
140 break;
141
142 default:
143 PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
144 urb->status = 0;
145 ret = 0;
146 }
147
148 if (ret == 0) {
149 ret = usb_submit_urb(urb, GFP_ATOMIC);
150 if (ret < 0)
151 err("Resubmit URB failed with error %i", ret);
152 }
153}
154
155static int gspca_input_connect(struct gspca_dev *dev)
156{
157 struct input_dev *input_dev;
158 int err = 0;
159
160 dev->input_dev = NULL;
161 if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) {
162 input_dev = input_allocate_device();
163 if (!input_dev)
164 return -ENOMEM;
165
166 usb_make_path(dev->dev, dev->phys, sizeof(dev->phys));
167 strlcat(dev->phys, "/input0", sizeof(dev->phys));
168
169 input_dev->name = dev->sd_desc->name;
170 input_dev->phys = dev->phys;
171
172 usb_to_input_id(dev->dev, &input_dev->id);
173
174 input_dev->evbit[0] = BIT_MASK(EV_KEY);
175 input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
176 input_dev->dev.parent = &dev->dev->dev;
177
178 err = input_register_device(input_dev);
179 if (err) {
180 err("Input device registration failed with error %i",
181 err);
182 input_dev->dev.parent = NULL;
183 input_free_device(input_dev);
184 } else {
185 dev->input_dev = input_dev;
186 }
187 }
188
189 return err;
190}
191
192static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
193 struct usb_endpoint_descriptor *ep)
194{
195 unsigned int buffer_len;
196 int interval;
197 struct urb *urb;
198 struct usb_device *dev;
199 void *buffer = NULL;
200 int ret = -EINVAL;
201
202 buffer_len = le16_to_cpu(ep->wMaxPacketSize);
203 interval = ep->bInterval;
204 PDEBUG(D_CONF, "found int in endpoint: 0x%x, "
205 "buffer_len=%u, interval=%u",
206 ep->bEndpointAddress, buffer_len, interval);
207
208 dev = gspca_dev->dev;
209
210 urb = usb_alloc_urb(0, GFP_KERNEL);
211 if (!urb) {
212 ret = -ENOMEM;
213 goto error;
214 }
215
216 buffer = usb_alloc_coherent(dev, buffer_len,
217 GFP_KERNEL, &urb->transfer_dma);
218 if (!buffer) {
219 ret = -ENOMEM;
220 goto error_buffer;
221 }
222 usb_fill_int_urb(urb, dev,
223 usb_rcvintpipe(dev, ep->bEndpointAddress),
224 buffer, buffer_len,
225 int_irq, (void *)gspca_dev, interval);
226 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
227 ret = usb_submit_urb(urb, GFP_KERNEL);
228 if (ret < 0) {
229 PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
230 goto error_submit;
231 }
232 gspca_dev->int_urb = urb;
233 return ret;
234
235error_submit:
236 usb_free_coherent(dev,
237 urb->transfer_buffer_length,
238 urb->transfer_buffer,
239 urb->transfer_dma);
240error_buffer:
241 usb_free_urb(urb);
242error:
243 return ret;
244}
245
246static void gspca_input_create_urb(struct gspca_dev *gspca_dev)
247{
248 struct usb_interface *intf;
249 struct usb_host_interface *intf_desc;
250 struct usb_endpoint_descriptor *ep;
251 int i;
252
253 if (gspca_dev->sd_desc->int_pkt_scan) {
254 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
255 intf_desc = intf->cur_altsetting;
256 for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
257 ep = &intf_desc->endpoint[i].desc;
258 if (usb_endpoint_dir_in(ep) &&
259 usb_endpoint_xfer_int(ep)) {
260
261 alloc_and_submit_int_urb(gspca_dev, ep);
262 break;
263 }
264 }
265 }
266}
267
268static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
269{
270 struct urb *urb;
271
272 urb = gspca_dev->int_urb;
273 if (urb) {
274 gspca_dev->int_urb = NULL;
275 usb_kill_urb(urb);
276 usb_free_coherent(gspca_dev->dev,
277 urb->transfer_buffer_length,
278 urb->transfer_buffer,
279 urb->transfer_dma);
280 usb_free_urb(urb);
281 }
282}
283#else
284static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
285{
286}
287
288static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev)
289{
290}
291
292static inline int gspca_input_connect(struct gspca_dev *dev)
293{
294 return 0;
295}
296#endif
297
298/*
299 * fill a video frame from an URB and resubmit
300 */
301static void fill_frame(struct gspca_dev *gspca_dev,
302 struct urb *urb)
303{
304 u8 *data; /* address of data in the iso message */
305 int i, len, st;
306 cam_pkt_op pkt_scan;
307
308 if (urb->status != 0) {
309 if (urb->status == -ESHUTDOWN)
310 return; /* disconnection */
311#ifdef CONFIG_PM
312 if (gspca_dev->frozen)
313 return;
314#endif
315 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
316 urb->status = 0;
317 goto resubmit;
318 }
319 pkt_scan = gspca_dev->sd_desc->pkt_scan;
320 for (i = 0; i < urb->number_of_packets; i++) {
321 len = urb->iso_frame_desc[i].actual_length;
322
323 /* check the packet status and length */
324 st = urb->iso_frame_desc[i].status;
325 if (st) {
326 err("ISOC data error: [%d] len=%d, status=%d",
327 i, len, st);
328 gspca_dev->last_packet_type = DISCARD_PACKET;
329 continue;
330 }
331 if (len == 0) {
332 if (gspca_dev->empty_packet == 0)
333 gspca_dev->empty_packet = 1;
334 continue;
335 }
336
337 /* let the packet be analyzed by the subdriver */
338 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
339 i, urb->iso_frame_desc[i].offset, len);
340 data = (u8 *) urb->transfer_buffer
341 + urb->iso_frame_desc[i].offset;
342 pkt_scan(gspca_dev, data, len);
343 }
344
345resubmit:
346 /* resubmit the URB */
347 st = usb_submit_urb(urb, GFP_ATOMIC);
348 if (st < 0)
349 err("usb_submit_urb() ret %d", st);
350}
351
352/*
353 * ISOC message interrupt from the USB device
354 *
355 * Analyse each packet and call the subdriver for copy to the frame buffer.
356 */
357static void isoc_irq(struct urb *urb)
358{
359 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
360
361 PDEBUG(D_PACK, "isoc irq");
362 if (!gspca_dev->streaming)
363 return;
364 fill_frame(gspca_dev, urb);
365}
366
367/*
368 * bulk message interrupt from the USB device
369 */
370static void bulk_irq(struct urb *urb)
371{
372 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
373 int st;
374
375 PDEBUG(D_PACK, "bulk irq");
376 if (!gspca_dev->streaming)
377 return;
378 switch (urb->status) {
379 case 0:
380 break;
381 case -ESHUTDOWN:
382 return; /* disconnection */
383 default:
384#ifdef CONFIG_PM
385 if (gspca_dev->frozen)
386 return;
387#endif
388 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
389 urb->status = 0;
390 goto resubmit;
391 }
392
393 PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
394 gspca_dev->sd_desc->pkt_scan(gspca_dev,
395 urb->transfer_buffer,
396 urb->actual_length);
397
398resubmit:
399 /* resubmit the URB */
400 if (gspca_dev->cam.bulk_nurbs != 0) {
401 st = usb_submit_urb(urb, GFP_ATOMIC);
402 if (st < 0)
403 err("usb_submit_urb() ret %d", st);
404 }
405}
406
407/*
408 * add data to the current frame
409 *
410 * This function is called by the subdrivers at interrupt level.
411 *
412 * To build a frame, these ones must add
413 * - one FIRST_PACKET
414 * - 0 or many INTER_PACKETs
415 * - one LAST_PACKET
416 * DISCARD_PACKET invalidates the whole frame.
417 */
418void gspca_frame_add(struct gspca_dev *gspca_dev,
419 enum gspca_packet_type packet_type,
420 const u8 *data,
421 int len)
422{
423 struct gspca_frame *frame;
424 int i, j;
425
426 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
427
428 if (packet_type == FIRST_PACKET) {
429 i = atomic_read(&gspca_dev->fr_i);
430
431 /* if there are no queued buffer, discard the whole frame */
432 if (i == atomic_read(&gspca_dev->fr_q)) {
433 gspca_dev->last_packet_type = DISCARD_PACKET;
434 gspca_dev->sequence++;
435 return;
436 }
437 j = gspca_dev->fr_queue[i];
438 frame = &gspca_dev->frame[j];
439 frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get());
440 frame->v4l2_buf.sequence = gspca_dev->sequence++;
441 gspca_dev->image = frame->data;
442 gspca_dev->image_len = 0;
443 } else {
444 switch (gspca_dev->last_packet_type) {
445 case DISCARD_PACKET:
446 if (packet_type == LAST_PACKET) {
447 gspca_dev->last_packet_type = packet_type;
448 gspca_dev->image = NULL;
449 gspca_dev->image_len = 0;
450 }
451 return;
452 case LAST_PACKET:
453 return;
454 }
455 }
456
457 /* append the packet to the frame buffer */
458 if (len > 0) {
459 if (gspca_dev->image_len + len > gspca_dev->frsz) {
460 PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
461 gspca_dev->image_len + len,
462 gspca_dev->frsz);
463 packet_type = DISCARD_PACKET;
464 } else {
465/* !! image is NULL only when last pkt is LAST or DISCARD
466 if (gspca_dev->image == NULL) {
467 err("gspca_frame_add() image == NULL");
468 return;
469 }
470 */
471 memcpy(gspca_dev->image + gspca_dev->image_len,
472 data, len);
473 gspca_dev->image_len += len;
474 }
475 }
476 gspca_dev->last_packet_type = packet_type;
477
478 /* if last packet, invalidate packet concatenation until
479 * next first packet, wake up the application and advance
480 * in the queue */
481 if (packet_type == LAST_PACKET) {
482 i = atomic_read(&gspca_dev->fr_i);
483 j = gspca_dev->fr_queue[i];
484 frame = &gspca_dev->frame[j];
485 frame->v4l2_buf.bytesused = gspca_dev->image_len;
486 frame->v4l2_buf.flags = (frame->v4l2_buf.flags
487 | V4L2_BUF_FLAG_DONE)
488 & ~V4L2_BUF_FLAG_QUEUED;
489 i = (i + 1) % GSPCA_MAX_FRAMES;
490 atomic_set(&gspca_dev->fr_i, i);
491 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
492 PDEBUG(D_FRAM, "frame complete len:%d",
493 frame->v4l2_buf.bytesused);
494 gspca_dev->image = NULL;
495 gspca_dev->image_len = 0;
496 }
497}
498EXPORT_SYMBOL(gspca_frame_add);
499
500static int gspca_is_compressed(__u32 format)
501{
502 switch (format) {
503 case V4L2_PIX_FMT_MJPEG:
504 case V4L2_PIX_FMT_JPEG:
505 case V4L2_PIX_FMT_SPCA561:
506 case V4L2_PIX_FMT_PAC207:
507 case V4L2_PIX_FMT_MR97310A:
508 return 1;
509 }
510 return 0;
511}
512
513static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
514 enum v4l2_memory memory, unsigned int count)
515{
516 struct gspca_frame *frame;
517 unsigned int frsz;
518 int i;
519
520 i = gspca_dev->curr_mode;
521 frsz = gspca_dev->cam.cam_mode[i].sizeimage;
522 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
523 frsz = PAGE_ALIGN(frsz);
524 if (count >= GSPCA_MAX_FRAMES)
525 count = GSPCA_MAX_FRAMES - 1;
526 gspca_dev->frbuf = vmalloc_32(frsz * count);
527 if (!gspca_dev->frbuf) {
528 err("frame alloc failed");
529 return -ENOMEM;
530 }
531 gspca_dev->capt_file = file;
532 gspca_dev->memory = memory;
533 gspca_dev->frsz = frsz;
534 gspca_dev->nframes = count;
535 for (i = 0; i < count; i++) {
536 frame = &gspca_dev->frame[i];
537 frame->v4l2_buf.index = i;
538 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
539 frame->v4l2_buf.flags = 0;
540 frame->v4l2_buf.field = V4L2_FIELD_NONE;
541 frame->v4l2_buf.length = frsz;
542 frame->v4l2_buf.memory = memory;
543 frame->v4l2_buf.sequence = 0;
544 frame->data = gspca_dev->frbuf + i * frsz;
545 frame->v4l2_buf.m.offset = i * frsz;
546 }
547 atomic_set(&gspca_dev->fr_q, 0);
548 atomic_set(&gspca_dev->fr_i, 0);
549 gspca_dev->fr_o = 0;
550 return 0;
551}
552
553static void frame_free(struct gspca_dev *gspca_dev)
554{
555 int i;
556
557 PDEBUG(D_STREAM, "frame free");
558 if (gspca_dev->frbuf != NULL) {
559 vfree(gspca_dev->frbuf);
560 gspca_dev->frbuf = NULL;
561 for (i = 0; i < gspca_dev->nframes; i++)
562 gspca_dev->frame[i].data = NULL;
563 }
564 gspca_dev->nframes = 0;
565 gspca_dev->frsz = 0;
566 gspca_dev->capt_file = NULL;
567 gspca_dev->memory = GSPCA_MEMORY_NO;
568}
569
570static void destroy_urbs(struct gspca_dev *gspca_dev)
571{
572 struct urb *urb;
573 unsigned int i;
574
575 PDEBUG(D_STREAM, "kill transfer");
576 for (i = 0; i < MAX_NURBS; i++) {
577 urb = gspca_dev->urb[i];
578 if (urb == NULL)
579 break;
580
581 gspca_dev->urb[i] = NULL;
582 usb_kill_urb(urb);
583 if (urb->transfer_buffer != NULL)
584 usb_free_coherent(gspca_dev->dev,
585 urb->transfer_buffer_length,
586 urb->transfer_buffer,
587 urb->transfer_dma);
588 usb_free_urb(urb);
589 }
590}
591
592static int gspca_set_alt0(struct gspca_dev *gspca_dev)
593{
594 int ret;
595
596 if (gspca_dev->alt == 0)
597 return 0;
598 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
599 if (ret < 0)
600 err("set alt 0 err %d", ret);
601 return ret;
602}
603
604/* Note: both the queue and the usb locks should be held when calling this */
605static void gspca_stream_off(struct gspca_dev *gspca_dev)
606{
607 gspca_dev->streaming = 0;
608 if (gspca_dev->present) {
609 if (gspca_dev->sd_desc->stopN)
610 gspca_dev->sd_desc->stopN(gspca_dev);
611 destroy_urbs(gspca_dev);
612 gspca_input_destroy_urb(gspca_dev);
613 gspca_set_alt0(gspca_dev);
614 gspca_input_create_urb(gspca_dev);
615 }
616
617 /* always call stop0 to free the subdriver's resources */
618 if (gspca_dev->sd_desc->stop0)
619 gspca_dev->sd_desc->stop0(gspca_dev);
620 PDEBUG(D_STREAM, "stream off OK");
621}
622
623/*
624 * look for an input transfer endpoint in an alternate setting
625 */
626static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
627 int xfer)
628{
629 struct usb_host_endpoint *ep;
630 int i, attr;
631
632 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
633 ep = &alt->endpoint[i];
634 attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
635 if (attr == xfer
636 && ep->desc.wMaxPacketSize != 0
637 && usb_endpoint_dir_in(&ep->desc))
638 return ep;
639 }
640 return NULL;
641}
642
643/*
644 * look for an input (isoc or bulk) endpoint
645 *
646 * The endpoint is defined by the subdriver.
647 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
648 * This routine may be called many times when the bandwidth is too small
649 * (the bandwidth is checked on urb submit).
650 */
651static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
652{
653 struct usb_interface *intf;
654 struct usb_host_endpoint *ep;
655 int xfer, i, ret;
656
657 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
658 ep = NULL;
659 xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
660 : USB_ENDPOINT_XFER_ISOC;
661 i = gspca_dev->alt; /* previous alt setting */
662 if (gspca_dev->cam.reverse_alts) {
663 while (++i < gspca_dev->nbalt) {
664 ep = alt_xfer(&intf->altsetting[i], xfer);
665 if (ep)
666 break;
667 }
668 } else {
669 while (--i >= 0) {
670 ep = alt_xfer(&intf->altsetting[i], xfer);
671 if (ep)
672 break;
673 }
674 }
675 if (ep == NULL) {
676 err("no transfer endpoint found");
677 return NULL;
678 }
679 PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
680 i, ep->desc.bEndpointAddress);
681 gspca_dev->alt = i; /* memorize the current alt setting */
682 if (gspca_dev->nbalt > 1) {
683 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
684 if (ret < 0) {
685 err("set alt %d err %d", i, ret);
686 ep = NULL;
687 }
688 }
689 return ep;
690}
691
692/*
693 * create the URBs for image transfer
694 */
695static int create_urbs(struct gspca_dev *gspca_dev,
696 struct usb_host_endpoint *ep)
697{
698 struct urb *urb;
699 int n, nurbs, i, psize, npkt, bsize;
700
701 /* calculate the packet size and the number of packets */
702 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
703
704 if (!gspca_dev->cam.bulk) { /* isoc */
705
706 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
707 if (gspca_dev->pkt_size == 0)
708 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
709 else
710 psize = gspca_dev->pkt_size;
711 npkt = gspca_dev->cam.npkt;
712 if (npkt == 0)
713 npkt = 32; /* default value */
714 bsize = psize * npkt;
715 PDEBUG(D_STREAM,
716 "isoc %d pkts size %d = bsize:%d",
717 npkt, psize, bsize);
718 nurbs = DEF_NURBS;
719 } else { /* bulk */
720 npkt = 0;
721 bsize = gspca_dev->cam.bulk_size;
722 if (bsize == 0)
723 bsize = psize;
724 PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
725 if (gspca_dev->cam.bulk_nurbs != 0)
726 nurbs = gspca_dev->cam.bulk_nurbs;
727 else
728 nurbs = 1;
729 }
730
731 for (n = 0; n < nurbs; n++) {
732 urb = usb_alloc_urb(npkt, GFP_KERNEL);
733 if (!urb) {
734 err("usb_alloc_urb failed");
735 return -ENOMEM;
736 }
737 gspca_dev->urb[n] = urb;
738 urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
739 bsize,
740 GFP_KERNEL,
741 &urb->transfer_dma);
742
743 if (urb->transfer_buffer == NULL) {
744 err("usb_alloc_coherent failed");
745 return -ENOMEM;
746 }
747 urb->dev = gspca_dev->dev;
748 urb->context = gspca_dev;
749 urb->transfer_buffer_length = bsize;
750 if (npkt != 0) { /* ISOC */
751 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
752 ep->desc.bEndpointAddress);
753 urb->transfer_flags = URB_ISO_ASAP
754 | URB_NO_TRANSFER_DMA_MAP;
755 urb->interval = ep->desc.bInterval;
756 urb->complete = isoc_irq;
757 urb->number_of_packets = npkt;
758 for (i = 0; i < npkt; i++) {
759 urb->iso_frame_desc[i].length = psize;
760 urb->iso_frame_desc[i].offset = psize * i;
761 }
762 } else { /* bulk */
763 urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
764 ep->desc.bEndpointAddress);
765 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
766 urb->complete = bulk_irq;
767 }
768 }
769 return 0;
770}
771
772/*
773 * start the USB transfer
774 */
775static int gspca_init_transfer(struct gspca_dev *gspca_dev)
776{
777 struct usb_host_endpoint *ep;
778 struct urb *urb;
779 int n, ret;
780
781 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
782 return -ERESTARTSYS;
783
784 if (!gspca_dev->present) {
785 ret = -ENODEV;
786 goto unlock;
787 }
788
789 /* reset the streaming variables */
790 gspca_dev->image = NULL;
791 gspca_dev->image_len = 0;
792 gspca_dev->last_packet_type = DISCARD_PACKET;
793 gspca_dev->sequence = 0;
794
795 gspca_dev->usb_err = 0;
796
797 /* set the higher alternate setting and
798 * loop until urb submit succeeds */
799 if (gspca_dev->cam.reverse_alts)
800 gspca_dev->alt = 0;
801 else
802 gspca_dev->alt = gspca_dev->nbalt;
803
804 if (gspca_dev->sd_desc->isoc_init) {
805 ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
806 if (ret < 0)
807 goto unlock;
808 }
809
810 gspca_input_destroy_urb(gspca_dev);
811 ep = get_ep(gspca_dev);
812 if (ep == NULL) {
813 ret = -EIO;
814 goto out;
815 }
816 for (;;) {
817 if (!gspca_dev->cam.no_urb_create) {
818 PDEBUG(D_STREAM, "init transfer alt %d",
819 gspca_dev->alt);
820 ret = create_urbs(gspca_dev, ep);
821 if (ret < 0) {
822 destroy_urbs(gspca_dev);
823 goto out;
824 }
825 }
826
827 /* clear the bulk endpoint */
828 if (gspca_dev->cam.bulk)
829 usb_clear_halt(gspca_dev->dev,
830 gspca_dev->urb[0]->pipe);
831
832 /* start the cam */
833 ret = gspca_dev->sd_desc->start(gspca_dev);
834 if (ret < 0) {
835 destroy_urbs(gspca_dev);
836 goto out;
837 }
838 gspca_dev->streaming = 1;
839
840 /* some bulk transfers are started by the subdriver */
841 if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
842 break;
843
844 /* submit the URBs */
845 for (n = 0; n < MAX_NURBS; n++) {
846 urb = gspca_dev->urb[n];
847 if (urb == NULL)
848 break;
849 ret = usb_submit_urb(urb, GFP_KERNEL);
850 if (ret < 0)
851 break;
852 }
853 if (ret >= 0)
854 break;
855 gspca_stream_off(gspca_dev);
856 if (ret != -ENOSPC) {
857 err("usb_submit_urb alt %d err %d",
858 gspca_dev->alt, ret);
859 goto out;
860 }
861
862 /* the bandwidth is not wide enough
863 * negotiate or try a lower alternate setting */
864 PDEBUG(D_ERR|D_STREAM,
865 "bandwidth not wide enough - trying again");
866 msleep(20); /* wait for kill complete */
867 if (gspca_dev->sd_desc->isoc_nego) {
868 ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
869 if (ret < 0)
870 goto out;
871 } else {
872 ep = get_ep(gspca_dev);
873 if (ep == NULL) {
874 ret = -EIO;
875 goto out;
876 }
877 }
878 }
879out:
880 gspca_input_create_urb(gspca_dev);
881unlock:
882 mutex_unlock(&gspca_dev->usb_lock);
883 return ret;
884}
885
886static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
887{
888 struct gspca_ctrl *ctrl;
889 int i;
890
891 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
892 gspca_dev->curr_mode = i;
893 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
894 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
895 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
896
897 /* set the current control values to their default values
898 * which may have changed in sd_init() */
899 ctrl = gspca_dev->cam.ctrls;
900 if (ctrl != NULL) {
901 for (i = 0;
902 i < gspca_dev->sd_desc->nctrls;
903 i++, ctrl++)
904 ctrl->val = ctrl->def;
905 }
906}
907
908static int wxh_to_mode(struct gspca_dev *gspca_dev,
909 int width, int height)
910{
911 int i;
912
913 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
914 if (width >= gspca_dev->cam.cam_mode[i].width
915 && height >= gspca_dev->cam.cam_mode[i].height)
916 break;
917 }
918 return i;
919}
920
921/*
922 * search a mode with the right pixel format
923 */
924static int gspca_get_mode(struct gspca_dev *gspca_dev,
925 int mode,
926 int pixfmt)
927{
928 int modeU, modeD;
929
930 modeU = modeD = mode;
931 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
932 if (--modeD >= 0) {
933 if (gspca_dev->cam.cam_mode[modeD].pixelformat
934 == pixfmt)
935 return modeD;
936 }
937 if (++modeU < gspca_dev->cam.nmodes) {
938 if (gspca_dev->cam.cam_mode[modeU].pixelformat
939 == pixfmt)
940 return modeU;
941 }
942 }
943 return -EINVAL;
944}
945
946#ifdef CONFIG_VIDEO_ADV_DEBUG
947static int vidioc_g_register(struct file *file, void *priv,
948 struct v4l2_dbg_register *reg)
949{
950 int ret;
951 struct gspca_dev *gspca_dev = priv;
952
953 if (!gspca_dev->sd_desc->get_chip_ident)
954 return -EINVAL;
955
956 if (!gspca_dev->sd_desc->get_register)
957 return -EINVAL;
958
959 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
960 return -ERESTARTSYS;
961 gspca_dev->usb_err = 0;
962 if (gspca_dev->present)
963 ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
964 else
965 ret = -ENODEV;
966 mutex_unlock(&gspca_dev->usb_lock);
967
968 return ret;
969}
970
971static int vidioc_s_register(struct file *file, void *priv,
972 struct v4l2_dbg_register *reg)
973{
974 int ret;
975 struct gspca_dev *gspca_dev = priv;
976
977 if (!gspca_dev->sd_desc->get_chip_ident)
978 return -EINVAL;
979
980 if (!gspca_dev->sd_desc->set_register)
981 return -EINVAL;
982
983 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
984 return -ERESTARTSYS;
985 gspca_dev->usb_err = 0;
986 if (gspca_dev->present)
987 ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
988 else
989 ret = -ENODEV;
990 mutex_unlock(&gspca_dev->usb_lock);
991
992 return ret;
993}
994#endif
995
996static int vidioc_g_chip_ident(struct file *file, void *priv,
997 struct v4l2_dbg_chip_ident *chip)
998{
999 int ret;
1000 struct gspca_dev *gspca_dev = priv;
1001
1002 if (!gspca_dev->sd_desc->get_chip_ident)
1003 return -EINVAL;
1004
1005 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1006 return -ERESTARTSYS;
1007 gspca_dev->usb_err = 0;
1008 if (gspca_dev->present)
1009 ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
1010 else
1011 ret = -ENODEV;
1012 mutex_unlock(&gspca_dev->usb_lock);
1013
1014 return ret;
1015}
1016
1017static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1018 struct v4l2_fmtdesc *fmtdesc)
1019{
1020 struct gspca_dev *gspca_dev = priv;
1021 int i, j, index;
1022 __u32 fmt_tb[8];
1023
1024 /* give an index to each format */
1025 index = 0;
1026 j = 0;
1027 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
1028 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
1029 j = 0;
1030 for (;;) {
1031 if (fmt_tb[j] == fmt_tb[index])
1032 break;
1033 j++;
1034 }
1035 if (j == index) {
1036 if (fmtdesc->index == index)
1037 break; /* new format */
1038 index++;
1039 if (index >= ARRAY_SIZE(fmt_tb))
1040 return -EINVAL;
1041 }
1042 }
1043 if (i < 0)
1044 return -EINVAL; /* no more format */
1045
1046 fmtdesc->pixelformat = fmt_tb[index];
1047 if (gspca_is_compressed(fmt_tb[index]))
1048 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
1049 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
1050 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
1051 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
1052 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
1053 fmtdesc->description[4] = '\0';
1054 return 0;
1055}
1056
1057static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1058 struct v4l2_format *fmt)
1059{
1060 struct gspca_dev *gspca_dev = priv;
1061 int mode;
1062
1063 mode = gspca_dev->curr_mode;
1064 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
1065 sizeof fmt->fmt.pix);
1066 return 0;
1067}
1068
1069static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
1070 struct v4l2_format *fmt)
1071{
1072 int w, h, mode, mode2;
1073
1074 w = fmt->fmt.pix.width;
1075 h = fmt->fmt.pix.height;
1076
1077#ifdef GSPCA_DEBUG
1078 if (gspca_debug & D_CONF)
1079 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
1080#endif
1081 /* search the closest mode for width and height */
1082 mode = wxh_to_mode(gspca_dev, w, h);
1083
1084 /* OK if right palette */
1085 if (gspca_dev->cam.cam_mode[mode].pixelformat
1086 != fmt->fmt.pix.pixelformat) {
1087
1088 /* else, search the closest mode with the same pixel format */
1089 mode2 = gspca_get_mode(gspca_dev, mode,
1090 fmt->fmt.pix.pixelformat);
1091 if (mode2 >= 0)
1092 mode = mode2;
1093/* else
1094 ; * no chance, return this mode */
1095 }
1096 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
1097 sizeof fmt->fmt.pix);
1098 return mode; /* used when s_fmt */
1099}
1100
1101static int vidioc_try_fmt_vid_cap(struct file *file,
1102 void *priv,
1103 struct v4l2_format *fmt)
1104{
1105 struct gspca_dev *gspca_dev = priv;
1106 int ret;
1107
1108 ret = try_fmt_vid_cap(gspca_dev, fmt);
1109 if (ret < 0)
1110 return ret;
1111 return 0;
1112}
1113
1114static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1115 struct v4l2_format *fmt)
1116{
1117 struct gspca_dev *gspca_dev = priv;
1118 int ret;
1119
1120 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1121 return -ERESTARTSYS;
1122
1123 ret = try_fmt_vid_cap(gspca_dev, fmt);
1124 if (ret < 0)
1125 goto out;
1126
1127 if (gspca_dev->nframes != 0
1128 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
1129 ret = -EINVAL;
1130 goto out;
1131 }
1132
1133 if (ret == gspca_dev->curr_mode) {
1134 ret = 0;
1135 goto out; /* same mode */
1136 }
1137
1138 if (gspca_dev->streaming) {
1139 ret = -EBUSY;
1140 goto out;
1141 }
1142 gspca_dev->width = fmt->fmt.pix.width;
1143 gspca_dev->height = fmt->fmt.pix.height;
1144 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
1145 gspca_dev->curr_mode = ret;
1146
1147 ret = 0;
1148out:
1149 mutex_unlock(&gspca_dev->queue_lock);
1150 return ret;
1151}
1152
1153static int vidioc_enum_framesizes(struct file *file, void *priv,
1154 struct v4l2_frmsizeenum *fsize)
1155{
1156 struct gspca_dev *gspca_dev = priv;
1157 int i;
1158 __u32 index = 0;
1159
1160 for (i = 0; i < gspca_dev->cam.nmodes; i++) {
1161 if (fsize->pixel_format !=
1162 gspca_dev->cam.cam_mode[i].pixelformat)
1163 continue;
1164
1165 if (fsize->index == index) {
1166 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1167 fsize->discrete.width =
1168 gspca_dev->cam.cam_mode[i].width;
1169 fsize->discrete.height =
1170 gspca_dev->cam.cam_mode[i].height;
1171 return 0;
1172 }
1173 index++;
1174 }
1175
1176 return -EINVAL;
1177}
1178
1179static int vidioc_enum_frameintervals(struct file *filp, void *priv,
1180 struct v4l2_frmivalenum *fival)
1181{
1182 struct gspca_dev *gspca_dev = priv;
1183 int mode = wxh_to_mode(gspca_dev, fival->width, fival->height);
1184 __u32 i;
1185
1186 if (gspca_dev->cam.mode_framerates == NULL ||
1187 gspca_dev->cam.mode_framerates[mode].nrates == 0)
1188 return -EINVAL;
1189
1190 if (fival->pixel_format !=
1191 gspca_dev->cam.cam_mode[mode].pixelformat)
1192 return -EINVAL;
1193
1194 for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) {
1195 if (fival->index == i) {
1196 fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1197 fival->discrete.numerator = 1;
1198 fival->discrete.denominator =
1199 gspca_dev->cam.mode_framerates[mode].rates[i];
1200 return 0;
1201 }
1202 }
1203
1204 return -EINVAL;
1205}
1206
1207static void gspca_release(struct video_device *vfd)
1208{
1209 struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev);
1210
1211 PDEBUG(D_PROBE, "%s released",
1212 video_device_node_name(&gspca_dev->vdev));
1213
1214 kfree(gspca_dev->usb_buf);
1215 kfree(gspca_dev);
1216}
1217
1218static int dev_open(struct file *file)
1219{
1220 struct gspca_dev *gspca_dev;
1221
1222 PDEBUG(D_STREAM, "[%s] open", current->comm);
1223 gspca_dev = (struct gspca_dev *) video_devdata(file);
1224 if (!gspca_dev->present)
1225 return -ENODEV;
1226
1227 /* protect the subdriver against rmmod */
1228 if (!try_module_get(gspca_dev->module))
1229 return -ENODEV;
1230
1231 file->private_data = gspca_dev;
1232#ifdef GSPCA_DEBUG
1233 /* activate the v4l2 debug */
1234 if (gspca_debug & D_V4L2)
1235 gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
1236 | V4L2_DEBUG_IOCTL_ARG;
1237 else
1238 gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
1239 | V4L2_DEBUG_IOCTL_ARG);
1240#endif
1241 return 0;
1242}
1243
1244static int dev_close(struct file *file)
1245{
1246 struct gspca_dev *gspca_dev = file->private_data;
1247
1248 PDEBUG(D_STREAM, "[%s] close", current->comm);
1249 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1250 return -ERESTARTSYS;
1251
1252 /* if the file did the capture, free the streaming resources */
1253 if (gspca_dev->capt_file == file) {
1254 if (gspca_dev->streaming) {
1255 mutex_lock(&gspca_dev->usb_lock);
1256 gspca_dev->usb_err = 0;
1257 gspca_stream_off(gspca_dev);
1258 mutex_unlock(&gspca_dev->usb_lock);
1259 }
1260 frame_free(gspca_dev);
1261 }
1262 file->private_data = NULL;
1263 module_put(gspca_dev->module);
1264 mutex_unlock(&gspca_dev->queue_lock);
1265
1266 PDEBUG(D_STREAM, "close done");
1267
1268 return 0;
1269}
1270
1271static int vidioc_querycap(struct file *file, void *priv,
1272 struct v4l2_capability *cap)
1273{
1274 struct gspca_dev *gspca_dev = priv;
1275 int ret;
1276
1277 /* protect the access to the usb device */
1278 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1279 return -ERESTARTSYS;
1280 if (!gspca_dev->present) {
1281 ret = -ENODEV;
1282 goto out;
1283 }
1284 strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
1285 sizeof cap->driver);
1286 if (gspca_dev->dev->product != NULL) {
1287 strlcpy((char *) cap->card, gspca_dev->dev->product,
1288 sizeof cap->card);
1289 } else {
1290 snprintf((char *) cap->card, sizeof cap->card,
1291 "USB Camera (%04x:%04x)",
1292 le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
1293 le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
1294 }
1295 usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
1296 sizeof(cap->bus_info));
1297 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
1298 | V4L2_CAP_STREAMING
1299 | V4L2_CAP_READWRITE;
1300 ret = 0;
1301out:
1302 mutex_unlock(&gspca_dev->usb_lock);
1303 return ret;
1304}
1305
1306static int get_ctrl(struct gspca_dev *gspca_dev,
1307 int id)
1308{
1309 const struct ctrl *ctrls;
1310 int i;
1311
1312 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
1313 i < gspca_dev->sd_desc->nctrls;
1314 i++, ctrls++) {
1315 if (gspca_dev->ctrl_dis & (1 << i))
1316 continue;
1317 if (id == ctrls->qctrl.id)
1318 return i;
1319 }
1320 return -1;
1321}
1322
1323static int vidioc_queryctrl(struct file *file, void *priv,
1324 struct v4l2_queryctrl *q_ctrl)
1325{
1326 struct gspca_dev *gspca_dev = priv;
1327 const struct ctrl *ctrls;
1328 struct gspca_ctrl *gspca_ctrl;
1329 int i, idx;
1330 u32 id;
1331
1332 id = q_ctrl->id;
1333 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1334 id &= V4L2_CTRL_ID_MASK;
1335 id++;
1336 idx = -1;
1337 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1338 if (gspca_dev->ctrl_dis & (1 << i))
1339 continue;
1340 if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
1341 continue;
1342 if (idx >= 0
1343 && gspca_dev->sd_desc->ctrls[i].qctrl.id
1344 > gspca_dev->sd_desc->ctrls[idx].qctrl.id)
1345 continue;
1346 idx = i;
1347 }
1348 } else {
1349 idx = get_ctrl(gspca_dev, id);
1350 }
1351 if (idx < 0)
1352 return -EINVAL;
1353 ctrls = &gspca_dev->sd_desc->ctrls[idx];
1354 memcpy(q_ctrl, &ctrls->qctrl, sizeof *q_ctrl);
1355 if (gspca_dev->cam.ctrls != NULL) {
1356 gspca_ctrl = &gspca_dev->cam.ctrls[idx];
1357 q_ctrl->default_value = gspca_ctrl->def;
1358 q_ctrl->minimum = gspca_ctrl->min;
1359 q_ctrl->maximum = gspca_ctrl->max;
1360 }
1361 if (gspca_dev->ctrl_inac & (1 << idx))
1362 q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
1363 return 0;
1364}
1365
1366static int vidioc_s_ctrl(struct file *file, void *priv,
1367 struct v4l2_control *ctrl)
1368{
1369 struct gspca_dev *gspca_dev = priv;
1370 const struct ctrl *ctrls;
1371 struct gspca_ctrl *gspca_ctrl;
1372 int idx, ret;
1373
1374 idx = get_ctrl(gspca_dev, ctrl->id);
1375 if (idx < 0)
1376 return -EINVAL;
1377 if (gspca_dev->ctrl_inac & (1 << idx))
1378 return -EINVAL;
1379 ctrls = &gspca_dev->sd_desc->ctrls[idx];
1380 if (gspca_dev->cam.ctrls != NULL) {
1381 gspca_ctrl = &gspca_dev->cam.ctrls[idx];
1382 if (ctrl->value < gspca_ctrl->min
1383 || ctrl->value > gspca_ctrl->max)
1384 return -ERANGE;
1385 } else {
1386 gspca_ctrl = NULL;
1387 if (ctrl->value < ctrls->qctrl.minimum
1388 || ctrl->value > ctrls->qctrl.maximum)
1389 return -ERANGE;
1390 }
1391 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
1392 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1393 return -ERESTARTSYS;
1394 if (!gspca_dev->present) {
1395 ret = -ENODEV;
1396 goto out;
1397 }
1398 gspca_dev->usb_err = 0;
1399 if (ctrls->set != NULL) {
1400 ret = ctrls->set(gspca_dev, ctrl->value);
1401 goto out;
1402 }
1403 if (gspca_ctrl != NULL) {
1404 gspca_ctrl->val = ctrl->value;
1405 if (ctrls->set_control != NULL
1406 && gspca_dev->streaming)
1407 ctrls->set_control(gspca_dev);
1408 }
1409 ret = gspca_dev->usb_err;
1410out:
1411 mutex_unlock(&gspca_dev->usb_lock);
1412 return ret;
1413}
1414
1415static int vidioc_g_ctrl(struct file *file, void *priv,
1416 struct v4l2_control *ctrl)
1417{
1418 struct gspca_dev *gspca_dev = priv;
1419 const struct ctrl *ctrls;
1420 int idx, ret;
1421
1422 idx = get_ctrl(gspca_dev, ctrl->id);
1423 if (idx < 0)
1424 return -EINVAL;
1425 ctrls = &gspca_dev->sd_desc->ctrls[idx];
1426
1427 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1428 return -ERESTARTSYS;
1429 if (!gspca_dev->present) {
1430 ret = -ENODEV;
1431 goto out;
1432 }
1433 gspca_dev->usb_err = 0;
1434 if (ctrls->get != NULL) {
1435 ret = ctrls->get(gspca_dev, &ctrl->value);
1436 goto out;
1437 }
1438 if (gspca_dev->cam.ctrls != NULL)
1439 ctrl->value = gspca_dev->cam.ctrls[idx].val;
1440 ret = 0;
1441out:
1442 mutex_unlock(&gspca_dev->usb_lock);
1443 return ret;
1444}
1445
1446static int vidioc_querymenu(struct file *file, void *priv,
1447 struct v4l2_querymenu *qmenu)
1448{
1449 struct gspca_dev *gspca_dev = priv;
1450
1451 if (!gspca_dev->sd_desc->querymenu)
1452 return -EINVAL;
1453 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
1454}
1455
1456static int vidioc_enum_input(struct file *file, void *priv,
1457 struct v4l2_input *input)
1458{
1459 struct gspca_dev *gspca_dev = priv;
1460
1461 if (input->index != 0)
1462 return -EINVAL;
1463 input->type = V4L2_INPUT_TYPE_CAMERA;
1464 input->status = gspca_dev->cam.input_flags;
1465 strlcpy(input->name, gspca_dev->sd_desc->name,
1466 sizeof input->name);
1467 return 0;
1468}
1469
1470static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1471{
1472 *i = 0;
1473 return 0;
1474}
1475
1476static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1477{
1478 if (i > 0)
1479 return -EINVAL;
1480 return (0);
1481}
1482
1483static int vidioc_reqbufs(struct file *file, void *priv,
1484 struct v4l2_requestbuffers *rb)
1485{
1486 struct gspca_dev *gspca_dev = priv;
1487 int i, ret = 0, streaming;
1488
1489 i = rb->memory; /* (avoid compilation warning) */
1490 switch (i) {
1491 case GSPCA_MEMORY_READ: /* (internal call) */
1492 case V4L2_MEMORY_MMAP:
1493 case V4L2_MEMORY_USERPTR:
1494 break;
1495 default:
1496 return -EINVAL;
1497 }
1498 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1499 return -ERESTARTSYS;
1500
1501 if (gspca_dev->memory != GSPCA_MEMORY_NO
1502 && gspca_dev->memory != GSPCA_MEMORY_READ
1503 && gspca_dev->memory != rb->memory) {
1504 ret = -EBUSY;
1505 goto out;
1506 }
1507
1508 /* only one file may do the capture */
1509 if (gspca_dev->capt_file != NULL
1510 && gspca_dev->capt_file != file) {
1511 ret = -EBUSY;
1512 goto out;
1513 }
1514
1515 /* if allocated, the buffers must not be mapped */
1516 for (i = 0; i < gspca_dev->nframes; i++) {
1517 if (gspca_dev->frame[i].vma_use_count) {
1518 ret = -EBUSY;
1519 goto out;
1520 }
1521 }
1522
1523 /* stop streaming */
1524 streaming = gspca_dev->streaming;
1525 if (streaming) {
1526 mutex_lock(&gspca_dev->usb_lock);
1527 gspca_dev->usb_err = 0;
1528 gspca_stream_off(gspca_dev);
1529 mutex_unlock(&gspca_dev->usb_lock);
1530
1531 /* Don't restart the stream when switching from read
1532 * to mmap mode */
1533 if (gspca_dev->memory == GSPCA_MEMORY_READ)
1534 streaming = 0;
1535 }
1536
1537 /* free the previous allocated buffers, if any */
1538 if (gspca_dev->nframes != 0)
1539 frame_free(gspca_dev);
1540 if (rb->count == 0) /* unrequest */
1541 goto out;
1542 ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
1543 if (ret == 0) {
1544 rb->count = gspca_dev->nframes;
1545 if (streaming)
1546 ret = gspca_init_transfer(gspca_dev);
1547 }
1548out:
1549 mutex_unlock(&gspca_dev->queue_lock);
1550 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1551 return ret;
1552}
1553
1554static int vidioc_querybuf(struct file *file, void *priv,
1555 struct v4l2_buffer *v4l2_buf)
1556{
1557 struct gspca_dev *gspca_dev = priv;
1558 struct gspca_frame *frame;
1559
1560 if (v4l2_buf->index < 0
1561 || v4l2_buf->index >= gspca_dev->nframes)
1562 return -EINVAL;
1563
1564 frame = &gspca_dev->frame[v4l2_buf->index];
1565 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1566 return 0;
1567}
1568
1569static int vidioc_streamon(struct file *file, void *priv,
1570 enum v4l2_buf_type buf_type)
1571{
1572 struct gspca_dev *gspca_dev = priv;
1573 int ret;
1574
1575 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1576 return -EINVAL;
1577 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1578 return -ERESTARTSYS;
1579
1580 /* check the capture file */
1581 if (gspca_dev->capt_file != file) {
1582 ret = -EBUSY;
1583 goto out;
1584 }
1585
1586 if (gspca_dev->nframes == 0
1587 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
1588 ret = -EINVAL;
1589 goto out;
1590 }
1591 if (!gspca_dev->streaming) {
1592 ret = gspca_init_transfer(gspca_dev);
1593 if (ret < 0)
1594 goto out;
1595 }
1596#ifdef GSPCA_DEBUG
1597 if (gspca_debug & D_STREAM) {
1598 PDEBUG_MODE("stream on OK",
1599 gspca_dev->pixfmt,
1600 gspca_dev->width,
1601 gspca_dev->height);
1602 }
1603#endif
1604 ret = 0;
1605out:
1606 mutex_unlock(&gspca_dev->queue_lock);
1607 return ret;
1608}
1609
1610static int vidioc_streamoff(struct file *file, void *priv,
1611 enum v4l2_buf_type buf_type)
1612{
1613 struct gspca_dev *gspca_dev = priv;
1614 int ret;
1615
1616 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1617 return -EINVAL;
1618
1619 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1620 return -ERESTARTSYS;
1621
1622 if (!gspca_dev->streaming) {
1623 ret = 0;
1624 goto out;
1625 }
1626
1627 /* check the capture file */
1628 if (gspca_dev->capt_file != file) {
1629 ret = -EBUSY;
1630 goto out;
1631 }
1632
1633 /* stop streaming */
1634 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1635 ret = -ERESTARTSYS;
1636 goto out;
1637 }
1638 gspca_dev->usb_err = 0;
1639 gspca_stream_off(gspca_dev);
1640 mutex_unlock(&gspca_dev->usb_lock);
1641 /* In case another thread is waiting in dqbuf */
1642 wake_up_interruptible(&gspca_dev->wq);
1643
1644 /* empty the transfer queues */
1645 atomic_set(&gspca_dev->fr_q, 0);
1646 atomic_set(&gspca_dev->fr_i, 0);
1647 gspca_dev->fr_o = 0;
1648 ret = 0;
1649out:
1650 mutex_unlock(&gspca_dev->queue_lock);
1651 return ret;
1652}
1653
1654static int vidioc_g_jpegcomp(struct file *file, void *priv,
1655 struct v4l2_jpegcompression *jpegcomp)
1656{
1657 struct gspca_dev *gspca_dev = priv;
1658 int ret;
1659
1660 if (!gspca_dev->sd_desc->get_jcomp)
1661 return -EINVAL;
1662 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1663 return -ERESTARTSYS;
1664 gspca_dev->usb_err = 0;
1665 if (gspca_dev->present)
1666 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1667 else
1668 ret = -ENODEV;
1669 mutex_unlock(&gspca_dev->usb_lock);
1670 return ret;
1671}
1672
1673static int vidioc_s_jpegcomp(struct file *file, void *priv,
1674 struct v4l2_jpegcompression *jpegcomp)
1675{
1676 struct gspca_dev *gspca_dev = priv;
1677 int ret;
1678
1679 if (!gspca_dev->sd_desc->set_jcomp)
1680 return -EINVAL;
1681 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1682 return -ERESTARTSYS;
1683 gspca_dev->usb_err = 0;
1684 if (gspca_dev->present)
1685 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1686 else
1687 ret = -ENODEV;
1688 mutex_unlock(&gspca_dev->usb_lock);
1689 return ret;
1690}
1691
1692static int vidioc_g_parm(struct file *filp, void *priv,
1693 struct v4l2_streamparm *parm)
1694{
1695 struct gspca_dev *gspca_dev = priv;
1696
1697 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1698
1699 if (gspca_dev->sd_desc->get_streamparm) {
1700 int ret;
1701
1702 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1703 return -ERESTARTSYS;
1704 if (gspca_dev->present) {
1705 gspca_dev->usb_err = 0;
1706 gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
1707 ret = gspca_dev->usb_err;
1708 } else {
1709 ret = -ENODEV;
1710 }
1711 mutex_unlock(&gspca_dev->usb_lock);
1712 return ret;
1713 }
1714
1715 return 0;
1716}
1717
1718static int vidioc_s_parm(struct file *filp, void *priv,
1719 struct v4l2_streamparm *parm)
1720{
1721 struct gspca_dev *gspca_dev = priv;
1722 int n;
1723
1724 n = parm->parm.capture.readbuffers;
1725 if (n == 0 || n >= GSPCA_MAX_FRAMES)
1726 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1727 else
1728 gspca_dev->nbufread = n;
1729
1730 if (gspca_dev->sd_desc->set_streamparm) {
1731 int ret;
1732
1733 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1734 return -ERESTARTSYS;
1735 if (gspca_dev->present) {
1736 gspca_dev->usb_err = 0;
1737 gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
1738 ret = gspca_dev->usb_err;
1739 } else {
1740 ret = -ENODEV;
1741 }
1742 mutex_unlock(&gspca_dev->usb_lock);
1743 return ret;
1744 }
1745
1746 return 0;
1747}
1748
1749static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1750{
1751 struct gspca_dev *gspca_dev = file->private_data;
1752 struct gspca_frame *frame;
1753 struct page *page;
1754 unsigned long addr, start, size;
1755 int i, ret;
1756
1757 start = vma->vm_start;
1758 size = vma->vm_end - vma->vm_start;
1759 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1760
1761 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1762 return -ERESTARTSYS;
1763 if (!gspca_dev->present) {
1764 ret = -ENODEV;
1765 goto out;
1766 }
1767 if (gspca_dev->capt_file != file) {
1768 ret = -EINVAL;
1769 goto out;
1770 }
1771
1772 frame = NULL;
1773 for (i = 0; i < gspca_dev->nframes; ++i) {
1774 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1775 PDEBUG(D_STREAM, "mmap bad memory type");
1776 break;
1777 }
1778 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1779 == vma->vm_pgoff) {
1780 frame = &gspca_dev->frame[i];
1781 break;
1782 }
1783 }
1784 if (frame == NULL) {
1785 PDEBUG(D_STREAM, "mmap no frame buffer found");
1786 ret = -EINVAL;
1787 goto out;
1788 }
1789 if (size != frame->v4l2_buf.length) {
1790 PDEBUG(D_STREAM, "mmap bad size");
1791 ret = -EINVAL;
1792 goto out;
1793 }
1794
1795 /*
1796 * - VM_IO marks the area as being a mmaped region for I/O to a
1797 * device. It also prevents the region from being core dumped.
1798 */
1799 vma->vm_flags |= VM_IO;
1800
1801 addr = (unsigned long) frame->data;
1802 while (size > 0) {
1803 page = vmalloc_to_page((void *) addr);
1804 ret = vm_insert_page(vma, start, page);
1805 if (ret < 0)
1806 goto out;
1807 start += PAGE_SIZE;
1808 addr += PAGE_SIZE;
1809 size -= PAGE_SIZE;
1810 }
1811
1812 vma->vm_ops = &gspca_vm_ops;
1813 vma->vm_private_data = frame;
1814 gspca_vm_open(vma);
1815 ret = 0;
1816out:
1817 mutex_unlock(&gspca_dev->queue_lock);
1818 return ret;
1819}
1820
1821static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file,
1822 enum v4l2_memory memory)
1823{
1824 if (!gspca_dev->present)
1825 return -ENODEV;
1826 if (gspca_dev->capt_file != file || gspca_dev->memory != memory ||
1827 !gspca_dev->streaming)
1828 return -EINVAL;
1829
1830 /* check if a frame is ready */
1831 return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i);
1832}
1833
1834static int frame_ready(struct gspca_dev *gspca_dev, struct file *file,
1835 enum v4l2_memory memory)
1836{
1837 int ret;
1838
1839 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1840 return -ERESTARTSYS;
1841 ret = frame_ready_nolock(gspca_dev, file, memory);
1842 mutex_unlock(&gspca_dev->queue_lock);
1843 return ret;
1844}
1845
1846/*
1847 * dequeue a video buffer
1848 *
1849 * If nonblock_ing is false, block until a buffer is available.
1850 */
1851static int vidioc_dqbuf(struct file *file, void *priv,
1852 struct v4l2_buffer *v4l2_buf)
1853{
1854 struct gspca_dev *gspca_dev = priv;
1855 struct gspca_frame *frame;
1856 int i, j, ret;
1857
1858 PDEBUG(D_FRAM, "dqbuf");
1859
1860 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1861 return -ERESTARTSYS;
1862
1863 for (;;) {
1864 ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory);
1865 if (ret < 0)
1866 goto out;
1867 if (ret > 0)
1868 break;
1869
1870 mutex_unlock(&gspca_dev->queue_lock);
1871
1872 if (file->f_flags & O_NONBLOCK)
1873 return -EAGAIN;
1874
1875 /* wait till a frame is ready */
1876 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1877 frame_ready(gspca_dev, file, v4l2_buf->memory),
1878 msecs_to_jiffies(3000));
1879 if (ret < 0)
1880 return ret;
1881 if (ret == 0)
1882 return -EIO;
1883
1884 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1885 return -ERESTARTSYS;
1886 }
1887
1888 i = gspca_dev->fr_o;
1889 j = gspca_dev->fr_queue[i];
1890 frame = &gspca_dev->frame[j];
1891
1892 gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES;
1893
1894 if (gspca_dev->sd_desc->dq_callback) {
1895 mutex_lock(&gspca_dev->usb_lock);
1896 gspca_dev->usb_err = 0;
1897 if (gspca_dev->present)
1898 gspca_dev->sd_desc->dq_callback(gspca_dev);
1899 mutex_unlock(&gspca_dev->usb_lock);
1900 }
1901
1902 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1903 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1904 PDEBUG(D_FRAM, "dqbuf %d", j);
1905 ret = 0;
1906
1907 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
1908 if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
1909 frame->data,
1910 frame->v4l2_buf.bytesused)) {
1911 PDEBUG(D_ERR|D_STREAM,
1912 "dqbuf cp to user failed");
1913 ret = -EFAULT;
1914 }
1915 }
1916out:
1917 mutex_unlock(&gspca_dev->queue_lock);
1918 return ret;
1919}
1920
1921/*
1922 * queue a video buffer
1923 *
1924 * Attempting to queue a buffer that has already been
1925 * queued will return -EINVAL.
1926 */
1927static int vidioc_qbuf(struct file *file, void *priv,
1928 struct v4l2_buffer *v4l2_buf)
1929{
1930 struct gspca_dev *gspca_dev = priv;
1931 struct gspca_frame *frame;
1932 int i, index, ret;
1933
1934 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1935
1936 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1937 return -ERESTARTSYS;
1938
1939 index = v4l2_buf->index;
1940 if ((unsigned) index >= gspca_dev->nframes) {
1941 PDEBUG(D_FRAM,
1942 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1943 ret = -EINVAL;
1944 goto out;
1945 }
1946 if (v4l2_buf->memory != gspca_dev->memory) {
1947 PDEBUG(D_FRAM, "qbuf bad memory type");
1948 ret = -EINVAL;
1949 goto out;
1950 }
1951
1952 frame = &gspca_dev->frame[index];
1953 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1954 PDEBUG(D_FRAM, "qbuf bad state");
1955 ret = -EINVAL;
1956 goto out;
1957 }
1958
1959 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
1960
1961 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
1962 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1963 frame->v4l2_buf.length = v4l2_buf->length;
1964 }
1965
1966 /* put the buffer in the 'queued' queue */
1967 i = atomic_read(&gspca_dev->fr_q);
1968 gspca_dev->fr_queue[i] = index;
1969 atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES);
1970
1971 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1972 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1973 ret = 0;
1974out:
1975 mutex_unlock(&gspca_dev->queue_lock);
1976 return ret;
1977}
1978
1979/*
1980 * allocate the resources for read()
1981 */
1982static int read_alloc(struct gspca_dev *gspca_dev,
1983 struct file *file)
1984{
1985 struct v4l2_buffer v4l2_buf;
1986 int i, ret;
1987
1988 PDEBUG(D_STREAM, "read alloc");
1989 if (gspca_dev->nframes == 0) {
1990 struct v4l2_requestbuffers rb;
1991
1992 memset(&rb, 0, sizeof rb);
1993 rb.count = gspca_dev->nbufread;
1994 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1995 rb.memory = GSPCA_MEMORY_READ;
1996 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1997 if (ret != 0) {
1998 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
1999 return ret;
2000 }
2001 memset(&v4l2_buf, 0, sizeof v4l2_buf);
2002 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2003 v4l2_buf.memory = GSPCA_MEMORY_READ;
2004 for (i = 0; i < gspca_dev->nbufread; i++) {
2005 v4l2_buf.index = i;
2006 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
2007 if (ret != 0) {
2008 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
2009 return ret;
2010 }
2011 }
2012 gspca_dev->memory = GSPCA_MEMORY_READ;
2013 }
2014
2015 /* start streaming */
2016 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
2017 if (ret != 0)
2018 PDEBUG(D_STREAM, "read streamon err %d", ret);
2019 return ret;
2020}
2021
2022static unsigned int dev_poll(struct file *file, poll_table *wait)
2023{
2024 struct gspca_dev *gspca_dev = file->private_data;
2025 int ret;
2026
2027 PDEBUG(D_FRAM, "poll");
2028
2029 poll_wait(file, &gspca_dev->wq, wait);
2030
2031 /* if reqbufs is not done, the user would use read() */
2032 if (gspca_dev->memory == GSPCA_MEMORY_NO) {
2033 ret = read_alloc(gspca_dev, file);
2034 if (ret != 0)
2035 return POLLERR;
2036 }
2037
2038 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
2039 return POLLERR;
2040
2041 /* check if an image has been received */
2042 if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i))
2043 ret = POLLIN | POLLRDNORM; /* yes */
2044 else
2045 ret = 0;
2046 mutex_unlock(&gspca_dev->queue_lock);
2047 if (!gspca_dev->present)
2048 return POLLHUP;
2049 return ret;
2050}
2051
2052static ssize_t dev_read(struct file *file, char __user *data,
2053 size_t count, loff_t *ppos)
2054{
2055 struct gspca_dev *gspca_dev = file->private_data;
2056 struct gspca_frame *frame;
2057 struct v4l2_buffer v4l2_buf;
2058 struct timeval timestamp;
2059 int n, ret, ret2;
2060
2061 PDEBUG(D_FRAM, "read (%zd)", count);
2062 if (!gspca_dev->present)
2063 return -ENODEV;
2064 if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */
2065 ret = read_alloc(gspca_dev, file);
2066 if (ret != 0)
2067 return ret;
2068 }
2069
2070 /* get a frame */
2071 timestamp = ktime_to_timeval(ktime_get());
2072 timestamp.tv_sec--;
2073 n = 2;
2074 for (;;) {
2075 memset(&v4l2_buf, 0, sizeof v4l2_buf);
2076 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2077 v4l2_buf.memory = GSPCA_MEMORY_READ;
2078 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
2079 if (ret != 0) {
2080 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
2081 return ret;
2082 }
2083
2084 /* if the process slept for more than 1 second,
2085 * get a newer frame */
2086 frame = &gspca_dev->frame[v4l2_buf.index];
2087 if (--n < 0)
2088 break; /* avoid infinite loop */
2089 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
2090 break;
2091 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
2092 if (ret != 0) {
2093 PDEBUG(D_STREAM, "read qbuf err %d", ret);
2094 return ret;
2095 }
2096 }
2097
2098 /* copy the frame */
2099 if (count > frame->v4l2_buf.bytesused)
2100 count = frame->v4l2_buf.bytesused;
2101 ret = copy_to_user(data, frame->data, count);
2102 if (ret != 0) {
2103 PDEBUG(D_ERR|D_STREAM,
2104 "read cp to user lack %d / %zd", ret, count);
2105 ret = -EFAULT;
2106 goto out;
2107 }
2108 ret = count;
2109out:
2110 /* in each case, requeue the buffer */
2111 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
2112 if (ret2 != 0)
2113 return ret2;
2114 return ret;
2115}
2116
2117static struct v4l2_file_operations dev_fops = {
2118 .owner = THIS_MODULE,
2119 .open = dev_open,
2120 .release = dev_close,
2121 .read = dev_read,
2122 .mmap = dev_mmap,
2123 .unlocked_ioctl = video_ioctl2,
2124 .poll = dev_poll,
2125};
2126
2127static const struct v4l2_ioctl_ops dev_ioctl_ops = {
2128 .vidioc_querycap = vidioc_querycap,
2129 .vidioc_dqbuf = vidioc_dqbuf,
2130 .vidioc_qbuf = vidioc_qbuf,
2131 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2132 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
2133 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
2134 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
2135 .vidioc_streamon = vidioc_streamon,
2136 .vidioc_queryctrl = vidioc_queryctrl,
2137 .vidioc_g_ctrl = vidioc_g_ctrl,
2138 .vidioc_s_ctrl = vidioc_s_ctrl,
2139 .vidioc_querymenu = vidioc_querymenu,
2140 .vidioc_enum_input = vidioc_enum_input,
2141 .vidioc_g_input = vidioc_g_input,
2142 .vidioc_s_input = vidioc_s_input,
2143 .vidioc_reqbufs = vidioc_reqbufs,
2144 .vidioc_querybuf = vidioc_querybuf,
2145 .vidioc_streamoff = vidioc_streamoff,
2146 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
2147 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
2148 .vidioc_g_parm = vidioc_g_parm,
2149 .vidioc_s_parm = vidioc_s_parm,
2150 .vidioc_enum_framesizes = vidioc_enum_framesizes,
2151 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
2152#ifdef CONFIG_VIDEO_ADV_DEBUG
2153 .vidioc_g_register = vidioc_g_register,
2154 .vidioc_s_register = vidioc_s_register,
2155#endif
2156 .vidioc_g_chip_ident = vidioc_g_chip_ident,
2157};
2158
2159static const struct video_device gspca_template = {
2160 .name = "gspca main driver",
2161 .fops = &dev_fops,
2162 .ioctl_ops = &dev_ioctl_ops,
2163 .release = gspca_release,
2164};
2165
2166/* initialize the controls */
2167static void ctrls_init(struct gspca_dev *gspca_dev)
2168{
2169 struct gspca_ctrl *ctrl;
2170 int i;
2171
2172 for (i = 0, ctrl = gspca_dev->cam.ctrls;
2173 i < gspca_dev->sd_desc->nctrls;
2174 i++, ctrl++) {
2175 ctrl->def = gspca_dev->sd_desc->ctrls[i].qctrl.default_value;
2176 ctrl->val = ctrl->def;
2177 ctrl->min = gspca_dev->sd_desc->ctrls[i].qctrl.minimum;
2178 ctrl->max = gspca_dev->sd_desc->ctrls[i].qctrl.maximum;
2179 }
2180}
2181
2182/*
2183 * probe and create a new gspca device
2184 *
2185 * This function must be called by the sub-driver when it is
2186 * called for probing a new device.
2187 */
2188int gspca_dev_probe2(struct usb_interface *intf,
2189 const struct usb_device_id *id,
2190 const struct sd_desc *sd_desc,
2191 int dev_size,
2192 struct module *module)
2193{
2194 struct gspca_dev *gspca_dev;
2195 struct usb_device *dev = interface_to_usbdev(intf);
2196 int ret;
2197
2198 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
2199
2200 /* create the device */
2201 if (dev_size < sizeof *gspca_dev)
2202 dev_size = sizeof *gspca_dev;
2203 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
2204 if (!gspca_dev) {
2205 err("couldn't kzalloc gspca struct");
2206 return -ENOMEM;
2207 }
2208 gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
2209 if (!gspca_dev->usb_buf) {
2210 err("out of memory");
2211 ret = -ENOMEM;
2212 goto out;
2213 }
2214 gspca_dev->dev = dev;
2215 gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
2216 gspca_dev->nbalt = intf->num_altsetting;
2217
2218 /* check if any audio device */
2219 if (dev->config->desc.bNumInterfaces != 1) {
2220 int i;
2221 struct usb_interface *intf2;
2222
2223 for (i = 0; i < dev->config->desc.bNumInterfaces; i++) {
2224 intf2 = dev->config->interface[i];
2225 if (intf2 != NULL
2226 && intf2->altsetting != NULL
2227 && intf2->altsetting->desc.bInterfaceClass ==
2228 USB_CLASS_AUDIO) {
2229 gspca_dev->audio = 1;
2230 break;
2231 }
2232 }
2233 }
2234
2235 gspca_dev->sd_desc = sd_desc;
2236 gspca_dev->nbufread = 2;
2237 gspca_dev->empty_packet = -1; /* don't check the empty packets */
2238
2239 /* configure the subdriver and initialize the USB device */
2240 ret = sd_desc->config(gspca_dev, id);
2241 if (ret < 0)
2242 goto out;
2243 if (gspca_dev->cam.ctrls != NULL)
2244 ctrls_init(gspca_dev);
2245 ret = sd_desc->init(gspca_dev);
2246 if (ret < 0)
2247 goto out;
2248 gspca_set_default_mode(gspca_dev);
2249
2250 ret = gspca_input_connect(gspca_dev);
2251 if (ret)
2252 goto out;
2253
2254 mutex_init(&gspca_dev->usb_lock);
2255 mutex_init(&gspca_dev->queue_lock);
2256 init_waitqueue_head(&gspca_dev->wq);
2257
2258 /* init video stuff */
2259 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
2260 gspca_dev->vdev.parent = &intf->dev;
2261 gspca_dev->module = module;
2262 gspca_dev->present = 1;
2263 ret = video_register_device(&gspca_dev->vdev,
2264 VFL_TYPE_GRABBER,
2265 -1);
2266 if (ret < 0) {
2267 err("video_register_device err %d", ret);
2268 goto out;
2269 }
2270
2271 usb_set_intfdata(intf, gspca_dev);
2272 PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
2273
2274 gspca_input_create_urb(gspca_dev);
2275
2276 return 0;
2277out:
2278#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2279 if (gspca_dev->input_dev)
2280 input_unregister_device(gspca_dev->input_dev);
2281#endif
2282 kfree(gspca_dev->usb_buf);
2283 kfree(gspca_dev);
2284 return ret;
2285}
2286EXPORT_SYMBOL(gspca_dev_probe2);
2287
2288/* same function as the previous one, but check the interface */
2289int gspca_dev_probe(struct usb_interface *intf,
2290 const struct usb_device_id *id,
2291 const struct sd_desc *sd_desc,
2292 int dev_size,
2293 struct module *module)
2294{
2295 struct usb_device *dev = interface_to_usbdev(intf);
2296
2297 /* we don't handle multi-config cameras */
2298 if (dev->descriptor.bNumConfigurations != 1) {
2299 err("%04x:%04x too many config",
2300 id->idVendor, id->idProduct);
2301 return -ENODEV;
2302 }
2303
2304 /* the USB video interface must be the first one */
2305 if (dev->config->desc.bNumInterfaces != 1
2306 && intf->cur_altsetting->desc.bInterfaceNumber != 0)
2307 return -ENODEV;
2308
2309 return gspca_dev_probe2(intf, id, sd_desc, dev_size, module);
2310}
2311EXPORT_SYMBOL(gspca_dev_probe);
2312
2313/*
2314 * USB disconnection
2315 *
2316 * This function must be called by the sub-driver
2317 * when the device disconnects, after the specific resources are freed.
2318 */
2319void gspca_disconnect(struct usb_interface *intf)
2320{
2321 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2322#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2323 struct input_dev *input_dev;
2324#endif
2325
2326 PDEBUG(D_PROBE, "%s disconnect",
2327 video_device_node_name(&gspca_dev->vdev));
2328 mutex_lock(&gspca_dev->usb_lock);
2329
2330 gspca_dev->present = 0;
2331 wake_up_interruptible(&gspca_dev->wq);
2332
2333 destroy_urbs(gspca_dev);
2334
2335#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2336 gspca_input_destroy_urb(gspca_dev);
2337 input_dev = gspca_dev->input_dev;
2338 if (input_dev) {
2339 gspca_dev->input_dev = NULL;
2340 input_unregister_device(input_dev);
2341 }
2342#endif
2343
2344 /* the device is freed at exit of this function */
2345 gspca_dev->dev = NULL;
2346 mutex_unlock(&gspca_dev->usb_lock);
2347
2348 usb_set_intfdata(intf, NULL);
2349
2350 /* release the device */
2351 /* (this will call gspca_release() immediately or on last close) */
2352 video_unregister_device(&gspca_dev->vdev);
2353
2354/* PDEBUG(D_PROBE, "disconnect complete"); */
2355}
2356EXPORT_SYMBOL(gspca_disconnect);
2357
2358#ifdef CONFIG_PM
2359int gspca_suspend(struct usb_interface *intf, pm_message_t message)
2360{
2361 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2362
2363 if (!gspca_dev->streaming)
2364 return 0;
2365 gspca_dev->frozen = 1; /* avoid urb error messages */
2366 if (gspca_dev->sd_desc->stopN)
2367 gspca_dev->sd_desc->stopN(gspca_dev);
2368 destroy_urbs(gspca_dev);
2369 gspca_input_destroy_urb(gspca_dev);
2370 gspca_set_alt0(gspca_dev);
2371 if (gspca_dev->sd_desc->stop0)
2372 gspca_dev->sd_desc->stop0(gspca_dev);
2373 return 0;
2374}
2375EXPORT_SYMBOL(gspca_suspend);
2376
2377int gspca_resume(struct usb_interface *intf)
2378{
2379 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2380
2381 gspca_dev->frozen = 0;
2382 gspca_dev->sd_desc->init(gspca_dev);
2383 gspca_input_create_urb(gspca_dev);
2384 if (gspca_dev->streaming)
2385 return gspca_init_transfer(gspca_dev);
2386 return 0;
2387}
2388EXPORT_SYMBOL(gspca_resume);
2389#endif
2390/* -- cam driver utility functions -- */
2391
2392/* auto gain and exposure algorithm based on the knee algorithm described here:
2393 http://ytse.tricolour.net/docs/LowLightOptimization.html
2394
2395 Returns 0 if no changes were made, 1 if the gain and or exposure settings
2396 where changed. */
2397int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
2398 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
2399{
2400 int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
2401 const struct ctrl *gain_ctrl = NULL;
2402 const struct ctrl *exposure_ctrl = NULL;
2403 const struct ctrl *autogain_ctrl = NULL;
2404 int retval = 0;
2405
2406 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
2407 if (gspca_dev->ctrl_dis & (1 << i))
2408 continue;
2409 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
2410 gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
2411 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
2412 exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
2413 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
2414 autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
2415 }
2416 if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
2417 PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
2418 "on cam without (auto)gain/exposure");
2419 return 0;
2420 }
2421
2422 if (gain_ctrl->get(gspca_dev, &gain) ||
2423 exposure_ctrl->get(gspca_dev, &exposure) ||
2424 autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
2425 return 0;
2426
2427 orig_gain = gain;
2428 orig_exposure = exposure;
2429
2430 /* If we are of a multiple of deadzone, do multiple steps to reach the
2431 desired lumination fast (with the risc of a slight overshoot) */
2432 steps = abs(desired_avg_lum - avg_lum) / deadzone;
2433
2434 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
2435 avg_lum, desired_avg_lum, steps);
2436
2437 for (i = 0; i < steps; i++) {
2438 if (avg_lum > desired_avg_lum) {
2439 if (gain > gain_knee)
2440 gain--;
2441 else if (exposure > exposure_knee)
2442 exposure--;
2443 else if (gain > gain_ctrl->qctrl.default_value)
2444 gain--;
2445 else if (exposure > exposure_ctrl->qctrl.minimum)
2446 exposure--;
2447 else if (gain > gain_ctrl->qctrl.minimum)
2448 gain--;
2449 else
2450 break;
2451 } else {
2452 if (gain < gain_ctrl->qctrl.default_value)
2453 gain++;
2454 else if (exposure < exposure_knee)
2455 exposure++;
2456 else if (gain < gain_knee)
2457 gain++;
2458 else if (exposure < exposure_ctrl->qctrl.maximum)
2459 exposure++;
2460 else if (gain < gain_ctrl->qctrl.maximum)
2461 gain++;
2462 else
2463 break;
2464 }
2465 }
2466
2467 if (gain != orig_gain) {
2468 gain_ctrl->set(gspca_dev, gain);
2469 retval = 1;
2470 }
2471 if (exposure != orig_exposure) {
2472 exposure_ctrl->set(gspca_dev, exposure);
2473 retval = 1;
2474 }
2475
2476 return retval;
2477}
2478EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
2479
2480/* -- module insert / remove -- */
2481static int __init gspca_init(void)
2482{
2483 info("v" DRIVER_VERSION_NUMBER " registered");
2484 return 0;
2485}
2486static void __exit gspca_exit(void)
2487{
2488}
2489
2490module_init(gspca_init);
2491module_exit(gspca_exit);
2492
2493#ifdef GSPCA_DEBUG
2494module_param_named(debug, gspca_debug, int, 0644);
2495MODULE_PARM_DESC(debug,
2496 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
2497 " 0x08:stream 0x10:frame 0x20:packet"
2498 " 0x0100: v4l2");
2499#endif
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
new file mode 100644
index 00000000000..49e2fcbe81f
--- /dev/null
+++ b/drivers/media/video/gspca/gspca.h
@@ -0,0 +1,244 @@
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 <linux/mutex.h>
10
11/* compilation option */
12/*#define GSPCA_DEBUG 1*/
13
14#ifdef GSPCA_DEBUG
15/* GSPCA our debug messages */
16extern int gspca_debug;
17#define PDEBUG(level, fmt, args...) \
18 do {\
19 if (gspca_debug & (level)) \
20 printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
21 } while (0)
22#define D_ERR 0x01
23#define D_PROBE 0x02
24#define D_CONF 0x04
25#define D_STREAM 0x08
26#define D_FRAM 0x10
27#define D_PACK 0x20
28#define D_USBI 0x00
29#define D_USBO 0x00
30#define D_V4L2 0x0100
31#else
32#define PDEBUG(level, fmt, args...)
33#endif
34#undef err
35#define err(fmt, args...) \
36 printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args)
37#undef info
38#define info(fmt, args...) \
39 printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args)
40#undef warn
41#define warn(fmt, args...) \
42 printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args)
43
44#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
45/* image transfers */
46#define MAX_NURBS 4 /* max number of URBs */
47
48
49/* used to list framerates supported by a camera mode (resolution) */
50struct framerates {
51 const u8 *rates;
52 int nrates;
53};
54
55/* control definition */
56struct gspca_ctrl {
57 s16 val; /* current value */
58 s16 def; /* default value */
59 s16 min, max; /* minimum and maximum values */
60};
61
62/* device information - set at probe time */
63struct cam {
64 const struct v4l2_pix_format *cam_mode; /* size nmodes */
65 const struct framerates *mode_framerates; /* must have size nmodes,
66 * just like cam_mode */
67 struct gspca_ctrl *ctrls; /* control table - size nctrls */
68 /* may be NULL */
69 u32 bulk_size; /* buffer size when image transfer by bulk */
70 u32 input_flags; /* value for ENUM_INPUT status flags */
71 u8 nmodes; /* size of cam_mode */
72 u8 no_urb_create; /* don't create transfer URBs */
73 u8 bulk_nurbs; /* number of URBs in bulk mode
74 * - cannot be > MAX_NURBS
75 * - when 0 and bulk_size != 0 means
76 * 1 URB and submit done by subdriver */
77 u8 bulk; /* image transfer by 0:isoc / 1:bulk */
78 u8 npkt; /* number of packets in an ISOC message
79 * 0 is the default value: 32 packets */
80 u8 reverse_alts; /* Alt settings are in high to low order */
81};
82
83struct gspca_dev;
84struct gspca_frame;
85
86/* subdriver operations */
87typedef int (*cam_op) (struct gspca_dev *);
88typedef void (*cam_v_op) (struct gspca_dev *);
89typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
90typedef int (*cam_jpg_op) (struct gspca_dev *,
91 struct v4l2_jpegcompression *);
92typedef int (*cam_reg_op) (struct gspca_dev *,
93 struct v4l2_dbg_register *);
94typedef int (*cam_ident_op) (struct gspca_dev *,
95 struct v4l2_dbg_chip_ident *);
96typedef void (*cam_streamparm_op) (struct gspca_dev *,
97 struct v4l2_streamparm *);
98typedef int (*cam_qmnu_op) (struct gspca_dev *,
99 struct v4l2_querymenu *);
100typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
101 u8 *data,
102 int len);
103typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
104 u8 *data,
105 int len);
106
107struct ctrl {
108 struct v4l2_queryctrl qctrl;
109 int (*set)(struct gspca_dev *, __s32);
110 int (*get)(struct gspca_dev *, __s32 *);
111 cam_v_op set_control;
112};
113
114/* subdriver description */
115struct sd_desc {
116/* information */
117 const char *name; /* sub-driver name */
118/* controls */
119 const struct ctrl *ctrls; /* static control definition */
120 int nctrls;
121/* mandatory operations */
122 cam_cf_op config; /* called on probe */
123 cam_op init; /* called on probe and resume */
124 cam_op start; /* called on stream on after URBs creation */
125 cam_pkt_op pkt_scan;
126/* optional operations */
127 cam_op isoc_init; /* called on stream on before getting the EP */
128 cam_op isoc_nego; /* called when URB submit failed with NOSPC */
129 cam_v_op stopN; /* called on stream off - main alt */
130 cam_v_op stop0; /* called on stream off & disconnect - alt 0 */
131 cam_v_op dq_callback; /* called when a frame has been dequeued */
132 cam_jpg_op get_jcomp;
133 cam_jpg_op set_jcomp;
134 cam_qmnu_op querymenu;
135 cam_streamparm_op get_streamparm;
136 cam_streamparm_op set_streamparm;
137#ifdef CONFIG_VIDEO_ADV_DEBUG
138 cam_reg_op set_register;
139 cam_reg_op get_register;
140#endif
141 cam_ident_op get_chip_ident;
142#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
143 cam_int_pkt_op int_pkt_scan;
144 /* other_input makes the gspca core create gspca_dev->input even when
145 int_pkt_scan is NULL, for cams with non interrupt driven buttons */
146 u8 other_input;
147#endif
148};
149
150/* packet types when moving from iso buf to frame buf */
151enum gspca_packet_type {
152 DISCARD_PACKET,
153 FIRST_PACKET,
154 INTER_PACKET,
155 LAST_PACKET
156};
157
158struct gspca_frame {
159 __u8 *data; /* frame buffer */
160 int vma_use_count;
161 struct v4l2_buffer v4l2_buf;
162};
163
164struct gspca_dev {
165 struct video_device vdev; /* !! must be the first item */
166 struct module *module; /* subdriver handling the device */
167 struct usb_device *dev;
168 struct file *capt_file; /* file doing video capture */
169#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
170 struct input_dev *input_dev;
171 char phys[64]; /* physical device path */
172#endif
173
174 struct cam cam; /* device information */
175 const struct sd_desc *sd_desc; /* subdriver description */
176 unsigned ctrl_dis; /* disabled controls (bit map) */
177 unsigned ctrl_inac; /* inactive controls (bit map) */
178
179#define USB_BUF_SZ 64
180 __u8 *usb_buf; /* buffer for USB exchanges */
181 struct urb *urb[MAX_NURBS];
182#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
183 struct urb *int_urb;
184#endif
185
186 __u8 *frbuf; /* buffer for nframes */
187 struct gspca_frame frame[GSPCA_MAX_FRAMES];
188 u8 *image; /* image beeing filled */
189 __u32 frsz; /* frame size */
190 u32 image_len; /* current length of image */
191 atomic_t fr_q; /* next frame to queue */
192 atomic_t fr_i; /* frame being filled */
193 signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
194 char nframes; /* number of frames */
195 u8 fr_o; /* next frame to dequeue */
196 __u8 last_packet_type;
197 __s8 empty_packet; /* if (-1) don't check empty packets */
198 __u8 streaming;
199
200 __u8 curr_mode; /* current camera mode */
201 __u32 pixfmt; /* current mode parameters */
202 __u16 width;
203 __u16 height;
204 __u32 sequence; /* frame sequence number */
205
206 wait_queue_head_t wq; /* wait queue */
207 struct mutex usb_lock; /* usb exchange protection */
208 struct mutex queue_lock; /* ISOC queue protection */
209 int usb_err; /* USB error - protected by usb_lock */
210 u16 pkt_size; /* ISOC packet size */
211#ifdef CONFIG_PM
212 char frozen; /* suspend - resume */
213#endif
214 char present; /* device connected */
215 char nbufread; /* number of buffers for read() */
216 char memory; /* memory type (V4L2_MEMORY_xxx) */
217 __u8 iface; /* USB interface number */
218 __u8 alt; /* USB alternate setting */
219 __u8 nbalt; /* number of USB alternate settings */
220 u8 audio; /* presence of audio device */
221};
222
223int gspca_dev_probe(struct usb_interface *intf,
224 const struct usb_device_id *id,
225 const struct sd_desc *sd_desc,
226 int dev_size,
227 struct module *module);
228int gspca_dev_probe2(struct usb_interface *intf,
229 const struct usb_device_id *id,
230 const struct sd_desc *sd_desc,
231 int dev_size,
232 struct module *module);
233void gspca_disconnect(struct usb_interface *intf);
234void gspca_frame_add(struct gspca_dev *gspca_dev,
235 enum gspca_packet_type packet_type,
236 const u8 *data,
237 int len);
238#ifdef CONFIG_PM
239int gspca_suspend(struct usb_interface *intf, pm_message_t message);
240int gspca_resume(struct usb_interface *intf);
241#endif
242int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
243 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
244#endif /* GSPCAV2_H */
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c
new file mode 100644
index 00000000000..1bd9c4b542d
--- /dev/null
+++ b/drivers/media/video/gspca/jeilinj.c
@@ -0,0 +1,601 @@
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 MODULE_NAME "jeilinj"
28
29#include <linux/slab.h>
30#include "gspca.h"
31#include "jpeg.h"
32
33MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
34MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37/* Default timeouts, in ms */
38#define JEILINJ_CMD_TIMEOUT 500
39#define JEILINJ_CMD_DELAY 160
40#define JEILINJ_DATA_TIMEOUT 1000
41
42/* Maximum transfer size to use. */
43#define JEILINJ_MAX_TRANSFER 0x200
44#define FRAME_HEADER_LEN 0x10
45#define FRAME_START 0xFFFFFFFF
46
47enum {
48 SAKAR_57379,
49 SPORTSCAM_DV15,
50};
51
52#define CAMQUALITY_MIN 0 /* highest cam quality */
53#define CAMQUALITY_MAX 97 /* lowest cam quality */
54
55enum e_ctrl {
56 LIGHTFREQ,
57 AUTOGAIN,
58 RED,
59 GREEN,
60 BLUE,
61 NCTRLS /* number of controls */
62};
63
64/* Structure to hold all of our device specific stuff */
65struct sd {
66 struct gspca_dev gspca_dev; /* !! must be the first item */
67 struct gspca_ctrl ctrls[NCTRLS];
68 int blocks_left;
69 const struct v4l2_pix_format *cap_mode;
70 /* Driver stuff */
71 u8 type;
72 u8 quality; /* image quality */
73#define QUALITY_MIN 35
74#define QUALITY_MAX 85
75#define QUALITY_DEF 85
76 u8 jpeg_hdr[JPEG_HDR_SZ];
77};
78
79struct jlj_command {
80 unsigned char instruction[2];
81 unsigned char ack_wanted;
82 unsigned char delay;
83};
84
85/* AFAICT these cameras will only do 320x240. */
86static struct v4l2_pix_format jlj_mode[] = {
87 { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
88 .bytesperline = 320,
89 .sizeimage = 320 * 240,
90 .colorspace = V4L2_COLORSPACE_JPEG,
91 .priv = 0},
92 { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
93 .bytesperline = 640,
94 .sizeimage = 640 * 480,
95 .colorspace = V4L2_COLORSPACE_JPEG,
96 .priv = 0}
97};
98
99/*
100 * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
101 * and 0x82 for bulk transfer.
102 */
103
104/* All commands are two bytes only */
105static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
106{
107 int retval;
108
109 if (gspca_dev->usb_err < 0)
110 return;
111 memcpy(gspca_dev->usb_buf, command, 2);
112 retval = usb_bulk_msg(gspca_dev->dev,
113 usb_sndbulkpipe(gspca_dev->dev, 3),
114 gspca_dev->usb_buf, 2, NULL, 500);
115 if (retval < 0) {
116 err("command write [%02x] error %d",
117 gspca_dev->usb_buf[0], retval);
118 gspca_dev->usb_err = retval;
119 }
120}
121
122/* Responses are one byte only */
123static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
124{
125 int retval;
126
127 if (gspca_dev->usb_err < 0)
128 return;
129 retval = usb_bulk_msg(gspca_dev->dev,
130 usb_rcvbulkpipe(gspca_dev->dev, 0x84),
131 gspca_dev->usb_buf, 1, NULL, 500);
132 response = gspca_dev->usb_buf[0];
133 if (retval < 0) {
134 err("read command [%02x] error %d",
135 gspca_dev->usb_buf[0], retval);
136 gspca_dev->usb_err = retval;
137 }
138}
139
140static void setfreq(struct gspca_dev *gspca_dev)
141{
142 struct sd *sd = (struct sd *) gspca_dev;
143 u8 freq_commands[][2] = {
144 {0x71, 0x80},
145 {0x70, 0x07}
146 };
147
148 freq_commands[0][1] |= (sd->ctrls[LIGHTFREQ].val >> 1);
149
150 jlj_write2(gspca_dev, freq_commands[0]);
151 jlj_write2(gspca_dev, freq_commands[1]);
152}
153
154static void setcamquality(struct gspca_dev *gspca_dev)
155{
156 struct sd *sd = (struct sd *) gspca_dev;
157 u8 quality_commands[][2] = {
158 {0x71, 0x1E},
159 {0x70, 0x06}
160 };
161 u8 camquality;
162
163 /* adapt camera quality from jpeg quality */
164 camquality = ((QUALITY_MAX - sd->quality) * CAMQUALITY_MAX)
165 / (QUALITY_MAX - QUALITY_MIN);
166 quality_commands[0][1] += camquality;
167
168 jlj_write2(gspca_dev, quality_commands[0]);
169 jlj_write2(gspca_dev, quality_commands[1]);
170}
171
172static void setautogain(struct gspca_dev *gspca_dev)
173{
174 struct sd *sd = (struct sd *) gspca_dev;
175 u8 autogain_commands[][2] = {
176 {0x94, 0x02},
177 {0xcf, 0x00}
178 };
179
180 autogain_commands[1][1] = (sd->ctrls[AUTOGAIN].val << 4);
181
182 jlj_write2(gspca_dev, autogain_commands[0]);
183 jlj_write2(gspca_dev, autogain_commands[1]);
184}
185
186static void setred(struct gspca_dev *gspca_dev)
187{
188 struct sd *sd = (struct sd *) gspca_dev;
189 u8 setred_commands[][2] = {
190 {0x94, 0x02},
191 {0xe6, 0x00}
192 };
193
194 setred_commands[1][1] = sd->ctrls[RED].val;
195
196 jlj_write2(gspca_dev, setred_commands[0]);
197 jlj_write2(gspca_dev, setred_commands[1]);
198}
199
200static void setgreen(struct gspca_dev *gspca_dev)
201{
202 struct sd *sd = (struct sd *) gspca_dev;
203 u8 setgreen_commands[][2] = {
204 {0x94, 0x02},
205 {0xe7, 0x00}
206 };
207
208 setgreen_commands[1][1] = sd->ctrls[GREEN].val;
209
210 jlj_write2(gspca_dev, setgreen_commands[0]);
211 jlj_write2(gspca_dev, setgreen_commands[1]);
212}
213
214static void setblue(struct gspca_dev *gspca_dev)
215{
216 struct sd *sd = (struct sd *) gspca_dev;
217 u8 setblue_commands[][2] = {
218 {0x94, 0x02},
219 {0xe9, 0x00}
220 };
221
222 setblue_commands[1][1] = sd->ctrls[BLUE].val;
223
224 jlj_write2(gspca_dev, setblue_commands[0]);
225 jlj_write2(gspca_dev, setblue_commands[1]);
226}
227
228static const struct ctrl sd_ctrls[NCTRLS] = {
229[LIGHTFREQ] = {
230 {
231 .id = V4L2_CID_POWER_LINE_FREQUENCY,
232 .type = V4L2_CTRL_TYPE_MENU,
233 .name = "Light frequency filter",
234 .minimum = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, /* 1 */
235 .maximum = V4L2_CID_POWER_LINE_FREQUENCY_60HZ, /* 2 */
236 .step = 1,
237 .default_value = V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
238 },
239 .set_control = setfreq
240 },
241[AUTOGAIN] = {
242 {
243 .id = V4L2_CID_AUTOGAIN,
244 .type = V4L2_CTRL_TYPE_INTEGER,
245 .name = "Automatic Gain (and Exposure)",
246 .minimum = 0,
247 .maximum = 3,
248 .step = 1,
249#define AUTOGAIN_DEF 0
250 .default_value = AUTOGAIN_DEF,
251 },
252 .set_control = setautogain
253 },
254[RED] = {
255 {
256 .id = V4L2_CID_RED_BALANCE,
257 .type = V4L2_CTRL_TYPE_INTEGER,
258 .name = "red balance",
259 .minimum = 0,
260 .maximum = 3,
261 .step = 1,
262#define RED_BALANCE_DEF 2
263 .default_value = RED_BALANCE_DEF,
264 },
265 .set_control = setred
266 },
267
268[GREEN] = {
269 {
270 .id = V4L2_CID_GAIN,
271 .type = V4L2_CTRL_TYPE_INTEGER,
272 .name = "green balance",
273 .minimum = 0,
274 .maximum = 3,
275 .step = 1,
276#define GREEN_BALANCE_DEF 2
277 .default_value = GREEN_BALANCE_DEF,
278 },
279 .set_control = setgreen
280 },
281[BLUE] = {
282 {
283 .id = V4L2_CID_BLUE_BALANCE,
284 .type = V4L2_CTRL_TYPE_INTEGER,
285 .name = "blue balance",
286 .minimum = 0,
287 .maximum = 3,
288 .step = 1,
289#define BLUE_BALANCE_DEF 2
290 .default_value = BLUE_BALANCE_DEF,
291 },
292 .set_control = setblue
293 },
294};
295
296static int jlj_start(struct gspca_dev *gspca_dev)
297{
298 int i;
299 int start_commands_size;
300 u8 response = 0xff;
301 struct sd *sd = (struct sd *) gspca_dev;
302 struct jlj_command start_commands[] = {
303 {{0x71, 0x81}, 0, 0},
304 {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
305 {{0x95, 0x70}, 1, 0},
306 {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
307 {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
308 {{0x95, 0x70}, 1, 0},
309 {{0x71, 0x00}, 0, 0}, /* start streaming ??*/
310 {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
311 {{0x95, 0x70}, 1, 0},
312#define SPORTSCAM_DV15_CMD_SIZE 9
313 {{0x94, 0x02}, 0, 0},
314 {{0xde, 0x24}, 0, 0},
315 {{0x94, 0x02}, 0, 0},
316 {{0xdd, 0xf0}, 0, 0},
317 {{0x94, 0x02}, 0, 0},
318 {{0xe3, 0x2c}, 0, 0},
319 {{0x94, 0x02}, 0, 0},
320 {{0xe4, 0x00}, 0, 0},
321 {{0x94, 0x02}, 0, 0},
322 {{0xe5, 0x00}, 0, 0},
323 {{0x94, 0x02}, 0, 0},
324 {{0xe6, 0x2c}, 0, 0},
325 {{0x94, 0x03}, 0, 0},
326 {{0xaa, 0x00}, 0, 0}
327 };
328
329 sd->blocks_left = 0;
330 /* Under Windows, USB spy shows that only the 9 first start
331 * commands are used for SPORTSCAM_DV15 webcam
332 */
333 if (sd->type == SPORTSCAM_DV15)
334 start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
335 else
336 start_commands_size = ARRAY_SIZE(start_commands);
337
338 for (i = 0; i < start_commands_size; i++) {
339 jlj_write2(gspca_dev, start_commands[i].instruction);
340 if (start_commands[i].delay)
341 msleep(start_commands[i].delay);
342 if (start_commands[i].ack_wanted)
343 jlj_read1(gspca_dev, response);
344 }
345 setcamquality(gspca_dev);
346 msleep(2);
347 setfreq(gspca_dev);
348 if (gspca_dev->usb_err < 0)
349 PDEBUG(D_ERR, "Start streaming command failed");
350 return gspca_dev->usb_err;
351}
352
353static void sd_pkt_scan(struct gspca_dev *gspca_dev,
354 u8 *data, int len)
355{
356 struct sd *sd = (struct sd *) gspca_dev;
357 int packet_type;
358 u32 header_marker;
359
360 PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0",
361 len, JEILINJ_MAX_TRANSFER);
362 if (len != JEILINJ_MAX_TRANSFER) {
363 PDEBUG(D_PACK, "bad length");
364 goto discard;
365 }
366 /* check if it's start of frame */
367 header_marker = ((u32 *)data)[0];
368 if (header_marker == FRAME_START) {
369 sd->blocks_left = data[0x0a] - 1;
370 PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left);
371 /* Start a new frame, and add the JPEG header, first thing */
372 gspca_frame_add(gspca_dev, FIRST_PACKET,
373 sd->jpeg_hdr, JPEG_HDR_SZ);
374 /* Toss line 0 of data block 0, keep the rest. */
375 gspca_frame_add(gspca_dev, INTER_PACKET,
376 data + FRAME_HEADER_LEN,
377 JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
378 } else if (sd->blocks_left > 0) {
379 PDEBUG(D_STREAM, "%d blocks remaining for frame",
380 sd->blocks_left);
381 sd->blocks_left -= 1;
382 if (sd->blocks_left == 0)
383 packet_type = LAST_PACKET;
384 else
385 packet_type = INTER_PACKET;
386 gspca_frame_add(gspca_dev, packet_type,
387 data, JEILINJ_MAX_TRANSFER);
388 } else
389 goto discard;
390 return;
391discard:
392 /* Discard data until a new frame starts. */
393 gspca_dev->last_packet_type = DISCARD_PACKET;
394}
395
396/* This function is called at probe time just before sd_init */
397static int sd_config(struct gspca_dev *gspca_dev,
398 const struct usb_device_id *id)
399{
400 struct cam *cam = &gspca_dev->cam;
401 struct sd *dev = (struct sd *) gspca_dev;
402
403 dev->type = id->driver_info;
404 gspca_dev->cam.ctrls = dev->ctrls;
405 dev->quality = QUALITY_DEF;
406 dev->ctrls[LIGHTFREQ].def = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
407 dev->ctrls[RED].def = RED_BALANCE_DEF;
408 dev->ctrls[GREEN].def = GREEN_BALANCE_DEF;
409 dev->ctrls[BLUE].def = BLUE_BALANCE_DEF;
410 PDEBUG(D_PROBE,
411 "JEILINJ camera detected"
412 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
413 cam->cam_mode = jlj_mode;
414 cam->nmodes = ARRAY_SIZE(jlj_mode);
415 cam->bulk = 1;
416 cam->bulk_nurbs = 1;
417 cam->bulk_size = JEILINJ_MAX_TRANSFER;
418 return 0;
419}
420
421static void sd_stopN(struct gspca_dev *gspca_dev)
422{
423 int i;
424 u8 *buf;
425 u8 stop_commands[][2] = {
426 {0x71, 0x00},
427 {0x70, 0x09},
428 {0x71, 0x80},
429 {0x70, 0x05}
430 };
431
432 for (;;) {
433 /* get the image remaining blocks */
434 usb_bulk_msg(gspca_dev->dev,
435 gspca_dev->urb[0]->pipe,
436 gspca_dev->urb[0]->transfer_buffer,
437 JEILINJ_MAX_TRANSFER, NULL,
438 JEILINJ_DATA_TIMEOUT);
439
440 /* search for 0xff 0xd9 (EOF for JPEG) */
441 i = 0;
442 buf = gspca_dev->urb[0]->transfer_buffer;
443 while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
444 ((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
445 i++;
446
447 if (i != (JEILINJ_MAX_TRANSFER - 1))
448 /* last remaining block found */
449 break;
450 }
451
452 for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
453 jlj_write2(gspca_dev, stop_commands[i]);
454}
455
456/* this function is called at probe and resume time */
457static int sd_init(struct gspca_dev *gspca_dev)
458{
459 return gspca_dev->usb_err;
460}
461
462/* Set up for getting frames. */
463static int sd_start(struct gspca_dev *gspca_dev)
464{
465 struct sd *dev = (struct sd *) gspca_dev;
466
467 /* create the JPEG header */
468 jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
469 0x21); /* JPEG 422 */
470 jpeg_set_qual(dev->jpeg_hdr, dev->quality);
471 PDEBUG(D_STREAM, "Start streaming at %dx%d",
472 gspca_dev->height, gspca_dev->width);
473 jlj_start(gspca_dev);
474 return gspca_dev->usb_err;
475}
476
477/* Table of supported USB devices */
478static const struct usb_device_id device_table[] = {
479 {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
480 {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
481 {}
482};
483
484MODULE_DEVICE_TABLE(usb, device_table);
485
486static int sd_querymenu(struct gspca_dev *gspca_dev,
487 struct v4l2_querymenu *menu)
488{
489 switch (menu->id) {
490 case V4L2_CID_POWER_LINE_FREQUENCY:
491 switch (menu->index) {
492 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
493 strcpy((char *) menu->name, "disable");
494 return 0;
495 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
496 strcpy((char *) menu->name, "50 Hz");
497 return 0;
498 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
499 strcpy((char *) menu->name, "60 Hz");
500 return 0;
501 }
502 break;
503 }
504 return -EINVAL;
505}
506
507static int sd_set_jcomp(struct gspca_dev *gspca_dev,
508 struct v4l2_jpegcompression *jcomp)
509{
510 struct sd *sd = (struct sd *) gspca_dev;
511
512 if (jcomp->quality < QUALITY_MIN)
513 sd->quality = QUALITY_MIN;
514 else if (jcomp->quality > QUALITY_MAX)
515 sd->quality = QUALITY_MAX;
516 else
517 sd->quality = jcomp->quality;
518 if (gspca_dev->streaming) {
519 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
520 setcamquality(gspca_dev);
521 }
522 return 0;
523}
524
525static int sd_get_jcomp(struct gspca_dev *gspca_dev,
526 struct v4l2_jpegcompression *jcomp)
527{
528 struct sd *sd = (struct sd *) gspca_dev;
529
530 memset(jcomp, 0, sizeof *jcomp);
531 jcomp->quality = sd->quality;
532 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
533 | V4L2_JPEG_MARKER_DQT;
534 return 0;
535}
536
537
538/* sub-driver description */
539static const struct sd_desc sd_desc_sakar_57379 = {
540 .name = MODULE_NAME,
541 .config = sd_config,
542 .init = sd_init,
543 .start = sd_start,
544 .stopN = sd_stopN,
545 .pkt_scan = sd_pkt_scan,
546};
547
548/* sub-driver description */
549static const struct sd_desc sd_desc_sportscam_dv15 = {
550 .name = MODULE_NAME,
551 .config = sd_config,
552 .init = sd_init,
553 .start = sd_start,
554 .stopN = sd_stopN,
555 .pkt_scan = sd_pkt_scan,
556 .ctrls = sd_ctrls,
557 .nctrls = ARRAY_SIZE(sd_ctrls),
558 .querymenu = sd_querymenu,
559 .get_jcomp = sd_get_jcomp,
560 .set_jcomp = sd_set_jcomp,
561};
562
563static const struct sd_desc *sd_desc[2] = {
564 &sd_desc_sakar_57379,
565 &sd_desc_sportscam_dv15
566};
567
568/* -- device connect -- */
569static int sd_probe(struct usb_interface *intf,
570 const struct usb_device_id *id)
571{
572 return gspca_dev_probe(intf, id,
573 sd_desc[id->driver_info],
574 sizeof(struct sd),
575 THIS_MODULE);
576}
577
578static struct usb_driver sd_driver = {
579 .name = MODULE_NAME,
580 .id_table = device_table,
581 .probe = sd_probe,
582 .disconnect = gspca_disconnect,
583#ifdef CONFIG_PM
584 .suspend = gspca_suspend,
585 .resume = gspca_resume,
586#endif
587};
588
589/* -- module insert / remove -- */
590static int __init sd_mod_init(void)
591{
592 return usb_register(&sd_driver);
593}
594
595static void __exit sd_mod_exit(void)
596{
597 usb_deregister(&sd_driver);
598}
599
600module_init(sd_mod_init);
601module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h
new file mode 100644
index 00000000000..ab54910418b
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c
new file mode 100644
index 00000000000..26fc206f095
--- /dev/null
+++ b/drivers/media/video/gspca/kinect.c
@@ -0,0 +1,429 @@
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 MODULE_NAME "kinect"
28
29#include "gspca.h"
30
31#define CTRL_TIMEOUT 500
32
33MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
34MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37#ifdef GSPCA_DEBUG
38int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
39 D_USBI | D_USBO | D_V4L2;
40#endif
41
42struct pkt_hdr {
43 uint8_t magic[2];
44 uint8_t pad;
45 uint8_t flag;
46 uint8_t unk1;
47 uint8_t seq;
48 uint8_t unk2;
49 uint8_t unk3;
50 uint32_t timestamp;
51};
52
53struct cam_hdr {
54 uint8_t magic[2];
55 uint16_t len;
56 uint16_t cmd;
57 uint16_t tag;
58};
59
60/* specific webcam descriptor */
61struct sd {
62 struct gspca_dev gspca_dev; /* !! must be the first item */
63 uint16_t cam_tag; /* a sequence number for packets */
64 uint8_t stream_flag; /* to identify different stream types */
65 uint8_t obuf[0x400]; /* output buffer for control commands */
66 uint8_t ibuf[0x200]; /* input buffer for control commands */
67};
68
69/* V4L2 controls supported by the driver */
70/* controls prototypes here */
71
72static const struct ctrl sd_ctrls[] = {
73};
74
75#define MODE_640x480 0x0001
76#define MODE_640x488 0x0002
77#define MODE_1280x1024 0x0004
78
79#define FORMAT_BAYER 0x0010
80#define FORMAT_UYVY 0x0020
81#define FORMAT_Y10B 0x0040
82
83#define FPS_HIGH 0x0100
84
85static const struct v4l2_pix_format video_camera_mode[] = {
86 {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
87 .bytesperline = 640,
88 .sizeimage = 640 * 480,
89 .colorspace = V4L2_COLORSPACE_SRGB,
90 .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH},
91 {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
92 .bytesperline = 640 * 2,
93 .sizeimage = 640 * 480 * 2,
94 .colorspace = V4L2_COLORSPACE_SRGB,
95 .priv = MODE_640x480 | FORMAT_UYVY},
96 {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
97 .bytesperline = 1280,
98 .sizeimage = 1280 * 1024,
99 .colorspace = V4L2_COLORSPACE_SRGB,
100 .priv = MODE_1280x1024 | FORMAT_BAYER},
101 {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
102 .bytesperline = 640 * 10 / 8,
103 .sizeimage = 640 * 488 * 10 / 8,
104 .colorspace = V4L2_COLORSPACE_SRGB,
105 .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH},
106 {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
107 .bytesperline = 1280 * 10 / 8,
108 .sizeimage = 1280 * 1024 * 10 / 8,
109 .colorspace = V4L2_COLORSPACE_SRGB,
110 .priv = MODE_1280x1024 | FORMAT_Y10B},
111};
112
113static int kinect_write(struct usb_device *udev, uint8_t *data,
114 uint16_t wLength)
115{
116 return usb_control_msg(udev,
117 usb_sndctrlpipe(udev, 0),
118 0x00,
119 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
120 0, 0, data, wLength, CTRL_TIMEOUT);
121}
122
123static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength)
124{
125 return usb_control_msg(udev,
126 usb_rcvctrlpipe(udev, 0),
127 0x00,
128 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
129 0, 0, data, wLength, CTRL_TIMEOUT);
130}
131
132static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
133 unsigned int cmd_len, void *replybuf, unsigned int reply_len)
134{
135 struct sd *sd = (struct sd *) gspca_dev;
136 struct usb_device *udev = gspca_dev->dev;
137 int res, actual_len;
138 uint8_t *obuf = sd->obuf;
139 uint8_t *ibuf = sd->ibuf;
140 struct cam_hdr *chdr = (void *)obuf;
141 struct cam_hdr *rhdr = (void *)ibuf;
142
143 if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
144 err("send_cmd: Invalid command length (0x%x)", cmd_len);
145 return -1;
146 }
147
148 chdr->magic[0] = 0x47;
149 chdr->magic[1] = 0x4d;
150 chdr->cmd = cpu_to_le16(cmd);
151 chdr->tag = cpu_to_le16(sd->cam_tag);
152 chdr->len = cpu_to_le16(cmd_len / 2);
153
154 memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);
155
156 res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr));
157 PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
158 sd->cam_tag, cmd_len, res);
159 if (res < 0) {
160 err("send_cmd: Output control transfer failed (%d)", res);
161 return res;
162 }
163
164 do {
165 actual_len = kinect_read(udev, ibuf, 0x200);
166 } while (actual_len == 0);
167 PDEBUG(D_USBO, "Control reply: %d", res);
168 if (actual_len < sizeof(*rhdr)) {
169 err("send_cmd: Input control transfer failed (%d)", res);
170 return res;
171 }
172 actual_len -= sizeof(*rhdr);
173
174 if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
175 err("send_cmd: Bad magic %02x %02x", rhdr->magic[0],
176 rhdr->magic[1]);
177 return -1;
178 }
179 if (rhdr->cmd != chdr->cmd) {
180 err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd);
181 return -1;
182 }
183 if (rhdr->tag != chdr->tag) {
184 err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag);
185 return -1;
186 }
187 if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
188 err("send_cmd: Bad len %04x != %04x",
189 cpu_to_le16(rhdr->len), (int)(actual_len/2));
190 return -1;
191 }
192
193 if (actual_len > reply_len) {
194 warn("send_cmd: Data buffer is %d bytes long, but got %d bytes",
195 reply_len, actual_len);
196 memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
197 } else {
198 memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
199 }
200
201 sd->cam_tag++;
202
203 return actual_len;
204}
205
206static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
207 uint16_t data)
208{
209 uint16_t reply[2];
210 uint16_t cmd[2];
211 int res;
212
213 cmd[0] = cpu_to_le16(reg);
214 cmd[1] = cpu_to_le16(data);
215
216 PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data);
217 res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4);
218 if (res < 0)
219 return res;
220 if (res != 2) {
221 warn("send_cmd returned %d [%04x %04x], 0000 expected",
222 res, reply[0], reply[1]);
223 }
224 return 0;
225}
226
227/* this function is called at probe time */
228static int sd_config(struct gspca_dev *gspca_dev,
229 const struct usb_device_id *id)
230{
231 struct sd *sd = (struct sd *) gspca_dev;
232 struct cam *cam;
233
234 sd->cam_tag = 0;
235
236 /* Only video stream is supported for now,
237 * which has stream flag = 0x80 */
238 sd->stream_flag = 0x80;
239
240 cam = &gspca_dev->cam;
241
242 cam->cam_mode = video_camera_mode;
243 cam->nmodes = ARRAY_SIZE(video_camera_mode);
244
245#if 0
246 /* Setting those values is not needed for video stream */
247 cam->npkt = 15;
248 gspca_dev->pkt_size = 960 * 2;
249#endif
250
251 return 0;
252}
253
254/* this function is called at probe and resume time */
255static int sd_init(struct gspca_dev *gspca_dev)
256{
257 PDEBUG(D_PROBE, "Kinect Camera device.");
258
259 return 0;
260}
261
262static int sd_start(struct gspca_dev *gspca_dev)
263{
264 int mode;
265 uint8_t fmt_reg, fmt_val;
266 uint8_t res_reg, res_val;
267 uint8_t fps_reg, fps_val;
268 uint8_t mode_val;
269
270 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
271
272 if (mode & FORMAT_Y10B) {
273 fmt_reg = 0x19;
274 res_reg = 0x1a;
275 fps_reg = 0x1b;
276 mode_val = 0x03;
277 } else {
278 fmt_reg = 0x0c;
279 res_reg = 0x0d;
280 fps_reg = 0x0e;
281 mode_val = 0x01;
282 }
283
284 /* format */
285 if (mode & FORMAT_UYVY)
286 fmt_val = 0x05;
287 else
288 fmt_val = 0x00;
289
290 if (mode & MODE_1280x1024)
291 res_val = 0x02;
292 else
293 res_val = 0x01;
294
295 if (mode & FPS_HIGH)
296 fps_val = 0x1e;
297 else
298 fps_val = 0x0f;
299
300
301 /* turn off IR-reset function */
302 write_register(gspca_dev, 0x105, 0x00);
303
304 /* Reset video stream */
305 write_register(gspca_dev, 0x05, 0x00);
306
307 /* Due to some ridiculous condition in the firmware, we have to start
308 * and stop the depth stream before the camera will hand us 1280x1024
309 * IR. This is a stupid workaround, but we've yet to find a better
310 * solution.
311 *
312 * Thanks to Drew Fisher for figuring this out.
313 */
314 if (mode & (FORMAT_Y10B | MODE_1280x1024)) {
315 write_register(gspca_dev, 0x13, 0x01);
316 write_register(gspca_dev, 0x14, 0x1e);
317 write_register(gspca_dev, 0x06, 0x02);
318 write_register(gspca_dev, 0x06, 0x00);
319 }
320
321 write_register(gspca_dev, fmt_reg, fmt_val);
322 write_register(gspca_dev, res_reg, res_val);
323 write_register(gspca_dev, fps_reg, fps_val);
324
325 /* Start video stream */
326 write_register(gspca_dev, 0x05, mode_val);
327
328 /* disable Hflip */
329 write_register(gspca_dev, 0x47, 0x00);
330
331 return 0;
332}
333
334static void sd_stopN(struct gspca_dev *gspca_dev)
335{
336 /* reset video stream */
337 write_register(gspca_dev, 0x05, 0x00);
338}
339
340static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
341{
342 struct sd *sd = (struct sd *) gspca_dev;
343
344 struct pkt_hdr *hdr = (void *)__data;
345 uint8_t *data = __data + sizeof(*hdr);
346 int datalen = len - sizeof(*hdr);
347
348 uint8_t sof = sd->stream_flag | 1;
349 uint8_t mof = sd->stream_flag | 2;
350 uint8_t eof = sd->stream_flag | 5;
351
352 if (len < 12)
353 return;
354
355 if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
356 warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag,
357 hdr->magic[0], hdr->magic[1]);
358 return;
359 }
360
361 if (hdr->flag == sof)
362 gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen);
363
364 else if (hdr->flag == mof)
365 gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen);
366
367 else if (hdr->flag == eof)
368 gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
369
370 else
371 warn("Packet type not recognized...");
372}
373
374/* sub-driver description */
375static const struct sd_desc sd_desc = {
376 .name = MODULE_NAME,
377 .ctrls = sd_ctrls,
378 .nctrls = ARRAY_SIZE(sd_ctrls),
379 .config = sd_config,
380 .init = sd_init,
381 .start = sd_start,
382 .stopN = sd_stopN,
383 .pkt_scan = sd_pkt_scan,
384 /*
385 .querymenu = sd_querymenu,
386 .get_streamparm = sd_get_streamparm,
387 .set_streamparm = sd_set_streamparm,
388 */
389};
390
391/* -- module initialisation -- */
392static const struct usb_device_id device_table[] = {
393 {USB_DEVICE(0x045e, 0x02ae)},
394 {}
395};
396
397MODULE_DEVICE_TABLE(usb, device_table);
398
399/* -- device connect -- */
400static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
401{
402 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
403 THIS_MODULE);
404}
405
406static struct usb_driver sd_driver = {
407 .name = MODULE_NAME,
408 .id_table = device_table,
409 .probe = sd_probe,
410 .disconnect = gspca_disconnect,
411#ifdef CONFIG_PM
412 .suspend = gspca_suspend,
413 .resume = gspca_resume,
414#endif
415};
416
417/* -- module insert / remove -- */
418static int __init sd_mod_init(void)
419{
420 return usb_register(&sd_driver);
421}
422
423static void __exit sd_mod_exit(void)
424{
425 usb_deregister(&sd_driver);
426}
427
428module_init(sd_mod_init);
429module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c
new file mode 100644
index 00000000000..5964691c0e9
--- /dev/null
+++ b/drivers/media/video/gspca/konica.c
@@ -0,0 +1,646 @@
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 MODULE_NAME "konica"
32
33#include <linux/input.h>
34#include "gspca.h"
35
36MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
37MODULE_DESCRIPTION("Konica chipset USB Camera Driver");
38MODULE_LICENSE("GPL");
39
40#define WHITEBAL_REG 0x01
41#define BRIGHTNESS_REG 0x02
42#define SHARPNESS_REG 0x03
43#define CONTRAST_REG 0x04
44#define SATURATION_REG 0x05
45
46/* specific webcam descriptor */
47struct sd {
48 struct gspca_dev gspca_dev; /* !! must be the first item */
49 struct urb *last_data_urb;
50 u8 snapshot_pressed;
51 u8 brightness;
52 u8 contrast;
53 u8 saturation;
54 u8 whitebal;
55 u8 sharpness;
56};
57
58/* V4L2 controls supported by the driver */
59static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setwhitebal(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getwhitebal(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69
70static const struct ctrl sd_ctrls[] = {
71#define SD_BRIGHTNESS 0
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 9,
79 .step = 1,
80#define BRIGHTNESS_DEFAULT 4
81 .default_value = BRIGHTNESS_DEFAULT,
82 .flags = 0,
83 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
87#define SD_CONTRAST 1
88 {
89 {
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Contrast",
93 .minimum = 0,
94 .maximum = 9,
95 .step = 4,
96#define CONTRAST_DEFAULT 10
97 .default_value = CONTRAST_DEFAULT,
98 .flags = 0,
99 },
100 .set = sd_setcontrast,
101 .get = sd_getcontrast,
102 },
103#define SD_SATURATION 2
104 {
105 {
106 .id = V4L2_CID_SATURATION,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Saturation",
109 .minimum = 0,
110 .maximum = 9,
111 .step = 1,
112#define SATURATION_DEFAULT 4
113 .default_value = SATURATION_DEFAULT,
114 .flags = 0,
115 },
116 .set = sd_setsaturation,
117 .get = sd_getsaturation,
118 },
119#define SD_WHITEBAL 3
120 {
121 {
122 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
123 .type = V4L2_CTRL_TYPE_INTEGER,
124 .name = "White Balance",
125 .minimum = 0,
126 .maximum = 33,
127 .step = 1,
128#define WHITEBAL_DEFAULT 25
129 .default_value = WHITEBAL_DEFAULT,
130 .flags = 0,
131 },
132 .set = sd_setwhitebal,
133 .get = sd_getwhitebal,
134 },
135#define SD_SHARPNESS 4
136 {
137 {
138 .id = V4L2_CID_SHARPNESS,
139 .type = V4L2_CTRL_TYPE_INTEGER,
140 .name = "Sharpness",
141 .minimum = 0,
142 .maximum = 9,
143 .step = 1,
144#define SHARPNESS_DEFAULT 4
145 .default_value = SHARPNESS_DEFAULT,
146 .flags = 0,
147 },
148 .set = sd_setsharpness,
149 .get = sd_getsharpness,
150 },
151};
152
153/* .priv is what goes to register 8 for this mode, known working values:
154 0x00 -> 176x144, cropped
155 0x01 -> 176x144, cropped
156 0x02 -> 176x144, cropped
157 0x03 -> 176x144, cropped
158 0x04 -> 176x144, binned
159 0x05 -> 320x240
160 0x06 -> 320x240
161 0x07 -> 160x120, cropped
162 0x08 -> 160x120, cropped
163 0x09 -> 160x120, binned (note has 136 lines)
164 0x0a -> 160x120, binned (note has 136 lines)
165 0x0b -> 160x120, cropped
166*/
167static const struct v4l2_pix_format vga_mode[] = {
168 {160, 120, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
169 .bytesperline = 160,
170 .sizeimage = 160 * 136 * 3 / 2 + 960,
171 .colorspace = V4L2_COLORSPACE_SRGB,
172 .priv = 0x0a},
173 {176, 144, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
174 .bytesperline = 176,
175 .sizeimage = 176 * 144 * 3 / 2 + 960,
176 .colorspace = V4L2_COLORSPACE_SRGB,
177 .priv = 0x04},
178 {320, 240, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
179 .bytesperline = 320,
180 .sizeimage = 320 * 240 * 3 / 2 + 960,
181 .colorspace = V4L2_COLORSPACE_SRGB,
182 .priv = 0x05},
183};
184
185static void sd_isoc_irq(struct urb *urb);
186
187static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
188{
189 struct usb_device *dev = gspca_dev->dev;
190 int ret;
191
192 if (gspca_dev->usb_err < 0)
193 return;
194 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
195 0x02,
196 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
197 value,
198 index,
199 NULL,
200 0,
201 1000);
202 if (ret < 0) {
203 err("reg_w err %d", ret);
204 gspca_dev->usb_err = ret;
205 }
206}
207
208static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index)
209{
210 struct usb_device *dev = gspca_dev->dev;
211 int ret;
212
213 if (gspca_dev->usb_err < 0)
214 return;
215 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
216 0x03,
217 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
218 value,
219 index,
220 gspca_dev->usb_buf,
221 2,
222 1000);
223 if (ret < 0) {
224 err("reg_w err %d", ret);
225 gspca_dev->usb_err = ret;
226 }
227}
228
229static void konica_stream_on(struct gspca_dev *gspca_dev)
230{
231 reg_w(gspca_dev, 1, 0x0b);
232}
233
234static void konica_stream_off(struct gspca_dev *gspca_dev)
235{
236 reg_w(gspca_dev, 0, 0x0b);
237}
238
239/* this function is called at probe time */
240static int sd_config(struct gspca_dev *gspca_dev,
241 const struct usb_device_id *id)
242{
243 struct sd *sd = (struct sd *) gspca_dev;
244
245 gspca_dev->cam.cam_mode = vga_mode;
246 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
247 gspca_dev->cam.no_urb_create = 1;
248 /* The highest alt setting has an isoc packetsize of 0, so we
249 don't want to use it */
250 gspca_dev->nbalt--;
251
252 sd->brightness = BRIGHTNESS_DEFAULT;
253 sd->contrast = CONTRAST_DEFAULT;
254 sd->saturation = SATURATION_DEFAULT;
255 sd->whitebal = WHITEBAL_DEFAULT;
256 sd->sharpness = SHARPNESS_DEFAULT;
257
258 return 0;
259}
260
261/* this function is called at probe and resume time */
262static int sd_init(struct gspca_dev *gspca_dev)
263{
264 /* HDG not sure if these 2 reads are needed */
265 reg_r(gspca_dev, 0, 0x10);
266 PDEBUG(D_PROBE, "Reg 0x10 reads: %02x %02x",
267 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
268 reg_r(gspca_dev, 0, 0x10);
269 PDEBUG(D_PROBE, "Reg 0x10 reads: %02x %02x",
270 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
271 reg_w(gspca_dev, 0, 0x0d);
272
273 return 0;
274}
275
276static int sd_start(struct gspca_dev *gspca_dev)
277{
278 struct sd *sd = (struct sd *) gspca_dev;
279 struct urb *urb;
280 int i, n, packet_size;
281 struct usb_host_interface *alt;
282 struct usb_interface *intf;
283
284 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
285 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
286 if (!alt) {
287 err("Couldn't get altsetting");
288 return -EIO;
289 }
290
291 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
292
293 reg_w(gspca_dev, sd->brightness, BRIGHTNESS_REG);
294 reg_w(gspca_dev, sd->whitebal, WHITEBAL_REG);
295 reg_w(gspca_dev, sd->contrast, CONTRAST_REG);
296 reg_w(gspca_dev, sd->saturation, SATURATION_REG);
297 reg_w(gspca_dev, sd->sharpness, SHARPNESS_REG);
298
299 n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
300 reg_w(gspca_dev, n, 0x08);
301
302 konica_stream_on(gspca_dev);
303
304 if (gspca_dev->usb_err)
305 return gspca_dev->usb_err;
306
307 /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
308#if MAX_NURBS < 4
309#error "Not enough URBs in the gspca table"
310#endif
311#define SD_NPKT 32
312 for (n = 0; n < 4; n++) {
313 i = n & 1 ? 0 : 1;
314 packet_size =
315 le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
316 urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
317 if (!urb) {
318 err("usb_alloc_urb failed");
319 return -ENOMEM;
320 }
321 gspca_dev->urb[n] = urb;
322 urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
323 packet_size * SD_NPKT,
324 GFP_KERNEL,
325 &urb->transfer_dma);
326 if (urb->transfer_buffer == NULL) {
327 err("usb_buffer_alloc failed");
328 return -ENOMEM;
329 }
330
331 urb->dev = gspca_dev->dev;
332 urb->context = gspca_dev;
333 urb->transfer_buffer_length = packet_size * SD_NPKT;
334 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
335 n & 1 ? 0x81 : 0x82);
336 urb->transfer_flags = URB_ISO_ASAP
337 | URB_NO_TRANSFER_DMA_MAP;
338 urb->interval = 1;
339 urb->complete = sd_isoc_irq;
340 urb->number_of_packets = SD_NPKT;
341 for (i = 0; i < SD_NPKT; i++) {
342 urb->iso_frame_desc[i].length = packet_size;
343 urb->iso_frame_desc[i].offset = packet_size * i;
344 }
345 }
346
347 return 0;
348}
349
350static void sd_stopN(struct gspca_dev *gspca_dev)
351{
352 struct sd *sd = (struct sd *) gspca_dev;
353
354 konica_stream_off(gspca_dev);
355#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
356 /* Don't keep the button in the pressed state "forever" if it was
357 pressed when streaming is stopped */
358 if (sd->snapshot_pressed) {
359 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
360 input_sync(gspca_dev->input_dev);
361 sd->snapshot_pressed = 0;
362 }
363#endif
364}
365
366/* reception of an URB */
367static void sd_isoc_irq(struct urb *urb)
368{
369 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
370 struct sd *sd = (struct sd *) gspca_dev;
371 struct urb *data_urb, *status_urb;
372 u8 *data;
373 int i, st;
374
375 PDEBUG(D_PACK, "sd isoc irq");
376 if (!gspca_dev->streaming)
377 return;
378
379 if (urb->status != 0) {
380 if (urb->status == -ESHUTDOWN)
381 return; /* disconnection */
382#ifdef CONFIG_PM
383 if (gspca_dev->frozen)
384 return;
385#endif
386 PDEBUG(D_ERR, "urb status: %d", urb->status);
387 st = usb_submit_urb(urb, GFP_ATOMIC);
388 if (st < 0)
389 err("resubmit urb error %d", st);
390 return;
391 }
392
393 /* if this is a data URB (ep 0x82), wait */
394 if (urb->transfer_buffer_length > 32) {
395 sd->last_data_urb = urb;
396 return;
397 }
398
399 status_urb = urb;
400 data_urb = sd->last_data_urb;
401 sd->last_data_urb = NULL;
402
403 if (!data_urb || data_urb->start_frame != status_urb->start_frame) {
404 PDEBUG(D_ERR|D_PACK, "lost sync on frames");
405 goto resubmit;
406 }
407
408 if (data_urb->number_of_packets != status_urb->number_of_packets) {
409 PDEBUG(D_ERR|D_PACK,
410 "no packets does not match, data: %d, status: %d",
411 data_urb->number_of_packets,
412 status_urb->number_of_packets);
413 goto resubmit;
414 }
415
416 for (i = 0; i < status_urb->number_of_packets; i++) {
417 if (data_urb->iso_frame_desc[i].status ||
418 status_urb->iso_frame_desc[i].status) {
419 PDEBUG(D_ERR|D_PACK,
420 "pkt %d data-status %d, status-status %d", i,
421 data_urb->iso_frame_desc[i].status,
422 status_urb->iso_frame_desc[i].status);
423 gspca_dev->last_packet_type = DISCARD_PACKET;
424 continue;
425 }
426
427 if (status_urb->iso_frame_desc[i].actual_length != 1) {
428 PDEBUG(D_ERR|D_PACK,
429 "bad status packet length %d",
430 status_urb->iso_frame_desc[i].actual_length);
431 gspca_dev->last_packet_type = DISCARD_PACKET;
432 continue;
433 }
434
435 st = *((u8 *)status_urb->transfer_buffer
436 + status_urb->iso_frame_desc[i].offset);
437
438 data = (u8 *)data_urb->transfer_buffer
439 + data_urb->iso_frame_desc[i].offset;
440
441 /* st: 0x80-0xff: frame start with frame number (ie 0-7f)
442 * otherwise:
443 * bit 0 0: keep packet
444 * 1: drop packet (padding data)
445 *
446 * bit 4 0 button not clicked
447 * 1 button clicked
448 * button is used to `take a picture' (in software)
449 */
450 if (st & 0x80) {
451 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
452 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
453 } else {
454#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
455 u8 button_state = st & 0x40 ? 1 : 0;
456 if (sd->snapshot_pressed != button_state) {
457 input_report_key(gspca_dev->input_dev,
458 KEY_CAMERA,
459 button_state);
460 input_sync(gspca_dev->input_dev);
461 sd->snapshot_pressed = button_state;
462 }
463#endif
464 if (st & 0x01)
465 continue;
466 }
467 gspca_frame_add(gspca_dev, INTER_PACKET, data,
468 data_urb->iso_frame_desc[i].actual_length);
469 }
470
471resubmit:
472 if (data_urb) {
473 st = usb_submit_urb(data_urb, GFP_ATOMIC);
474 if (st < 0)
475 PDEBUG(D_ERR|D_PACK,
476 "usb_submit_urb(data_urb) ret %d", st);
477 }
478 st = usb_submit_urb(status_urb, GFP_ATOMIC);
479 if (st < 0)
480 err("usb_submit_urb(status_urb) ret %d", st);
481}
482
483static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
484{
485 struct sd *sd = (struct sd *) gspca_dev;
486
487 sd->brightness = val;
488 if (gspca_dev->streaming) {
489 konica_stream_off(gspca_dev);
490 reg_w(gspca_dev, sd->brightness, BRIGHTNESS_REG);
491 konica_stream_on(gspca_dev);
492 }
493
494 return 0;
495}
496
497static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
498{
499 struct sd *sd = (struct sd *) gspca_dev;
500
501 *val = sd->brightness;
502
503 return 0;
504}
505
506static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
507{
508 struct sd *sd = (struct sd *) gspca_dev;
509
510 sd->contrast = val;
511 if (gspca_dev->streaming) {
512 konica_stream_off(gspca_dev);
513 reg_w(gspca_dev, sd->contrast, CONTRAST_REG);
514 konica_stream_on(gspca_dev);
515 }
516
517 return 0;
518}
519
520static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
521{
522 struct sd *sd = (struct sd *) gspca_dev;
523
524 *val = sd->contrast;
525
526 return 0;
527}
528
529static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
530{
531 struct sd *sd = (struct sd *) gspca_dev;
532
533 sd->saturation = val;
534 if (gspca_dev->streaming) {
535 konica_stream_off(gspca_dev);
536 reg_w(gspca_dev, sd->saturation, SATURATION_REG);
537 konica_stream_on(gspca_dev);
538 }
539 return 0;
540}
541
542static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
543{
544 struct sd *sd = (struct sd *) gspca_dev;
545
546 *val = sd->saturation;
547
548 return 0;
549}
550
551static int sd_setwhitebal(struct gspca_dev *gspca_dev, __s32 val)
552{
553 struct sd *sd = (struct sd *) gspca_dev;
554
555 sd->whitebal = val;
556 if (gspca_dev->streaming) {
557 konica_stream_off(gspca_dev);
558 reg_w(gspca_dev, sd->whitebal, WHITEBAL_REG);
559 konica_stream_on(gspca_dev);
560 }
561 return 0;
562}
563
564static int sd_getwhitebal(struct gspca_dev *gspca_dev, __s32 *val)
565{
566 struct sd *sd = (struct sd *) gspca_dev;
567
568 *val = sd->whitebal;
569
570 return 0;
571}
572
573static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
574{
575 struct sd *sd = (struct sd *) gspca_dev;
576
577 sd->sharpness = val;
578 if (gspca_dev->streaming) {
579 konica_stream_off(gspca_dev);
580 reg_w(gspca_dev, sd->sharpness, SHARPNESS_REG);
581 konica_stream_on(gspca_dev);
582 }
583 return 0;
584}
585
586static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
587{
588 struct sd *sd = (struct sd *) gspca_dev;
589
590 *val = sd->sharpness;
591
592 return 0;
593}
594
595/* sub-driver description */
596static const struct sd_desc sd_desc = {
597 .name = MODULE_NAME,
598 .ctrls = sd_ctrls,
599 .nctrls = ARRAY_SIZE(sd_ctrls),
600 .config = sd_config,
601 .init = sd_init,
602 .start = sd_start,
603 .stopN = sd_stopN,
604#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
605 .other_input = 1,
606#endif
607};
608
609/* -- module initialisation -- */
610static const struct usb_device_id device_table[] = {
611 {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */
612 {}
613};
614MODULE_DEVICE_TABLE(usb, device_table);
615
616/* -- device connect -- */
617static int sd_probe(struct usb_interface *intf,
618 const struct usb_device_id *id)
619{
620 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
621 THIS_MODULE);
622}
623
624static struct usb_driver sd_driver = {
625 .name = MODULE_NAME,
626 .id_table = device_table,
627 .probe = sd_probe,
628 .disconnect = gspca_disconnect,
629#ifdef CONFIG_PM
630 .suspend = gspca_suspend,
631 .resume = gspca_resume,
632#endif
633};
634
635/* -- module insert / remove -- */
636static int __init sd_mod_init(void)
637{
638 return usb_register(&sd_driver);
639}
640static void __exit sd_mod_exit(void)
641{
642 usb_deregister(&sd_driver);
643}
644
645module_init(sd_mod_init);
646module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig
new file mode 100644
index 00000000000..5a69016ed75
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
new file mode 100644
index 00000000000..bf7a19a1e6d
--- /dev/null
+++ b/drivers/media/video/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
11EXTRA_CFLAGS += -Idrivers/media/video/gspca
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
new file mode 100644
index 00000000000..51af3ee3ab8
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
new file mode 100644
index 00000000000..a7722b1aef9
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -0,0 +1,434 @@
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#include "m5602_ov9650.h"
20#include "m5602_ov7660.h"
21#include "m5602_mt9m111.h"
22#include "m5602_po1030.h"
23#include "m5602_s5k83a.h"
24#include "m5602_s5k4aa.h"
25
26/* Kernel module parameters */
27int force_sensor;
28static int dump_bridge;
29int dump_sensor;
30
31static const struct usb_device_id m5602_table[] = {
32 {USB_DEVICE(0x0402, 0x5602)},
33 {}
34};
35
36MODULE_DEVICE_TABLE(usb, m5602_table);
37
38/* Reads a byte from the m5602 */
39int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
40{
41 int err;
42 struct usb_device *udev = sd->gspca_dev.dev;
43 __u8 *buf = sd->gspca_dev.usb_buf;
44
45 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
46 0x04, 0xc0, 0x14,
47 0x8100 + address, buf,
48 1, M5602_URB_MSG_TIMEOUT);
49 *i2c_data = buf[0];
50
51 PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x",
52 address, *i2c_data);
53
54 /* usb_control_msg(...) returns the number of bytes sent upon success,
55 mask that and return zero instead*/
56 return (err < 0) ? err : 0;
57}
58
59/* Writes a byte to the m5602 */
60int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
61{
62 int err;
63 struct usb_device *udev = sd->gspca_dev.dev;
64 __u8 *buf = sd->gspca_dev.usb_buf;
65
66 PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x",
67 address, i2c_data);
68
69 memcpy(buf, bridge_urb_skeleton,
70 sizeof(bridge_urb_skeleton));
71 buf[1] = address;
72 buf[3] = i2c_data;
73
74 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
75 0x04, 0x40, 0x19,
76 0x0000, buf,
77 4, M5602_URB_MSG_TIMEOUT);
78
79 /* usb_control_msg(...) returns the number of bytes sent upon success,
80 mask that and return zero instead */
81 return (err < 0) ? err : 0;
82}
83
84static int m5602_wait_for_i2c(struct sd *sd)
85{
86 int err;
87 u8 data;
88
89 do {
90 err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data);
91 } while ((data & I2C_BUSY) && !err);
92 return err;
93}
94
95int m5602_read_sensor(struct sd *sd, const u8 address,
96 u8 *i2c_data, const u8 len)
97{
98 int err, i;
99
100 if (!len || len > sd->sensor->i2c_regW)
101 return -EINVAL;
102
103 err = m5602_wait_for_i2c(sd);
104 if (err < 0)
105 return err;
106
107 err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
108 sd->sensor->i2c_slave_id);
109 if (err < 0)
110 return err;
111
112 err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
113 if (err < 0)
114 return err;
115
116 /* Sensors with registers that are of only
117 one byte width are differently read */
118
119 /* FIXME: This works with the ov9650, but has issues with the po1030 */
120 if (sd->sensor->i2c_regW == 1) {
121 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1);
122 if (err < 0)
123 return err;
124
125 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
126 } else {
127 err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
128 }
129
130 for (i = 0; (i < len) && !err; i++) {
131 err = m5602_wait_for_i2c(sd);
132 if (err < 0)
133 return err;
134
135 err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
136
137 PDEBUG(D_CONF, "Reading sensor register "
138 "0x%x containing 0x%x ", address, *i2c_data);
139 }
140 return err;
141}
142
143int m5602_write_sensor(struct sd *sd, const u8 address,
144 u8 *i2c_data, const u8 len)
145{
146 int err, i;
147 u8 *p;
148 struct usb_device *udev = sd->gspca_dev.dev;
149 __u8 *buf = sd->gspca_dev.usb_buf;
150
151 /* No sensor with a data width larger than 16 bits has yet been seen */
152 if (len > sd->sensor->i2c_regW || !len)
153 return -EINVAL;
154
155 memcpy(buf, sensor_urb_skeleton,
156 sizeof(sensor_urb_skeleton));
157
158 buf[11] = sd->sensor->i2c_slave_id;
159 buf[15] = address;
160
161 /* Special case larger sensor writes */
162 p = buf + 16;
163
164 /* Copy a four byte write sequence for each byte to be written to */
165 for (i = 0; i < len; i++) {
166 memcpy(p, sensor_urb_skeleton + 16, 4);
167 p[3] = i2c_data[i];
168 p += 4;
169 PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
170 address, i2c_data[i]);
171 }
172
173 /* Copy the tailer */
174 memcpy(p, sensor_urb_skeleton + 20, 4);
175
176 /* Set the total length */
177 p[3] = 0x10 + len;
178
179 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
180 0x04, 0x40, 0x19,
181 0x0000, buf,
182 20 + len * 4, M5602_URB_MSG_TIMEOUT);
183
184 return (err < 0) ? err : 0;
185}
186
187/* Dump all the registers of the m5602 bridge,
188 unfortunately this breaks the camera until it's power cycled */
189static void m5602_dump_bridge(struct sd *sd)
190{
191 int i;
192 for (i = 0; i < 0x80; i++) {
193 unsigned char val = 0;
194 m5602_read_bridge(sd, i, &val);
195 info("ALi m5602 address 0x%x contains 0x%x", i, val);
196 }
197 info("Warning: The ALi m5602 webcam probably won't work "
198 "until it's power cycled");
199}
200
201static int m5602_probe_sensor(struct sd *sd)
202{
203 /* Try the po1030 */
204 sd->sensor = &po1030;
205 if (!sd->sensor->probe(sd))
206 return 0;
207
208 /* Try the mt9m111 sensor */
209 sd->sensor = &mt9m111;
210 if (!sd->sensor->probe(sd))
211 return 0;
212
213 /* Try the s5k4aa */
214 sd->sensor = &s5k4aa;
215 if (!sd->sensor->probe(sd))
216 return 0;
217
218 /* Try the ov9650 */
219 sd->sensor = &ov9650;
220 if (!sd->sensor->probe(sd))
221 return 0;
222
223 /* Try the ov7660 */
224 sd->sensor = &ov7660;
225 if (!sd->sensor->probe(sd))
226 return 0;
227
228 /* Try the s5k83a */
229 sd->sensor = &s5k83a;
230 if (!sd->sensor->probe(sd))
231 return 0;
232
233 /* More sensor probe function goes here */
234 info("Failed to find a sensor");
235 sd->sensor = NULL;
236 return -ENODEV;
237}
238
239static int m5602_configure(struct gspca_dev *gspca_dev,
240 const struct usb_device_id *id);
241
242static int m5602_init(struct gspca_dev *gspca_dev)
243{
244 struct sd *sd = (struct sd *) gspca_dev;
245 int err;
246
247 PDEBUG(D_CONF, "Initializing ALi m5602 webcam");
248 /* Run the init sequence */
249 err = sd->sensor->init(sd);
250
251 return err;
252}
253
254static int m5602_start_transfer(struct gspca_dev *gspca_dev)
255{
256 struct sd *sd = (struct sd *) gspca_dev;
257 __u8 *buf = sd->gspca_dev.usb_buf;
258 int err;
259
260 /* Send start command to the camera */
261 const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
262
263 if (sd->sensor->start)
264 sd->sensor->start(sd);
265
266 memcpy(buf, buffer, sizeof(buffer));
267 err = usb_control_msg(gspca_dev->dev,
268 usb_sndctrlpipe(gspca_dev->dev, 0),
269 0x04, 0x40, 0x19, 0x0000, buf,
270 sizeof(buffer), M5602_URB_MSG_TIMEOUT);
271
272 PDEBUG(D_STREAM, "Transfer started");
273 return (err < 0) ? err : 0;
274}
275
276static void m5602_urb_complete(struct gspca_dev *gspca_dev,
277 u8 *data, int len)
278{
279 struct sd *sd = (struct sd *) gspca_dev;
280
281 if (len < 6) {
282 PDEBUG(D_PACK, "Packet is less than 6 bytes");
283 return;
284 }
285
286 /* Frame delimiter: ff xx xx xx ff ff */
287 if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
288 data[2] != sd->frame_id) {
289 PDEBUG(D_FRAM, "Frame delimiter detected");
290 sd->frame_id = data[2];
291
292 /* Remove the extra fluff appended on each header */
293 data += 6;
294 len -= 6;
295
296 /* Complete the last frame (if any) */
297 gspca_frame_add(gspca_dev, LAST_PACKET,
298 NULL, 0);
299 sd->frame_count++;
300
301 /* Create a new frame */
302 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
303
304 PDEBUG(D_FRAM, "Starting new frame %d",
305 sd->frame_count);
306
307 } else {
308 int cur_frame_len;
309
310 cur_frame_len = gspca_dev->image_len;
311 /* Remove urb header */
312 data += 4;
313 len -= 4;
314
315 if (cur_frame_len + len <= gspca_dev->frsz) {
316 PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
317 sd->frame_count, len);
318
319 gspca_frame_add(gspca_dev, INTER_PACKET,
320 data, len);
321 } else {
322 /* Add the remaining data up to frame size */
323 gspca_frame_add(gspca_dev, INTER_PACKET, data,
324 gspca_dev->frsz - cur_frame_len);
325 }
326 }
327}
328
329static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
330{
331 struct sd *sd = (struct sd *) gspca_dev;
332
333 /* Run the sensor specific end transfer sequence */
334 if (sd->sensor->stop)
335 sd->sensor->stop(sd);
336}
337
338/* sub-driver description, the ctrl and nctrl is filled at probe time */
339static struct sd_desc sd_desc = {
340 .name = MODULE_NAME,
341 .config = m5602_configure,
342 .init = m5602_init,
343 .start = m5602_start_transfer,
344 .stopN = m5602_stop_transfer,
345 .pkt_scan = m5602_urb_complete
346};
347
348/* this function is called at probe time */
349static int m5602_configure(struct gspca_dev *gspca_dev,
350 const struct usb_device_id *id)
351{
352 struct sd *sd = (struct sd *) gspca_dev;
353 struct cam *cam;
354 int err;
355
356 cam = &gspca_dev->cam;
357 sd->desc = &sd_desc;
358
359 if (dump_bridge)
360 m5602_dump_bridge(sd);
361
362 /* Probe sensor */
363 err = m5602_probe_sensor(sd);
364 if (err)
365 goto fail;
366
367 return 0;
368
369fail:
370 PDEBUG(D_ERR, "ALi m5602 webcam failed");
371 cam->cam_mode = NULL;
372 cam->nmodes = 0;
373
374 return err;
375}
376
377static int m5602_probe(struct usb_interface *intf,
378 const struct usb_device_id *id)
379{
380 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
381 THIS_MODULE);
382}
383
384static void m5602_disconnect(struct usb_interface *intf)
385{
386 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
387 struct sd *sd = (struct sd *) gspca_dev;
388
389 if (sd->sensor->disconnect)
390 sd->sensor->disconnect(sd);
391
392 gspca_disconnect(intf);
393}
394
395static struct usb_driver sd_driver = {
396 .name = MODULE_NAME,
397 .id_table = m5602_table,
398 .probe = m5602_probe,
399#ifdef CONFIG_PM
400 .suspend = gspca_suspend,
401 .resume = gspca_resume,
402#endif
403 .disconnect = m5602_disconnect
404};
405
406/* -- module insert / remove -- */
407static int __init mod_m5602_init(void)
408{
409 return usb_register(&sd_driver);
410}
411
412static void __exit mod_m5602_exit(void)
413{
414 usb_deregister(&sd_driver);
415}
416
417module_init(mod_m5602_init);
418module_exit(mod_m5602_exit);
419
420MODULE_AUTHOR(DRIVER_AUTHOR);
421MODULE_DESCRIPTION(DRIVER_DESC);
422MODULE_LICENSE("GPL");
423module_param(force_sensor, int, S_IRUGO | S_IWUSR);
424MODULE_PARM_DESC(force_sensor,
425 "forces detection of a sensor, "
426 "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
427 "4 = MT9M111, 5 = PO1030, 6 = OV7660");
428
429module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
430MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
431
432module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
433MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
434 "at startup providing a sensor is found");
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
new file mode 100644
index 00000000000..0d605a52b92
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
@@ -0,0 +1,645 @@
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#include "m5602_mt9m111.h"
20
21static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
22static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
23static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
24static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
25static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
27static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
28 __s32 val);
29static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
30 __s32 *val);
31static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
32static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
33static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
34static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
35static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
36static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
37
38static struct v4l2_pix_format mt9m111_modes[] = {
39 {
40 640,
41 480,
42 V4L2_PIX_FMT_SBGGR8,
43 V4L2_FIELD_NONE,
44 .sizeimage = 640 * 480,
45 .bytesperline = 640,
46 .colorspace = V4L2_COLORSPACE_SRGB,
47 .priv = 0
48 }
49};
50
51static const struct ctrl mt9m111_ctrls[] = {
52#define VFLIP_IDX 0
53 {
54 {
55 .id = V4L2_CID_VFLIP,
56 .type = V4L2_CTRL_TYPE_BOOLEAN,
57 .name = "vertical flip",
58 .minimum = 0,
59 .maximum = 1,
60 .step = 1,
61 .default_value = 0
62 },
63 .set = mt9m111_set_vflip,
64 .get = mt9m111_get_vflip
65 },
66#define HFLIP_IDX 1
67 {
68 {
69 .id = V4L2_CID_HFLIP,
70 .type = V4L2_CTRL_TYPE_BOOLEAN,
71 .name = "horizontal flip",
72 .minimum = 0,
73 .maximum = 1,
74 .step = 1,
75 .default_value = 0
76 },
77 .set = mt9m111_set_hflip,
78 .get = mt9m111_get_hflip
79 },
80#define GAIN_IDX 2
81 {
82 {
83 .id = V4L2_CID_GAIN,
84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "gain",
86 .minimum = 0,
87 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
88 .step = 1,
89 .default_value = MT9M111_DEFAULT_GAIN,
90 .flags = V4L2_CTRL_FLAG_SLIDER
91 },
92 .set = mt9m111_set_gain,
93 .get = mt9m111_get_gain
94 },
95#define AUTO_WHITE_BALANCE_IDX 3
96 {
97 {
98 .id = V4L2_CID_AUTO_WHITE_BALANCE,
99 .type = V4L2_CTRL_TYPE_BOOLEAN,
100 .name = "auto white balance",
101 .minimum = 0,
102 .maximum = 1,
103 .step = 1,
104 .default_value = 0,
105 },
106 .set = mt9m111_set_auto_white_balance,
107 .get = mt9m111_get_auto_white_balance
108 },
109#define GREEN_BALANCE_IDX 4
110 {
111 {
112 .id = M5602_V4L2_CID_GREEN_BALANCE,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "green balance",
115 .minimum = 0x00,
116 .maximum = 0x7ff,
117 .step = 0x1,
118 .default_value = MT9M111_GREEN_GAIN_DEFAULT,
119 .flags = V4L2_CTRL_FLAG_SLIDER
120 },
121 .set = mt9m111_set_green_balance,
122 .get = mt9m111_get_green_balance
123 },
124#define BLUE_BALANCE_IDX 5
125 {
126 {
127 .id = V4L2_CID_BLUE_BALANCE,
128 .type = V4L2_CTRL_TYPE_INTEGER,
129 .name = "blue balance",
130 .minimum = 0x00,
131 .maximum = 0x7ff,
132 .step = 0x1,
133 .default_value = MT9M111_BLUE_GAIN_DEFAULT,
134 .flags = V4L2_CTRL_FLAG_SLIDER
135 },
136 .set = mt9m111_set_blue_balance,
137 .get = mt9m111_get_blue_balance
138 },
139#define RED_BALANCE_IDX 5
140 {
141 {
142 .id = V4L2_CID_RED_BALANCE,
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "red balance",
145 .minimum = 0x00,
146 .maximum = 0x7ff,
147 .step = 0x1,
148 .default_value = MT9M111_RED_GAIN_DEFAULT,
149 .flags = V4L2_CTRL_FLAG_SLIDER
150 },
151 .set = mt9m111_set_red_balance,
152 .get = mt9m111_get_red_balance
153 },
154};
155
156static void mt9m111_dump_registers(struct sd *sd);
157
158int mt9m111_probe(struct sd *sd)
159{
160 u8 data[2] = {0x00, 0x00};
161 int i;
162 s32 *sensor_settings;
163
164 if (force_sensor) {
165 if (force_sensor == MT9M111_SENSOR) {
166 info("Forcing a %s sensor", mt9m111.name);
167 goto sensor_found;
168 }
169 /* If we want to force another sensor, don't try to probe this
170 * one */
171 return -ENODEV;
172 }
173
174 PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
175
176 /* Do the preinit */
177 for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
178 if (preinit_mt9m111[i][0] == BRIDGE) {
179 m5602_write_bridge(sd,
180 preinit_mt9m111[i][1],
181 preinit_mt9m111[i][2]);
182 } else {
183 data[0] = preinit_mt9m111[i][2];
184 data[1] = preinit_mt9m111[i][3];
185 m5602_write_sensor(sd,
186 preinit_mt9m111[i][1], data, 2);
187 }
188 }
189
190 if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
191 return -ENODEV;
192
193 if ((data[0] == 0x14) && (data[1] == 0x3a)) {
194 info("Detected a mt9m111 sensor");
195 goto sensor_found;
196 }
197
198 return -ENODEV;
199
200sensor_found:
201 sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
202 GFP_KERNEL);
203 if (!sensor_settings)
204 return -ENOMEM;
205
206 sd->gspca_dev.cam.cam_mode = mt9m111_modes;
207 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
208 sd->desc->ctrls = mt9m111_ctrls;
209 sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
210
211 for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
212 sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
213 sd->sensor_priv = sensor_settings;
214
215 return 0;
216}
217
218int mt9m111_init(struct sd *sd)
219{
220 int i, err = 0;
221 s32 *sensor_settings = sd->sensor_priv;
222
223 /* Init the sensor */
224 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
225 u8 data[2];
226
227 if (init_mt9m111[i][0] == BRIDGE) {
228 err = m5602_write_bridge(sd,
229 init_mt9m111[i][1],
230 init_mt9m111[i][2]);
231 } else {
232 data[0] = init_mt9m111[i][2];
233 data[1] = init_mt9m111[i][3];
234 err = m5602_write_sensor(sd,
235 init_mt9m111[i][1], data, 2);
236 }
237 }
238
239 if (dump_sensor)
240 mt9m111_dump_registers(sd);
241
242 err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
243 if (err < 0)
244 return err;
245
246 err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
247 if (err < 0)
248 return err;
249
250 err = mt9m111_set_green_balance(&sd->gspca_dev,
251 sensor_settings[GREEN_BALANCE_IDX]);
252 if (err < 0)
253 return err;
254
255 err = mt9m111_set_blue_balance(&sd->gspca_dev,
256 sensor_settings[BLUE_BALANCE_IDX]);
257 if (err < 0)
258 return err;
259
260 err = mt9m111_set_red_balance(&sd->gspca_dev,
261 sensor_settings[RED_BALANCE_IDX]);
262 if (err < 0)
263 return err;
264
265 return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
266}
267
268int mt9m111_start(struct sd *sd)
269{
270 int i, err = 0;
271 u8 data[2];
272 struct cam *cam = &sd->gspca_dev.cam;
273 s32 *sensor_settings = sd->sensor_priv;
274
275 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
276 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
277
278 for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
279 if (start_mt9m111[i][0] == BRIDGE) {
280 err = m5602_write_bridge(sd,
281 start_mt9m111[i][1],
282 start_mt9m111[i][2]);
283 } else {
284 data[0] = start_mt9m111[i][2];
285 data[1] = start_mt9m111[i][3];
286 err = m5602_write_sensor(sd,
287 start_mt9m111[i][1], data, 2);
288 }
289 }
290 if (err < 0)
291 return err;
292
293 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
294 if (err < 0)
295 return err;
296
297 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
298 if (err < 0)
299 return err;
300
301 for (i = 0; i < 2 && !err; i++)
302 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
303 if (err < 0)
304 return err;
305
306 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
307 if (err < 0)
308 return err;
309
310 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
311 if (err < 0)
312 return err;
313
314 for (i = 0; i < 2 && !err; i++)
315 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
316 if (err < 0)
317 return err;
318
319 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
320 (width >> 8) & 0xff);
321 if (err < 0)
322 return err;
323
324 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
325 if (err < 0)
326 return err;
327
328 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
329 if (err < 0)
330 return err;
331
332 switch (width) {
333 case 640:
334 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
335 data[0] = MT9M111_RMB_OVER_SIZED;
336 data[1] = MT9M111_RMB_ROW_SKIP_2X |
337 MT9M111_RMB_COLUMN_SKIP_2X |
338 (sensor_settings[VFLIP_IDX] << 0) |
339 (sensor_settings[HFLIP_IDX] << 1);
340
341 err = m5602_write_sensor(sd,
342 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
343 break;
344
345 case 320:
346 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
347 data[0] = MT9M111_RMB_OVER_SIZED;
348 data[1] = MT9M111_RMB_ROW_SKIP_4X |
349 MT9M111_RMB_COLUMN_SKIP_4X |
350 (sensor_settings[VFLIP_IDX] << 0) |
351 (sensor_settings[HFLIP_IDX] << 1);
352 err = m5602_write_sensor(sd,
353 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
354 break;
355 }
356 return err;
357}
358
359void mt9m111_disconnect(struct sd *sd)
360{
361 sd->sensor = NULL;
362 kfree(sd->sensor_priv);
363}
364
365static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
366{
367 struct sd *sd = (struct sd *) gspca_dev;
368 s32 *sensor_settings = sd->sensor_priv;
369
370 *val = sensor_settings[VFLIP_IDX];
371 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
372
373 return 0;
374}
375
376static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
377{
378 int err;
379 u8 data[2] = {0x00, 0x00};
380 struct sd *sd = (struct sd *) gspca_dev;
381 s32 *sensor_settings = sd->sensor_priv;
382
383 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
384
385 sensor_settings[VFLIP_IDX] = val;
386
387 /* The mt9m111 is flipped by default */
388 val = !val;
389
390 /* Set the correct page map */
391 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
392 if (err < 0)
393 return err;
394
395 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
396 if (err < 0)
397 return err;
398
399 data[1] = (data[1] & 0xfe) | val;
400 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
401 data, 2);
402 return err;
403}
404
405static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
406{
407 struct sd *sd = (struct sd *) gspca_dev;
408 s32 *sensor_settings = sd->sensor_priv;
409
410 *val = sensor_settings[HFLIP_IDX];
411 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
412
413 return 0;
414}
415
416static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
417{
418 int err;
419 u8 data[2] = {0x00, 0x00};
420 struct sd *sd = (struct sd *) gspca_dev;
421 s32 *sensor_settings = sd->sensor_priv;
422
423 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
424
425 sensor_settings[HFLIP_IDX] = val;
426
427 /* The mt9m111 is flipped by default */
428 val = !val;
429
430 /* Set the correct page map */
431 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
432 if (err < 0)
433 return err;
434
435 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
436 if (err < 0)
437 return err;
438
439 data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
440 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
441 data, 2);
442 return err;
443}
444
445static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
446{
447 struct sd *sd = (struct sd *) gspca_dev;
448 s32 *sensor_settings = sd->sensor_priv;
449
450 *val = sensor_settings[GAIN_IDX];
451 PDEBUG(D_V4L2, "Read gain %d", *val);
452
453 return 0;
454}
455
456static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
457 __s32 val)
458{
459 struct sd *sd = (struct sd *) gspca_dev;
460 s32 *sensor_settings = sd->sensor_priv;
461 int err;
462 u8 data[2];
463
464 err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
465 if (err < 0)
466 return err;
467
468 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
469 data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
470
471 err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
472
473 PDEBUG(D_V4L2, "Set auto white balance %d", val);
474 return err;
475}
476
477static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
478 __s32 *val) {
479 struct sd *sd = (struct sd *) gspca_dev;
480 s32 *sensor_settings = sd->sensor_priv;
481
482 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
483 PDEBUG(D_V4L2, "Read auto white balance %d", *val);
484 return 0;
485}
486
487static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
488{
489 int err, tmp;
490 u8 data[2] = {0x00, 0x00};
491 struct sd *sd = (struct sd *) gspca_dev;
492 s32 *sensor_settings = sd->sensor_priv;
493
494 sensor_settings[GAIN_IDX] = val;
495
496 /* Set the correct page map */
497 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
498 if (err < 0)
499 return err;
500
501 if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
502 return -EINVAL;
503
504 if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
505 (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
506 tmp = (1 << 10) | (val << 9) |
507 (val << 8) | (val / 8);
508 else if ((val >= INITIAL_MAX_GAIN * 2) &&
509 (val < INITIAL_MAX_GAIN * 2 * 2))
510 tmp = (1 << 9) | (1 << 8) | (val / 4);
511 else if ((val >= INITIAL_MAX_GAIN) &&
512 (val < INITIAL_MAX_GAIN * 2))
513 tmp = (1 << 8) | (val / 2);
514 else
515 tmp = val;
516
517 data[1] = (tmp & 0xff);
518 data[0] = (tmp & 0xff00) >> 8;
519 PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
520 data[1], data[0]);
521
522 err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
523 data, 2);
524
525 return err;
526}
527
528static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
529{
530 int err;
531 u8 data[2];
532 struct sd *sd = (struct sd *) gspca_dev;
533 s32 *sensor_settings = sd->sensor_priv;
534
535 sensor_settings[GREEN_BALANCE_IDX] = val;
536 data[1] = (val & 0xff);
537 data[0] = (val & 0xff00) >> 8;
538
539 PDEBUG(D_V4L2, "Set green balance %d", val);
540 err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
541 data, 2);
542 if (err < 0)
543 return err;
544
545 return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
546 data, 2);
547}
548
549static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
550{
551 struct sd *sd = (struct sd *) gspca_dev;
552 s32 *sensor_settings = sd->sensor_priv;
553
554 *val = sensor_settings[GREEN_BALANCE_IDX];
555 PDEBUG(D_V4L2, "Read green balance %d", *val);
556 return 0;
557}
558
559static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
560{
561 u8 data[2];
562 struct sd *sd = (struct sd *) gspca_dev;
563 s32 *sensor_settings = sd->sensor_priv;
564
565 sensor_settings[BLUE_BALANCE_IDX] = val;
566 data[1] = (val & 0xff);
567 data[0] = (val & 0xff00) >> 8;
568
569 PDEBUG(D_V4L2, "Set blue balance %d", val);
570
571 return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
572 data, 2);
573}
574
575static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
576{
577 struct sd *sd = (struct sd *) gspca_dev;
578 s32 *sensor_settings = sd->sensor_priv;
579
580 *val = sensor_settings[BLUE_BALANCE_IDX];
581 PDEBUG(D_V4L2, "Read blue balance %d", *val);
582 return 0;
583}
584
585static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
586{
587 u8 data[2];
588 struct sd *sd = (struct sd *) gspca_dev;
589 s32 *sensor_settings = sd->sensor_priv;
590
591 sensor_settings[RED_BALANCE_IDX] = val;
592 data[1] = (val & 0xff);
593 data[0] = (val & 0xff00) >> 8;
594
595 PDEBUG(D_V4L2, "Set red balance %d", val);
596
597 return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
598 data, 2);
599}
600
601static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
602{
603 struct sd *sd = (struct sd *) gspca_dev;
604 s32 *sensor_settings = sd->sensor_priv;
605
606 *val = sensor_settings[RED_BALANCE_IDX];
607 PDEBUG(D_V4L2, "Read red balance %d", *val);
608 return 0;
609}
610
611static void mt9m111_dump_registers(struct sd *sd)
612{
613 u8 address, value[2] = {0x00, 0x00};
614
615 info("Dumping the mt9m111 register state");
616
617 info("Dumping the mt9m111 sensor core registers");
618 value[1] = MT9M111_SENSOR_CORE;
619 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
620 for (address = 0; address < 0xff; address++) {
621 m5602_read_sensor(sd, address, value, 2);
622 info("register 0x%x contains 0x%x%x",
623 address, value[0], value[1]);
624 }
625
626 info("Dumping the mt9m111 color pipeline registers");
627 value[1] = MT9M111_COLORPIPE;
628 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
629 for (address = 0; address < 0xff; address++) {
630 m5602_read_sensor(sd, address, value, 2);
631 info("register 0x%x contains 0x%x%x",
632 address, value[0], value[1]);
633 }
634
635 info("Dumping the mt9m111 camera control registers");
636 value[1] = MT9M111_CAMERA_CONTROL;
637 m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
638 for (address = 0; address < 0xff; address++) {
639 m5602_read_sensor(sd, address, value, 2);
640 info("register 0x%x contains 0x%x%x",
641 address, value[0], value[1]);
642 }
643
644 info("mt9m111 register state dump complete");
645}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
new file mode 100644
index 00000000000..b1f0c492036
--- /dev/null
+++ b/drivers/media/video/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 int 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/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c
new file mode 100644
index 00000000000..b12f60464b3
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c
@@ -0,0 +1,487 @@
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#include "m5602_ov7660.h"
20
21static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
22static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
23static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
24 __s32 *val);
25static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
26 __s32 val);
27static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
28static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
29static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
30static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
31static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
35
36static const struct ctrl ov7660_ctrls[] = {
37#define GAIN_IDX 1
38 {
39 {
40 .id = V4L2_CID_GAIN,
41 .type = V4L2_CTRL_TYPE_INTEGER,
42 .name = "gain",
43 .minimum = 0x00,
44 .maximum = 0xff,
45 .step = 0x1,
46 .default_value = OV7660_DEFAULT_GAIN,
47 .flags = V4L2_CTRL_FLAG_SLIDER
48 },
49 .set = ov7660_set_gain,
50 .get = ov7660_get_gain
51 },
52#define BLUE_BALANCE_IDX 2
53#define RED_BALANCE_IDX 3
54#define AUTO_WHITE_BALANCE_IDX 4
55 {
56 {
57 .id = V4L2_CID_AUTO_WHITE_BALANCE,
58 .type = V4L2_CTRL_TYPE_BOOLEAN,
59 .name = "auto white balance",
60 .minimum = 0,
61 .maximum = 1,
62 .step = 1,
63 .default_value = 1
64 },
65 .set = ov7660_set_auto_white_balance,
66 .get = ov7660_get_auto_white_balance
67 },
68#define AUTO_GAIN_CTRL_IDX 5
69 {
70 {
71 .id = V4L2_CID_AUTOGAIN,
72 .type = V4L2_CTRL_TYPE_BOOLEAN,
73 .name = "auto gain control",
74 .minimum = 0,
75 .maximum = 1,
76 .step = 1,
77 .default_value = 1
78 },
79 .set = ov7660_set_auto_gain,
80 .get = ov7660_get_auto_gain
81 },
82#define AUTO_EXPOSURE_IDX 6
83 {
84 {
85 .id = V4L2_CID_EXPOSURE_AUTO,
86 .type = V4L2_CTRL_TYPE_BOOLEAN,
87 .name = "auto exposure",
88 .minimum = 0,
89 .maximum = 1,
90 .step = 1,
91 .default_value = 1
92 },
93 .set = ov7660_set_auto_exposure,
94 .get = ov7660_get_auto_exposure
95 },
96#define HFLIP_IDX 7
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 = ov7660_set_hflip,
108 .get = ov7660_get_hflip
109 },
110#define VFLIP_IDX 8
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 = ov7660_set_vflip,
122 .get = ov7660_get_vflip
123 },
124
125};
126
127static struct v4l2_pix_format ov7660_modes[] = {
128 {
129 640,
130 480,
131 V4L2_PIX_FMT_SBGGR8,
132 V4L2_FIELD_NONE,
133 .sizeimage =
134 640 * 480,
135 .bytesperline = 640,
136 .colorspace = V4L2_COLORSPACE_SRGB,
137 .priv = 0
138 }
139};
140
141static void ov7660_dump_registers(struct sd *sd);
142
143int ov7660_probe(struct sd *sd)
144{
145 int err = 0, i;
146 u8 prod_id = 0, ver_id = 0;
147
148 s32 *sensor_settings;
149
150 if (force_sensor) {
151 if (force_sensor == OV7660_SENSOR) {
152 info("Forcing an %s sensor", ov7660.name);
153 goto sensor_found;
154 }
155 /* If we want to force another sensor,
156 don't try to probe this one */
157 return -ENODEV;
158 }
159
160 /* Do the preinit */
161 for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
162 u8 data[2];
163
164 if (preinit_ov7660[i][0] == BRIDGE) {
165 err = m5602_write_bridge(sd,
166 preinit_ov7660[i][1],
167 preinit_ov7660[i][2]);
168 } else {
169 data[0] = preinit_ov7660[i][2];
170 err = m5602_write_sensor(sd,
171 preinit_ov7660[i][1], data, 1);
172 }
173 }
174 if (err < 0)
175 return err;
176
177 if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
178 return -ENODEV;
179
180 if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
181 return -ENODEV;
182
183 info("Sensor reported 0x%x%x", prod_id, ver_id);
184
185 if ((prod_id == 0x76) && (ver_id == 0x60)) {
186 info("Detected a ov7660 sensor");
187 goto sensor_found;
188 }
189 return -ENODEV;
190
191sensor_found:
192 sensor_settings = kmalloc(
193 ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
194 if (!sensor_settings)
195 return -ENOMEM;
196
197 sd->gspca_dev.cam.cam_mode = ov7660_modes;
198 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
199 sd->desc->ctrls = ov7660_ctrls;
200 sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
201
202 for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
203 sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
204 sd->sensor_priv = sensor_settings;
205
206 return 0;
207}
208
209int ov7660_init(struct sd *sd)
210{
211 int i, err = 0;
212 s32 *sensor_settings = sd->sensor_priv;
213
214 /* Init the sensor */
215 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
216 u8 data[2];
217
218 if (init_ov7660[i][0] == BRIDGE) {
219 err = m5602_write_bridge(sd,
220 init_ov7660[i][1],
221 init_ov7660[i][2]);
222 } else {
223 data[0] = init_ov7660[i][2];
224 err = m5602_write_sensor(sd,
225 init_ov7660[i][1], data, 1);
226 }
227 }
228
229 if (dump_sensor)
230 ov7660_dump_registers(sd);
231
232 err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
233 if (err < 0)
234 return err;
235
236 err = ov7660_set_auto_white_balance(&sd->gspca_dev,
237 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
238 if (err < 0)
239 return err;
240
241 err = ov7660_set_auto_gain(&sd->gspca_dev,
242 sensor_settings[AUTO_GAIN_CTRL_IDX]);
243 if (err < 0)
244 return err;
245
246 err = ov7660_set_auto_exposure(&sd->gspca_dev,
247 sensor_settings[AUTO_EXPOSURE_IDX]);
248 if (err < 0)
249 return err;
250 err = ov7660_set_hflip(&sd->gspca_dev,
251 sensor_settings[HFLIP_IDX]);
252 if (err < 0)
253 return err;
254
255 err = ov7660_set_vflip(&sd->gspca_dev,
256 sensor_settings[VFLIP_IDX]);
257
258 return err;
259}
260
261int ov7660_start(struct sd *sd)
262{
263 return 0;
264}
265
266int ov7660_stop(struct sd *sd)
267{
268 return 0;
269}
270
271void ov7660_disconnect(struct sd *sd)
272{
273 ov7660_stop(sd);
274
275 sd->sensor = NULL;
276 kfree(sd->sensor_priv);
277}
278
279static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
280{
281 struct sd *sd = (struct sd *) gspca_dev;
282 s32 *sensor_settings = sd->sensor_priv;
283
284 *val = sensor_settings[GAIN_IDX];
285 PDEBUG(D_V4L2, "Read gain %d", *val);
286 return 0;
287}
288
289static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
290{
291 int err;
292 u8 i2c_data;
293 struct sd *sd = (struct sd *) gspca_dev;
294 s32 *sensor_settings = sd->sensor_priv;
295
296 PDEBUG(D_V4L2, "Setting gain to %d", val);
297
298 sensor_settings[GAIN_IDX] = val;
299
300 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
301 return err;
302}
303
304
305static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
306 __s32 *val)
307{
308 struct sd *sd = (struct sd *) gspca_dev;
309 s32 *sensor_settings = sd->sensor_priv;
310
311 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
312 return 0;
313}
314
315static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
316 __s32 val)
317{
318 int err;
319 u8 i2c_data;
320 struct sd *sd = (struct sd *) gspca_dev;
321 s32 *sensor_settings = sd->sensor_priv;
322
323 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
324
325 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
326 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
327 if (err < 0)
328 return err;
329
330 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
331 err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
332
333 return err;
334}
335
336static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
337{
338 struct sd *sd = (struct sd *) gspca_dev;
339 s32 *sensor_settings = sd->sensor_priv;
340
341 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
342 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
343 return 0;
344}
345
346static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
347{
348 int err;
349 u8 i2c_data;
350 struct sd *sd = (struct sd *) gspca_dev;
351 s32 *sensor_settings = sd->sensor_priv;
352
353 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
354
355 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
356 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
357 if (err < 0)
358 return err;
359
360 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
361
362 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
363}
364
365static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
366{
367 struct sd *sd = (struct sd *) gspca_dev;
368 s32 *sensor_settings = sd->sensor_priv;
369
370 *val = sensor_settings[AUTO_EXPOSURE_IDX];
371 PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
372 return 0;
373}
374
375static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
376 __s32 val)
377{
378 int err;
379 u8 i2c_data;
380 struct sd *sd = (struct sd *) gspca_dev;
381 s32 *sensor_settings = sd->sensor_priv;
382
383 PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
384
385 sensor_settings[AUTO_EXPOSURE_IDX] = val;
386 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
387 if (err < 0)
388 return err;
389
390 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
391
392 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
393}
394
395static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
396{
397 struct sd *sd = (struct sd *) gspca_dev;
398 s32 *sensor_settings = sd->sensor_priv;
399
400 *val = sensor_settings[HFLIP_IDX];
401 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
402 return 0;
403}
404
405static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
406{
407 int err;
408 u8 i2c_data;
409 struct sd *sd = (struct sd *) gspca_dev;
410 s32 *sensor_settings = sd->sensor_priv;
411
412 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
413
414 sensor_settings[HFLIP_IDX] = val;
415
416 i2c_data = ((val & 0x01) << 5) |
417 (sensor_settings[VFLIP_IDX] << 4);
418
419 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
420
421 return err;
422}
423
424static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
425{
426 struct sd *sd = (struct sd *) gspca_dev;
427 s32 *sensor_settings = sd->sensor_priv;
428
429 *val = sensor_settings[VFLIP_IDX];
430 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
431
432 return 0;
433}
434
435static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
436{
437 int err;
438 u8 i2c_data;
439 struct sd *sd = (struct sd *) gspca_dev;
440 s32 *sensor_settings = sd->sensor_priv;
441
442 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
443 sensor_settings[VFLIP_IDX] = val;
444
445 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
446 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
447 if (err < 0)
448 return err;
449
450 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
451 if (gspca_dev->streaming)
452 err = ov7660_start(sd);
453
454 return err;
455}
456
457static void ov7660_dump_registers(struct sd *sd)
458{
459 int address;
460 info("Dumping the ov7660 register state");
461 for (address = 0; address < 0xa9; address++) {
462 u8 value;
463 m5602_read_sensor(sd, address, &value, 1);
464 info("register 0x%x contains 0x%x",
465 address, value);
466 }
467
468 info("ov7660 register state dump complete");
469
470 info("Probing for which registers that are read/write");
471 for (address = 0; address < 0xff; address++) {
472 u8 old_value, ctrl_value;
473 u8 test_value[2] = {0xff, 0xff};
474
475 m5602_read_sensor(sd, address, &old_value, 1);
476 m5602_write_sensor(sd, address, test_value, 1);
477 m5602_read_sensor(sd, address, &ctrl_value, 1);
478
479 if (ctrl_value == test_value[0])
480 info("register 0x%x is writeable", address);
481 else
482 info("register 0x%x is read only", address);
483
484 /* Restore original value */
485 m5602_write_sensor(sd, address, &old_value, 1);
486 }
487}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h
new file mode 100644
index 00000000000..2efd607987e
--- /dev/null
+++ b/drivers/media/video/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 int 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/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
new file mode 100644
index 00000000000..703d48670a2
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -0,0 +1,880 @@
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#include "m5602_ov9650.h"
20
21static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
22static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
23static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
25static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
26static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
27static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
29static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
30static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
31static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
33static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
34 __s32 *val);
35static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
36 __s32 val);
37static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
38static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
39static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
40static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
41
42/* Vertically and horizontally flips the image if matched, needed for machines
43 where the sensor is mounted upside down */
44static
45 const
46 struct dmi_system_id ov9650_flip_dmi_table[] = {
47 {
48 .ident = "ASUS A6Ja",
49 .matches = {
50 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
51 DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
52 }
53 },
54 {
55 .ident = "ASUS A6JC",
56 .matches = {
57 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
58 DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
59 }
60 },
61 {
62 .ident = "ASUS A6K",
63 .matches = {
64 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
65 DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
66 }
67 },
68 {
69 .ident = "ASUS A6Kt",
70 .matches = {
71 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
72 DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
73 }
74 },
75 {
76 .ident = "ASUS A6VA",
77 .matches = {
78 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
79 DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
80 }
81 },
82 {
83
84 .ident = "ASUS A6VC",
85 .matches = {
86 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
87 DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
88 }
89 },
90 {
91 .ident = "ASUS A6VM",
92 .matches = {
93 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
94 DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
95 }
96 },
97 {
98 .ident = "ASUS A7V",
99 .matches = {
100 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
101 DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
102 }
103 },
104 {
105 .ident = "Alienware Aurora m9700",
106 .matches = {
107 DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
108 DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
109 }
110 },
111 {}
112};
113
114static const struct ctrl ov9650_ctrls[] = {
115#define EXPOSURE_IDX 0
116 {
117 {
118 .id = V4L2_CID_EXPOSURE,
119 .type = V4L2_CTRL_TYPE_INTEGER,
120 .name = "exposure",
121 .minimum = 0x00,
122 .maximum = 0x1ff,
123 .step = 0x4,
124 .default_value = EXPOSURE_DEFAULT,
125 .flags = V4L2_CTRL_FLAG_SLIDER
126 },
127 .set = ov9650_set_exposure,
128 .get = ov9650_get_exposure
129 },
130#define GAIN_IDX 1
131 {
132 {
133 .id = V4L2_CID_GAIN,
134 .type = V4L2_CTRL_TYPE_INTEGER,
135 .name = "gain",
136 .minimum = 0x00,
137 .maximum = 0x3ff,
138 .step = 0x1,
139 .default_value = GAIN_DEFAULT,
140 .flags = V4L2_CTRL_FLAG_SLIDER
141 },
142 .set = ov9650_set_gain,
143 .get = ov9650_get_gain
144 },
145#define RED_BALANCE_IDX 2
146 {
147 {
148 .id = V4L2_CID_RED_BALANCE,
149 .type = V4L2_CTRL_TYPE_INTEGER,
150 .name = "red balance",
151 .minimum = 0x00,
152 .maximum = 0xff,
153 .step = 0x1,
154 .default_value = RED_GAIN_DEFAULT,
155 .flags = V4L2_CTRL_FLAG_SLIDER
156 },
157 .set = ov9650_set_red_balance,
158 .get = ov9650_get_red_balance
159 },
160#define BLUE_BALANCE_IDX 3
161 {
162 {
163 .id = V4L2_CID_BLUE_BALANCE,
164 .type = V4L2_CTRL_TYPE_INTEGER,
165 .name = "blue balance",
166 .minimum = 0x00,
167 .maximum = 0xff,
168 .step = 0x1,
169 .default_value = BLUE_GAIN_DEFAULT,
170 .flags = V4L2_CTRL_FLAG_SLIDER
171 },
172 .set = ov9650_set_blue_balance,
173 .get = ov9650_get_blue_balance
174 },
175#define HFLIP_IDX 4
176 {
177 {
178 .id = V4L2_CID_HFLIP,
179 .type = V4L2_CTRL_TYPE_BOOLEAN,
180 .name = "horizontal flip",
181 .minimum = 0,
182 .maximum = 1,
183 .step = 1,
184 .default_value = 0
185 },
186 .set = ov9650_set_hflip,
187 .get = ov9650_get_hflip
188 },
189#define VFLIP_IDX 5
190 {
191 {
192 .id = V4L2_CID_VFLIP,
193 .type = V4L2_CTRL_TYPE_BOOLEAN,
194 .name = "vertical flip",
195 .minimum = 0,
196 .maximum = 1,
197 .step = 1,
198 .default_value = 0
199 },
200 .set = ov9650_set_vflip,
201 .get = ov9650_get_vflip
202 },
203#define AUTO_WHITE_BALANCE_IDX 6
204 {
205 {
206 .id = V4L2_CID_AUTO_WHITE_BALANCE,
207 .type = V4L2_CTRL_TYPE_BOOLEAN,
208 .name = "auto white balance",
209 .minimum = 0,
210 .maximum = 1,
211 .step = 1,
212 .default_value = 1
213 },
214 .set = ov9650_set_auto_white_balance,
215 .get = ov9650_get_auto_white_balance
216 },
217#define AUTO_GAIN_CTRL_IDX 7
218 {
219 {
220 .id = V4L2_CID_AUTOGAIN,
221 .type = V4L2_CTRL_TYPE_BOOLEAN,
222 .name = "auto gain control",
223 .minimum = 0,
224 .maximum = 1,
225 .step = 1,
226 .default_value = 1
227 },
228 .set = ov9650_set_auto_gain,
229 .get = ov9650_get_auto_gain
230 },
231#define AUTO_EXPOSURE_IDX 8
232 {
233 {
234 .id = V4L2_CID_EXPOSURE_AUTO,
235 .type = V4L2_CTRL_TYPE_BOOLEAN,
236 .name = "auto exposure",
237 .minimum = 0,
238 .maximum = 1,
239 .step = 1,
240 .default_value = 1
241 },
242 .set = ov9650_set_auto_exposure,
243 .get = ov9650_get_auto_exposure
244 }
245
246};
247
248static struct v4l2_pix_format ov9650_modes[] = {
249 {
250 176,
251 144,
252 V4L2_PIX_FMT_SBGGR8,
253 V4L2_FIELD_NONE,
254 .sizeimage =
255 176 * 144,
256 .bytesperline = 176,
257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 9
259 }, {
260 320,
261 240,
262 V4L2_PIX_FMT_SBGGR8,
263 V4L2_FIELD_NONE,
264 .sizeimage =
265 320 * 240,
266 .bytesperline = 320,
267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 8
269 }, {
270 352,
271 288,
272 V4L2_PIX_FMT_SBGGR8,
273 V4L2_FIELD_NONE,
274 .sizeimage =
275 352 * 288,
276 .bytesperline = 352,
277 .colorspace = V4L2_COLORSPACE_SRGB,
278 .priv = 9
279 }, {
280 640,
281 480,
282 V4L2_PIX_FMT_SBGGR8,
283 V4L2_FIELD_NONE,
284 .sizeimage =
285 640 * 480,
286 .bytesperline = 640,
287 .colorspace = V4L2_COLORSPACE_SRGB,
288 .priv = 9
289 }
290};
291
292static void ov9650_dump_registers(struct sd *sd);
293
294int ov9650_probe(struct sd *sd)
295{
296 int err = 0;
297 u8 prod_id = 0, ver_id = 0, i;
298 s32 *sensor_settings;
299
300 if (force_sensor) {
301 if (force_sensor == OV9650_SENSOR) {
302 info("Forcing an %s sensor", ov9650.name);
303 goto sensor_found;
304 }
305 /* If we want to force another sensor,
306 don't try to probe this one */
307 return -ENODEV;
308 }
309
310 PDEBUG(D_PROBE, "Probing for an ov9650 sensor");
311
312 /* Run the pre-init before probing the sensor */
313 for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
314 u8 data = preinit_ov9650[i][2];
315 if (preinit_ov9650[i][0] == SENSOR)
316 err = m5602_write_sensor(sd,
317 preinit_ov9650[i][1], &data, 1);
318 else
319 err = m5602_write_bridge(sd,
320 preinit_ov9650[i][1], data);
321 }
322
323 if (err < 0)
324 return err;
325
326 if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
327 return -ENODEV;
328
329 if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
330 return -ENODEV;
331
332 if ((prod_id == 0x96) && (ver_id == 0x52)) {
333 info("Detected an ov9650 sensor");
334 goto sensor_found;
335 }
336 return -ENODEV;
337
338sensor_found:
339 sensor_settings = kmalloc(
340 ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
341 if (!sensor_settings)
342 return -ENOMEM;
343
344 sd->gspca_dev.cam.cam_mode = ov9650_modes;
345 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
346 sd->desc->ctrls = ov9650_ctrls;
347 sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
348
349 for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
350 sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
351 sd->sensor_priv = sensor_settings;
352 return 0;
353}
354
355int ov9650_init(struct sd *sd)
356{
357 int i, err = 0;
358 u8 data;
359 s32 *sensor_settings = sd->sensor_priv;
360
361 if (dump_sensor)
362 ov9650_dump_registers(sd);
363
364 for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
365 data = init_ov9650[i][2];
366 if (init_ov9650[i][0] == SENSOR)
367 err = m5602_write_sensor(sd, init_ov9650[i][1],
368 &data, 1);
369 else
370 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
371 }
372
373 err = ov9650_set_exposure(&sd->gspca_dev,
374 sensor_settings[EXPOSURE_IDX]);
375 if (err < 0)
376 return err;
377
378 err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
379 if (err < 0)
380 return err;
381
382 err = ov9650_set_red_balance(&sd->gspca_dev,
383 sensor_settings[RED_BALANCE_IDX]);
384 if (err < 0)
385 return err;
386
387 err = ov9650_set_blue_balance(&sd->gspca_dev,
388 sensor_settings[BLUE_BALANCE_IDX]);
389 if (err < 0)
390 return err;
391
392 err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
393 if (err < 0)
394 return err;
395
396 err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
397 if (err < 0)
398 return err;
399
400 err = ov9650_set_auto_exposure(&sd->gspca_dev,
401 sensor_settings[AUTO_EXPOSURE_IDX]);
402 if (err < 0)
403 return err;
404
405 err = ov9650_set_auto_white_balance(&sd->gspca_dev,
406 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
407 if (err < 0)
408 return err;
409
410 err = ov9650_set_auto_gain(&sd->gspca_dev,
411 sensor_settings[AUTO_GAIN_CTRL_IDX]);
412 return err;
413}
414
415int ov9650_start(struct sd *sd)
416{
417 u8 data;
418 int i, err = 0;
419 struct cam *cam = &sd->gspca_dev.cam;
420 s32 *sensor_settings = sd->sensor_priv;
421
422 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
423 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
424 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
425 int hor_offs = OV9650_LEFT_OFFSET;
426
427 if ((!dmi_check_system(ov9650_flip_dmi_table) &&
428 sensor_settings[VFLIP_IDX]) ||
429 (dmi_check_system(ov9650_flip_dmi_table) &&
430 !sensor_settings[VFLIP_IDX]))
431 ver_offs--;
432
433 if (width <= 320)
434 hor_offs /= 2;
435
436 /* Synthesize the vsync/hsync setup */
437 for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
438 if (res_init_ov9650[i][0] == BRIDGE)
439 err = m5602_write_bridge(sd, res_init_ov9650[i][1],
440 res_init_ov9650[i][2]);
441 else if (res_init_ov9650[i][0] == SENSOR) {
442 data = res_init_ov9650[i][2];
443 err = m5602_write_sensor(sd,
444 res_init_ov9650[i][1], &data, 1);
445 }
446 }
447 if (err < 0)
448 return err;
449
450 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
451 ((ver_offs >> 8) & 0xff));
452 if (err < 0)
453 return err;
454
455 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
456 if (err < 0)
457 return err;
458
459 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
460 if (err < 0)
461 return err;
462
463 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
464 if (err < 0)
465 return err;
466
467 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
468 if (err < 0)
469 return err;
470
471 for (i = 0; i < 2 && !err; i++)
472 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
473 if (err < 0)
474 return err;
475
476 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
477 if (err < 0)
478 return err;
479
480 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
481 if (err < 0)
482 return err;
483
484 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
485 (hor_offs >> 8) & 0xff);
486 if (err < 0)
487 return err;
488
489 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
490 if (err < 0)
491 return err;
492
493 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
494 ((width + hor_offs) >> 8) & 0xff);
495 if (err < 0)
496 return err;
497
498 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
499 ((width + hor_offs) & 0xff));
500 if (err < 0)
501 return err;
502
503 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
504 if (err < 0)
505 return err;
506
507 switch (width) {
508 case 640:
509 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
510
511 data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
512 OV9650_RAW_RGB_SELECT;
513 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
514 break;
515
516 case 352:
517 PDEBUG(D_V4L2, "Configuring camera for CIF mode");
518
519 data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
520 OV9650_RAW_RGB_SELECT;
521 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
522 break;
523
524 case 320:
525 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
526
527 data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
528 OV9650_RAW_RGB_SELECT;
529 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
530 break;
531
532 case 176:
533 PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
534
535 data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
536 OV9650_RAW_RGB_SELECT;
537 err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
538 break;
539 }
540 return err;
541}
542
543int ov9650_stop(struct sd *sd)
544{
545 u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
546 return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
547}
548
549void ov9650_disconnect(struct sd *sd)
550{
551 ov9650_stop(sd);
552
553 sd->sensor = NULL;
554 kfree(sd->sensor_priv);
555}
556
557static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
558{
559 struct sd *sd = (struct sd *) gspca_dev;
560 s32 *sensor_settings = sd->sensor_priv;
561
562 *val = sensor_settings[EXPOSURE_IDX];
563 PDEBUG(D_V4L2, "Read exposure %d", *val);
564 return 0;
565}
566
567static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
568{
569 struct sd *sd = (struct sd *) gspca_dev;
570 s32 *sensor_settings = sd->sensor_priv;
571 u8 i2c_data;
572 int err;
573
574 PDEBUG(D_V4L2, "Set exposure to %d", val);
575
576 sensor_settings[EXPOSURE_IDX] = val;
577 /* The 6 MSBs */
578 i2c_data = (val >> 10) & 0x3f;
579 err = m5602_write_sensor(sd, OV9650_AECHM,
580 &i2c_data, 1);
581 if (err < 0)
582 return err;
583
584 /* The 8 middle bits */
585 i2c_data = (val >> 2) & 0xff;
586 err = m5602_write_sensor(sd, OV9650_AECH,
587 &i2c_data, 1);
588 if (err < 0)
589 return err;
590
591 /* The 2 LSBs */
592 i2c_data = val & 0x03;
593 err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
594 return err;
595}
596
597static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
598{
599 struct sd *sd = (struct sd *) gspca_dev;
600 s32 *sensor_settings = sd->sensor_priv;
601
602 *val = sensor_settings[GAIN_IDX];
603 PDEBUG(D_V4L2, "Read gain %d", *val);
604 return 0;
605}
606
607static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
608{
609 int err;
610 u8 i2c_data;
611 struct sd *sd = (struct sd *) gspca_dev;
612 s32 *sensor_settings = sd->sensor_priv;
613
614 PDEBUG(D_V4L2, "Setting gain to %d", val);
615
616 sensor_settings[GAIN_IDX] = val;
617
618 /* The 2 MSB */
619 /* Read the OV9650_VREF register first to avoid
620 corrupting the VREF high and low bits */
621 err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
622 if (err < 0)
623 return err;
624
625 /* Mask away all uninteresting bits */
626 i2c_data = ((val & 0x0300) >> 2) |
627 (i2c_data & 0x3f);
628 err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
629 if (err < 0)
630 return err;
631
632 /* The 8 LSBs */
633 i2c_data = val & 0xff;
634 err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
635 return err;
636}
637
638static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
639{
640 struct sd *sd = (struct sd *) gspca_dev;
641 s32 *sensor_settings = sd->sensor_priv;
642
643 *val = sensor_settings[RED_BALANCE_IDX];
644 PDEBUG(D_V4L2, "Read red gain %d", *val);
645 return 0;
646}
647
648static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
649{
650 int err;
651 u8 i2c_data;
652 struct sd *sd = (struct sd *) gspca_dev;
653 s32 *sensor_settings = sd->sensor_priv;
654
655 PDEBUG(D_V4L2, "Set red gain to %d", val);
656
657 sensor_settings[RED_BALANCE_IDX] = val;
658
659 i2c_data = val & 0xff;
660 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
661 return err;
662}
663
664static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
665{
666 struct sd *sd = (struct sd *) gspca_dev;
667 s32 *sensor_settings = sd->sensor_priv;
668
669 *val = sensor_settings[BLUE_BALANCE_IDX];
670 PDEBUG(D_V4L2, "Read blue gain %d", *val);
671
672 return 0;
673}
674
675static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
676{
677 int err;
678 u8 i2c_data;
679 struct sd *sd = (struct sd *) gspca_dev;
680 s32 *sensor_settings = sd->sensor_priv;
681
682 PDEBUG(D_V4L2, "Set blue gain to %d", val);
683
684 sensor_settings[BLUE_BALANCE_IDX] = val;
685
686 i2c_data = val & 0xff;
687 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
688 return err;
689}
690
691static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
692{
693 struct sd *sd = (struct sd *) gspca_dev;
694 s32 *sensor_settings = sd->sensor_priv;
695
696 *val = sensor_settings[HFLIP_IDX];
697 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
698 return 0;
699}
700
701static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
702{
703 int err;
704 u8 i2c_data;
705 struct sd *sd = (struct sd *) gspca_dev;
706 s32 *sensor_settings = sd->sensor_priv;
707
708 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
709
710 sensor_settings[HFLIP_IDX] = val;
711
712 if (!dmi_check_system(ov9650_flip_dmi_table))
713 i2c_data = ((val & 0x01) << 5) |
714 (sensor_settings[VFLIP_IDX] << 4);
715 else
716 i2c_data = ((val & 0x01) << 5) |
717 (!sensor_settings[VFLIP_IDX] << 4);
718
719 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
720
721 return err;
722}
723
724static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
725{
726 struct sd *sd = (struct sd *) gspca_dev;
727 s32 *sensor_settings = sd->sensor_priv;
728
729 *val = sensor_settings[VFLIP_IDX];
730 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
731
732 return 0;
733}
734
735static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
736{
737 int err;
738 u8 i2c_data;
739 struct sd *sd = (struct sd *) gspca_dev;
740 s32 *sensor_settings = sd->sensor_priv;
741
742 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
743 sensor_settings[VFLIP_IDX] = val;
744
745 if (dmi_check_system(ov9650_flip_dmi_table))
746 val = !val;
747
748 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
749 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
750 if (err < 0)
751 return err;
752
753 /* When vflip is toggled we need to readjust the bridge hsync/vsync */
754 if (gspca_dev->streaming)
755 err = ov9650_start(sd);
756
757 return err;
758}
759
760static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
761{
762 struct sd *sd = (struct sd *) gspca_dev;
763 s32 *sensor_settings = sd->sensor_priv;
764
765 *val = sensor_settings[AUTO_EXPOSURE_IDX];
766 PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
767 return 0;
768}
769
770static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
771 __s32 val)
772{
773 int err;
774 u8 i2c_data;
775 struct sd *sd = (struct sd *) gspca_dev;
776 s32 *sensor_settings = sd->sensor_priv;
777
778 PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
779
780 sensor_settings[AUTO_EXPOSURE_IDX] = val;
781 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
782 if (err < 0)
783 return err;
784
785 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
786
787 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
788}
789
790static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
791 __s32 *val)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794 s32 *sensor_settings = sd->sensor_priv;
795
796 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
797 return 0;
798}
799
800static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
801 __s32 val)
802{
803 int err;
804 u8 i2c_data;
805 struct sd *sd = (struct sd *) gspca_dev;
806 s32 *sensor_settings = sd->sensor_priv;
807
808 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
809
810 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
811 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
812 if (err < 0)
813 return err;
814
815 i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
816 err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
817
818 return err;
819}
820
821static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
822{
823 struct sd *sd = (struct sd *) gspca_dev;
824 s32 *sensor_settings = sd->sensor_priv;
825
826 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
827 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
828 return 0;
829}
830
831static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
832{
833 int err;
834 u8 i2c_data;
835 struct sd *sd = (struct sd *) gspca_dev;
836 s32 *sensor_settings = sd->sensor_priv;
837
838 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
839
840 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
841 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
842 if (err < 0)
843 return err;
844
845 i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
846
847 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
848}
849
850static void ov9650_dump_registers(struct sd *sd)
851{
852 int address;
853 info("Dumping the ov9650 register state");
854 for (address = 0; address < 0xa9; address++) {
855 u8 value;
856 m5602_read_sensor(sd, address, &value, 1);
857 info("register 0x%x contains 0x%x",
858 address, value);
859 }
860
861 info("ov9650 register state dump complete");
862
863 info("Probing for which registers that are read/write");
864 for (address = 0; address < 0xff; address++) {
865 u8 old_value, ctrl_value;
866 u8 test_value[2] = {0xff, 0xff};
867
868 m5602_read_sensor(sd, address, &old_value, 1);
869 m5602_write_sensor(sd, address, test_value, 1);
870 m5602_read_sensor(sd, address, &ctrl_value, 1);
871
872 if (ctrl_value == test_value[0])
873 info("register 0x%x is writeable", address);
874 else
875 info("register 0x%x is read only", address);
876
877 /* Restore original value */
878 m5602_write_sensor(sd, address, &old_value, 1);
879 }
880}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
new file mode 100644
index 00000000000..da9a129b739
--- /dev/null
+++ b/drivers/media/video/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 int 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/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
new file mode 100644
index 00000000000..1febd34c2f0
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.c
@@ -0,0 +1,762 @@
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#include "m5602_po1030.h"
20
21static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
22static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
23static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
25static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
26static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
27static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
29static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
30static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
31static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
35static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
36 __s32 val);
37static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
38 __s32 *val);
39static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
40 __s32 val);
41static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
42 __s32 *val);
43
44static struct v4l2_pix_format po1030_modes[] = {
45 {
46 640,
47 480,
48 V4L2_PIX_FMT_SBGGR8,
49 V4L2_FIELD_NONE,
50 .sizeimage = 640 * 480,
51 .bytesperline = 640,
52 .colorspace = V4L2_COLORSPACE_SRGB,
53 .priv = 2
54 }
55};
56
57static const struct ctrl po1030_ctrls[] = {
58#define GAIN_IDX 0
59 {
60 {
61 .id = V4L2_CID_GAIN,
62 .type = V4L2_CTRL_TYPE_INTEGER,
63 .name = "gain",
64 .minimum = 0x00,
65 .maximum = 0x4f,
66 .step = 0x1,
67 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
68 .flags = V4L2_CTRL_FLAG_SLIDER
69 },
70 .set = po1030_set_gain,
71 .get = po1030_get_gain
72 },
73#define EXPOSURE_IDX 1
74 {
75 {
76 .id = V4L2_CID_EXPOSURE,
77 .type = V4L2_CTRL_TYPE_INTEGER,
78 .name = "exposure",
79 .minimum = 0x00,
80 .maximum = 0x02ff,
81 .step = 0x1,
82 .default_value = PO1030_EXPOSURE_DEFAULT,
83 .flags = V4L2_CTRL_FLAG_SLIDER
84 },
85 .set = po1030_set_exposure,
86 .get = po1030_get_exposure
87 },
88#define RED_BALANCE_IDX 2
89 {
90 {
91 .id = V4L2_CID_RED_BALANCE,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "red balance",
94 .minimum = 0x00,
95 .maximum = 0xff,
96 .step = 0x1,
97 .default_value = PO1030_RED_GAIN_DEFAULT,
98 .flags = V4L2_CTRL_FLAG_SLIDER
99 },
100 .set = po1030_set_red_balance,
101 .get = po1030_get_red_balance
102 },
103#define BLUE_BALANCE_IDX 3
104 {
105 {
106 .id = V4L2_CID_BLUE_BALANCE,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "blue balance",
109 .minimum = 0x00,
110 .maximum = 0xff,
111 .step = 0x1,
112 .default_value = PO1030_BLUE_GAIN_DEFAULT,
113 .flags = V4L2_CTRL_FLAG_SLIDER
114 },
115 .set = po1030_set_blue_balance,
116 .get = po1030_get_blue_balance
117 },
118#define HFLIP_IDX 4
119 {
120 {
121 .id = V4L2_CID_HFLIP,
122 .type = V4L2_CTRL_TYPE_BOOLEAN,
123 .name = "horizontal flip",
124 .minimum = 0,
125 .maximum = 1,
126 .step = 1,
127 .default_value = 0,
128 },
129 .set = po1030_set_hflip,
130 .get = po1030_get_hflip
131 },
132#define VFLIP_IDX 5
133 {
134 {
135 .id = V4L2_CID_VFLIP,
136 .type = V4L2_CTRL_TYPE_BOOLEAN,
137 .name = "vertical flip",
138 .minimum = 0,
139 .maximum = 1,
140 .step = 1,
141 .default_value = 0,
142 },
143 .set = po1030_set_vflip,
144 .get = po1030_get_vflip
145 },
146#define AUTO_WHITE_BALANCE_IDX 6
147 {
148 {
149 .id = V4L2_CID_AUTO_WHITE_BALANCE,
150 .type = V4L2_CTRL_TYPE_BOOLEAN,
151 .name = "auto white balance",
152 .minimum = 0,
153 .maximum = 1,
154 .step = 1,
155 .default_value = 0,
156 },
157 .set = po1030_set_auto_white_balance,
158 .get = po1030_get_auto_white_balance
159 },
160#define AUTO_EXPOSURE_IDX 7
161 {
162 {
163 .id = V4L2_CID_EXPOSURE_AUTO,
164 .type = V4L2_CTRL_TYPE_BOOLEAN,
165 .name = "auto exposure",
166 .minimum = 0,
167 .maximum = 1,
168 .step = 1,
169 .default_value = 0,
170 },
171 .set = po1030_set_auto_exposure,
172 .get = po1030_get_auto_exposure
173 },
174#define GREEN_BALANCE_IDX 8
175 {
176 {
177 .id = M5602_V4L2_CID_GREEN_BALANCE,
178 .type = V4L2_CTRL_TYPE_INTEGER,
179 .name = "green balance",
180 .minimum = 0x00,
181 .maximum = 0xff,
182 .step = 0x1,
183 .default_value = PO1030_GREEN_GAIN_DEFAULT,
184 .flags = V4L2_CTRL_FLAG_SLIDER
185 },
186 .set = po1030_set_green_balance,
187 .get = po1030_get_green_balance
188 },
189};
190
191static void po1030_dump_registers(struct sd *sd);
192
193int po1030_probe(struct sd *sd)
194{
195 u8 dev_id_h = 0, i;
196 s32 *sensor_settings;
197
198 if (force_sensor) {
199 if (force_sensor == PO1030_SENSOR) {
200 info("Forcing a %s sensor", po1030.name);
201 goto sensor_found;
202 }
203 /* If we want to force another sensor, don't try to probe this
204 * one */
205 return -ENODEV;
206 }
207
208 PDEBUG(D_PROBE, "Probing for a po1030 sensor");
209
210 /* Run the pre-init to actually probe the unit */
211 for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
212 u8 data = preinit_po1030[i][2];
213 if (preinit_po1030[i][0] == SENSOR)
214 m5602_write_sensor(sd,
215 preinit_po1030[i][1], &data, 1);
216 else
217 m5602_write_bridge(sd, preinit_po1030[i][1], data);
218 }
219
220 if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
221 return -ENODEV;
222
223 if (dev_id_h == 0x30) {
224 info("Detected a po1030 sensor");
225 goto sensor_found;
226 }
227 return -ENODEV;
228
229sensor_found:
230 sensor_settings = kmalloc(
231 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
232 if (!sensor_settings)
233 return -ENOMEM;
234
235 sd->gspca_dev.cam.cam_mode = po1030_modes;
236 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
237 sd->desc->ctrls = po1030_ctrls;
238 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
239
240 for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
241 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
242 sd->sensor_priv = sensor_settings;
243
244 return 0;
245}
246
247int po1030_init(struct sd *sd)
248{
249 s32 *sensor_settings = sd->sensor_priv;
250 int i, err = 0;
251
252 /* Init the sensor */
253 for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
254 u8 data[2] = {0x00, 0x00};
255
256 switch (init_po1030[i][0]) {
257 case BRIDGE:
258 err = m5602_write_bridge(sd,
259 init_po1030[i][1],
260 init_po1030[i][2]);
261 break;
262
263 case SENSOR:
264 data[0] = init_po1030[i][2];
265 err = m5602_write_sensor(sd,
266 init_po1030[i][1], data, 1);
267 break;
268
269 default:
270 info("Invalid stream command, exiting init");
271 return -EINVAL;
272 }
273 }
274 if (err < 0)
275 return err;
276
277 if (dump_sensor)
278 po1030_dump_registers(sd);
279
280 err = po1030_set_exposure(&sd->gspca_dev,
281 sensor_settings[EXPOSURE_IDX]);
282 if (err < 0)
283 return err;
284
285 err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
286 if (err < 0)
287 return err;
288
289 err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
290 if (err < 0)
291 return err;
292
293 err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
294 if (err < 0)
295 return err;
296
297 err = po1030_set_red_balance(&sd->gspca_dev,
298 sensor_settings[RED_BALANCE_IDX]);
299 if (err < 0)
300 return err;
301
302 err = po1030_set_blue_balance(&sd->gspca_dev,
303 sensor_settings[BLUE_BALANCE_IDX]);
304 if (err < 0)
305 return err;
306
307 err = po1030_set_green_balance(&sd->gspca_dev,
308 sensor_settings[GREEN_BALANCE_IDX]);
309 if (err < 0)
310 return err;
311
312 err = po1030_set_auto_white_balance(&sd->gspca_dev,
313 sensor_settings[AUTO_WHITE_BALANCE_IDX]);
314 if (err < 0)
315 return err;
316
317 err = po1030_set_auto_exposure(&sd->gspca_dev,
318 sensor_settings[AUTO_EXPOSURE_IDX]);
319 return err;
320}
321
322int po1030_start(struct sd *sd)
323{
324 struct cam *cam = &sd->gspca_dev.cam;
325 int i, err = 0;
326 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
327 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
328 int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
329 u8 data;
330
331 switch (width) {
332 case 320:
333 data = PO1030_SUBSAMPLING;
334 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
335 if (err < 0)
336 return err;
337
338 data = ((width + 3) >> 8) & 0xff;
339 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
340 if (err < 0)
341 return err;
342
343 data = (width + 3) & 0xff;
344 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
345 if (err < 0)
346 return err;
347
348 data = ((height + 1) >> 8) & 0xff;
349 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
350 if (err < 0)
351 return err;
352
353 data = (height + 1) & 0xff;
354 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
355
356 height += 6;
357 width -= 1;
358 break;
359
360 case 640:
361 data = 0;
362 err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
363 if (err < 0)
364 return err;
365
366 data = ((width + 7) >> 8) & 0xff;
367 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
368 if (err < 0)
369 return err;
370
371 data = (width + 7) & 0xff;
372 err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
373 if (err < 0)
374 return err;
375
376 data = ((height + 3) >> 8) & 0xff;
377 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
378 if (err < 0)
379 return err;
380
381 data = (height + 3) & 0xff;
382 err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
383
384 height += 12;
385 width -= 2;
386 break;
387 }
388 err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
389 if (err < 0)
390 return err;
391
392 err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
393 if (err < 0)
394 return err;
395
396 err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
397 if (err < 0)
398 return err;
399
400 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
401 if (err < 0)
402 return err;
403
404 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
405 ((ver_offs >> 8) & 0xff));
406 if (err < 0)
407 return err;
408
409 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
410 if (err < 0)
411 return err;
412
413 for (i = 0; i < 2 && !err; i++)
414 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
415 if (err < 0)
416 return err;
417
418 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
419 if (err < 0)
420 return err;
421
422 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
423 if (err < 0)
424 return err;
425
426 for (i = 0; i < 2 && !err; i++)
427 err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
428
429 for (i = 0; i < 2 && !err; i++)
430 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
431
432 for (i = 0; i < 2 && !err; i++)
433 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
434 if (err < 0)
435 return err;
436
437 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
438 if (err < 0)
439 return err;
440
441 err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
442 if (err < 0)
443 return err;
444
445 err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
446 return err;
447}
448
449static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
450{
451 struct sd *sd = (struct sd *) gspca_dev;
452 s32 *sensor_settings = sd->sensor_priv;
453
454 *val = sensor_settings[EXPOSURE_IDX];
455 PDEBUG(D_V4L2, "Exposure read as %d", *val);
456 return 0;
457}
458
459static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
460{
461 struct sd *sd = (struct sd *) gspca_dev;
462 s32 *sensor_settings = sd->sensor_priv;
463 u8 i2c_data;
464 int err;
465
466 sensor_settings[EXPOSURE_IDX] = val;
467 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
468
469 i2c_data = ((val & 0xff00) >> 8);
470 PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
471 i2c_data);
472
473 err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
474 &i2c_data, 1);
475 if (err < 0)
476 return err;
477
478 i2c_data = (val & 0xff);
479 PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
480 i2c_data);
481 err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
482 &i2c_data, 1);
483
484 return err;
485}
486
487static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
488{
489 struct sd *sd = (struct sd *) gspca_dev;
490 s32 *sensor_settings = sd->sensor_priv;
491
492 *val = sensor_settings[GAIN_IDX];
493 PDEBUG(D_V4L2, "Read global gain %d", *val);
494 return 0;
495}
496
497static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
498{
499 struct sd *sd = (struct sd *) gspca_dev;
500 s32 *sensor_settings = sd->sensor_priv;
501 u8 i2c_data;
502 int err;
503
504 sensor_settings[GAIN_IDX] = val;
505
506 i2c_data = val & 0xff;
507 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
508 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
509 &i2c_data, 1);
510 return err;
511}
512
513static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
514{
515 struct sd *sd = (struct sd *) gspca_dev;
516 s32 *sensor_settings = sd->sensor_priv;
517
518 *val = sensor_settings[HFLIP_IDX];
519 PDEBUG(D_V4L2, "Read hflip %d", *val);
520
521 return 0;
522}
523
524static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
525{
526 struct sd *sd = (struct sd *) gspca_dev;
527 s32 *sensor_settings = sd->sensor_priv;
528 u8 i2c_data;
529 int err;
530
531 sensor_settings[HFLIP_IDX] = val;
532
533 PDEBUG(D_V4L2, "Set hflip %d", val);
534 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
535 if (err < 0)
536 return err;
537
538 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
539
540 err = m5602_write_sensor(sd, PO1030_CONTROL2,
541 &i2c_data, 1);
542
543 return err;
544}
545
546static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
547{
548 struct sd *sd = (struct sd *) gspca_dev;
549 s32 *sensor_settings = sd->sensor_priv;
550
551 *val = sensor_settings[VFLIP_IDX];
552 PDEBUG(D_V4L2, "Read vflip %d", *val);
553
554 return 0;
555}
556
557static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
558{
559 struct sd *sd = (struct sd *) gspca_dev;
560 s32 *sensor_settings = sd->sensor_priv;
561 u8 i2c_data;
562 int err;
563
564 sensor_settings[VFLIP_IDX] = val;
565
566 PDEBUG(D_V4L2, "Set vflip %d", val);
567 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
568 if (err < 0)
569 return err;
570
571 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
572
573 err = m5602_write_sensor(sd, PO1030_CONTROL2,
574 &i2c_data, 1);
575
576 return err;
577}
578
579static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
580{
581 struct sd *sd = (struct sd *) gspca_dev;
582 s32 *sensor_settings = sd->sensor_priv;
583
584 *val = sensor_settings[RED_BALANCE_IDX];
585 PDEBUG(D_V4L2, "Read red gain %d", *val);
586 return 0;
587}
588
589static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
590{
591 struct sd *sd = (struct sd *) gspca_dev;
592 s32 *sensor_settings = sd->sensor_priv;
593 u8 i2c_data;
594 int err;
595
596 sensor_settings[RED_BALANCE_IDX] = val;
597
598 i2c_data = val & 0xff;
599 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
600 err = m5602_write_sensor(sd, PO1030_RED_GAIN,
601 &i2c_data, 1);
602 return err;
603}
604
605static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608 s32 *sensor_settings = sd->sensor_priv;
609
610 *val = sensor_settings[BLUE_BALANCE_IDX];
611 PDEBUG(D_V4L2, "Read blue gain %d", *val);
612
613 return 0;
614}
615
616static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
617{
618 struct sd *sd = (struct sd *) gspca_dev;
619 s32 *sensor_settings = sd->sensor_priv;
620 u8 i2c_data;
621 int err;
622
623 sensor_settings[BLUE_BALANCE_IDX] = val;
624
625 i2c_data = val & 0xff;
626 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
627 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
628 &i2c_data, 1);
629
630 return err;
631}
632
633static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
634{
635 struct sd *sd = (struct sd *) gspca_dev;
636 s32 *sensor_settings = sd->sensor_priv;
637
638 *val = sensor_settings[GREEN_BALANCE_IDX];
639 PDEBUG(D_V4L2, "Read green gain %d", *val);
640
641 return 0;
642}
643
644static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
645{
646 struct sd *sd = (struct sd *) gspca_dev;
647 s32 *sensor_settings = sd->sensor_priv;
648 u8 i2c_data;
649 int err;
650
651 sensor_settings[GREEN_BALANCE_IDX] = val;
652 i2c_data = val & 0xff;
653 PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
654
655 err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
656 &i2c_data, 1);
657 if (err < 0)
658 return err;
659
660 return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
661 &i2c_data, 1);
662}
663
664static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
665 __s32 *val)
666{
667 struct sd *sd = (struct sd *) gspca_dev;
668 s32 *sensor_settings = sd->sensor_priv;
669
670 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
671 PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
672
673 return 0;
674}
675
676static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
677 __s32 val)
678{
679 struct sd *sd = (struct sd *) gspca_dev;
680 s32 *sensor_settings = sd->sensor_priv;
681 u8 i2c_data;
682 int err;
683
684 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
685
686 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
687 if (err < 0)
688 return err;
689
690 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
691 i2c_data = (i2c_data & 0xfe) | (val & 0x01);
692 err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
693 return err;
694}
695
696static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
697 __s32 *val)
698{
699 struct sd *sd = (struct sd *) gspca_dev;
700 s32 *sensor_settings = sd->sensor_priv;
701
702 *val = sensor_settings[AUTO_EXPOSURE_IDX];
703 PDEBUG(D_V4L2, "Auto exposure is %d", *val);
704 return 0;
705}
706
707static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
708 __s32 val)
709{
710 struct sd *sd = (struct sd *) gspca_dev;
711 s32 *sensor_settings = sd->sensor_priv;
712 u8 i2c_data;
713 int err;
714
715 sensor_settings[AUTO_EXPOSURE_IDX] = val;
716 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
717 if (err < 0)
718 return err;
719
720 PDEBUG(D_V4L2, "Set auto exposure to %d", val);
721 i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
722 return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
723}
724
725void po1030_disconnect(struct sd *sd)
726{
727 sd->sensor = NULL;
728 kfree(sd->sensor_priv);
729}
730
731static void po1030_dump_registers(struct sd *sd)
732{
733 int address;
734 u8 value = 0;
735
736 info("Dumping the po1030 sensor core registers");
737 for (address = 0; address < 0x7f; address++) {
738 m5602_read_sensor(sd, address, &value, 1);
739 info("register 0x%x contains 0x%x",
740 address, value);
741 }
742
743 info("po1030 register state dump complete");
744
745 info("Probing for which registers that are read/write");
746 for (address = 0; address < 0xff; address++) {
747 u8 old_value, ctrl_value;
748 u8 test_value[2] = {0xff, 0xff};
749
750 m5602_read_sensor(sd, address, &old_value, 1);
751 m5602_write_sensor(sd, address, test_value, 1);
752 m5602_read_sensor(sd, address, &ctrl_value, 1);
753
754 if (ctrl_value == test_value[0])
755 info("register 0x%x is writeable", address);
756 else
757 info("register 0x%x is read only", address);
758
759 /* Restore original value */
760 m5602_write_sensor(sd, address, &old_value, 1);
761 }
762}
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
new file mode 100644
index 00000000000..33835959639
--- /dev/null
+++ b/drivers/media/video/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 int 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/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
new file mode 100644
index 00000000000..d27280be985
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -0,0 +1,721 @@
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#include "m5602_s5k4aa.h"
20
21static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
22static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
23static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
24static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
25static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
26static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
27static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
28static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
29static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
30static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
31static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
32static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
33
34static
35 const
36 struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
37 {
38 .ident = "BRUNEINIT",
39 .matches = {
40 DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
41 DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
42 DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
43 }
44 }, {
45 .ident = "Fujitsu-Siemens Amilo Xa 2528",
46 .matches = {
47 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
48 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
49 }
50 }, {
51 .ident = "Fujitsu-Siemens Amilo Xi 2428",
52 .matches = {
53 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
54 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
55 }
56 }, {
57 .ident = "Fujitsu-Siemens Amilo Xi 2528",
58 .matches = {
59 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
60 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
61 }
62 }, {
63 .ident = "Fujitsu-Siemens Amilo Xi 2550",
64 .matches = {
65 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
66 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
67 }
68 }, {
69 .ident = "Fujitsu-Siemens Amilo Pa 2548",
70 .matches = {
71 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
72 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
73 }
74 }, {
75 .ident = "MSI GX700",
76 .matches = {
77 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
78 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
79 DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
80 }
81 }, {
82 .ident = "MSI GX700",
83 .matches = {
84 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
85 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
86 DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
87 }
88 }, {
89 .ident = "MSI GX700",
90 .matches = {
91 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
92 DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
93 DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
94 }
95 }, {
96 .ident = "MSI GX700/GX705/EX700",
97 .matches = {
98 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
99 DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
100 }
101 }, {
102 .ident = "MSI L735",
103 .matches = {
104 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
105 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
106 }
107 }, {
108 .ident = "Lenovo Y300",
109 .matches = {
110 DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
111 DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
112 }
113 },
114 { }
115};
116
117static struct v4l2_pix_format s5k4aa_modes[] = {
118 {
119 640,
120 480,
121 V4L2_PIX_FMT_SBGGR8,
122 V4L2_FIELD_NONE,
123 .sizeimage =
124 640 * 480,
125 .bytesperline = 640,
126 .colorspace = V4L2_COLORSPACE_SRGB,
127 .priv = 0
128 },
129 {
130 1280,
131 1024,
132 V4L2_PIX_FMT_SBGGR8,
133 V4L2_FIELD_NONE,
134 .sizeimage =
135 1280 * 1024,
136 .bytesperline = 1280,
137 .colorspace = V4L2_COLORSPACE_SRGB,
138 .priv = 0
139 }
140};
141
142static const struct ctrl s5k4aa_ctrls[] = {
143#define VFLIP_IDX 0
144 {
145 {
146 .id = V4L2_CID_VFLIP,
147 .type = V4L2_CTRL_TYPE_BOOLEAN,
148 .name = "vertical flip",
149 .minimum = 0,
150 .maximum = 1,
151 .step = 1,
152 .default_value = 0
153 },
154 .set = s5k4aa_set_vflip,
155 .get = s5k4aa_get_vflip
156 },
157#define HFLIP_IDX 1
158 {
159 {
160 .id = V4L2_CID_HFLIP,
161 .type = V4L2_CTRL_TYPE_BOOLEAN,
162 .name = "horizontal flip",
163 .minimum = 0,
164 .maximum = 1,
165 .step = 1,
166 .default_value = 0
167 },
168 .set = s5k4aa_set_hflip,
169 .get = s5k4aa_get_hflip
170 },
171#define GAIN_IDX 2
172 {
173 {
174 .id = V4L2_CID_GAIN,
175 .type = V4L2_CTRL_TYPE_INTEGER,
176 .name = "Gain",
177 .minimum = 0,
178 .maximum = 127,
179 .step = 1,
180 .default_value = S5K4AA_DEFAULT_GAIN,
181 .flags = V4L2_CTRL_FLAG_SLIDER
182 },
183 .set = s5k4aa_set_gain,
184 .get = s5k4aa_get_gain
185 },
186#define EXPOSURE_IDX 3
187 {
188 {
189 .id = V4L2_CID_EXPOSURE,
190 .type = V4L2_CTRL_TYPE_INTEGER,
191 .name = "Exposure",
192 .minimum = 13,
193 .maximum = 0xfff,
194 .step = 1,
195 .default_value = 0x100,
196 .flags = V4L2_CTRL_FLAG_SLIDER
197 },
198 .set = s5k4aa_set_exposure,
199 .get = s5k4aa_get_exposure
200 },
201#define NOISE_SUPP_IDX 4
202 {
203 {
204 .id = V4L2_CID_PRIVATE_BASE,
205 .type = V4L2_CTRL_TYPE_BOOLEAN,
206 .name = "Noise suppression (smoothing)",
207 .minimum = 0,
208 .maximum = 1,
209 .step = 1,
210 .default_value = 1,
211 },
212 .set = s5k4aa_set_noise,
213 .get = s5k4aa_get_noise
214 },
215#define BRIGHTNESS_IDX 5
216 {
217 {
218 .id = V4L2_CID_BRIGHTNESS,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "Brightness",
221 .minimum = 0,
222 .maximum = 0x1f,
223 .step = 1,
224 .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
225 },
226 .set = s5k4aa_set_brightness,
227 .get = s5k4aa_get_brightness
228 },
229
230};
231
232static void s5k4aa_dump_registers(struct sd *sd);
233
234int s5k4aa_probe(struct sd *sd)
235{
236 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
237 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
238 int i, err = 0;
239 s32 *sensor_settings;
240
241 if (force_sensor) {
242 if (force_sensor == S5K4AA_SENSOR) {
243 info("Forcing a %s sensor", s5k4aa.name);
244 goto sensor_found;
245 }
246 /* If we want to force another sensor, don't try to probe this
247 * one */
248 return -ENODEV;
249 }
250
251 PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
252
253 /* Preinit the sensor */
254 for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
255 u8 data[2] = {0x00, 0x00};
256
257 switch (preinit_s5k4aa[i][0]) {
258 case BRIDGE:
259 err = m5602_write_bridge(sd,
260 preinit_s5k4aa[i][1],
261 preinit_s5k4aa[i][2]);
262 break;
263
264 case SENSOR:
265 data[0] = preinit_s5k4aa[i][2];
266 err = m5602_write_sensor(sd,
267 preinit_s5k4aa[i][1],
268 data, 1);
269 break;
270
271 case SENSOR_LONG:
272 data[0] = preinit_s5k4aa[i][2];
273 data[1] = preinit_s5k4aa[i][3];
274 err = m5602_write_sensor(sd,
275 preinit_s5k4aa[i][1],
276 data, 2);
277 break;
278 default:
279 info("Invalid stream command, exiting init");
280 return -EINVAL;
281 }
282 }
283
284 /* Test some registers, but we don't know their exact meaning yet */
285 if (m5602_read_sensor(sd, 0x00, prod_id, 2))
286 return -ENODEV;
287 if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
288 return -ENODEV;
289 if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
290 return -ENODEV;
291
292 if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
293 return -ENODEV;
294 else
295 info("Detected a s5k4aa sensor");
296
297sensor_found:
298 sensor_settings = kmalloc(
299 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
300 if (!sensor_settings)
301 return -ENOMEM;
302
303 sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
304 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
305 sd->desc->ctrls = s5k4aa_ctrls;
306 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
307
308 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
309 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
310 sd->sensor_priv = sensor_settings;
311
312 return 0;
313}
314
315int s5k4aa_start(struct sd *sd)
316{
317 int i, err = 0;
318 u8 data[2];
319 struct cam *cam = &sd->gspca_dev.cam;
320 s32 *sensor_settings = sd->sensor_priv;
321
322 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
323 case 1280:
324 PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
325
326 for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
327 switch (SXGA_s5k4aa[i][0]) {
328 case BRIDGE:
329 err = m5602_write_bridge(sd,
330 SXGA_s5k4aa[i][1],
331 SXGA_s5k4aa[i][2]);
332 break;
333
334 case SENSOR:
335 data[0] = SXGA_s5k4aa[i][2];
336 err = m5602_write_sensor(sd,
337 SXGA_s5k4aa[i][1],
338 data, 1);
339 break;
340
341 case SENSOR_LONG:
342 data[0] = SXGA_s5k4aa[i][2];
343 data[1] = SXGA_s5k4aa[i][3];
344 err = m5602_write_sensor(sd,
345 SXGA_s5k4aa[i][1],
346 data, 2);
347 break;
348
349 default:
350 err("Invalid stream command, exiting init");
351 return -EINVAL;
352 }
353 }
354 err = s5k4aa_set_noise(&sd->gspca_dev, 0);
355 if (err < 0)
356 return err;
357 break;
358
359 case 640:
360 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
361
362 for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
363 switch (VGA_s5k4aa[i][0]) {
364 case BRIDGE:
365 err = m5602_write_bridge(sd,
366 VGA_s5k4aa[i][1],
367 VGA_s5k4aa[i][2]);
368 break;
369
370 case SENSOR:
371 data[0] = VGA_s5k4aa[i][2];
372 err = m5602_write_sensor(sd,
373 VGA_s5k4aa[i][1],
374 data, 1);
375 break;
376
377 case SENSOR_LONG:
378 data[0] = VGA_s5k4aa[i][2];
379 data[1] = VGA_s5k4aa[i][3];
380 err = m5602_write_sensor(sd,
381 VGA_s5k4aa[i][1],
382 data, 2);
383 break;
384
385 default:
386 err("Invalid stream command, exiting init");
387 return -EINVAL;
388 }
389 }
390 err = s5k4aa_set_noise(&sd->gspca_dev, 1);
391 if (err < 0)
392 return err;
393 break;
394 }
395 if (err < 0)
396 return err;
397
398 err = s5k4aa_set_exposure(&sd->gspca_dev,
399 sensor_settings[EXPOSURE_IDX]);
400 if (err < 0)
401 return err;
402
403 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
404 if (err < 0)
405 return err;
406
407 err = s5k4aa_set_brightness(&sd->gspca_dev,
408 sensor_settings[BRIGHTNESS_IDX]);
409 if (err < 0)
410 return err;
411
412 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
413 if (err < 0)
414 return err;
415
416 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
417 if (err < 0)
418 return err;
419
420 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
421}
422
423int s5k4aa_init(struct sd *sd)
424{
425 int i, err = 0;
426
427 for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
428 u8 data[2] = {0x00, 0x00};
429
430 switch (init_s5k4aa[i][0]) {
431 case BRIDGE:
432 err = m5602_write_bridge(sd,
433 init_s5k4aa[i][1],
434 init_s5k4aa[i][2]);
435 break;
436
437 case SENSOR:
438 data[0] = init_s5k4aa[i][2];
439 err = m5602_write_sensor(sd,
440 init_s5k4aa[i][1], data, 1);
441 break;
442
443 case SENSOR_LONG:
444 data[0] = init_s5k4aa[i][2];
445 data[1] = init_s5k4aa[i][3];
446 err = m5602_write_sensor(sd,
447 init_s5k4aa[i][1], data, 2);
448 break;
449 default:
450 info("Invalid stream command, exiting init");
451 return -EINVAL;
452 }
453 }
454
455 if (dump_sensor)
456 s5k4aa_dump_registers(sd);
457
458 return err;
459}
460
461static int s5k4aa_get_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
466 *val = sensor_settings[EXPOSURE_IDX];
467 PDEBUG(D_V4L2, "Read exposure %d", *val);
468
469 return 0;
470}
471
472static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
473{
474 struct sd *sd = (struct sd *) gspca_dev;
475 s32 *sensor_settings = sd->sensor_priv;
476 u8 data = S5K4AA_PAGE_MAP_2;
477 int err;
478
479 sensor_settings[EXPOSURE_IDX] = val;
480 PDEBUG(D_V4L2, "Set exposure to %d", val);
481 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
482 if (err < 0)
483 return err;
484 data = (val >> 8) & 0xff;
485 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
486 if (err < 0)
487 return err;
488 data = val & 0xff;
489 err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
490
491 return err;
492}
493
494static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
495{
496 struct sd *sd = (struct sd *) gspca_dev;
497 s32 *sensor_settings = sd->sensor_priv;
498
499 *val = sensor_settings[VFLIP_IDX];
500 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
501
502 return 0;
503}
504
505static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
506{
507 struct sd *sd = (struct sd *) gspca_dev;
508 s32 *sensor_settings = sd->sensor_priv;
509 u8 data = S5K4AA_PAGE_MAP_2;
510 int err;
511
512 sensor_settings[VFLIP_IDX] = val;
513
514 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
515 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
516 if (err < 0)
517 return err;
518
519 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
520 if (err < 0)
521 return err;
522
523 if (dmi_check_system(s5k4aa_vflip_dmi_table))
524 val = !val;
525
526 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
527 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
528 if (err < 0)
529 return err;
530
531 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
532 if (err < 0)
533 return err;
534 if (val)
535 data &= 0xfe;
536 else
537 data |= 0x01;
538 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
539 return err;
540}
541
542static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
543{
544 struct sd *sd = (struct sd *) gspca_dev;
545 s32 *sensor_settings = sd->sensor_priv;
546
547 *val = sensor_settings[HFLIP_IDX];
548 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
549
550 return 0;
551}
552
553static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
554{
555 struct sd *sd = (struct sd *) gspca_dev;
556 s32 *sensor_settings = sd->sensor_priv;
557 u8 data = S5K4AA_PAGE_MAP_2;
558 int err;
559
560 sensor_settings[HFLIP_IDX] = val;
561
562 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
563 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
564 if (err < 0)
565 return err;
566
567 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
568 if (err < 0)
569 return err;
570
571 if (dmi_check_system(s5k4aa_vflip_dmi_table))
572 val = !val;
573
574 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
575 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
576 if (err < 0)
577 return err;
578
579 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
580 if (err < 0)
581 return err;
582 if (val)
583 data &= 0xfe;
584 else
585 data |= 0x01;
586 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
587 return err;
588}
589
590static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
591{
592 struct sd *sd = (struct sd *) gspca_dev;
593 s32 *sensor_settings = sd->sensor_priv;
594
595 *val = sensor_settings[GAIN_IDX];
596 PDEBUG(D_V4L2, "Read gain %d", *val);
597 return 0;
598}
599
600static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
601{
602 struct sd *sd = (struct sd *) gspca_dev;
603 s32 *sensor_settings = sd->sensor_priv;
604 u8 data = S5K4AA_PAGE_MAP_2;
605 int err;
606
607 sensor_settings[GAIN_IDX] = val;
608
609 PDEBUG(D_V4L2, "Set gain to %d", val);
610 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
611 if (err < 0)
612 return err;
613
614 data = val & 0xff;
615 err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
616
617 return err;
618}
619
620static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
621{
622 struct sd *sd = (struct sd *) gspca_dev;
623 s32 *sensor_settings = sd->sensor_priv;
624
625 *val = sensor_settings[BRIGHTNESS_IDX];
626 PDEBUG(D_V4L2, "Read brightness %d", *val);
627 return 0;
628}
629
630static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
631{
632 struct sd *sd = (struct sd *) gspca_dev;
633 s32 *sensor_settings = sd->sensor_priv;
634 u8 data = S5K4AA_PAGE_MAP_2;
635 int err;
636
637 sensor_settings[BRIGHTNESS_IDX] = val;
638
639 PDEBUG(D_V4L2, "Set brightness to %d", val);
640 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
641 if (err < 0)
642 return err;
643
644 data = val & 0xff;
645 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
646}
647
648static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
649{
650 struct sd *sd = (struct sd *) gspca_dev;
651 s32 *sensor_settings = sd->sensor_priv;
652
653 *val = sensor_settings[NOISE_SUPP_IDX];
654 PDEBUG(D_V4L2, "Read noise %d", *val);
655 return 0;
656}
657
658static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
659{
660 struct sd *sd = (struct sd *) gspca_dev;
661 s32 *sensor_settings = sd->sensor_priv;
662 u8 data = S5K4AA_PAGE_MAP_2;
663 int err;
664
665 sensor_settings[NOISE_SUPP_IDX] = val;
666
667 PDEBUG(D_V4L2, "Set noise to %d", val);
668 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
669 if (err < 0)
670 return err;
671
672 data = val & 0x01;
673 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
674}
675
676void s5k4aa_disconnect(struct sd *sd)
677{
678 sd->sensor = NULL;
679 kfree(sd->sensor_priv);
680}
681
682static void s5k4aa_dump_registers(struct sd *sd)
683{
684 int address;
685 u8 page, old_page;
686 m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
687 for (page = 0; page < 16; page++) {
688 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
689 info("Dumping the s5k4aa register state for page 0x%x", page);
690 for (address = 0; address <= 0xff; address++) {
691 u8 value = 0;
692 m5602_read_sensor(sd, address, &value, 1);
693 info("register 0x%x contains 0x%x",
694 address, value);
695 }
696 }
697 info("s5k4aa register state dump complete");
698
699 for (page = 0; page < 16; page++) {
700 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
701 info("Probing for which registers that are "
702 "read/write for page 0x%x", page);
703 for (address = 0; address <= 0xff; address++) {
704 u8 old_value, ctrl_value, test_value = 0xff;
705
706 m5602_read_sensor(sd, address, &old_value, 1);
707 m5602_write_sensor(sd, address, &test_value, 1);
708 m5602_read_sensor(sd, address, &ctrl_value, 1);
709
710 if (ctrl_value == test_value)
711 info("register 0x%x is writeable", address);
712 else
713 info("register 0x%x is read only", address);
714
715 /* Restore original value */
716 m5602_write_sensor(sd, address, &old_value, 1);
717 }
718 }
719 info("Read/write register probing complete");
720 m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
721}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
new file mode 100644
index 00000000000..8cc7a3f6da7
--- /dev/null
+++ b/drivers/media/video/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 int 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/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
new file mode 100644
index 00000000000..fbd91545497
--- /dev/null
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -0,0 +1,601 @@
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#include <linux/kthread.h>
20#include "m5602_s5k83a.h"
21
22static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
23static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
24static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
25static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
26static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
27static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
28static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
29static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
30static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
31static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
32
33static struct v4l2_pix_format s5k83a_modes[] = {
34 {
35 640,
36 480,
37 V4L2_PIX_FMT_SBGGR8,
38 V4L2_FIELD_NONE,
39 .sizeimage =
40 640 * 480,
41 .bytesperline = 640,
42 .colorspace = V4L2_COLORSPACE_SRGB,
43 .priv = 0
44 }
45};
46
47static const struct ctrl s5k83a_ctrls[] = {
48#define GAIN_IDX 0
49 {
50 {
51 .id = V4L2_CID_GAIN,
52 .type = V4L2_CTRL_TYPE_INTEGER,
53 .name = "gain",
54 .minimum = 0x00,
55 .maximum = 0xff,
56 .step = 0x01,
57 .default_value = S5K83A_DEFAULT_GAIN,
58 .flags = V4L2_CTRL_FLAG_SLIDER
59 },
60 .set = s5k83a_set_gain,
61 .get = s5k83a_get_gain
62
63 },
64#define BRIGHTNESS_IDX 1
65 {
66 {
67 .id = V4L2_CID_BRIGHTNESS,
68 .type = V4L2_CTRL_TYPE_INTEGER,
69 .name = "brightness",
70 .minimum = 0x00,
71 .maximum = 0xff,
72 .step = 0x01,
73 .default_value = S5K83A_DEFAULT_BRIGHTNESS,
74 .flags = V4L2_CTRL_FLAG_SLIDER
75 },
76 .set = s5k83a_set_brightness,
77 .get = s5k83a_get_brightness,
78 },
79#define EXPOSURE_IDX 2
80 {
81 {
82 .id = V4L2_CID_EXPOSURE,
83 .type = V4L2_CTRL_TYPE_INTEGER,
84 .name = "exposure",
85 .minimum = 0x00,
86 .maximum = S5K83A_MAXIMUM_EXPOSURE,
87 .step = 0x01,
88 .default_value = S5K83A_DEFAULT_EXPOSURE,
89 .flags = V4L2_CTRL_FLAG_SLIDER
90 },
91 .set = s5k83a_set_exposure,
92 .get = s5k83a_get_exposure
93 },
94#define HFLIP_IDX 3
95 {
96 {
97 .id = V4L2_CID_HFLIP,
98 .type = V4L2_CTRL_TYPE_BOOLEAN,
99 .name = "horizontal flip",
100 .minimum = 0,
101 .maximum = 1,
102 .step = 1,
103 .default_value = 0
104 },
105 .set = s5k83a_set_hflip,
106 .get = s5k83a_get_hflip
107 },
108#define VFLIP_IDX 4
109 {
110 {
111 .id = V4L2_CID_VFLIP,
112 .type = V4L2_CTRL_TYPE_BOOLEAN,
113 .name = "vertical flip",
114 .minimum = 0,
115 .maximum = 1,
116 .step = 1,
117 .default_value = 0
118 },
119 .set = s5k83a_set_vflip,
120 .get = s5k83a_get_vflip
121 }
122};
123
124static void s5k83a_dump_registers(struct sd *sd);
125static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
126static int s5k83a_set_led_indication(struct sd *sd, u8 val);
127static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
128 __s32 vflip, __s32 hflip);
129
130int s5k83a_probe(struct sd *sd)
131{
132 struct s5k83a_priv *sens_priv;
133 u8 prod_id = 0, ver_id = 0;
134 int i, err = 0;
135
136 if (force_sensor) {
137 if (force_sensor == S5K83A_SENSOR) {
138 info("Forcing a %s sensor", s5k83a.name);
139 goto sensor_found;
140 }
141 /* If we want to force another sensor, don't try to probe this
142 * one */
143 return -ENODEV;
144 }
145
146 PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
147
148 /* Preinit the sensor */
149 for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
150 u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
151 if (preinit_s5k83a[i][0] == SENSOR)
152 err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
153 data, 2);
154 else
155 err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
156 data[0]);
157 }
158
159 /* We don't know what register (if any) that contain the product id
160 * Just pick the first addresses that seem to produce the same results
161 * on multiple machines */
162 if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
163 return -ENODEV;
164
165 if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
166 return -ENODEV;
167
168 if ((prod_id == 0xff) || (ver_id == 0xff))
169 return -ENODEV;
170 else
171 info("Detected a s5k83a sensor");
172
173sensor_found:
174 sens_priv = kmalloc(
175 sizeof(struct s5k83a_priv), GFP_KERNEL);
176 if (!sens_priv)
177 return -ENOMEM;
178
179 sens_priv->settings =
180 kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
181 if (!sens_priv->settings) {
182 kfree(sens_priv);
183 return -ENOMEM;
184 }
185
186 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
187 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
188 sd->desc->ctrls = s5k83a_ctrls;
189 sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
190
191 /* null the pointer! thread is't running now */
192 sens_priv->rotation_thread = NULL;
193
194 for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
195 sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
196
197 sd->sensor_priv = sens_priv;
198 return 0;
199}
200
201int s5k83a_init(struct sd *sd)
202{
203 int i, err = 0;
204 s32 *sensor_settings =
205 ((struct s5k83a_priv *) sd->sensor_priv)->settings;
206
207 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
208 u8 data[2] = {0x00, 0x00};
209
210 switch (init_s5k83a[i][0]) {
211 case BRIDGE:
212 err = m5602_write_bridge(sd,
213 init_s5k83a[i][1],
214 init_s5k83a[i][2]);
215 break;
216
217 case SENSOR:
218 data[0] = init_s5k83a[i][2];
219 err = m5602_write_sensor(sd,
220 init_s5k83a[i][1], data, 1);
221 break;
222
223 case SENSOR_LONG:
224 data[0] = init_s5k83a[i][2];
225 data[1] = init_s5k83a[i][3];
226 err = m5602_write_sensor(sd,
227 init_s5k83a[i][1], data, 2);
228 break;
229 default:
230 info("Invalid stream command, exiting init");
231 return -EINVAL;
232 }
233 }
234
235 if (dump_sensor)
236 s5k83a_dump_registers(sd);
237
238 err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
239 if (err < 0)
240 return err;
241
242 err = s5k83a_set_brightness(&sd->gspca_dev,
243 sensor_settings[BRIGHTNESS_IDX]);
244 if (err < 0)
245 return err;
246
247 err = s5k83a_set_exposure(&sd->gspca_dev,
248 sensor_settings[EXPOSURE_IDX]);
249 if (err < 0)
250 return err;
251
252 err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
253 if (err < 0)
254 return err;
255
256 err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
257
258 return err;
259}
260
261static int rotation_thread_function(void *data)
262{
263 struct sd *sd = (struct sd *) data;
264 struct s5k83a_priv *sens_priv = sd->sensor_priv;
265 u8 reg, previous_rotation = 0;
266 __s32 vflip, hflip;
267
268 set_current_state(TASK_INTERRUPTIBLE);
269 while (!schedule_timeout(100)) {
270 if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
271 break;
272
273 s5k83a_get_rotation(sd, &reg);
274 if (previous_rotation != reg) {
275 previous_rotation = reg;
276 info("Camera was flipped");
277
278 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
279 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
280
281 if (reg) {
282 vflip = !vflip;
283 hflip = !hflip;
284 }
285 s5k83a_set_flip_real((struct gspca_dev *) sd,
286 vflip, hflip);
287 }
288
289 mutex_unlock(&sd->gspca_dev.usb_lock);
290 set_current_state(TASK_INTERRUPTIBLE);
291 }
292
293 /* return to "front" flip */
294 if (previous_rotation) {
295 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
296 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
297 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
298 }
299
300 sens_priv->rotation_thread = NULL;
301 return 0;
302}
303
304int s5k83a_start(struct sd *sd)
305{
306 int i, err = 0;
307 struct s5k83a_priv *sens_priv = sd->sensor_priv;
308
309 /* Create another thread, polling the GPIO ports of the camera to check
310 if it got rotated. This is how the windows driver does it so we have
311 to assume that there is no better way of accomplishing this */
312 sens_priv->rotation_thread = kthread_create(rotation_thread_function,
313 sd, "rotation thread");
314 wake_up_process(sens_priv->rotation_thread);
315
316 /* Preinit the sensor */
317 for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
318 u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
319 if (start_s5k83a[i][0] == SENSOR)
320 err = m5602_write_sensor(sd, start_s5k83a[i][1],
321 data, 2);
322 else
323 err = m5602_write_bridge(sd, start_s5k83a[i][1],
324 data[0]);
325 }
326 if (err < 0)
327 return err;
328
329 return s5k83a_set_led_indication(sd, 1);
330}
331
332int s5k83a_stop(struct sd *sd)
333{
334 struct s5k83a_priv *sens_priv = sd->sensor_priv;
335
336 if (sens_priv->rotation_thread)
337 kthread_stop(sens_priv->rotation_thread);
338
339 return s5k83a_set_led_indication(sd, 0);
340}
341
342void s5k83a_disconnect(struct sd *sd)
343{
344 struct s5k83a_priv *sens_priv = sd->sensor_priv;
345
346 s5k83a_stop(sd);
347
348 sd->sensor = NULL;
349 kfree(sens_priv->settings);
350 kfree(sens_priv);
351}
352
353static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
354{
355 struct sd *sd = (struct sd *) gspca_dev;
356 struct s5k83a_priv *sens_priv = sd->sensor_priv;
357
358 *val = sens_priv->settings[GAIN_IDX];
359 return 0;
360}
361
362static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
363{
364 int err;
365 u8 data[2];
366 struct sd *sd = (struct sd *) gspca_dev;
367 struct s5k83a_priv *sens_priv = sd->sensor_priv;
368
369 sens_priv->settings[GAIN_IDX] = val;
370
371 data[0] = 0x00;
372 data[1] = 0x20;
373 err = m5602_write_sensor(sd, 0x14, data, 2);
374 if (err < 0)
375 return err;
376
377 data[0] = 0x01;
378 data[1] = 0x00;
379 err = m5602_write_sensor(sd, 0x0d, data, 2);
380 if (err < 0)
381 return err;
382
383 /* FIXME: This is not sane, we need to figure out the composition
384 of these registers */
385 data[0] = val >> 3; /* gain, high 5 bits */
386 data[1] = val >> 1; /* gain, high 7 bits */
387 err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
388
389 return err;
390}
391
392static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
393{
394 struct sd *sd = (struct sd *) gspca_dev;
395 struct s5k83a_priv *sens_priv = sd->sensor_priv;
396
397 *val = sens_priv->settings[BRIGHTNESS_IDX];
398 return 0;
399}
400
401static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
402{
403 int err;
404 u8 data[1];
405 struct sd *sd = (struct sd *) gspca_dev;
406 struct s5k83a_priv *sens_priv = sd->sensor_priv;
407
408 sens_priv->settings[BRIGHTNESS_IDX] = val;
409 data[0] = val;
410 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
411 return err;
412}
413
414static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
415{
416 struct sd *sd = (struct sd *) gspca_dev;
417 struct s5k83a_priv *sens_priv = sd->sensor_priv;
418
419 *val = sens_priv->settings[EXPOSURE_IDX];
420 return 0;
421}
422
423static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
424{
425 int err;
426 u8 data[2];
427 struct sd *sd = (struct sd *) gspca_dev;
428 struct s5k83a_priv *sens_priv = sd->sensor_priv;
429
430 sens_priv->settings[EXPOSURE_IDX] = val;
431 data[0] = 0;
432 data[1] = val;
433 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
434 return err;
435}
436
437static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
438{
439 struct sd *sd = (struct sd *) gspca_dev;
440 struct s5k83a_priv *sens_priv = sd->sensor_priv;
441
442 *val = sens_priv->settings[VFLIP_IDX];
443 return 0;
444}
445
446static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
447 __s32 vflip, __s32 hflip)
448{
449 int err;
450 u8 data[1];
451 struct sd *sd = (struct sd *) gspca_dev;
452
453 data[0] = 0x05;
454 err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
455 if (err < 0)
456 return err;
457
458 /* six bit is vflip, seven is hflip */
459 data[0] = S5K83A_FLIP_MASK;
460 data[0] = (vflip) ? data[0] | 0x40 : data[0];
461 data[0] = (hflip) ? data[0] | 0x80 : data[0];
462
463 err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
464 if (err < 0)
465 return err;
466
467 data[0] = (vflip) ? 0x0b : 0x0a;
468 err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
469 if (err < 0)
470 return err;
471
472 data[0] = (hflip) ? 0x0a : 0x0b;
473 err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
474 return err;
475}
476
477static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
478{
479 int err;
480 u8 reg;
481 __s32 hflip;
482 struct sd *sd = (struct sd *) gspca_dev;
483 struct s5k83a_priv *sens_priv = sd->sensor_priv;
484
485 sens_priv->settings[VFLIP_IDX] = val;
486
487 s5k83a_get_hflip(gspca_dev, &hflip);
488
489 err = s5k83a_get_rotation(sd, &reg);
490 if (err < 0)
491 return err;
492 if (reg) {
493 val = !val;
494 hflip = !hflip;
495 }
496
497 err = s5k83a_set_flip_real(gspca_dev, val, hflip);
498 return err;
499}
500
501static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
502{
503 struct sd *sd = (struct sd *) gspca_dev;
504 struct s5k83a_priv *sens_priv = sd->sensor_priv;
505
506 *val = sens_priv->settings[HFLIP_IDX];
507 return 0;
508}
509
510static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
511{
512 int err;
513 u8 reg;
514 __s32 vflip;
515 struct sd *sd = (struct sd *) gspca_dev;
516 struct s5k83a_priv *sens_priv = sd->sensor_priv;
517
518 sens_priv->settings[HFLIP_IDX] = val;
519
520 s5k83a_get_vflip(gspca_dev, &vflip);
521
522 err = s5k83a_get_rotation(sd, &reg);
523 if (err < 0)
524 return err;
525 if (reg) {
526 val = !val;
527 vflip = !vflip;
528 }
529
530 err = s5k83a_set_flip_real(gspca_dev, vflip, val);
531 return err;
532}
533
534static int s5k83a_set_led_indication(struct sd *sd, u8 val)
535{
536 int err = 0;
537 u8 data[1];
538
539 err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
540 if (err < 0)
541 return err;
542
543 if (val)
544 data[0] = data[0] | S5K83A_GPIO_LED_MASK;
545 else
546 data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
547
548 err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
549
550 return err;
551}
552
553/* Get camera rotation on Acer notebooks */
554static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
555{
556 int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
557 *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
558 return err;
559}
560
561static void s5k83a_dump_registers(struct sd *sd)
562{
563 int address;
564 u8 page, old_page;
565 m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
566
567 for (page = 0; page < 16; page++) {
568 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
569 info("Dumping the s5k83a register state for page 0x%x", page);
570 for (address = 0; address <= 0xff; address++) {
571 u8 val = 0;
572 m5602_read_sensor(sd, address, &val, 1);
573 info("register 0x%x contains 0x%x",
574 address, val);
575 }
576 }
577 info("s5k83a register state dump complete");
578
579 for (page = 0; page < 16; page++) {
580 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
581 info("Probing for which registers that are read/write "
582 "for page 0x%x", page);
583 for (address = 0; address <= 0xff; address++) {
584 u8 old_val, ctrl_val, test_val = 0xff;
585
586 m5602_read_sensor(sd, address, &old_val, 1);
587 m5602_write_sensor(sd, address, &test_val, 1);
588 m5602_read_sensor(sd, address, &ctrl_val, 1);
589
590 if (ctrl_val == test_val)
591 info("register 0x%x is writeable", address);
592 else
593 info("register 0x%x is read only", address);
594
595 /* Restore original val */
596 m5602_write_sensor(sd, address, &old_val, 1);
597 }
598 }
599 info("Read/write register probing complete");
600 m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
601}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
new file mode 100644
index 00000000000..80a63a236e2
--- /dev/null
+++ b/drivers/media/video/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 int 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/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
new file mode 100644
index 00000000000..edff4f1f586
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
new file mode 100644
index 00000000000..0196209a948
--- /dev/null
+++ b/drivers/media/video/gspca/mars.c
@@ -0,0 +1,529 @@
1/*
2 * Mars-Semi MR97311A library
3 * Copyright (C) 2005 <bradlch@hotmail.com>
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "mars"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31/* controls */
32enum e_ctrl {
33 BRIGHTNESS,
34 COLORS,
35 GAMMA,
36 SHARPNESS,
37 ILLUM_TOP,
38 ILLUM_BOT,
39 NCTRLS /* number of controls */
40};
41
42/* specific webcam descriptor */
43struct sd {
44 struct gspca_dev gspca_dev; /* !! must be the first item */
45
46 struct gspca_ctrl ctrls[NCTRLS];
47
48 u8 quality;
49#define QUALITY_MIN 40
50#define QUALITY_MAX 70
51#define QUALITY_DEF 50
52
53 u8 jpeg_hdr[JPEG_HDR_SZ];
54};
55
56/* V4L2 controls supported by the driver */
57static void setbrightness(struct gspca_dev *gspca_dev);
58static void setcolors(struct gspca_dev *gspca_dev);
59static void setgamma(struct gspca_dev *gspca_dev);
60static void setsharpness(struct gspca_dev *gspca_dev);
61static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val);
63
64static const struct ctrl sd_ctrls[NCTRLS] = {
65[BRIGHTNESS] = {
66 {
67 .id = V4L2_CID_BRIGHTNESS,
68 .type = V4L2_CTRL_TYPE_INTEGER,
69 .name = "Brightness",
70 .minimum = 0,
71 .maximum = 30,
72 .step = 1,
73 .default_value = 15,
74 },
75 .set_control = setbrightness
76 },
77[COLORS] = {
78 {
79 .id = V4L2_CID_SATURATION,
80 .type = V4L2_CTRL_TYPE_INTEGER,
81 .name = "Color",
82 .minimum = 1,
83 .maximum = 255,
84 .step = 1,
85 .default_value = 200,
86 },
87 .set_control = setcolors
88 },
89[GAMMA] = {
90 {
91 .id = V4L2_CID_GAMMA,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Gamma",
94 .minimum = 0,
95 .maximum = 3,
96 .step = 1,
97 .default_value = 1,
98 },
99 .set_control = setgamma
100 },
101[SHARPNESS] = {
102 {
103 .id = V4L2_CID_SHARPNESS,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Sharpness",
106 .minimum = 0,
107 .maximum = 2,
108 .step = 1,
109 .default_value = 1,
110 },
111 .set_control = setsharpness
112 },
113[ILLUM_TOP] = {
114 {
115 .id = V4L2_CID_ILLUMINATORS_1,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "Top illuminator",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121 .default_value = 0,
122 .flags = V4L2_CTRL_FLAG_UPDATE,
123 },
124 .set = sd_setilluminator1
125 },
126[ILLUM_BOT] = {
127 {
128 .id = V4L2_CID_ILLUMINATORS_2,
129 .type = V4L2_CTRL_TYPE_BOOLEAN,
130 .name = "Bottom illuminator",
131 .minimum = 0,
132 .maximum = 1,
133 .step = 1,
134 .default_value = 0,
135 .flags = V4L2_CTRL_FLAG_UPDATE,
136 },
137 .set = sd_setilluminator2
138 },
139};
140
141static const struct v4l2_pix_format vga_mode[] = {
142 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 320,
144 .sizeimage = 320 * 240 * 3 / 8 + 590,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 2},
147 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
148 .bytesperline = 640,
149 .sizeimage = 640 * 480 * 3 / 8 + 590,
150 .colorspace = V4L2_COLORSPACE_JPEG,
151 .priv = 1},
152};
153
154static const __u8 mi_data[0x20] = {
155/* 01 02 03 04 05 06 07 08 */
156 0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
157/* 09 0a 0b 0c 0d 0e 0f 10 */
158 0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
159/* 11 12 13 14 15 16 17 18 */
160 0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
161/* 19 1a 1b 1c 1d 1e 1f 20 */
162 0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
163};
164
165/* write <len> bytes from gspca_dev->usb_buf */
166static void reg_w(struct gspca_dev *gspca_dev,
167 int len)
168{
169 int alen, ret;
170
171 if (gspca_dev->usb_err < 0)
172 return;
173
174 ret = usb_bulk_msg(gspca_dev->dev,
175 usb_sndbulkpipe(gspca_dev->dev, 4),
176 gspca_dev->usb_buf,
177 len,
178 &alen,
179 500); /* timeout in milliseconds */
180 if (ret < 0) {
181 err("reg write [%02x] error %d",
182 gspca_dev->usb_buf[0], ret);
183 gspca_dev->usb_err = ret;
184 }
185}
186
187static void mi_w(struct gspca_dev *gspca_dev,
188 u8 addr,
189 u8 value)
190{
191 gspca_dev->usb_buf[0] = 0x1f;
192 gspca_dev->usb_buf[1] = 0; /* control byte */
193 gspca_dev->usb_buf[2] = addr;
194 gspca_dev->usb_buf[3] = value;
195
196 reg_w(gspca_dev, 4);
197}
198
199static void setbrightness(struct gspca_dev *gspca_dev)
200{
201 struct sd *sd = (struct sd *) gspca_dev;
202
203 gspca_dev->usb_buf[0] = 0x61;
204 gspca_dev->usb_buf[1] = sd->ctrls[BRIGHTNESS].val;
205 reg_w(gspca_dev, 2);
206}
207
208static void setcolors(struct gspca_dev *gspca_dev)
209{
210 struct sd *sd = (struct sd *) gspca_dev;
211 s16 val;
212
213 val = sd->ctrls[COLORS].val;
214 gspca_dev->usb_buf[0] = 0x5f;
215 gspca_dev->usb_buf[1] = val << 3;
216 gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
217 reg_w(gspca_dev, 3);
218}
219
220static void setgamma(struct gspca_dev *gspca_dev)
221{
222 struct sd *sd = (struct sd *) gspca_dev;
223
224 gspca_dev->usb_buf[0] = 0x06;
225 gspca_dev->usb_buf[1] = sd->ctrls[GAMMA].val * 0x40;
226 reg_w(gspca_dev, 2);
227}
228
229static void setsharpness(struct gspca_dev *gspca_dev)
230{
231 struct sd *sd = (struct sd *) gspca_dev;
232
233 gspca_dev->usb_buf[0] = 0x67;
234 gspca_dev->usb_buf[1] = sd->ctrls[SHARPNESS].val * 4 + 3;
235 reg_w(gspca_dev, 2);
236}
237
238static void setilluminators(struct gspca_dev *gspca_dev)
239{
240 struct sd *sd = (struct sd *) gspca_dev;
241
242 gspca_dev->usb_buf[0] = 0x22;
243 if (sd->ctrls[ILLUM_TOP].val)
244 gspca_dev->usb_buf[1] = 0x76;
245 else if (sd->ctrls[ILLUM_BOT].val)
246 gspca_dev->usb_buf[1] = 0x7a;
247 else
248 gspca_dev->usb_buf[1] = 0x7e;
249 reg_w(gspca_dev, 2);
250}
251
252/* this function is called at probe time */
253static int sd_config(struct gspca_dev *gspca_dev,
254 const struct usb_device_id *id)
255{
256 struct sd *sd = (struct sd *) gspca_dev;
257 struct cam *cam;
258
259 cam = &gspca_dev->cam;
260 cam->cam_mode = vga_mode;
261 cam->nmodes = ARRAY_SIZE(vga_mode);
262 cam->ctrls = sd->ctrls;
263 sd->quality = QUALITY_DEF;
264 gspca_dev->nbalt = 9; /* use the altsetting 08 */
265 return 0;
266}
267
268/* this function is called at probe and resume time */
269static int sd_init(struct gspca_dev *gspca_dev)
270{
271 gspca_dev->ctrl_inac = (1 << ILLUM_TOP) | (1 << ILLUM_BOT);
272 return 0;
273}
274
275static int sd_start(struct gspca_dev *gspca_dev)
276{
277 struct sd *sd = (struct sd *) gspca_dev;
278 u8 *data;
279 int i;
280
281 /* create the JPEG header */
282 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
283 0x21); /* JPEG 422 */
284 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
285
286 data = gspca_dev->usb_buf;
287
288 data[0] = 0x01; /* address */
289 data[1] = 0x01;
290 reg_w(gspca_dev, 2);
291
292 /*
293 Initialize the MR97113 chip register
294 */
295 data[0] = 0x00; /* address */
296 data[1] = 0x0c | 0x01; /* reg 0 */
297 data[2] = 0x01; /* reg 1 */
298 data[3] = gspca_dev->width / 8; /* h_size , reg 2 */
299 data[4] = gspca_dev->height / 8; /* v_size , reg 3 */
300 data[5] = 0x30; /* reg 4, MI, PAS5101 :
301 * 0x30 for 24mhz , 0x28 for 12mhz */
302 data[6] = 0x02; /* reg 5, H start - was 0x04 */
303 data[7] = sd->ctrls[GAMMA].val * 0x40; /* reg 0x06: gamma */
304 data[8] = 0x01; /* reg 7, V start - was 0x03 */
305/* if (h_size == 320 ) */
306/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
307/* else */
308 data[9] = 0x52; /* reg 8, 24MHz, no scale down */
309/*jfm: from win trace*/
310 data[10] = 0x18;
311
312 reg_w(gspca_dev, 11);
313
314 data[0] = 0x23; /* address */
315 data[1] = 0x09; /* reg 35, append frame header */
316
317 reg_w(gspca_dev, 2);
318
319 data[0] = 0x3c; /* address */
320/* if (gspca_dev->width == 1280) */
321/* data[1] = 200; * reg 60, pc-cam frame size
322 * (unit: 4KB) 800KB */
323/* else */
324 data[1] = 50; /* 50 reg 60, pc-cam frame size
325 * (unit: 4KB) 200KB */
326 reg_w(gspca_dev, 2);
327
328 /* auto dark-gain */
329 data[0] = 0x5e; /* address */
330 data[1] = 0; /* reg 94, Y Gain (auto) */
331/*jfm: from win trace*/
332 /* reg 0x5f/0x60 (LE) = saturation */
333 /* h (60): xxxx x100
334 * l (5f): xxxx x000 */
335 data[2] = sd->ctrls[COLORS].val << 3;
336 data[3] = ((sd->ctrls[COLORS].val >> 2) & 0xf8) | 0x04;
337 data[4] = sd->ctrls[BRIGHTNESS].val; /* reg 0x61 = brightness */
338 data[5] = 0x00;
339
340 reg_w(gspca_dev, 6);
341
342 data[0] = 0x67;
343/*jfm: from win trace*/
344 data[1] = sd->ctrls[SHARPNESS].val * 4 + 3;
345 data[2] = 0x14;
346 reg_w(gspca_dev, 3);
347
348 data[0] = 0x69;
349 data[1] = 0x2f;
350 data[2] = 0x28;
351 data[3] = 0x42;
352 reg_w(gspca_dev, 4);
353
354 data[0] = 0x63;
355 data[1] = 0x07;
356 reg_w(gspca_dev, 2);
357/*jfm: win trace - many writes here to reg 0x64*/
358
359 /* initialize the MI sensor */
360 for (i = 0; i < sizeof mi_data; i++)
361 mi_w(gspca_dev, i + 1, mi_data[i]);
362
363 data[0] = 0x00;
364 data[1] = 0x4d; /* ISOC transferring enable... */
365 reg_w(gspca_dev, 2);
366
367 gspca_dev->ctrl_inac = 0; /* activate the illuminator controls */
368 return gspca_dev->usb_err;
369}
370
371static void sd_stopN(struct gspca_dev *gspca_dev)
372{
373 struct sd *sd = (struct sd *) gspca_dev;
374
375 gspca_dev->ctrl_inac = (1 << ILLUM_TOP) | (1 << ILLUM_BOT);
376 if (sd->ctrls[ILLUM_TOP].val || sd->ctrls[ILLUM_BOT].val) {
377 sd->ctrls[ILLUM_TOP].val = 0;
378 sd->ctrls[ILLUM_BOT].val = 0;
379 setilluminators(gspca_dev);
380 msleep(20);
381 }
382
383 gspca_dev->usb_buf[0] = 1;
384 gspca_dev->usb_buf[1] = 0;
385 reg_w(gspca_dev, 2);
386}
387
388static void sd_pkt_scan(struct gspca_dev *gspca_dev,
389 u8 *data, /* isoc packet */
390 int len) /* iso packet length */
391{
392 struct sd *sd = (struct sd *) gspca_dev;
393 int p;
394
395 if (len < 6) {
396/* gspca_dev->last_packet_type = DISCARD_PACKET; */
397 return;
398 }
399 for (p = 0; p < len - 6; p++) {
400 if (data[0 + p] == 0xff
401 && data[1 + p] == 0xff
402 && data[2 + p] == 0x00
403 && data[3 + p] == 0xff
404 && data[4 + p] == 0x96) {
405 if (data[5 + p] == 0x64
406 || data[5 + p] == 0x65
407 || data[5 + p] == 0x66
408 || data[5 + p] == 0x67) {
409 PDEBUG(D_PACK, "sof offset: %d len: %d",
410 p, len);
411 gspca_frame_add(gspca_dev, LAST_PACKET,
412 data, p);
413
414 /* put the JPEG header */
415 gspca_frame_add(gspca_dev, FIRST_PACKET,
416 sd->jpeg_hdr, JPEG_HDR_SZ);
417 data += p + 16;
418 len -= p + 16;
419 break;
420 }
421 }
422 }
423 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
424}
425
426static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val)
427{
428 struct sd *sd = (struct sd *) gspca_dev;
429
430 /* only one illuminator may be on */
431 sd->ctrls[ILLUM_TOP].val = val;
432 if (val)
433 sd->ctrls[ILLUM_BOT].val = 0;
434 setilluminators(gspca_dev);
435 return gspca_dev->usb_err;
436}
437
438static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val)
439{
440 struct sd *sd = (struct sd *) gspca_dev;
441
442 /* only one illuminator may be on */
443 sd->ctrls[ILLUM_BOT].val = val;
444 if (val)
445 sd->ctrls[ILLUM_TOP].val = 0;
446 setilluminators(gspca_dev);
447 return gspca_dev->usb_err;
448}
449
450static int sd_set_jcomp(struct gspca_dev *gspca_dev,
451 struct v4l2_jpegcompression *jcomp)
452{
453 struct sd *sd = (struct sd *) gspca_dev;
454
455 if (jcomp->quality < QUALITY_MIN)
456 sd->quality = QUALITY_MIN;
457 else if (jcomp->quality > QUALITY_MAX)
458 sd->quality = QUALITY_MAX;
459 else
460 sd->quality = jcomp->quality;
461 if (gspca_dev->streaming)
462 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
463 return 0;
464}
465
466static int sd_get_jcomp(struct gspca_dev *gspca_dev,
467 struct v4l2_jpegcompression *jcomp)
468{
469 struct sd *sd = (struct sd *) gspca_dev;
470
471 memset(jcomp, 0, sizeof *jcomp);
472 jcomp->quality = sd->quality;
473 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
474 | V4L2_JPEG_MARKER_DQT;
475 return 0;
476}
477
478/* sub-driver description */
479static const struct sd_desc sd_desc = {
480 .name = MODULE_NAME,
481 .ctrls = sd_ctrls,
482 .nctrls = NCTRLS,
483 .config = sd_config,
484 .init = sd_init,
485 .start = sd_start,
486 .stopN = sd_stopN,
487 .pkt_scan = sd_pkt_scan,
488 .get_jcomp = sd_get_jcomp,
489 .set_jcomp = sd_set_jcomp,
490};
491
492/* -- module initialisation -- */
493static const struct usb_device_id device_table[] = {
494 {USB_DEVICE(0x093a, 0x050f)},
495 {}
496};
497MODULE_DEVICE_TABLE(usb, device_table);
498
499/* -- device connect -- */
500static int sd_probe(struct usb_interface *intf,
501 const struct usb_device_id *id)
502{
503 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
504 THIS_MODULE);
505}
506
507static struct usb_driver sd_driver = {
508 .name = MODULE_NAME,
509 .id_table = device_table,
510 .probe = sd_probe,
511 .disconnect = gspca_disconnect,
512#ifdef CONFIG_PM
513 .suspend = gspca_suspend,
514 .resume = gspca_resume,
515#endif
516};
517
518/* -- module insert / remove -- */
519static int __init sd_mod_init(void)
520{
521 return usb_register(&sd_driver);
522}
523static void __exit sd_mod_exit(void)
524{
525 usb_deregister(&sd_driver);
526}
527
528module_init(sd_mod_init);
529module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
new file mode 100644
index 00000000000..97e50796743
--- /dev/null
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -0,0 +1,1271 @@
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 MODULE_NAME "mr97310a"
44
45#include "gspca.h"
46
47#define CAM_TYPE_CIF 0
48#define CAM_TYPE_VGA 1
49
50#define MR97310A_BRIGHTNESS_DEFAULT 0
51
52#define MR97310A_EXPOSURE_MIN 0
53#define MR97310A_EXPOSURE_MAX 4095
54#define MR97310A_EXPOSURE_DEFAULT 1000
55
56#define MR97310A_GAIN_MIN 0
57#define MR97310A_GAIN_MAX 31
58#define MR97310A_GAIN_DEFAULT 25
59
60#define MR97310A_CONTRAST_MIN 0
61#define MR97310A_CONTRAST_MAX 31
62#define MR97310A_CONTRAST_DEFAULT 23
63
64#define MR97310A_CS_GAIN_MIN 0
65#define MR97310A_CS_GAIN_MAX 0x7ff
66#define MR97310A_CS_GAIN_DEFAULT 0x110
67
68#define MR97310A_MIN_CLOCKDIV_MIN 3
69#define MR97310A_MIN_CLOCKDIV_MAX 8
70#define MR97310A_MIN_CLOCKDIV_DEFAULT 3
71
72MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
73 "Theodore Kilgore <kilgota@auburn.edu>");
74MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
75MODULE_LICENSE("GPL");
76
77/* global parameters */
78static int force_sensor_type = -1;
79module_param(force_sensor_type, int, 0644);
80MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
81
82/* specific webcam descriptor */
83struct sd {
84 struct gspca_dev gspca_dev; /* !! must be the first item */
85 u8 sof_read;
86 u8 cam_type; /* 0 is CIF and 1 is VGA */
87 u8 sensor_type; /* We use 0 and 1 here, too. */
88 u8 do_lcd_stop;
89 u8 adj_colors;
90
91 int brightness;
92 u16 exposure;
93 u32 gain;
94 u8 contrast;
95 u8 min_clockdiv;
96};
97
98struct sensor_w_data {
99 u8 reg;
100 u8 flags;
101 u8 data[16];
102 int len;
103};
104
105static void sd_stopN(struct gspca_dev *gspca_dev);
106static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
108static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
110static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
111static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
112static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
113static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
114static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);
115static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val);
116static void setbrightness(struct gspca_dev *gspca_dev);
117static void setexposure(struct gspca_dev *gspca_dev);
118static void setgain(struct gspca_dev *gspca_dev);
119static void setcontrast(struct gspca_dev *gspca_dev);
120
121/* V4L2 controls supported by the driver */
122static const struct ctrl sd_ctrls[] = {
123/* Separate brightness control description for Argus QuickClix as it has
124 * different limits from the other mr97310a cameras, and separate gain
125 * control for Sakar CyberPix camera. */
126 {
127#define NORM_BRIGHTNESS_IDX 0
128 {
129 .id = V4L2_CID_BRIGHTNESS,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "Brightness",
132 .minimum = -254,
133 .maximum = 255,
134 .step = 1,
135 .default_value = MR97310A_BRIGHTNESS_DEFAULT,
136 .flags = 0,
137 },
138 .set = sd_setbrightness,
139 .get = sd_getbrightness,
140 },
141 {
142#define ARGUS_QC_BRIGHTNESS_IDX 1
143 {
144 .id = V4L2_CID_BRIGHTNESS,
145 .type = V4L2_CTRL_TYPE_INTEGER,
146 .name = "Brightness",
147 .minimum = 0,
148 .maximum = 15,
149 .step = 1,
150 .default_value = MR97310A_BRIGHTNESS_DEFAULT,
151 .flags = 0,
152 },
153 .set = sd_setbrightness,
154 .get = sd_getbrightness,
155 },
156 {
157#define EXPOSURE_IDX 2
158 {
159 .id = V4L2_CID_EXPOSURE,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Exposure",
162 .minimum = MR97310A_EXPOSURE_MIN,
163 .maximum = MR97310A_EXPOSURE_MAX,
164 .step = 1,
165 .default_value = MR97310A_EXPOSURE_DEFAULT,
166 .flags = 0,
167 },
168 .set = sd_setexposure,
169 .get = sd_getexposure,
170 },
171 {
172#define GAIN_IDX 3
173 {
174 .id = V4L2_CID_GAIN,
175 .type = V4L2_CTRL_TYPE_INTEGER,
176 .name = "Gain",
177 .minimum = MR97310A_GAIN_MIN,
178 .maximum = MR97310A_GAIN_MAX,
179 .step = 1,
180 .default_value = MR97310A_GAIN_DEFAULT,
181 .flags = 0,
182 },
183 .set = sd_setgain,
184 .get = sd_getgain,
185 },
186 {
187#define SAKAR_CS_GAIN_IDX 4
188 {
189 .id = V4L2_CID_GAIN,
190 .type = V4L2_CTRL_TYPE_INTEGER,
191 .name = "Gain",
192 .minimum = MR97310A_CS_GAIN_MIN,
193 .maximum = MR97310A_CS_GAIN_MAX,
194 .step = 1,
195 .default_value = MR97310A_CS_GAIN_DEFAULT,
196 .flags = 0,
197 },
198 .set = sd_setgain,
199 .get = sd_getgain,
200 },
201 {
202#define CONTRAST_IDX 5
203 {
204 .id = V4L2_CID_CONTRAST,
205 .type = V4L2_CTRL_TYPE_INTEGER,
206 .name = "Contrast",
207 .minimum = MR97310A_CONTRAST_MIN,
208 .maximum = MR97310A_CONTRAST_MAX,
209 .step = 1,
210 .default_value = MR97310A_CONTRAST_DEFAULT,
211 .flags = 0,
212 },
213 .set = sd_setcontrast,
214 .get = sd_getcontrast,
215 },
216 {
217#define MIN_CLOCKDIV_IDX 6
218 {
219 .id = V4L2_CID_PRIVATE_BASE,
220 .type = V4L2_CTRL_TYPE_INTEGER,
221 .name = "Minimum Clock Divider",
222 .minimum = MR97310A_MIN_CLOCKDIV_MIN,
223 .maximum = MR97310A_MIN_CLOCKDIV_MAX,
224 .step = 1,
225 .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT,
226 .flags = 0,
227 },
228 .set = sd_setmin_clockdiv,
229 .get = sd_getmin_clockdiv,
230 },
231};
232
233static const struct v4l2_pix_format vga_mode[] = {
234 {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
235 .bytesperline = 160,
236 .sizeimage = 160 * 120,
237 .colorspace = V4L2_COLORSPACE_SRGB,
238 .priv = 4},
239 {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
240 .bytesperline = 176,
241 .sizeimage = 176 * 144,
242 .colorspace = V4L2_COLORSPACE_SRGB,
243 .priv = 3},
244 {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
245 .bytesperline = 320,
246 .sizeimage = 320 * 240,
247 .colorspace = V4L2_COLORSPACE_SRGB,
248 .priv = 2},
249 {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
250 .bytesperline = 352,
251 .sizeimage = 352 * 288,
252 .colorspace = V4L2_COLORSPACE_SRGB,
253 .priv = 1},
254 {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
255 .bytesperline = 640,
256 .sizeimage = 640 * 480,
257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 0},
259};
260
261/* the bytes to write are in gspca_dev->usb_buf */
262static int mr_write(struct gspca_dev *gspca_dev, int len)
263{
264 int rc;
265
266 rc = usb_bulk_msg(gspca_dev->dev,
267 usb_sndbulkpipe(gspca_dev->dev, 4),
268 gspca_dev->usb_buf, len, NULL, 500);
269 if (rc < 0)
270 err("reg write [%02x] error %d",
271 gspca_dev->usb_buf[0], rc);
272 return rc;
273}
274
275/* the bytes are read into gspca_dev->usb_buf */
276static int mr_read(struct gspca_dev *gspca_dev, int len)
277{
278 int rc;
279
280 rc = usb_bulk_msg(gspca_dev->dev,
281 usb_rcvbulkpipe(gspca_dev->dev, 3),
282 gspca_dev->usb_buf, len, NULL, 500);
283 if (rc < 0)
284 err("reg read [%02x] error %d",
285 gspca_dev->usb_buf[0], rc);
286 return rc;
287}
288
289static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
290 const u8 *data, int len)
291{
292 gspca_dev->usb_buf[0] = 0x1f;
293 gspca_dev->usb_buf[1] = flags;
294 gspca_dev->usb_buf[2] = reg;
295 memcpy(gspca_dev->usb_buf + 3, data, len);
296
297 return mr_write(gspca_dev, len + 3);
298}
299
300static int sensor_write_regs(struct gspca_dev *gspca_dev,
301 const struct sensor_w_data *data, int len)
302{
303 int i, rc;
304
305 for (i = 0; i < len; i++) {
306 rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
307 data[i].data, data[i].len);
308 if (rc < 0)
309 return rc;
310 }
311
312 return 0;
313}
314
315static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
316{
317 struct sd *sd = (struct sd *) gspca_dev;
318 u8 buf, confirm_reg;
319 int rc;
320
321 buf = data;
322 if (sd->cam_type == CAM_TYPE_CIF) {
323 rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
324 confirm_reg = sd->sensor_type ? 0x13 : 0x11;
325 } else {
326 rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
327 confirm_reg = 0x11;
328 }
329 if (rc < 0)
330 return rc;
331
332 buf = 0x01;
333 rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
334 if (rc < 0)
335 return rc;
336
337 return 0;
338}
339
340static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
341{
342 int err_code;
343
344 gspca_dev->usb_buf[0] = reg;
345 err_code = mr_write(gspca_dev, 1);
346 if (err_code < 0)
347 return err_code;
348
349 err_code = mr_read(gspca_dev, 16);
350 if (err_code < 0)
351 return err_code;
352
353 if (verbose)
354 PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,
355 gspca_dev->usb_buf[0],
356 gspca_dev->usb_buf[1],
357 gspca_dev->usb_buf[2]);
358
359 return 0;
360}
361
362static int zero_the_pointer(struct gspca_dev *gspca_dev)
363{
364 __u8 *data = gspca_dev->usb_buf;
365 int err_code;
366 u8 status = 0;
367 int tries = 0;
368
369 err_code = cam_get_response16(gspca_dev, 0x21, 0);
370 if (err_code < 0)
371 return err_code;
372
373 data[0] = 0x19;
374 data[1] = 0x51;
375 err_code = mr_write(gspca_dev, 2);
376 if (err_code < 0)
377 return err_code;
378
379 err_code = cam_get_response16(gspca_dev, 0x21, 0);
380 if (err_code < 0)
381 return err_code;
382
383 data[0] = 0x19;
384 data[1] = 0xba;
385 err_code = mr_write(gspca_dev, 2);
386 if (err_code < 0)
387 return err_code;
388
389 err_code = cam_get_response16(gspca_dev, 0x21, 0);
390 if (err_code < 0)
391 return err_code;
392
393 data[0] = 0x19;
394 data[1] = 0x00;
395 err_code = mr_write(gspca_dev, 2);
396 if (err_code < 0)
397 return err_code;
398
399 err_code = cam_get_response16(gspca_dev, 0x21, 0);
400 if (err_code < 0)
401 return err_code;
402
403 data[0] = 0x19;
404 data[1] = 0x00;
405 err_code = mr_write(gspca_dev, 2);
406 if (err_code < 0)
407 return err_code;
408
409 while (status != 0x0a && tries < 256) {
410 err_code = cam_get_response16(gspca_dev, 0x21, 0);
411 status = data[0];
412 tries++;
413 if (err_code < 0)
414 return err_code;
415 }
416 if (status != 0x0a)
417 PDEBUG(D_ERR, "status is %02x", status);
418
419 tries = 0;
420 while (tries < 4) {
421 data[0] = 0x19;
422 data[1] = 0x00;
423 err_code = mr_write(gspca_dev, 2);
424 if (err_code < 0)
425 return err_code;
426
427 err_code = cam_get_response16(gspca_dev, 0x21, 0);
428 status = data[0];
429 tries++;
430 if (err_code < 0)
431 return err_code;
432 }
433
434 data[0] = 0x19;
435 err_code = mr_write(gspca_dev, 1);
436 if (err_code < 0)
437 return err_code;
438
439 err_code = mr_read(gspca_dev, 16);
440 if (err_code < 0)
441 return err_code;
442
443 return 0;
444}
445
446static int stream_start(struct gspca_dev *gspca_dev)
447{
448 gspca_dev->usb_buf[0] = 0x01;
449 gspca_dev->usb_buf[1] = 0x01;
450 return mr_write(gspca_dev, 2);
451}
452
453static void stream_stop(struct gspca_dev *gspca_dev)
454{
455 gspca_dev->usb_buf[0] = 0x01;
456 gspca_dev->usb_buf[1] = 0x00;
457 if (mr_write(gspca_dev, 2) < 0)
458 PDEBUG(D_ERR, "Stream Stop failed");
459}
460
461static void lcd_stop(struct gspca_dev *gspca_dev)
462{
463 gspca_dev->usb_buf[0] = 0x19;
464 gspca_dev->usb_buf[1] = 0x54;
465 if (mr_write(gspca_dev, 2) < 0)
466 PDEBUG(D_ERR, "LCD Stop failed");
467}
468
469static int isoc_enable(struct gspca_dev *gspca_dev)
470{
471 gspca_dev->usb_buf[0] = 0x00;
472 gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */
473 return mr_write(gspca_dev, 2);
474}
475
476/* This function is called at probe time */
477static int sd_config(struct gspca_dev *gspca_dev,
478 const struct usb_device_id *id)
479{
480 struct sd *sd = (struct sd *) gspca_dev;
481 struct cam *cam;
482 int gain_default = MR97310A_GAIN_DEFAULT;
483 int err_code;
484
485 cam = &gspca_dev->cam;
486 cam->cam_mode = vga_mode;
487 cam->nmodes = ARRAY_SIZE(vga_mode);
488 sd->do_lcd_stop = 0;
489
490 /* Several of the supported CIF cameras share the same USB ID but
491 * require different initializations and different control settings.
492 * The same is true of the VGA cameras. Therefore, we are forced
493 * to start the initialization process in order to determine which
494 * camera is present. Some of the supported cameras require the
495 * memory pointer to be set to 0 as the very first item of business
496 * or else they will not stream. So we do that immediately.
497 */
498 err_code = zero_the_pointer(gspca_dev);
499 if (err_code < 0)
500 return err_code;
501
502 err_code = stream_start(gspca_dev);
503 if (err_code < 0)
504 return err_code;
505
506 /* Now, the query for sensor type. */
507 err_code = cam_get_response16(gspca_dev, 0x07, 1);
508 if (err_code < 0)
509 return err_code;
510
511 if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
512 sd->cam_type = CAM_TYPE_CIF;
513 cam->nmodes--;
514 /*
515 * All but one of the known CIF cameras share the same USB ID,
516 * but two different init routines are in use, and the control
517 * settings are different, too. We need to detect which camera
518 * of the two known varieties is connected!
519 *
520 * A list of known CIF cameras follows. They all report either
521 * 0200 for type 0 or 0300 for type 1.
522 * If you have another to report, please do
523 *
524 * Name sd->sensor_type reported by
525 *
526 * Sakar 56379 Spy-shot 0 T. Kilgore
527 * Innovage 0 T. Kilgore
528 * Vivitar Mini 0 H. De Goede
529 * Vivitar Mini 0 E. Rodriguez
530 * Vivitar Mini 1 T. Kilgore
531 * Elta-Media 8212dc 1 T. Kaiser
532 * Philips dig. keych. 1 T. Kilgore
533 * Trust Spyc@m 100 1 A. Jacobs
534 */
535 switch (gspca_dev->usb_buf[0]) {
536 case 2:
537 sd->sensor_type = 0;
538 break;
539 case 3:
540 sd->sensor_type = 1;
541 break;
542 default:
543 err("Unknown CIF Sensor id : %02x",
544 gspca_dev->usb_buf[1]);
545 return -ENODEV;
546 }
547 PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
548 sd->sensor_type);
549 } else {
550 sd->cam_type = CAM_TYPE_VGA;
551
552 /*
553 * Here is a table of the responses to the query for sensor
554 * type, from the known MR97310A VGA cameras. Six different
555 * cameras of which five share the same USB ID.
556 *
557 * Name gspca_dev->usb_buf[] sd->sensor_type
558 * sd->do_lcd_stop
559 * Aiptek Pencam VGA+ 0300 0 1
560 * ION digital 0300 0 1
561 * Argus DC-1620 0450 1 0
562 * Argus QuickClix 0420 1 1
563 * Sakar 77379 Digital 0350 0 1
564 * Sakar 1638x CyberPix 0120 0 2
565 *
566 * Based upon these results, we assume default settings
567 * and then correct as necessary, as follows.
568 *
569 */
570
571 sd->sensor_type = 1;
572 sd->do_lcd_stop = 0;
573 sd->adj_colors = 0;
574 if (gspca_dev->usb_buf[0] == 0x01) {
575 sd->sensor_type = 2;
576 } else if ((gspca_dev->usb_buf[0] != 0x03) &&
577 (gspca_dev->usb_buf[0] != 0x04)) {
578 err("Unknown VGA Sensor id Byte 0: %02x",
579 gspca_dev->usb_buf[0]);
580 err("Defaults assumed, may not work");
581 err("Please report this");
582 }
583 /* Sakar Digital color needs to be adjusted. */
584 if ((gspca_dev->usb_buf[0] == 0x03) &&
585 (gspca_dev->usb_buf[1] == 0x50))
586 sd->adj_colors = 1;
587 if (gspca_dev->usb_buf[0] == 0x04) {
588 sd->do_lcd_stop = 1;
589 switch (gspca_dev->usb_buf[1]) {
590 case 0x50:
591 sd->sensor_type = 0;
592 PDEBUG(D_PROBE, "sensor_type corrected to 0");
593 break;
594 case 0x20:
595 /* Nothing to do here. */
596 break;
597 default:
598 err("Unknown VGA Sensor id Byte 1: %02x",
599 gspca_dev->usb_buf[1]);
600 err("Defaults assumed, may not work");
601 err("Please report this");
602 }
603 }
604 PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
605 sd->sensor_type);
606 }
607 /* Stop streaming as we've started it only to probe the sensor type. */
608 sd_stopN(gspca_dev);
609
610 if (force_sensor_type != -1) {
611 sd->sensor_type = !!force_sensor_type;
612 PDEBUG(D_PROBE, "Forcing sensor type to: %d",
613 sd->sensor_type);
614 }
615
616 /* Setup controls depending on camera type */
617 if (sd->cam_type == CAM_TYPE_CIF) {
618 /* No brightness for sensor_type 0 */
619 if (sd->sensor_type == 0)
620 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
621 (1 << ARGUS_QC_BRIGHTNESS_IDX) |
622 (1 << CONTRAST_IDX) |
623 (1 << SAKAR_CS_GAIN_IDX);
624 else
625 gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
626 (1 << CONTRAST_IDX) |
627 (1 << SAKAR_CS_GAIN_IDX) |
628 (1 << MIN_CLOCKDIV_IDX);
629 } else {
630 /* All controls need to be disabled if VGA sensor_type is 0 */
631 if (sd->sensor_type == 0)
632 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
633 (1 << ARGUS_QC_BRIGHTNESS_IDX) |
634 (1 << EXPOSURE_IDX) |
635 (1 << GAIN_IDX) |
636 (1 << CONTRAST_IDX) |
637 (1 << SAKAR_CS_GAIN_IDX) |
638 (1 << MIN_CLOCKDIV_IDX);
639 else if (sd->sensor_type == 2) {
640 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
641 (1 << ARGUS_QC_BRIGHTNESS_IDX) |
642 (1 << GAIN_IDX) |
643 (1 << MIN_CLOCKDIV_IDX);
644 gain_default = MR97310A_CS_GAIN_DEFAULT;
645 } else if (sd->do_lcd_stop)
646 /* Argus QuickClix has different brightness limits */
647 gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) |
648 (1 << CONTRAST_IDX) |
649 (1 << SAKAR_CS_GAIN_IDX);
650 else
651 gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) |
652 (1 << CONTRAST_IDX) |
653 (1 << SAKAR_CS_GAIN_IDX);
654 }
655
656 sd->brightness = MR97310A_BRIGHTNESS_DEFAULT;
657 sd->exposure = MR97310A_EXPOSURE_DEFAULT;
658 sd->gain = gain_default;
659 sd->contrast = MR97310A_CONTRAST_DEFAULT;
660 sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT;
661
662 return 0;
663}
664
665/* this function is called at probe and resume time */
666static int sd_init(struct gspca_dev *gspca_dev)
667{
668 return 0;
669}
670
671static int start_cif_cam(struct gspca_dev *gspca_dev)
672{
673 struct sd *sd = (struct sd *) gspca_dev;
674 __u8 *data = gspca_dev->usb_buf;
675 int err_code;
676 static const __u8 startup_string[] = {
677 0x00,
678 0x0d,
679 0x01,
680 0x00, /* Hsize/8 for 352 or 320 */
681 0x00, /* Vsize/4 for 288 or 240 */
682 0x13, /* or 0xbb, depends on sensor */
683 0x00, /* Hstart, depends on res. */
684 0x00, /* reserved ? */
685 0x00, /* Vstart, depends on res. and sensor */
686 0x50, /* 0x54 to get 176 or 160 */
687 0xc0
688 };
689
690 /* Note: Some of the above descriptions guessed from MR97113A driver */
691
692 memcpy(data, startup_string, 11);
693 if (sd->sensor_type)
694 data[5] = 0xbb;
695
696 switch (gspca_dev->width) {
697 case 160:
698 data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
699 /* fall thru */
700 case 320:
701 default:
702 data[3] = 0x28; /* reg 2, H size/8 */
703 data[4] = 0x3c; /* reg 3, V size/4 */
704 data[6] = 0x14; /* reg 5, H start */
705 data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */
706 break;
707 case 176:
708 data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */
709 /* fall thru */
710 case 352:
711 data[3] = 0x2c; /* reg 2, H size/8 */
712 data[4] = 0x48; /* reg 3, V size/4 */
713 data[6] = 0x06; /* reg 5, H start */
714 data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */
715 break;
716 }
717 err_code = mr_write(gspca_dev, 11);
718 if (err_code < 0)
719 return err_code;
720
721 if (!sd->sensor_type) {
722 static const struct sensor_w_data cif_sensor0_init_data[] = {
723 {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
724 0x0f, 0x14, 0x0f, 0x10}, 8},
725 {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
726 {0x12, 0x00, {0x07}, 1},
727 {0x1f, 0x00, {0x06}, 1},
728 {0x27, 0x00, {0x04}, 1},
729 {0x29, 0x00, {0x0c}, 1},
730 {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
731 {0x50, 0x00, {0x60}, 1},
732 {0x60, 0x00, {0x06}, 1},
733 {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
734 {0x72, 0x00, {0x1e, 0x56}, 2},
735 {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
736 0x31, 0x80, 0x00}, 9},
737 {0x11, 0x00, {0x01}, 1},
738 {0, 0, {0}, 0}
739 };
740 err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
741 ARRAY_SIZE(cif_sensor0_init_data));
742 } else { /* sd->sensor_type = 1 */
743 static const struct sensor_w_data cif_sensor1_init_data[] = {
744 /* Reg 3,4, 7,8 get set by the controls */
745 {0x02, 0x00, {0x10}, 1},
746 {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
747 {0x06, 0x01, {0x00}, 1},
748 {0x09, 0x02, {0x0e}, 1},
749 {0x0a, 0x02, {0x05}, 1},
750 {0x0b, 0x02, {0x05}, 1},
751 {0x0c, 0x02, {0x0f}, 1},
752 {0x0d, 0x02, {0x07}, 1},
753 {0x0e, 0x02, {0x0c}, 1},
754 {0x0f, 0x00, {0x00}, 1},
755 {0x10, 0x00, {0x06}, 1},
756 {0x11, 0x00, {0x07}, 1},
757 {0x12, 0x00, {0x00}, 1},
758 {0x13, 0x00, {0x01}, 1},
759 {0, 0, {0}, 0}
760 };
761 /* Without this command the cam won't work with USB-UHCI */
762 gspca_dev->usb_buf[0] = 0x0a;
763 gspca_dev->usb_buf[1] = 0x00;
764 err_code = mr_write(gspca_dev, 2);
765 if (err_code < 0)
766 return err_code;
767 err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
768 ARRAY_SIZE(cif_sensor1_init_data));
769 }
770 return err_code;
771}
772
773static int start_vga_cam(struct gspca_dev *gspca_dev)
774{
775 struct sd *sd = (struct sd *) gspca_dev;
776 __u8 *data = gspca_dev->usb_buf;
777 int err_code;
778 static const __u8 startup_string[] =
779 {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
780 0x00, 0x50, 0xc0};
781 /* What some of these mean is explained in start_cif_cam(), above */
782
783 memcpy(data, startup_string, 11);
784 if (!sd->sensor_type) {
785 data[5] = 0x00;
786 data[10] = 0x91;
787 }
788 if (sd->sensor_type == 2) {
789 data[5] = 0x00;
790 data[10] = 0x18;
791 }
792
793 switch (gspca_dev->width) {
794 case 160:
795 data[9] |= 0x0c; /* reg 8, 4:1 scale down */
796 /* fall thru */
797 case 320:
798 data[9] |= 0x04; /* reg 8, 2:1 scale down */
799 /* fall thru */
800 case 640:
801 default:
802 data[3] = 0x50; /* reg 2, H size/8 */
803 data[4] = 0x78; /* reg 3, V size/4 */
804 data[6] = 0x04; /* reg 5, H start */
805 data[8] = 0x03; /* reg 7, V start */
806 if (sd->sensor_type == 2) {
807 data[6] = 2;
808 data[8] = 1;
809 }
810 if (sd->do_lcd_stop)
811 data[8] = 0x04; /* Bayer tile shifted */
812 break;
813
814 case 176:
815 data[9] |= 0x04; /* reg 8, 2:1 scale down */
816 /* fall thru */
817 case 352:
818 data[3] = 0x2c; /* reg 2, H size */
819 data[4] = 0x48; /* reg 3, V size */
820 data[6] = 0x94; /* reg 5, H start */
821 data[8] = 0x63; /* reg 7, V start */
822 if (sd->do_lcd_stop)
823 data[8] = 0x64; /* Bayer tile shifted */
824 break;
825 }
826
827 err_code = mr_write(gspca_dev, 11);
828 if (err_code < 0)
829 return err_code;
830
831 if (!sd->sensor_type) {
832 static const struct sensor_w_data vga_sensor0_init_data[] = {
833 {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
834 {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
835 {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
836 {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
837 {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
838 {0, 0, {0}, 0}
839 };
840 err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
841 ARRAY_SIZE(vga_sensor0_init_data));
842 } else if (sd->sensor_type == 1) {
843 static const struct sensor_w_data color_adj[] = {
844 {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
845 /* adjusted blue, green, red gain correct
846 too much blue from the Sakar Digital */
847 0x05, 0x01, 0x04}, 8}
848 };
849
850 static const struct sensor_w_data color_no_adj[] = {
851 {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
852 /* default blue, green, red gain settings */
853 0x07, 0x00, 0x01}, 8}
854 };
855
856 static const struct sensor_w_data vga_sensor1_init_data[] = {
857 {0x11, 0x04, {0x01}, 1},
858 {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
859 /* These settings may be better for some cameras */
860 /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
861 0x00, 0x0a}, 7},
862 {0x11, 0x04, {0x01}, 1},
863 {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
864 {0x11, 0x04, {0x01}, 1},
865 {0, 0, {0}, 0}
866 };
867
868 if (sd->adj_colors)
869 err_code = sensor_write_regs(gspca_dev, color_adj,
870 ARRAY_SIZE(color_adj));
871 else
872 err_code = sensor_write_regs(gspca_dev, color_no_adj,
873 ARRAY_SIZE(color_no_adj));
874
875 if (err_code < 0)
876 return err_code;
877
878 err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
879 ARRAY_SIZE(vga_sensor1_init_data));
880 } else { /* sensor type == 2 */
881 static const struct sensor_w_data vga_sensor2_init_data[] = {
882
883 {0x01, 0x00, {0x48}, 1},
884 {0x02, 0x00, {0x22}, 1},
885 /* Reg 3 msb and 4 is lsb of the exposure setting*/
886 {0x05, 0x00, {0x10}, 1},
887 {0x06, 0x00, {0x00}, 1},
888 {0x07, 0x00, {0x00}, 1},
889 {0x08, 0x00, {0x00}, 1},
890 {0x09, 0x00, {0x00}, 1},
891 /* The following are used in the gain control
892 * which is BTW completely borked in the OEM driver
893 * The values for each color go from 0 to 0x7ff
894 *{0x0a, 0x00, {0x01}, 1}, green1 gain msb
895 *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb
896 *{0x0c, 0x00, {0x01}, 1}, red gain msb
897 *{0x0d, 0x00, {0x10}, 1}, red gain lsb
898 *{0x0e, 0x00, {0x01}, 1}, blue gain msb
899 *{0x0f, 0x00, {0x10}, 1}, blue gain lsb
900 *{0x10, 0x00, {0x01}, 1}, green2 gain msb
901 *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
902 */
903 {0x12, 0x00, {0x00}, 1},
904 {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
905 {0x14, 0x00, {0x00}, 1},
906 {0x15, 0x00, {0x06}, 1},
907 {0x16, 0x00, {0x01}, 1},
908 {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
909 {0x18, 0x00, {0x02}, 1},
910 {0x19, 0x00, {0x82}, 1}, /* don't mess with */
911 {0x1a, 0x00, {0x00}, 1},
912 {0x1b, 0x00, {0x20}, 1},
913 /* {0x1c, 0x00, {0x17}, 1}, contrast control */
914 {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
915 {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
916 {0x1f, 0x00, {0x0c}, 1},
917 {0x20, 0x00, {0x00}, 1},
918 {0, 0, {0}, 0}
919 };
920 err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
921 ARRAY_SIZE(vga_sensor2_init_data));
922 }
923 return err_code;
924}
925
926static int sd_start(struct gspca_dev *gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929 int err_code;
930
931 sd->sof_read = 0;
932
933 /* Some of the VGA cameras require the memory pointer
934 * to be set to 0 again. We have been forced to start the
935 * stream in sd_config() to detect the hardware, and closed it.
936 * Thus, we need here to do a completely fresh and clean start. */
937 err_code = zero_the_pointer(gspca_dev);
938 if (err_code < 0)
939 return err_code;
940
941 err_code = stream_start(gspca_dev);
942 if (err_code < 0)
943 return err_code;
944
945 if (sd->cam_type == CAM_TYPE_CIF) {
946 err_code = start_cif_cam(gspca_dev);
947 } else {
948 err_code = start_vga_cam(gspca_dev);
949 }
950 if (err_code < 0)
951 return err_code;
952
953 setbrightness(gspca_dev);
954 setcontrast(gspca_dev);
955 setexposure(gspca_dev);
956 setgain(gspca_dev);
957
958 return isoc_enable(gspca_dev);
959}
960
961static void sd_stopN(struct gspca_dev *gspca_dev)
962{
963 struct sd *sd = (struct sd *) gspca_dev;
964
965 stream_stop(gspca_dev);
966 /* Not all the cams need this, but even if not, probably a good idea */
967 zero_the_pointer(gspca_dev);
968 if (sd->do_lcd_stop)
969 lcd_stop(gspca_dev);
970}
971
972static void setbrightness(struct gspca_dev *gspca_dev)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
975 u8 val;
976 u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */
977 u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
978 static const u8 quick_clix_table[] =
979 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
980 { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15};
981 /*
982 * This control is disabled for CIF type 1 and VGA type 0 cameras.
983 * It does not quite act linearly for the Argus QuickClix camera,
984 * but it does control brightness. The values are 0 - 15 only, and
985 * the table above makes them act consecutively.
986 */
987 if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) &&
988 (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX)))
989 return;
990
991 if (sd->cam_type == CAM_TYPE_VGA) {
992 sign_reg += 4;
993 value_reg += 4;
994 }
995
996 /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
997 if (sd->brightness > 0) {
998 sensor_write1(gspca_dev, sign_reg, 0x00);
999 val = sd->brightness;
1000 } else {
1001 sensor_write1(gspca_dev, sign_reg, 0x01);
1002 val = (257 - sd->brightness);
1003 }
1004 /* Use lookup table for funky Argus QuickClix brightness */
1005 if (sd->do_lcd_stop)
1006 val = quick_clix_table[val];
1007
1008 sensor_write1(gspca_dev, value_reg, val);
1009}
1010
1011static void setexposure(struct gspca_dev *gspca_dev)
1012{
1013 struct sd *sd = (struct sd *) gspca_dev;
1014 int exposure = MR97310A_EXPOSURE_DEFAULT;
1015 u8 buf[2];
1016
1017 if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
1018 return;
1019
1020 if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
1021 /* This cam does not like exposure settings < 300,
1022 so scale 0 - 4095 to 300 - 4095 */
1023 exposure = (sd->exposure * 9267) / 10000 + 300;
1024 sensor_write1(gspca_dev, 3, exposure >> 4);
1025 sensor_write1(gspca_dev, 4, exposure & 0x0f);
1026 } else if (sd->sensor_type == 2) {
1027 exposure = sd->exposure;
1028 exposure >>= 3;
1029 sensor_write1(gspca_dev, 3, exposure >> 8);
1030 sensor_write1(gspca_dev, 4, exposure & 0xff);
1031 } else {
1032 /* We have both a clock divider and an exposure register.
1033 We first calculate the clock divider, as that determines
1034 the maximum exposure and then we calculate the exposure
1035 register setting (which goes from 0 - 511).
1036
1037 Note our 0 - 4095 exposure is mapped to 0 - 511
1038 milliseconds exposure time */
1039 u8 clockdiv = (60 * sd->exposure + 7999) / 8000;
1040
1041 /* Limit framerate to not exceed usb bandwidth */
1042 if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320)
1043 clockdiv = sd->min_clockdiv;
1044 else if (clockdiv < 2)
1045 clockdiv = 2;
1046
1047 if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
1048 clockdiv = 4;
1049
1050 /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
1051 exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
1052 exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv);
1053 if (exposure > 511)
1054 exposure = 511;
1055
1056 /* exposure register value is reversed! */
1057 exposure = 511 - exposure;
1058
1059 buf[0] = exposure & 0xff;
1060 buf[1] = exposure >> 8;
1061 sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
1062 sensor_write1(gspca_dev, 0x02, clockdiv);
1063 }
1064}
1065
1066static void setgain(struct gspca_dev *gspca_dev)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069 u8 gainreg;
1070
1071 if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) &&
1072 (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX)))
1073 return;
1074
1075 if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
1076 sensor_write1(gspca_dev, 0x0e, sd->gain);
1077 else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
1078 for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
1079 sensor_write1(gspca_dev, gainreg, sd->gain >> 8);
1080 sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff);
1081 }
1082 else
1083 sensor_write1(gspca_dev, 0x10, sd->gain);
1084}
1085
1086static void setcontrast(struct gspca_dev *gspca_dev)
1087{
1088 struct sd *sd = (struct sd *) gspca_dev;
1089
1090 if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))
1091 return;
1092
1093 sensor_write1(gspca_dev, 0x1c, sd->contrast);
1094}
1095
1096
1097static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1098{
1099 struct sd *sd = (struct sd *) gspca_dev;
1100
1101 sd->brightness = val;
1102 if (gspca_dev->streaming)
1103 setbrightness(gspca_dev);
1104 return 0;
1105}
1106
1107static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1108{
1109 struct sd *sd = (struct sd *) gspca_dev;
1110
1111 *val = sd->brightness;
1112 return 0;
1113}
1114
1115static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1116{
1117 struct sd *sd = (struct sd *) gspca_dev;
1118
1119 sd->exposure = val;
1120 if (gspca_dev->streaming)
1121 setexposure(gspca_dev);
1122 return 0;
1123}
1124
1125static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1126{
1127 struct sd *sd = (struct sd *) gspca_dev;
1128
1129 *val = sd->exposure;
1130 return 0;
1131}
1132
1133static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1134{
1135 struct sd *sd = (struct sd *) gspca_dev;
1136
1137 sd->gain = val;
1138 if (gspca_dev->streaming)
1139 setgain(gspca_dev);
1140 return 0;
1141}
1142
1143static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1144{
1145 struct sd *sd = (struct sd *) gspca_dev;
1146
1147 *val = sd->gain;
1148 return 0;
1149}
1150
1151static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1152{
1153 struct sd *sd = (struct sd *) gspca_dev;
1154
1155 sd->contrast = val;
1156 if (gspca_dev->streaming)
1157 setcontrast(gspca_dev);
1158 return 0;
1159}
1160
1161
1162static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1163{
1164 struct sd *sd = (struct sd *) gspca_dev;
1165
1166 *val = sd->contrast;
1167 return 0;
1168}
1169
1170static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val)
1171{
1172 struct sd *sd = (struct sd *) gspca_dev;
1173
1174 sd->min_clockdiv = val;
1175 if (gspca_dev->streaming)
1176 setexposure(gspca_dev);
1177 return 0;
1178}
1179
1180static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val)
1181{
1182 struct sd *sd = (struct sd *) gspca_dev;
1183
1184 *val = sd->min_clockdiv;
1185 return 0;
1186}
1187
1188/* Include pac common sof detection functions */
1189#include "pac_common.h"
1190
1191static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1192 u8 *data, /* isoc packet */
1193 int len) /* iso packet length */
1194{
1195 struct sd *sd = (struct sd *) gspca_dev;
1196 unsigned char *sof;
1197
1198 sof = pac_find_sof(&sd->sof_read, data, len);
1199 if (sof) {
1200 int n;
1201
1202 /* finish decoding current frame */
1203 n = sof - data;
1204 if (n > sizeof pac_sof_marker)
1205 n -= sizeof pac_sof_marker;
1206 else
1207 n = 0;
1208 gspca_frame_add(gspca_dev, LAST_PACKET,
1209 data, n);
1210 /* Start next frame. */
1211 gspca_frame_add(gspca_dev, FIRST_PACKET,
1212 pac_sof_marker, sizeof pac_sof_marker);
1213 len -= sof - data;
1214 data = sof;
1215 }
1216 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1217}
1218
1219/* sub-driver description */
1220static const struct sd_desc sd_desc = {
1221 .name = MODULE_NAME,
1222 .ctrls = sd_ctrls,
1223 .nctrls = ARRAY_SIZE(sd_ctrls),
1224 .config = sd_config,
1225 .init = sd_init,
1226 .start = sd_start,
1227 .stopN = sd_stopN,
1228 .pkt_scan = sd_pkt_scan,
1229};
1230
1231/* -- module initialisation -- */
1232static const struct usb_device_id device_table[] = {
1233 {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */
1234 {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */
1235 {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */
1236 {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */
1237 {}
1238};
1239MODULE_DEVICE_TABLE(usb, device_table);
1240
1241/* -- device connect -- */
1242static int sd_probe(struct usb_interface *intf,
1243 const struct usb_device_id *id)
1244{
1245 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1246 THIS_MODULE);
1247}
1248
1249static struct usb_driver sd_driver = {
1250 .name = MODULE_NAME,
1251 .id_table = device_table,
1252 .probe = sd_probe,
1253 .disconnect = gspca_disconnect,
1254#ifdef CONFIG_PM
1255 .suspend = gspca_suspend,
1256 .resume = gspca_resume,
1257#endif
1258};
1259
1260/* -- module insert / remove -- */
1261static int __init sd_mod_init(void)
1262{
1263 return usb_register(&sd_driver);
1264}
1265static void __exit sd_mod_exit(void)
1266{
1267 usb_deregister(&sd_driver);
1268}
1269
1270module_init(sd_mod_init);
1271module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c
new file mode 100644
index 00000000000..8e754fd4dc5
--- /dev/null
+++ b/drivers/media/video/gspca/nw80x.c
@@ -0,0 +1,2145 @@
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 MODULE_NAME "nw80x"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
28MODULE_DESCRIPTION("NW80x USB Camera Driver");
29MODULE_LICENSE("GPL");
30
31static int webcam;
32
33/* controls */
34enum e_ctrl {
35 GAIN,
36 EXPOSURE,
37 AUTOGAIN,
38 NCTRLS /* number of controls */
39};
40
41#define AUTOGAIN_DEF 1
42
43/* specific webcam descriptor */
44struct sd {
45 struct gspca_dev gspca_dev; /* !! must be the first item */
46
47 struct gspca_ctrl ctrls[NCTRLS];
48
49 u32 ae_res;
50 s8 ag_cnt;
51#define AG_CNT_START 13
52 u8 exp_too_low_cnt;
53 u8 exp_too_high_cnt;
54
55 u8 bridge;
56 u8 webcam;
57};
58
59enum bridges {
60 BRIDGE_NW800, /* and et31x110 */
61 BRIDGE_NW801,
62 BRIDGE_NW802,
63};
64enum webcams {
65 Generic800,
66 SpaceCam, /* Trust 120 SpaceCam */
67 SpaceCam2, /* other Trust 120 SpaceCam */
68 Cvideopro, /* Conceptronic Video Pro */
69 Dlink350c,
70 DS3303u,
71 Kr651us,
72 Kritter,
73 Mustek300,
74 Proscope,
75 Twinkle,
76 DvcV6,
77 P35u,
78 Generic802,
79 NWEBCAMS /* number of webcams */
80};
81
82static const u8 webcam_chip[NWEBCAMS] = {
83 [Generic800] = BRIDGE_NW800, /* 06a5:0000
84 * Typhoon Webcam 100 USB */
85
86 [SpaceCam] = BRIDGE_NW800, /* 06a5:d800
87 * Trust SpaceCam120 or SpaceCam100 PORTABLE */
88
89 [SpaceCam2] = BRIDGE_NW800, /* 06a5:d800 - pas106
90 * other Trust SpaceCam120 or SpaceCam100 PORTABLE */
91
92 [Cvideopro] = BRIDGE_NW802, /* 06a5:d001
93 * Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' */
94
95 [Dlink350c] = BRIDGE_NW802, /* 06a5:d001
96 * D-Link NetQam Pro 250plus */
97
98 [DS3303u] = BRIDGE_NW801, /* 06a5:d001
99 * Plustek Opticam 500U or ProLink DS3303u */
100
101 [Kr651us] = BRIDGE_NW802, /* 06a5:d001
102 * Panasonic GP-KR651US */
103
104 [Kritter] = BRIDGE_NW802, /* 06a5:d001
105 * iRez Kritter cam */
106
107 [Mustek300] = BRIDGE_NW802, /* 055f:d001
108 * Mustek Wcam 300 mini */
109
110 [Proscope] = BRIDGE_NW802, /* 06a5:d001
111 * Scalar USB Microscope (ProScope) */
112
113 [Twinkle] = BRIDGE_NW800, /* 06a5:d800 - hv7121b? (seems pas106)
114 * Divio Chicony TwinkleCam
115 * DSB-C110 */
116
117 [DvcV6] = BRIDGE_NW802, /* 0502:d001
118 * DVC V6 */
119
120 [P35u] = BRIDGE_NW801, /* 052b:d001, 06a5:d001 and 06be:d001
121 * EZCam Pro p35u */
122
123 [Generic802] = BRIDGE_NW802,
124};
125/*
126 * other webcams:
127 * - nw801 046d:d001
128 * Logitech QuickCam Pro (dark focus ring)
129 * - nw801 0728:d001
130 * AVerMedia Camguard
131 * - nw??? 06a5:d001
132 * D-Link NetQam Pro 250plus
133 * - nw800 065a:d800
134 * Showcam NGS webcam
135 * - nw??? ????:????
136 * Sceptre svc300
137 */
138
139/*
140 * registers
141 * nw800/et31x110 nw801 nw802
142 * 0000..009e 0000..00a1 0000..009e
143 * 0200..0211 id id
144 * 0300..0302 id id
145 * 0400..0406 (inex) 0400..0406
146 * 0500..0505 0500..0506 (inex)
147 * 0600..061a 0600..0601 0600..0601
148 * 0800..0814 id id
149 * 1000..109c 1000..10a1 1000..109a
150 */
151
152/* resolutions
153 * nw800: 320x240, 352x288
154 * nw801/802: 320x240, 640x480
155 */
156static const struct v4l2_pix_format cif_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 {352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
162 .bytesperline = 352,
163 .sizeimage = 352 * 288 * 4 / 8,
164 .colorspace = V4L2_COLORSPACE_JPEG}
165};
166static const struct v4l2_pix_format vga_mode[] = {
167 {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
168 .bytesperline = 320,
169 .sizeimage = 320 * 240 * 4 / 8,
170 .colorspace = V4L2_COLORSPACE_JPEG},
171 {640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8,
174 .colorspace = V4L2_COLORSPACE_JPEG},
175};
176
177/*
178 * The sequences below contain:
179 * - 1st and 2nd bytes: either
180 * - register number (BE)
181 * - I2C0 + i2c address
182 * - 3rd byte: data length (=0 for end of sequence)
183 * - n bytes: data
184 */
185#define I2C0 0xff
186
187static const u8 nw800_init[] = {
188 0x04, 0x05, 0x01, 0x61,
189 0x04, 0x04, 0x01, 0x01,
190 0x04, 0x06, 0x01, 0x04,
191 0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
192 0x05, 0x05, 0x01, 0x00,
193 0, 0, 0
194};
195static const u8 nw800_start[] = {
196 0x04, 0x06, 0x01, 0xc0,
197 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
198 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
199 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
200 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
201 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
202 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
203 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
204 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
205 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
206 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
207 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
208 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
209 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
210 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
212 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
213 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
215 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
216 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
217 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
218 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
219 0x40, 0x20,
220 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
221 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
222 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
223 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00,
227 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
232 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
235 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
236 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
237 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
238 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
239 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
240 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
241 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
242 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
243 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
244 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
245 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
246 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
248 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
249 0x01, 0x60, 0x01, 0x00, 0x00,
250
251 0x04, 0x04, 0x01, 0xff,
252 0x04, 0x06, 0x01, 0xc4,
253
254 0x04, 0x06, 0x01, 0xc0,
255 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
256 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
257 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
258 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
259 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
260 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
261 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
262 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
263 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
264 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
265 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
266 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
267 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
268 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
270 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
271 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
273 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
274 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
275 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
276 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
277 0x40, 0x20,
278 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
279 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
280 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
281 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00,
285 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
290 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
293 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
294 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
295 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
296 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
297 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
298 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
299 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
300 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
301 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
302 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
303 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
304 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
306 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
307 0x01, 0x60, 0x01, 0x00, 0x00,
308
309 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
310 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
311 0x40,
312 0x00, 0x80, 0x01, 0xa0,
313 0x10, 0x1a, 0x01, 0x00,
314 0x00, 0x91, 0x02, 0x6c, 0x01,
315 0x00, 0x03, 0x02, 0xc8, 0x01,
316 0x10, 0x1a, 0x01, 0x00,
317 0x10, 0x00, 0x01, 0x83,
318 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
319 0x20, 0x01, 0x60, 0x01,
320 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
321 0x10, 0x1b, 0x02, 0x69, 0x00,
322 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
323 0x05, 0x02, 0x01, 0x02,
324 0x06, 0x00, 0x02, 0x04, 0xd9,
325 0x05, 0x05, 0x01, 0x20,
326 0x05, 0x05, 0x01, 0x21,
327 0x10, 0x0e, 0x01, 0x08,
328 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
329 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
330 0xea,
331 0x10, 0x03, 0x01, 0x00,
332 0x10, 0x0f, 0x02, 0x13, 0x13,
333 0x10, 0x03, 0x01, 0x14,
334 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
335 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
336 0xea,
337 0x10, 0x0b, 0x01, 0x14,
338 0x10, 0x0d, 0x01, 0x20,
339 0x10, 0x0c, 0x01, 0x34,
340 0x04, 0x06, 0x01, 0xc3,
341 0x04, 0x04, 0x01, 0x00,
342 0x05, 0x02, 0x01, 0x02,
343 0x06, 0x00, 0x02, 0x00, 0x48,
344 0x05, 0x05, 0x01, 0x20,
345 0x05, 0x05, 0x01, 0x21,
346 0, 0, 0
347};
348
349/* 06a5:d001 - nw801 - Panasonic
350 * P35u */
351static const u8 nw801_start_1[] = {
352 0x05, 0x06, 0x01, 0x04,
353 0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
354 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
355 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
356 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
357 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
358 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
359 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
360 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
361 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
362 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
363 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
364 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
365 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
366 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
368 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
369 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00,
371 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
372 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
373 0x36, 0x00,
374 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
375 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
376 0x40, 0x20,
377 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
378 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x06, 0x00, 0x02, 0x09, 0x99,
380 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a,
385 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02,
388 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
389 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06,
390 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
391 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
392 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4,
393 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf,
394 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
395 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
396 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
397 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
398 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
399 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
400 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02,
402 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
403 0xf0, 0x00,
404 0, 0, 0,
405};
406static const u8 nw801_start_qvga[] = {
407 0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
408 0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78,
409 0x02, 0x0f, 0x01, 0x6b,
410 0x10, 0x1a, 0x01, 0x15,
411 0x00, 0x00, 0x01, 0x1e,
412 0x10, 0x00, 0x01, 0x2f,
413 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
414 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
415 /* AE window */
416 0, 0, 0,
417};
418static const u8 nw801_start_vga[] = {
419 0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00,
420 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0,
421 0x02, 0x0f, 0x01, 0xd5,
422 0x10, 0x1a, 0x01, 0x15,
423 0x00, 0x00, 0x01, 0x0e,
424 0x10, 0x00, 0x01, 0x22,
425 0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
426 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
427 0, 0, 0,
428};
429static const u8 nw801_start_2[] = {
430 0x10, 0x04, 0x01, 0x1a,
431 0x10, 0x19, 0x01, 0x09, /* clock */
432 0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01,
433 /* .. gain .. */
434 0x00, 0x03, 0x02, 0x92, 0x03,
435 0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07,
436 0x00, 0x7b, 0x01, 0xcf,
437 0x10, 0x94, 0x01, 0x07,
438 0x05, 0x05, 0x01, 0x01,
439 0x05, 0x04, 0x01, 0x01,
440 0x10, 0x0e, 0x01, 0x08,
441 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
442 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
443 0xf0,
444 0x10, 0x03, 0x01, 0x00,
445 0x10, 0x0f, 0x02, 0x0c, 0x0c,
446 0x10, 0x03, 0x01, 0x08,
447 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
448 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
449 0xf0,
450 0x10, 0x0b, 0x01, 0x0b,
451 0x10, 0x0d, 0x01, 0x0b,
452 0x10, 0x0c, 0x01, 0x1f,
453 0x05, 0x06, 0x01, 0x03,
454 0, 0, 0
455};
456
457/* nw802 (sharp IR3Y38M?) */
458static const u8 nw802_start[] = {
459 0x04, 0x06, 0x01, 0x04,
460 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d,
461 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
462 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
463 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
464 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
465 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
466 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
467 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
468 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
469 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
470 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
471 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
472 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
473 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
475 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
476 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
477 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
478 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
479 0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00,
480 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
481 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
482 0x40, 0x20,
483 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
484 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
485 0x06, 0x00, 0x02, 0x09, 0x99,
486 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
491 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14,
493 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
494 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
495 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
496 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
497 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
498 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
499 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
500 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
501 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
502 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
503 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
504 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
505 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
506 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82,
507 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
508 0x01, 0xf0, 0x00,
509 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
510 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
511 0x40,
512 0x10, 0x1a, 0x01, 0x00,
513 0x10, 0x00, 0x01, 0xad,
514 0x00, 0x00, 0x01, 0x08,
515 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
516 0x10, 0x1b, 0x02, 0x00, 0x00,
517 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
518 0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
519 0x10, 0x0e, 0x01, 0x27,
520 0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
521 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
522 0xd8,
523 0x10, 0x03, 0x01, 0x00,
524 0x10, 0x0f, 0x02, 0x14, 0x14,
525 0x10, 0x03, 0x01, 0x0c,
526 0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74,
527 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1,
528 0xff,
529/* 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
530 * 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
531 * 0xd8, */
532 0x10, 0x0b, 0x01, 0x10,
533 0x10, 0x0d, 0x01, 0x11,
534 0x10, 0x0c, 0x01, 0x1c,
535 0x04, 0x06, 0x01, 0x03,
536 0x04, 0x04, 0x01, 0x00,
537 0, 0, 0
538};
539/* et31x110 - Trust 120 SpaceCam */
540static const u8 spacecam_init[] = {
541 0x04, 0x05, 0x01, 0x01,
542 0x04, 0x04, 0x01, 0x01,
543 0x04, 0x06, 0x01, 0x04,
544 0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
545 0x05, 0x05, 0x01, 0x00,
546 0, 0, 0
547};
548static const u8 spacecam_start[] = {
549 0x04, 0x06, 0x01, 0x44,
550 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
551 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
552 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
553 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
554 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
555 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
556 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
557 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
558 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
559 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
560 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
561 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
562 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
563 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
565 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
566 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
568 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
569 0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00,
570 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
571 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
572 0x40, 0x20,
573 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
574 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00,
580 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
585 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
587 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
588 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
589 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
590 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
591 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
592 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
593 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
594 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
595 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
596 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
597 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
598 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
599 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
601 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
602 0x01, 0x60, 0x01, 0x00, 0x00,
603 0x04, 0x06, 0x01, 0xc0,
604 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
605 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
606 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
607 0x40,
608 0x00, 0x80, 0x01, 0xa0,
609 0x10, 0x1a, 0x01, 0x00,
610 0x00, 0x91, 0x02, 0x32, 0x01,
611 0x00, 0x03, 0x02, 0x08, 0x02,
612 0x10, 0x00, 0x01, 0x83,
613 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
614 0x20, 0x01, 0x60, 0x01,
615 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
616 0x10, 0x0e, 0x01, 0x08,
617 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
618 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
619 0xf9,
620 0x10, 0x03, 0x01, 0x00,
621 0x10, 0x0f, 0x02, 0x13, 0x13,
622 0x10, 0x03, 0x01, 0x06,
623 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
624 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
625 0xf9,
626 0x10, 0x0b, 0x01, 0x08,
627 0x10, 0x0d, 0x01, 0x10,
628 0x10, 0x0c, 0x01, 0x1f,
629 0x04, 0x06, 0x01, 0xc3,
630 0x04, 0x05, 0x01, 0x40,
631 0x04, 0x04, 0x01, 0x40,
632 0, 0, 0
633};
634/* et31x110 - pas106 - other Trust SpaceCam120 */
635static const u8 spacecam2_start[] = {
636 0x04, 0x06, 0x01, 0x44,
637 0x04, 0x06, 0x01, 0x00,
638 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
639 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
640 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
641 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
642 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
643 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
644 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
645 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
646 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
647 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
648 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
649 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
650 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
651 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
653 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
654 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
656 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
657 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
658 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
659 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
660 0x40, 0x20,
661 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
662 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
663 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
664 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00,
668 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 0x00, 0x00, 0x00, 0x00, 0x00,
671 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
673 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
676 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
677 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
678 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
679 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
680 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
681 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
682 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
683 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
684 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
685 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
686 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
687 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
689 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
690 0x01, 0x60, 0x01, 0x00, 0x00,
691 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
692 0x04, 0x04, 0x01, 0x40,
693 0x04, 0x04, 0x01, 0x00,
694 I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05,
695 0x00, 0x00, 0x05, 0x05,
696 I2C0, 0x40, 0x02, 0x11, 0x06,
697 I2C0, 0x40, 0x02, 0x14, 0x00,
698 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
699 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
700 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
701 0x40,
702 I2C0, 0x40, 0x02, 0x02, 0x0c, /* pixel clock */
703 I2C0, 0x40, 0x02, 0x0f, 0x00,
704 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
705 0x10, 0x00, 0x01, 0x01,
706 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
707 0x20, 0x01, 0x60, 0x01,
708 I2C0, 0x40, 0x02, 0x05, 0x0f, /* exposure */
709 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
710 I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00,
711 /* gains */
712 I2C0, 0x40, 0x03, 0x12, 0x04, 0x01,
713 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
714 0x10, 0x0e, 0x01, 0x08,
715 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
716 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
717 0xf9,
718 0x10, 0x03, 0x01, 0x00,
719 0x10, 0x0f, 0x02, 0x13, 0x13,
720 0x10, 0x03, 0x01, 0x06,
721 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
722 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
723 0xf9,
724 0x10, 0x0b, 0x01, 0x11,
725 0x10, 0x0d, 0x01, 0x10,
726 0x10, 0x0c, 0x01, 0x14,
727 0x04, 0x06, 0x01, 0x03,
728 0x04, 0x05, 0x01, 0x61,
729 0x04, 0x04, 0x01, 0x00,
730 0, 0, 0
731};
732
733/* nw802 - Conceptronic Video Pro */
734static const u8 cvideopro_start[] = {
735 0x04, 0x06, 0x01, 0x04,
736 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
737 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
738 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
739 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
740 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
741 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
742 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
743 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
744 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
745 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
746 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
747 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
748 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
749 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
750 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
751 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
752 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
753 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
754 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
755 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
756 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
757 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
758 0x40, 0x20,
759 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
760 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
761 0x06, 0x00, 0x02, 0x09, 0x99,
762 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
767 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
769 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
770 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
771 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
772 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
773 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
774 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
775 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
776 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
777 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
778 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
779 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
780 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
781 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
783 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
784 0x01, 0xf0, 0x00,
785 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
786 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
787 0x40,
788 0x10, 0x1a, 0x01, 0x03,
789 0x10, 0x00, 0x01, 0xac,
790 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
791 0x10, 0x1b, 0x02, 0x3b, 0x01,
792 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
793 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
794 0x10, 0x1d, 0x02, 0x40, 0x06,
795 0x10, 0x0e, 0x01, 0x08,
796 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
797 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
798 0xdc,
799 0x10, 0x03, 0x01, 0x00,
800 0x10, 0x0f, 0x02, 0x12, 0x12,
801 0x10, 0x03, 0x01, 0x0c,
802 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
803 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
804 0xdc,
805 0x10, 0x0b, 0x01, 0x09,
806 0x10, 0x0d, 0x01, 0x10,
807 0x10, 0x0c, 0x01, 0x2f,
808 0x04, 0x06, 0x01, 0x03,
809 0x04, 0x04, 0x01, 0x00,
810 0, 0, 0
811};
812
813/* nw802 - D-link dru-350c cam */
814static const u8 dlink_start[] = {
815 0x04, 0x06, 0x01, 0x04,
816 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
817 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
818 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
819 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
820 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
821 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
822 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
823 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
824 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
825 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
826 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
827 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
828 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
829 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
831 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
832 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
833 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
834 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
835 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
836 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
837 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
838 0x40, 0x20,
839 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
840 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
841 0x06, 0x00, 0x02, 0x09, 0x99,
842 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00, 0x00,
845 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
847 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
848 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
849 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
850 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
851 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
852 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
853 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
854 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
855 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
856 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
857 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
858 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
859 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
860 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
861 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82,
863 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
864 0x01, 0xf0, 0x00,
865 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
866 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
867 0x40,
868 0x10, 0x1a, 0x01, 0x00,
869 0x10, 0x00, 0x01, 0xad,
870 0x00, 0x00, 0x01, 0x08,
871 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
872 0x10, 0x1b, 0x02, 0x00, 0x00,
873 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
874 0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
875 0x10, 0x0e, 0x01, 0x20,
876 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
877 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
878 0xea,
879 0x10, 0x03, 0x01, 0x00,
880 0x10, 0x0f, 0x02, 0x11, 0x11,
881 0x10, 0x03, 0x01, 0x10,
882 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
883 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
884 0xea,
885 0x10, 0x0b, 0x01, 0x19,
886 0x10, 0x0d, 0x01, 0x10,
887 0x10, 0x0c, 0x01, 0x1e,
888 0x04, 0x06, 0x01, 0x03,
889 0x04, 0x04, 0x01, 0x00,
890 0, 0, 0
891};
892
893/* 06a5:d001 - nw801 - Sony
894 * Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */
895/*fixme: 320x240 only*/
896static const u8 ds3303_start[] = {
897 0x05, 0x06, 0x01, 0x04,
898 0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
899 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
900 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
901 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
902 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
903 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
904 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
905 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
906 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
907 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
908 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
909 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
910 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
911 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
912 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
913 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
914 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
915 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00,
916 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
917 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
918 0x36, 0x00,
919 0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
920 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50,
921 0x40, 0x20,
922 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
923 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
924 0x06, 0x00, 0x02, 0x09, 0x99,
925 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927 0x00, 0x00, 0x00, 0x00, 0x00,
928 0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
929 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
930 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
931 0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20,
933 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00,
934 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03,
935 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
936 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
937 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88,
938 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb,
939 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
940 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
941 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
942 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
943 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
944 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
945 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01,
946 0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02,
947 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
948 0xf0, 0x00,
949
950 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
951 0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81,
952 0x40,
953 0x10, 0x1a, 0x01, 0x15,
954 0x10, 0x00, 0x01, 0x2f,
955 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
956 0x10, 0x1b, 0x02, 0x00, 0x00,
957 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
958 0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
959 0x10, 0x24, 0x02, 0x40, 0x06,
960 0x10, 0x0e, 0x01, 0x08,
961 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
962 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
963 0xf9,
964 0x10, 0x03, 0x01, 0x00,
965 0x10, 0x0f, 0x02, 0x16, 0x16,
966 0x10, 0x03, 0x01, 0x0c,
967 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
968 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
969 0xf9,
970 0x10, 0x0b, 0x01, 0x26,
971 0x10, 0x0d, 0x01, 0x10,
972 0x10, 0x0c, 0x01, 0x1c,
973 0x05, 0x06, 0x01, 0x03,
974 0x05, 0x04, 0x01, 0x00,
975 0, 0, 0
976};
977
978/* 06a5:d001 - nw802 - Panasonic
979 * GP-KR651US (Philips TDA8786) */
980static const u8 kr651_start_1[] = {
981 0x04, 0x06, 0x01, 0x04,
982 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48,
983 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
984 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
985 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
986 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
987 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
988 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
989 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
990 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
991 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
992 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
993 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
994 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
995 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
996 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
997 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
998 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
999 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1000 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
1001 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
1002 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1003 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1004 0x40, 0x20,
1005 0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
1006 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
1007 0x06, 0x00, 0x02, 0x09, 0x99,
1008 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1012 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1013 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
1015 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1016 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1017 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1018 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1019 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1020 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1021 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1022 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1023 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1024 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1025 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1026 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1027 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
1029 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1030 0x01, 0xf0, 0x00,
1031 0, 0, 0
1032};
1033static const u8 kr651_start_qvga[] = {
1034 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
1035 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
1036 0x40,
1037 0x10, 0x1a, 0x01, 0x03,
1038 0x10, 0x00, 0x01, 0xac,
1039 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1040 0x10, 0x1b, 0x02, 0x00, 0x00,
1041 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
1042 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
1043 0x10, 0x1d, 0x02, 0x28, 0x01,
1044 0, 0, 0
1045};
1046static const u8 kr651_start_vga[] = {
1047 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
1048 0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98,
1049 0x80,
1050 0x10, 0x1a, 0x01, 0x03,
1051 0x10, 0x00, 0x01, 0xa0,
1052 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
1053 0x10, 0x1b, 0x02, 0x00, 0x00,
1054 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
1055 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
1056 0x10, 0x1d, 0x02, 0x68, 0x00,
1057};
1058static const u8 kr651_start_2[] = {
1059 0x10, 0x0e, 0x01, 0x08,
1060 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
1061 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
1062 0xdc,
1063 0x10, 0x03, 0x01, 0x00,
1064 0x10, 0x0f, 0x02, 0x0c, 0x0c,
1065 0x10, 0x03, 0x01, 0x0c,
1066 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
1067 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
1068 0xdc,
1069 0x10, 0x0b, 0x01, 0x10,
1070 0x10, 0x0d, 0x01, 0x10,
1071 0x10, 0x0c, 0x01, 0x2d,
1072 0x04, 0x06, 0x01, 0x03,
1073 0x04, 0x04, 0x01, 0x00,
1074 0, 0, 0
1075};
1076
1077/* nw802 - iRez Kritter cam */
1078static const u8 kritter_start[] = {
1079 0x04, 0x06, 0x01, 0x06,
1080 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48,
1081 0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19,
1082 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1083 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28,
1084 0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
1085 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1086 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
1087 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1088 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
1089 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1090 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
1091 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1092 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
1093 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
1095 0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30,
1096 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
1097 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1098 0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
1099 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
1100 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1101 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1102 0x40, 0x20,
1103 0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
1104 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
1105 0x06, 0x00, 0x02, 0x09, 0x99,
1106 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0x00,
1109 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1111 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
1113 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1114 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1115 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1116 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1117 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1118 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1119 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1120 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1121 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1122 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1123 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1124 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1125 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82,
1127 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1128 0x01, 0xf0, 0x00,
1129 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
1130 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
1131 0x40,
1132 0x10, 0x1a, 0x01, 0x03,
1133 0x10, 0x00, 0x01, 0xaf,
1134 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1135 0x10, 0x1b, 0x02, 0x3b, 0x01,
1136 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
1137 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
1138 0x10, 0x1d, 0x02, 0x00, 0x00,
1139 0x10, 0x0e, 0x01, 0x08,
1140 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
1141 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
1142 0xcb,
1143 0x10, 0x03, 0x01, 0x00,
1144 0x10, 0x0f, 0x02, 0x0d, 0x0d,
1145 0x10, 0x03, 0x01, 0x02,
1146 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
1147 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
1148 0xcb,
1149 0x10, 0x0b, 0x01, 0x17,
1150 0x10, 0x0d, 0x01, 0x10,
1151 0x10, 0x0c, 0x01, 0x1e,
1152 0x04, 0x06, 0x01, 0x03,
1153 0x04, 0x04, 0x01, 0x00,
1154 0, 0, 0
1155};
1156
1157/* nw802 - Mustek Wcam 300 mini */
1158static const u8 mustek_start[] = {
1159 0x04, 0x06, 0x01, 0x04,
1160 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
1161 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
1162 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1163 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
1164 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
1165 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
1166 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
1167 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
1168 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1169 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1170 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1171 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1172 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
1173 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1174 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
1175 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
1176 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1178 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
1179 0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06,
1180 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1181 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1182 0x40, 0x20,
1183 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1184 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
1185 0x06, 0x00, 0x02, 0x09, 0x99,
1186 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x00,
1189 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00,
1190 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1191 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1192 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
1193 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
1194 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1195 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1196 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1197 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1198 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1199 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1200 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1201 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1202 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1203 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1204 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1205 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1206 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82,
1207 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1208 0x01, 0xf0, 0x00,
1209 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
1210 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
1211 0x40,
1212 0x10, 0x1a, 0x01, 0x00,
1213 0x10, 0x00, 0x01, 0xad,
1214 0x00, 0x00, 0x01, 0x08,
1215 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1216 0x10, 0x1b, 0x02, 0x00, 0x00,
1217 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1218 0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
1219 0x10, 0x0e, 0x01, 0x0f,
1220 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
1221 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
1222 0xff,
1223 0x10, 0x0f, 0x02, 0x11, 0x11,
1224 0x10, 0x03, 0x01, 0x0c,
1225 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
1226 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
1227 0xff,
1228 0x10, 0x0b, 0x01, 0x1c,
1229 0x10, 0x0d, 0x01, 0x1a,
1230 0x10, 0x0c, 0x01, 0x34,
1231 0x04, 0x05, 0x01, 0x61,
1232 0x04, 0x04, 0x01, 0x40,
1233 0x04, 0x06, 0x01, 0x03,
1234 0, 0, 0
1235};
1236
1237/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */
1238static const u8 proscope_init[] = {
1239 0x04, 0x05, 0x01, 0x21,
1240 0x04, 0x04, 0x01, 0x01,
1241 0, 0, 0
1242};
1243static const u8 proscope_start_1[] = {
1244 0x04, 0x06, 0x01, 0x04,
1245 0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04,
1246 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
1247 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1248 0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4,
1249 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
1250 0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86,
1251 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
1252 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
1253 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6,
1254 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1255 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1256 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1257 0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34,
1258 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8,
1260 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
1261 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1263 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94,
1264 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
1265 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1266 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1267 0x40, 0x20,
1268 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1269 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
1270 0x06, 0x00, 0x02, 0x09, 0x99,
1271 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
1276 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
1277 0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01,
1278 0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
1279 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1280 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1281 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1282 0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f,
1283 0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4,
1284 0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1285 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1286 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1287 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1288 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1289 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1290 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f,
1291 0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82,
1292 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1293 0x01, 0xf0, 0x00,
1294 0, 0, 0
1295};
1296static const u8 proscope_start_qvga[] = {
1297 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
1298 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
1299 0x40,
1300 0x10, 0x1a, 0x01, 0x06,
1301 0x00, 0x03, 0x02, 0xf9, 0x02,
1302 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1303 0x10, 0x1b, 0x02, 0x00, 0x00,
1304 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1305 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
1306 0x10, 0x0e, 0x01, 0x10,
1307 0, 0, 0
1308};
1309static const u8 proscope_start_vga[] = {
1310 0x00, 0x03, 0x02, 0xf9, 0x02,
1311 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
1312 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
1313 0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00,
1314 0x80,
1315 0x10, 0x1a, 0x01, 0x06,
1316 0x10, 0x00, 0x01, 0xa1,
1317 0x10, 0x1b, 0x02, 0x00, 0x00,
1318 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
1319 0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
1320 0x10, 0x0e, 0x01, 0x10,
1321 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
1322 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
1323 0xf9,
1324 0x10, 0x03, 0x01, 0x00,
1325 0, 0, 0
1326};
1327static const u8 proscope_start_2[] = {
1328 0x10, 0x0f, 0x02, 0x0c, 0x0c,
1329 0x10, 0x03, 0x01, 0x0c,
1330 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
1331 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
1332 0xf9,
1333 0x10, 0x0b, 0x01, 0x0b,
1334 0x10, 0x0d, 0x01, 0x10,
1335 0x10, 0x0c, 0x01, 0x1b,
1336 0x04, 0x06, 0x01, 0x03,
1337 0x04, 0x05, 0x01, 0x21,
1338 0x04, 0x04, 0x01, 0x00,
1339 0, 0, 0
1340};
1341
1342/* nw800 - hv7121b? (seems pas106) - Divio Chicony TwinkleCam */
1343static const u8 twinkle_start[] = {
1344 0x04, 0x06, 0x01, 0x44,
1345 0x04, 0x06, 0x01, 0x00,
1346 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
1347 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
1348 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1349 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
1350 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
1351 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
1352 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
1353 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
1354 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1355 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1356 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
1357 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
1358 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
1359 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1360 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
1361 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
1362 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
1363 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
1364 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
1365 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
1366 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1367 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1368 0x40, 0x20,
1369 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1370 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
1371 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
1372 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1375 0x00, 0x00, 0x00,
1376 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08,
1381 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1384 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1385 0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06,
1386 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80,
1387 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1388 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1389 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1390 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1391 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1392 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1393 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1394 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1395 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
1397 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
1398 0x01, 0x60, 0x01, 0x00, 0x00,
1399
1400 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
1401 0x04, 0x04, 0x01, 0x10,
1402 0x04, 0x04, 0x01, 0x00,
1403 0x04, 0x05, 0x01, 0x61,
1404 0x04, 0x04, 0x01, 0x01,
1405 I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00,
1406 0x00, 0x00, 0x00, 0x0a,
1407 I2C0, 0x40, 0x02, 0x11, 0x06,
1408 I2C0, 0x40, 0x02, 0x14, 0x00,
1409 I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */
1410 I2C0, 0x40, 0x02, 0x07, 0x01,
1411 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
1412 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
1413 0x40,
1414 I2C0, 0x40, 0x02, 0x02, 0x0c,
1415 I2C0, 0x40, 0x02, 0x13, 0x01,
1416 0x10, 0x00, 0x01, 0x01,
1417 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
1418 0x20, 0x01, 0x60, 0x01,
1419 I2C0, 0x40, 0x02, 0x05, 0x0f,
1420 I2C0, 0x40, 0x02, 0x13, 0x01,
1421 I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17,
1422 I2C0, 0x40, 0x03, 0x12, 0x00, 0x01,
1423 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
1424 I2C0, 0x40, 0x02, 0x12, 0x00,
1425 I2C0, 0x40, 0x02, 0x0e, 0x00,
1426 I2C0, 0x40, 0x02, 0x11, 0x06,
1427 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
1428 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
1429 0xf9,
1430 0x10, 0x03, 0x01, 0x00,
1431 0x10, 0x0f, 0x02, 0x0c, 0x0c,
1432 0x10, 0x03, 0x01, 0x06,
1433 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
1434 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
1435 0xf9,
1436 0x10, 0x0b, 0x01, 0x19,
1437 0x10, 0x0d, 0x01, 0x10,
1438 0x10, 0x0c, 0x01, 0x0d,
1439 0x04, 0x06, 0x01, 0x03,
1440 0x04, 0x05, 0x01, 0x61,
1441 0x04, 0x04, 0x01, 0x41,
1442 0, 0, 0
1443};
1444
1445/* nw802 dvc-v6 */
1446static const u8 dvcv6_start[] = {
1447 0x04, 0x06, 0x01, 0x06,
1448 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
1449 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
1450 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
1451 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
1452 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
1453 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1454 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
1455 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1456 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
1457 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1458 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
1459 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
1460 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
1461 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
1462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
1463 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
1464 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
1465 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
1466 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
1467 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
1468 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
1469 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
1470 0x40, 0x20,
1471 0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
1472 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
1473 0x06, 0x00, 0x02, 0x09, 0x99,
1474 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1476 0x00, 0x00, 0x00, 0x00, 0x00,
1477 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
1478 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
1479 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1480 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
1481 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
1482 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
1483 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
1484 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
1485 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
1486 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
1487 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
1488 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
1489 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
1490 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
1491 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
1492 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
1493 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
1494 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
1495 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
1496 0x01, 0xf0, 0x00,
1497 0x00, 0x03, 0x02, 0x94, 0x03,
1498 0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07,
1499 0x00, 0x7b, 0x02, 0xe0, 0x00,
1500 0x10, 0x8d, 0x01, 0x00,
1501 0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02,
1502 0x00, 0x91, 0x02, 0x0b, 0x02,
1503 0x10, 0x00, 0x01, 0xaf,
1504 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00,
1505 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
1506 0x40,
1507 0x10, 0x1a, 0x01, 0x02,
1508 0x10, 0x00, 0x01, 0xaf,
1509 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
1510 0x10, 0x1b, 0x02, 0x07, 0x01,
1511 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
1512 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
1513 0x10, 0x1d, 0x02, 0x40, 0x06,
1514 0x10, 0x0e, 0x01, 0x08,
1515 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
1516 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
1517 0xdc,
1518 0x10, 0x03, 0x01, 0x00,
1519 0x10, 0x0f, 0x02, 0x12, 0x12,
1520 0x10, 0x03, 0x01, 0x11,
1521 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
1522 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
1523 0xdc,
1524 0x10, 0x0b, 0x01, 0x16,
1525 0x10, 0x0d, 0x01, 0x10,
1526 0x10, 0x0c, 0x01, 0x1a,
1527 0x04, 0x06, 0x01, 0x03,
1528 0x04, 0x04, 0x01, 0x00,
1529};
1530
1531static const u8 *webcam_start[] = {
1532 [Generic800] = nw800_start,
1533 [SpaceCam] = spacecam_start,
1534 [SpaceCam2] = spacecam2_start,
1535 [Cvideopro] = cvideopro_start,
1536 [Dlink350c] = dlink_start,
1537 [DS3303u] = ds3303_start,
1538 [Kr651us] = kr651_start_1,
1539 [Kritter] = kritter_start,
1540 [Mustek300] = mustek_start,
1541 [Proscope] = proscope_start_1,
1542 [Twinkle] = twinkle_start,
1543 [DvcV6] = dvcv6_start,
1544 [P35u] = nw801_start_1,
1545 [Generic802] = nw802_start,
1546};
1547
1548/* -- write a register -- */
1549static void reg_w(struct gspca_dev *gspca_dev,
1550 u16 index,
1551 const u8 *data,
1552 int len)
1553{
1554 struct usb_device *dev = gspca_dev->dev;
1555 int ret;
1556
1557 if (gspca_dev->usb_err < 0)
1558 return;
1559 if (len == 1)
1560 PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data);
1561 else
1562 PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...",
1563 index, *data, data[1]);
1564 memcpy(gspca_dev->usb_buf, data, len);
1565 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1566 0x00,
1567 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1568 0x00, /* value */
1569 index,
1570 gspca_dev->usb_buf,
1571 len,
1572 500);
1573 if (ret < 0) {
1574 err("reg_w err %d", ret);
1575 gspca_dev->usb_err = ret;
1576 }
1577}
1578
1579/* -- read registers in usb_buf -- */
1580static void reg_r(struct gspca_dev *gspca_dev,
1581 u16 index,
1582 int len)
1583{
1584 struct usb_device *dev = gspca_dev->dev;
1585 int ret;
1586
1587 if (gspca_dev->usb_err < 0)
1588 return;
1589 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1590 0x00,
1591 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1592 0x00, index,
1593 gspca_dev->usb_buf, len, 500);
1594 if (ret < 0) {
1595 err("reg_r err %d", ret);
1596 gspca_dev->usb_err = ret;
1597 return;
1598 }
1599 if (len == 1)
1600 PDEBUG(D_USBI, "GET 00 0000 %04x %02x",
1601 index, gspca_dev->usb_buf[0]);
1602 else
1603 PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..",
1604 index, gspca_dev->usb_buf[0],
1605 gspca_dev->usb_buf[1]);
1606}
1607
1608static void i2c_w(struct gspca_dev *gspca_dev,
1609 u8 i2c_addr,
1610 const u8 *data,
1611 int len)
1612{
1613 u8 val[2];
1614 int i;
1615
1616 reg_w(gspca_dev, 0x0600, data + 1, len - 1);
1617 reg_w(gspca_dev, 0x0600, data, len);
1618 val[0] = len;
1619 val[1] = i2c_addr;
1620 reg_w(gspca_dev, 0x0502, val, 2);
1621 val[0] = 0x01;
1622 reg_w(gspca_dev, 0x0501, val, 1);
1623 for (i = 5; --i >= 0; ) {
1624 msleep(4);
1625 reg_r(gspca_dev, 0x0505, 1);
1626 if (gspca_dev->usb_err < 0)
1627 return;
1628 if (gspca_dev->usb_buf[0] == 0)
1629 return;
1630 }
1631 gspca_dev->usb_err = -ETIME;
1632}
1633
1634static void reg_w_buf(struct gspca_dev *gspca_dev,
1635 const u8 *cmd)
1636{
1637 u16 reg;
1638 int len;
1639
1640 for (;;) {
1641 reg = *cmd++ << 8;
1642 reg += *cmd++;
1643 len = *cmd++;
1644 if (len == 0)
1645 break;
1646 if (cmd[-3] != I2C0)
1647 reg_w(gspca_dev, reg, cmd, len);
1648 else
1649 i2c_w(gspca_dev, reg, cmd, len);
1650 cmd += len;
1651 }
1652}
1653
1654static int swap_bits(int v)
1655{
1656 int r, i;
1657
1658 r = 0;
1659 for (i = 0; i < 8; i++) {
1660 r <<= 1;
1661 if (v & 1)
1662 r++;
1663 v >>= 1;
1664 }
1665 return r;
1666}
1667
1668static void setgain(struct gspca_dev *gspca_dev)
1669{
1670 struct sd *sd = (struct sd *) gspca_dev;
1671 u8 val, v[2];
1672
1673 val = sd->ctrls[GAIN].val;
1674 switch (sd->webcam) {
1675 case P35u:
1676 /* Note the control goes from 0-255 not 0-127, but anything
1677 above 127 just means amplifying noise */
1678 val >>= 1; /* 0 - 255 -> 0 - 127 */
1679 reg_w(gspca_dev, 0x1026, &val, 1);
1680 break;
1681 case Kr651us:
1682 /* 0 - 253 */
1683 val = swap_bits(val);
1684 v[0] = val << 3;
1685 v[1] = val >> 5;
1686 reg_w(gspca_dev, 0x101d, v, 2); /* SIF reg0/1 (AGC) */
1687 break;
1688 }
1689}
1690
1691static void setexposure(struct gspca_dev *gspca_dev)
1692{
1693 struct sd *sd = (struct sd *) gspca_dev;
1694 s16 val;
1695 u8 v[2];
1696
1697 val = sd->ctrls[EXPOSURE].val;
1698 switch (sd->webcam) {
1699 case P35u:
1700 v[0] = ((9 - val) << 3) | 0x01;
1701 reg_w(gspca_dev, 0x1019, v, 1);
1702 break;
1703 case Cvideopro:
1704 case DvcV6:
1705 case Kritter:
1706 case Kr651us:
1707 v[0] = val;
1708 v[1] = val >> 8;
1709 reg_w(gspca_dev, 0x101b, v, 2);
1710 break;
1711 }
1712}
1713
1714static void setautogain(struct gspca_dev *gspca_dev)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717 int w, h;
1718
1719 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
1720 return;
1721 if (!sd->ctrls[AUTOGAIN].val) {
1722 sd->ag_cnt = -1;
1723 return;
1724 }
1725 sd->ag_cnt = AG_CNT_START;
1726
1727 reg_r(gspca_dev, 0x1004, 1);
1728 if (gspca_dev->usb_buf[0] & 0x04) { /* if AE_FULL_FRM */
1729 sd->ae_res = gspca_dev->width * gspca_dev->height;
1730 } else { /* get the AE window size */
1731 reg_r(gspca_dev, 0x1011, 8);
1732 w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]
1733 - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2];
1734 h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4]
1735 - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6];
1736 sd->ae_res = h * w;
1737 if (sd->ae_res == 0)
1738 sd->ae_res = gspca_dev->width * gspca_dev->height;
1739 }
1740}
1741
1742static int nw802_test_reg(struct gspca_dev *gspca_dev,
1743 u16 index,
1744 u8 value)
1745{
1746 /* write the value */
1747 reg_w(gspca_dev, index, &value, 1);
1748
1749 /* read it */
1750 reg_r(gspca_dev, index, 1);
1751
1752 return gspca_dev->usb_buf[0] == value;
1753}
1754
1755/* this function is called at probe time */
1756static int sd_config(struct gspca_dev *gspca_dev,
1757 const struct usb_device_id *id)
1758{
1759 struct sd *sd = (struct sd *) gspca_dev;
1760
1761 if ((unsigned) webcam >= NWEBCAMS)
1762 webcam = 0;
1763 sd->webcam = webcam;
1764 gspca_dev->cam.reverse_alts = 1;
1765 gspca_dev->cam.ctrls = sd->ctrls;
1766 sd->ag_cnt = -1;
1767
1768 /*
1769 * Autodetect sequence inspired from some log.
1770 * We try to detect what registers exist or not.
1771 * If 0x0500 does not exist => NW802
1772 * If it does, test 0x109b. If it doesn't exist,
1773 * then it's a NW801. Else, a NW800
1774 * If a et31x110 (nw800 and 06a5:d800)
1775 * get the sensor ID
1776 */
1777 if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) {
1778 sd->bridge = BRIDGE_NW802;
1779 if (sd->webcam == Generic800)
1780 sd->webcam = Generic802;
1781 } else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) {
1782 sd->bridge = BRIDGE_NW801;
1783 if (sd->webcam == Generic800)
1784 sd->webcam = P35u;
1785 } else if (id->idVendor == 0x06a5 && id->idProduct == 0xd800) {
1786 reg_r(gspca_dev, 0x0403, 1); /* GPIO */
1787 PDEBUG(D_PROBE, "et31x110 sensor type %02x",
1788 gspca_dev->usb_buf[0]);
1789 switch (gspca_dev->usb_buf[0] >> 1) {
1790 case 0x00: /* ?? */
1791 if (sd->webcam == Generic800)
1792 sd->webcam = SpaceCam;
1793 break;
1794 case 0x01: /* Hynix? */
1795 if (sd->webcam == Generic800)
1796 sd->webcam = Twinkle;
1797 break;
1798 case 0x0a: /* Pixart */
1799 if (sd->webcam == Generic800)
1800 sd->webcam = SpaceCam2;
1801 break;
1802 }
1803 }
1804 if (webcam_chip[sd->webcam] != sd->bridge) {
1805 err("Bad webcam type %d for NW80%d", sd->webcam, sd->bridge);
1806 gspca_dev->usb_err = -ENODEV;
1807 return gspca_dev->usb_err;
1808 }
1809 PDEBUG(D_PROBE, "Bridge nw80%d - type: %d", sd->bridge, sd->webcam);
1810
1811 if (sd->bridge == BRIDGE_NW800) {
1812 switch (sd->webcam) {
1813 case DS3303u:
1814 gspca_dev->cam.cam_mode = cif_mode; /* qvga */
1815 break;
1816 default:
1817 gspca_dev->cam.cam_mode = &cif_mode[1]; /* cif */
1818 break;
1819 }
1820 gspca_dev->cam.nmodes = 1;
1821 } else {
1822 gspca_dev->cam.cam_mode = vga_mode;
1823 switch (sd->webcam) {
1824 case Kr651us:
1825 case Proscope:
1826 case P35u:
1827 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
1828 break;
1829 default:
1830 gspca_dev->cam.nmodes = 1; /* qvga only */
1831 break;
1832 }
1833 }
1834 switch (sd->webcam) {
1835 case P35u:
1836/* sd->ctrls[EXPOSURE].max = 9;
1837 * sd->ctrls[EXPOSURE].def = 9; */
1838 /* coarse expo auto gain function gain minimum, to avoid
1839 * a large settings jump the first auto adjustment */
1840 sd->ctrls[GAIN].def = 255 / 5 * 2;
1841 break;
1842 case Cvideopro:
1843 case DvcV6:
1844 case Kritter:
1845 gspca_dev->ctrl_dis = (1 << GAIN) | (1 << AUTOGAIN);
1846 /* fall thru */
1847 case Kr651us:
1848 sd->ctrls[EXPOSURE].max = 315;
1849 sd->ctrls[EXPOSURE].def = 150;
1850 break;
1851 default:
1852 gspca_dev->ctrl_dis = (1 << GAIN) | (1 << EXPOSURE)
1853 | (1 << AUTOGAIN);
1854 break;
1855 }
1856
1857#if AUTOGAIN_DEF
1858 if (!(gspca_dev->ctrl_dis & (1 << AUTOGAIN)))
1859 gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
1860#endif
1861 return gspca_dev->usb_err;
1862}
1863
1864/* this function is called at probe and resume time */
1865static int sd_init(struct gspca_dev *gspca_dev)
1866{
1867 struct sd *sd = (struct sd *) gspca_dev;
1868
1869 switch (sd->bridge) {
1870 case BRIDGE_NW800:
1871 switch (sd->webcam) {
1872 case SpaceCam:
1873 reg_w_buf(gspca_dev, spacecam_init);
1874 break;
1875 default:
1876 reg_w_buf(gspca_dev, nw800_init);
1877 break;
1878 }
1879 break;
1880 default:
1881 switch (sd->webcam) {
1882 case Mustek300:
1883 case P35u:
1884 case Proscope:
1885 reg_w_buf(gspca_dev, proscope_init);
1886 break;
1887 }
1888 break;
1889 }
1890 return gspca_dev->usb_err;
1891}
1892
1893/* -- start the camera -- */
1894static int sd_start(struct gspca_dev *gspca_dev)
1895{
1896 struct sd *sd = (struct sd *) gspca_dev;
1897 const u8 *cmd;
1898
1899 cmd = webcam_start[sd->webcam];
1900 reg_w_buf(gspca_dev, cmd);
1901 switch (sd->webcam) {
1902 case P35u:
1903 if (gspca_dev->width == 320)
1904 reg_w_buf(gspca_dev, nw801_start_qvga);
1905 else
1906 reg_w_buf(gspca_dev, nw801_start_vga);
1907 reg_w_buf(gspca_dev, nw801_start_2);
1908 break;
1909 case Kr651us:
1910 if (gspca_dev->width == 320)
1911 reg_w_buf(gspca_dev, kr651_start_qvga);
1912 else
1913 reg_w_buf(gspca_dev, kr651_start_vga);
1914 reg_w_buf(gspca_dev, kr651_start_2);
1915 break;
1916 case Proscope:
1917 if (gspca_dev->width == 320)
1918 reg_w_buf(gspca_dev, proscope_start_qvga);
1919 else
1920 reg_w_buf(gspca_dev, proscope_start_vga);
1921 reg_w_buf(gspca_dev, proscope_start_2);
1922 break;
1923 }
1924
1925 setgain(gspca_dev);
1926 setexposure(gspca_dev);
1927 setautogain(gspca_dev);
1928 sd->exp_too_high_cnt = 0;
1929 sd->exp_too_low_cnt = 0;
1930 return gspca_dev->usb_err;
1931}
1932
1933static void sd_stopN(struct gspca_dev *gspca_dev)
1934{
1935 struct sd *sd = (struct sd *) gspca_dev;
1936 u8 value;
1937
1938 /* 'go' off */
1939 if (sd->bridge != BRIDGE_NW801) {
1940 value = 0x02;
1941 reg_w(gspca_dev, 0x0406, &value, 1);
1942 }
1943
1944 /* LED off */
1945 switch (sd->webcam) {
1946 case Cvideopro:
1947 case Kr651us:
1948 case DvcV6:
1949 case Kritter:
1950 value = 0xff;
1951 break;
1952 case Dlink350c:
1953 value = 0x21;
1954 break;
1955 case SpaceCam:
1956 case SpaceCam2:
1957 case Proscope:
1958 case Twinkle:
1959 value = 0x01;
1960 break;
1961 default:
1962 return;
1963 }
1964 reg_w(gspca_dev, 0x0404, &value, 1);
1965}
1966
1967static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1968 u8 *data, /* isoc packet */
1969 int len) /* iso packet length */
1970{
1971 /*
1972 * frame header = '00 00 hh ww ss xx ff ff'
1973 * with:
1974 * - 'hh': height / 4
1975 * - 'ww': width / 4
1976 * - 'ss': frame sequence number c0..dd
1977 */
1978 if (data[0] == 0x00 && data[1] == 0x00
1979 && data[6] == 0xff && data[7] == 0xff) {
1980 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1981 gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8);
1982 } else {
1983 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1984 }
1985}
1986
1987static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1988{
1989 struct sd *sd = (struct sd *) gspca_dev;
1990
1991 sd->ctrls[AUTOGAIN].val = val;
1992 if (val)
1993 gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
1994 else
1995 gspca_dev->ctrl_inac = 0;
1996 if (gspca_dev->streaming)
1997 setautogain(gspca_dev);
1998 return gspca_dev->usb_err;
1999}
2000
2001#include "autogain_functions.h"
2002
2003static void do_autogain(struct gspca_dev *gspca_dev)
2004{
2005 struct sd *sd = (struct sd *) gspca_dev;
2006 int luma;
2007
2008 if (sd->ag_cnt < 0)
2009 return;
2010 if (--sd->ag_cnt >= 0)
2011 return;
2012 sd->ag_cnt = AG_CNT_START;
2013
2014 /* get the average luma */
2015 reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4);
2016 luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16)
2017 + (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
2018 luma /= sd->ae_res;
2019
2020 switch (sd->webcam) {
2021 case P35u:
2022 coarse_grained_expo_autogain(gspca_dev, luma, 100, 5);
2023 break;
2024 default:
2025 auto_gain_n_exposure(gspca_dev, luma, 100, 5, 230, 0);
2026 break;
2027 }
2028}
2029
2030/* V4L2 controls supported by the driver */
2031static const struct ctrl sd_ctrls[NCTRLS] = {
2032[GAIN] = {
2033 {
2034 .id = V4L2_CID_GAIN,
2035 .type = V4L2_CTRL_TYPE_INTEGER,
2036 .name = "Gain",
2037 .minimum = 0,
2038 .maximum = 253,
2039 .step = 1,
2040 .default_value = 128
2041 },
2042 .set_control = setgain
2043 },
2044[EXPOSURE] = {
2045 {
2046 .id = V4L2_CID_EXPOSURE,
2047 .type = V4L2_CTRL_TYPE_INTEGER,
2048 .name = "Exposure",
2049 .minimum = 0,
2050 .maximum = 9,
2051 .step = 1,
2052 .default_value = 9
2053 },
2054 .set_control = setexposure
2055 },
2056[AUTOGAIN] = {
2057 {
2058 .id = V4L2_CID_AUTOGAIN,
2059 .type = V4L2_CTRL_TYPE_BOOLEAN,
2060 .name = "Auto Gain",
2061 .minimum = 0,
2062 .maximum = 1,
2063 .step = 1,
2064 .default_value = AUTOGAIN_DEF,
2065 .flags = V4L2_CTRL_FLAG_UPDATE
2066 },
2067 .set = sd_setautogain
2068 },
2069};
2070
2071/* sub-driver description */
2072static const struct sd_desc sd_desc = {
2073 .name = MODULE_NAME,
2074 .ctrls = sd_ctrls,
2075 .nctrls = ARRAY_SIZE(sd_ctrls),
2076 .config = sd_config,
2077 .init = sd_init,
2078 .start = sd_start,
2079 .stopN = sd_stopN,
2080 .pkt_scan = sd_pkt_scan,
2081 .dq_callback = do_autogain,
2082};
2083
2084/* -- module initialisation -- */
2085static const struct usb_device_id device_table[] = {
2086 {USB_DEVICE(0x046d, 0xd001)},
2087 {USB_DEVICE(0x0502, 0xd001)},
2088 {USB_DEVICE(0x052b, 0xd001)},
2089 {USB_DEVICE(0x055f, 0xd001)},
2090 {USB_DEVICE(0x06a5, 0x0000)},
2091 {USB_DEVICE(0x06a5, 0xd001)},
2092 {USB_DEVICE(0x06a5, 0xd800)},
2093 {USB_DEVICE(0x06be, 0xd001)},
2094 {USB_DEVICE(0x0728, 0xd001)},
2095 {}
2096};
2097MODULE_DEVICE_TABLE(usb, device_table);
2098
2099/* -- device connect -- */
2100static int sd_probe(struct usb_interface *intf,
2101 const struct usb_device_id *id)
2102{
2103 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2104 THIS_MODULE);
2105}
2106
2107static struct usb_driver sd_driver = {
2108 .name = MODULE_NAME,
2109 .id_table = device_table,
2110 .probe = sd_probe,
2111 .disconnect = gspca_disconnect,
2112#ifdef CONFIG_PM
2113 .suspend = gspca_suspend,
2114 .resume = gspca_resume,
2115#endif
2116};
2117
2118/* -- module insert / remove -- */
2119static int __init sd_mod_init(void)
2120{
2121 return usb_register(&sd_driver);
2122}
2123static void __exit sd_mod_exit(void)
2124{
2125 usb_deregister(&sd_driver);
2126}
2127
2128module_init(sd_mod_init);
2129module_exit(sd_mod_exit);
2130
2131module_param(webcam, int, 0644);
2132MODULE_PARM_DESC(webcam,
2133 "Webcam type\n"
2134 "0: generic\n"
2135 "1: Trust 120 SpaceCam\n"
2136 "2: other Trust 120 SpaceCam\n"
2137 "3: Conceptronic Video Pro\n"
2138 "4: D-link dru-350c\n"
2139 "5: Plustek Opticam 500U\n"
2140 "6: Panasonic GP-KR651US\n"
2141 "7: iRez Kritter\n"
2142 "8: Mustek Wcam 300 mini\n"
2143 "9: Scalar USB Microscope M2 (Proscope)\n"
2144 "10: Divio Chicony TwinkleCam\n"
2145 "11: DVC-V6\n");
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
new file mode 100644
index 00000000000..18305c89083
--- /dev/null
+++ b/drivers/media/video/gspca/ov519.c
@@ -0,0 +1,5072 @@
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#define MODULE_NAME "ov519"
40
41#include <linux/input.h>
42#include "gspca.h"
43
44/* The jpeg_hdr is used by w996Xcf only */
45/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */
46#define CONEX_CAM
47#include "jpeg.h"
48
49MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
50MODULE_DESCRIPTION("OV519 USB Camera Driver");
51MODULE_LICENSE("GPL");
52
53/* global parameters */
54static int frame_rate;
55
56/* Number of times to retry a failed I2C transaction. Increase this if you
57 * are getting "Failed to read sensor ID..." */
58static int i2c_detect_tries = 10;
59
60/* controls */
61enum e_ctrl {
62 BRIGHTNESS,
63 CONTRAST,
64 EXPOSURE,
65 COLORS,
66 HFLIP,
67 VFLIP,
68 AUTOBRIGHT,
69 AUTOGAIN,
70 FREQ,
71 NCTRL /* number of controls */
72};
73
74/* ov519 device descriptor */
75struct sd {
76 struct gspca_dev gspca_dev; /* !! must be the first item */
77
78 struct gspca_ctrl ctrls[NCTRL];
79
80 u8 packet_nr;
81
82 char bridge;
83#define BRIDGE_OV511 0
84#define BRIDGE_OV511PLUS 1
85#define BRIDGE_OV518 2
86#define BRIDGE_OV518PLUS 3
87#define BRIDGE_OV519 4 /* = ov530 */
88#define BRIDGE_OVFX2 5
89#define BRIDGE_W9968CF 6
90#define BRIDGE_MASK 7
91
92 char invert_led;
93#define BRIDGE_INVERT_LED 8
94
95 char snapshot_pressed;
96 char snapshot_needs_reset;
97
98 /* Determined by sensor type */
99 u8 sif;
100
101 u8 quality;
102#define QUALITY_MIN 50
103#define QUALITY_MAX 70
104#define QUALITY_DEF 50
105
106 u8 stopped; /* Streaming is temporarily paused */
107 u8 first_frame;
108
109 u8 frame_rate; /* current Framerate */
110 u8 clockdiv; /* clockdiv override */
111
112 s8 sensor; /* Type of image sensor chip (SEN_*) */
113
114 u8 sensor_addr;
115 u16 sensor_width;
116 u16 sensor_height;
117 s16 sensor_reg_cache[256];
118
119 u8 jpeg_hdr[JPEG_HDR_SZ];
120};
121enum sensors {
122 SEN_OV2610,
123 SEN_OV2610AE,
124 SEN_OV3610,
125 SEN_OV6620,
126 SEN_OV6630,
127 SEN_OV66308AF,
128 SEN_OV7610,
129 SEN_OV7620,
130 SEN_OV7620AE,
131 SEN_OV7640,
132 SEN_OV7648,
133 SEN_OV7660,
134 SEN_OV7670,
135 SEN_OV76BE,
136 SEN_OV8610,
137 SEN_OV9600,
138};
139
140/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
141 the ov sensors which is already present here. When we have the time we
142 really should move the sensor drivers to v4l2 sub drivers. */
143#include "w996Xcf.c"
144
145/* V4L2 controls supported by the driver */
146static void setbrightness(struct gspca_dev *gspca_dev);
147static void setcontrast(struct gspca_dev *gspca_dev);
148static void setexposure(struct gspca_dev *gspca_dev);
149static void setcolors(struct gspca_dev *gspca_dev);
150static void sethvflip(struct gspca_dev *gspca_dev);
151static void setautobright(struct gspca_dev *gspca_dev);
152static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
153static void setfreq(struct gspca_dev *gspca_dev);
154static void setfreq_i(struct sd *sd);
155
156static const struct ctrl sd_ctrls[] = {
157[BRIGHTNESS] = {
158 {
159 .id = V4L2_CID_BRIGHTNESS,
160 .type = V4L2_CTRL_TYPE_INTEGER,
161 .name = "Brightness",
162 .minimum = 0,
163 .maximum = 255,
164 .step = 1,
165 .default_value = 127,
166 },
167 .set_control = setbrightness,
168 },
169[CONTRAST] = {
170 {
171 .id = V4L2_CID_CONTRAST,
172 .type = V4L2_CTRL_TYPE_INTEGER,
173 .name = "Contrast",
174 .minimum = 0,
175 .maximum = 255,
176 .step = 1,
177 .default_value = 127,
178 },
179 .set_control = setcontrast,
180 },
181[EXPOSURE] = {
182 {
183 .id = V4L2_CID_EXPOSURE,
184 .type = V4L2_CTRL_TYPE_INTEGER,
185 .name = "Exposure",
186 .minimum = 0,
187 .maximum = 255,
188 .step = 1,
189 .default_value = 127,
190 },
191 .set_control = setexposure,
192 },
193[COLORS] = {
194 {
195 .id = V4L2_CID_SATURATION,
196 .type = V4L2_CTRL_TYPE_INTEGER,
197 .name = "Color",
198 .minimum = 0,
199 .maximum = 255,
200 .step = 1,
201 .default_value = 127,
202 },
203 .set_control = setcolors,
204 },
205/* The flip controls work for sensors ov7660 and ov7670 only */
206[HFLIP] = {
207 {
208 .id = V4L2_CID_HFLIP,
209 .type = V4L2_CTRL_TYPE_BOOLEAN,
210 .name = "Mirror",
211 .minimum = 0,
212 .maximum = 1,
213 .step = 1,
214 .default_value = 0,
215 },
216 .set_control = sethvflip,
217 },
218[VFLIP] = {
219 {
220 .id = V4L2_CID_VFLIP,
221 .type = V4L2_CTRL_TYPE_BOOLEAN,
222 .name = "Vflip",
223 .minimum = 0,
224 .maximum = 1,
225 .step = 1,
226 .default_value = 0,
227 },
228 .set_control = sethvflip,
229 },
230[AUTOBRIGHT] = {
231 {
232 .id = V4L2_CID_AUTOBRIGHTNESS,
233 .type = V4L2_CTRL_TYPE_BOOLEAN,
234 .name = "Auto Brightness",
235 .minimum = 0,
236 .maximum = 1,
237 .step = 1,
238 .default_value = 1,
239 },
240 .set_control = setautobright,
241 },
242[AUTOGAIN] = {
243 {
244 .id = V4L2_CID_AUTOGAIN,
245 .type = V4L2_CTRL_TYPE_BOOLEAN,
246 .name = "Auto Gain",
247 .minimum = 0,
248 .maximum = 1,
249 .step = 1,
250 .default_value = 1,
251 .flags = V4L2_CTRL_FLAG_UPDATE
252 },
253 .set = sd_setautogain,
254 },
255[FREQ] = {
256 {
257 .id = V4L2_CID_POWER_LINE_FREQUENCY,
258 .type = V4L2_CTRL_TYPE_MENU,
259 .name = "Light frequency filter",
260 .minimum = 0,
261 .maximum = 2, /* 0: no flicker, 1: 50Hz, 2:60Hz, 3: auto */
262 .step = 1,
263 .default_value = 0,
264 },
265 .set_control = setfreq,
266 },
267};
268
269/* table of the disabled controls */
270static const unsigned ctrl_dis[] = {
271[SEN_OV2610] = ((1 << NCTRL) - 1) /* no control */
272 ^ ((1 << EXPOSURE) /* but exposure */
273 | (1 << AUTOGAIN)), /* and autogain */
274
275[SEN_OV2610AE] = ((1 << NCTRL) - 1) /* no control */
276 ^ ((1 << EXPOSURE) /* but exposure */
277 | (1 << AUTOGAIN)), /* and autogain */
278
279[SEN_OV3610] = (1 << NCTRL) - 1, /* no control */
280
281[SEN_OV6620] = (1 << HFLIP) |
282 (1 << VFLIP) |
283 (1 << EXPOSURE) |
284 (1 << AUTOGAIN),
285
286[SEN_OV6630] = (1 << HFLIP) |
287 (1 << VFLIP) |
288 (1 << EXPOSURE) |
289 (1 << AUTOGAIN),
290
291[SEN_OV66308AF] = (1 << HFLIP) |
292 (1 << VFLIP) |
293 (1 << EXPOSURE) |
294 (1 << AUTOGAIN),
295
296[SEN_OV7610] = (1 << HFLIP) |
297 (1 << VFLIP) |
298 (1 << EXPOSURE) |
299 (1 << AUTOGAIN),
300
301[SEN_OV7620] = (1 << HFLIP) |
302 (1 << VFLIP) |
303 (1 << EXPOSURE) |
304 (1 << AUTOGAIN),
305
306[SEN_OV7620AE] = (1 << HFLIP) |
307 (1 << VFLIP) |
308 (1 << EXPOSURE) |
309 (1 << AUTOGAIN),
310
311[SEN_OV7640] = (1 << HFLIP) |
312 (1 << VFLIP) |
313 (1 << AUTOBRIGHT) |
314 (1 << CONTRAST) |
315 (1 << EXPOSURE) |
316 (1 << AUTOGAIN),
317
318[SEN_OV7648] = (1 << HFLIP) |
319 (1 << VFLIP) |
320 (1 << AUTOBRIGHT) |
321 (1 << CONTRAST) |
322 (1 << EXPOSURE) |
323 (1 << AUTOGAIN),
324
325[SEN_OV7660] = (1 << AUTOBRIGHT) |
326 (1 << EXPOSURE) |
327 (1 << AUTOGAIN),
328
329[SEN_OV7670] = (1 << COLORS) |
330 (1 << AUTOBRIGHT) |
331 (1 << EXPOSURE) |
332 (1 << AUTOGAIN),
333
334[SEN_OV76BE] = (1 << HFLIP) |
335 (1 << VFLIP) |
336 (1 << EXPOSURE) |
337 (1 << AUTOGAIN),
338
339[SEN_OV8610] = (1 << HFLIP) |
340 (1 << VFLIP) |
341 (1 << EXPOSURE) |
342 (1 << AUTOGAIN) |
343 (1 << FREQ),
344[SEN_OV9600] = ((1 << NCTRL) - 1) /* no control */
345 ^ ((1 << EXPOSURE) /* but exposure */
346 | (1 << AUTOGAIN)), /* and autogain */
347
348};
349
350static const struct v4l2_pix_format ov519_vga_mode[] = {
351 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
352 .bytesperline = 320,
353 .sizeimage = 320 * 240 * 3 / 8 + 590,
354 .colorspace = V4L2_COLORSPACE_JPEG,
355 .priv = 1},
356 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
357 .bytesperline = 640,
358 .sizeimage = 640 * 480 * 3 / 8 + 590,
359 .colorspace = V4L2_COLORSPACE_JPEG,
360 .priv = 0},
361};
362static const struct v4l2_pix_format ov519_sif_mode[] = {
363 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
364 .bytesperline = 160,
365 .sizeimage = 160 * 120 * 3 / 8 + 590,
366 .colorspace = V4L2_COLORSPACE_JPEG,
367 .priv = 3},
368 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
369 .bytesperline = 176,
370 .sizeimage = 176 * 144 * 3 / 8 + 590,
371 .colorspace = V4L2_COLORSPACE_JPEG,
372 .priv = 1},
373 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
374 .bytesperline = 320,
375 .sizeimage = 320 * 240 * 3 / 8 + 590,
376 .colorspace = V4L2_COLORSPACE_JPEG,
377 .priv = 2},
378 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
379 .bytesperline = 352,
380 .sizeimage = 352 * 288 * 3 / 8 + 590,
381 .colorspace = V4L2_COLORSPACE_JPEG,
382 .priv = 0},
383};
384
385/* Note some of the sizeimage values for the ov511 / ov518 may seem
386 larger then necessary, however they need to be this big as the ov511 /
387 ov518 always fills the entire isoc frame, using 0 padding bytes when
388 it doesn't have any data. So with low framerates the amount of data
389 transferred can become quite large (libv4l will remove all the 0 padding
390 in userspace). */
391static const struct v4l2_pix_format ov518_vga_mode[] = {
392 {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
393 .bytesperline = 320,
394 .sizeimage = 320 * 240 * 3,
395 .colorspace = V4L2_COLORSPACE_JPEG,
396 .priv = 1},
397 {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
398 .bytesperline = 640,
399 .sizeimage = 640 * 480 * 2,
400 .colorspace = V4L2_COLORSPACE_JPEG,
401 .priv = 0},
402};
403static const struct v4l2_pix_format ov518_sif_mode[] = {
404 {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
405 .bytesperline = 160,
406 .sizeimage = 70000,
407 .colorspace = V4L2_COLORSPACE_JPEG,
408 .priv = 3},
409 {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
410 .bytesperline = 176,
411 .sizeimage = 70000,
412 .colorspace = V4L2_COLORSPACE_JPEG,
413 .priv = 1},
414 {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
415 .bytesperline = 320,
416 .sizeimage = 320 * 240 * 3,
417 .colorspace = V4L2_COLORSPACE_JPEG,
418 .priv = 2},
419 {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
420 .bytesperline = 352,
421 .sizeimage = 352 * 288 * 3,
422 .colorspace = V4L2_COLORSPACE_JPEG,
423 .priv = 0},
424};
425
426static const struct v4l2_pix_format ov511_vga_mode[] = {
427 {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
428 .bytesperline = 320,
429 .sizeimage = 320 * 240 * 3,
430 .colorspace = V4L2_COLORSPACE_JPEG,
431 .priv = 1},
432 {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
433 .bytesperline = 640,
434 .sizeimage = 640 * 480 * 2,
435 .colorspace = V4L2_COLORSPACE_JPEG,
436 .priv = 0},
437};
438static const struct v4l2_pix_format ov511_sif_mode[] = {
439 {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
440 .bytesperline = 160,
441 .sizeimage = 70000,
442 .colorspace = V4L2_COLORSPACE_JPEG,
443 .priv = 3},
444 {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
445 .bytesperline = 176,
446 .sizeimage = 70000,
447 .colorspace = V4L2_COLORSPACE_JPEG,
448 .priv = 1},
449 {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
450 .bytesperline = 320,
451 .sizeimage = 320 * 240 * 3,
452 .colorspace = V4L2_COLORSPACE_JPEG,
453 .priv = 2},
454 {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
455 .bytesperline = 352,
456 .sizeimage = 352 * 288 * 3,
457 .colorspace = V4L2_COLORSPACE_JPEG,
458 .priv = 0},
459};
460
461static const struct v4l2_pix_format ovfx2_vga_mode[] = {
462 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
463 .bytesperline = 320,
464 .sizeimage = 320 * 240,
465 .colorspace = V4L2_COLORSPACE_SRGB,
466 .priv = 1},
467 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
468 .bytesperline = 640,
469 .sizeimage = 640 * 480,
470 .colorspace = V4L2_COLORSPACE_SRGB,
471 .priv = 0},
472};
473static const struct v4l2_pix_format ovfx2_cif_mode[] = {
474 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
475 .bytesperline = 160,
476 .sizeimage = 160 * 120,
477 .colorspace = V4L2_COLORSPACE_SRGB,
478 .priv = 3},
479 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
480 .bytesperline = 176,
481 .sizeimage = 176 * 144,
482 .colorspace = V4L2_COLORSPACE_SRGB,
483 .priv = 1},
484 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
485 .bytesperline = 320,
486 .sizeimage = 320 * 240,
487 .colorspace = V4L2_COLORSPACE_SRGB,
488 .priv = 2},
489 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
490 .bytesperline = 352,
491 .sizeimage = 352 * 288,
492 .colorspace = V4L2_COLORSPACE_SRGB,
493 .priv = 0},
494};
495static const struct v4l2_pix_format ovfx2_ov2610_mode[] = {
496 {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
497 .bytesperline = 800,
498 .sizeimage = 800 * 600,
499 .colorspace = V4L2_COLORSPACE_SRGB,
500 .priv = 1},
501 {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
502 .bytesperline = 1600,
503 .sizeimage = 1600 * 1200,
504 .colorspace = V4L2_COLORSPACE_SRGB},
505};
506static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
507 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
508 .bytesperline = 640,
509 .sizeimage = 640 * 480,
510 .colorspace = V4L2_COLORSPACE_SRGB,
511 .priv = 1},
512 {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
513 .bytesperline = 800,
514 .sizeimage = 800 * 600,
515 .colorspace = V4L2_COLORSPACE_SRGB,
516 .priv = 1},
517 {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
518 .bytesperline = 1024,
519 .sizeimage = 1024 * 768,
520 .colorspace = V4L2_COLORSPACE_SRGB,
521 .priv = 1},
522 {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
523 .bytesperline = 1600,
524 .sizeimage = 1600 * 1200,
525 .colorspace = V4L2_COLORSPACE_SRGB,
526 .priv = 0},
527 {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
528 .bytesperline = 2048,
529 .sizeimage = 2048 * 1536,
530 .colorspace = V4L2_COLORSPACE_SRGB,
531 .priv = 0},
532};
533static const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
534 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
535 .bytesperline = 640,
536 .sizeimage = 640 * 480,
537 .colorspace = V4L2_COLORSPACE_SRGB,
538 .priv = 1},
539 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
540 .bytesperline = 1280,
541 .sizeimage = 1280 * 1024,
542 .colorspace = V4L2_COLORSPACE_SRGB},
543};
544
545/* Registers common to OV511 / OV518 */
546#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */
547#define R51x_SYS_RESET 0x50
548 /* Reset type flags */
549 #define OV511_RESET_OMNICE 0x08
550#define R51x_SYS_INIT 0x53
551#define R51x_SYS_SNAP 0x52
552#define R51x_SYS_CUST_ID 0x5f
553#define R51x_COMP_LUT_BEGIN 0x80
554
555/* OV511 Camera interface register numbers */
556#define R511_CAM_DELAY 0x10
557#define R511_CAM_EDGE 0x11
558#define R511_CAM_PXCNT 0x12
559#define R511_CAM_LNCNT 0x13
560#define R511_CAM_PXDIV 0x14
561#define R511_CAM_LNDIV 0x15
562#define R511_CAM_UV_EN 0x16
563#define R511_CAM_LINE_MODE 0x17
564#define R511_CAM_OPTS 0x18
565
566#define R511_SNAP_FRAME 0x19
567#define R511_SNAP_PXCNT 0x1a
568#define R511_SNAP_LNCNT 0x1b
569#define R511_SNAP_PXDIV 0x1c
570#define R511_SNAP_LNDIV 0x1d
571#define R511_SNAP_UV_EN 0x1e
572#define R511_SNAP_OPTS 0x1f
573
574#define R511_DRAM_FLOW_CTL 0x20
575#define R511_FIFO_OPTS 0x31
576#define R511_I2C_CTL 0x40
577#define R511_SYS_LED_CTL 0x55 /* OV511+ only */
578#define R511_COMP_EN 0x78
579#define R511_COMP_LUT_EN 0x79
580
581/* OV518 Camera interface register numbers */
582#define R518_GPIO_OUT 0x56 /* OV518(+) only */
583#define R518_GPIO_CTL 0x57 /* OV518(+) only */
584
585/* OV519 Camera interface register numbers */
586#define OV519_R10_H_SIZE 0x10
587#define OV519_R11_V_SIZE 0x11
588#define OV519_R12_X_OFFSETL 0x12
589#define OV519_R13_X_OFFSETH 0x13
590#define OV519_R14_Y_OFFSETL 0x14
591#define OV519_R15_Y_OFFSETH 0x15
592#define OV519_R16_DIVIDER 0x16
593#define OV519_R20_DFR 0x20
594#define OV519_R25_FORMAT 0x25
595
596/* OV519 System Controller register numbers */
597#define OV519_R51_RESET1 0x51
598#define OV519_R54_EN_CLK1 0x54
599#define OV519_R57_SNAPSHOT 0x57
600
601#define OV519_GPIO_DATA_OUT0 0x71
602#define OV519_GPIO_IO_CTRL0 0x72
603
604/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */
605
606/*
607 * The FX2 chip does not give us a zero length read at end of frame.
608 * It does, however, give a short read at the end of a frame, if
609 * necessary, rather than run two frames together.
610 *
611 * By choosing the right bulk transfer size, we are guaranteed to always
612 * get a short read for the last read of each frame. Frame sizes are
613 * always a composite number (width * height, or a multiple) so if we
614 * choose a prime number, we are guaranteed that the last read of a
615 * frame will be short.
616 *
617 * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB,
618 * otherwise EOVERFLOW "babbling" errors occur. I have not been able
619 * to figure out why. [PMiller]
620 *
621 * The constant (13 * 4096) is the largest "prime enough" number less than 64KB.
622 *
623 * It isn't enough to know the number of bytes per frame, in case we
624 * have data dropouts or buffer overruns (even though the FX2 double
625 * buffers, there are some pretty strict real time constraints for
626 * isochronous transfer for larger frame sizes).
627 */
628/*jfm: this value does not work for 800x600 - see isoc_init */
629#define OVFX2_BULK_SIZE (13 * 4096)
630
631/* I2C registers */
632#define R51x_I2C_W_SID 0x41
633#define R51x_I2C_SADDR_3 0x42
634#define R51x_I2C_SADDR_2 0x43
635#define R51x_I2C_R_SID 0x44
636#define R51x_I2C_DATA 0x45
637#define R518_I2C_CTL 0x47 /* OV518(+) only */
638#define OVFX2_I2C_ADDR 0x00
639
640/* I2C ADDRESSES */
641#define OV7xx0_SID 0x42
642#define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */
643#define OV8xx0_SID 0xa0
644#define OV6xx0_SID 0xc0
645
646/* OV7610 registers */
647#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
648#define OV7610_REG_BLUE 0x01 /* blue channel balance */
649#define OV7610_REG_RED 0x02 /* red channel balance */
650#define OV7610_REG_SAT 0x03 /* saturation */
651#define OV8610_REG_HUE 0x04 /* 04 reserved */
652#define OV7610_REG_CNT 0x05 /* Y contrast */
653#define OV7610_REG_BRT 0x06 /* Y brightness */
654#define OV7610_REG_COM_C 0x14 /* misc common regs */
655#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
656#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
657#define OV7610_REG_COM_I 0x29 /* misc settings */
658
659/* OV7660 and OV7670 registers */
660#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
661#define OV7670_R01_BLUE 0x01 /* blue gain */
662#define OV7670_R02_RED 0x02 /* red gain */
663#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */
664#define OV7670_R04_COM1 0x04 /* Control 1 */
665/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */
666#define OV7670_R0C_COM3 0x0c /* Control 3 */
667#define OV7670_R0D_COM4 0x0d /* Control 4 */
668#define OV7670_R0E_COM5 0x0e /* All "reserved" */
669#define OV7670_R0F_COM6 0x0f /* Control 6 */
670#define OV7670_R10_AECH 0x10 /* More bits of AEC value */
671#define OV7670_R11_CLKRC 0x11 /* Clock control */
672#define OV7670_R12_COM7 0x12 /* Control 7 */
673#define OV7670_COM7_FMT_VGA 0x00
674/*#define OV7670_COM7_YUV 0x00 * YUV */
675#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */
676#define OV7670_COM7_FMT_MASK 0x38
677#define OV7670_COM7_RESET 0x80 /* Register reset */
678#define OV7670_R13_COM8 0x13 /* Control 8 */
679#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */
680#define OV7670_COM8_AWB 0x02 /* White balance enable */
681#define OV7670_COM8_AGC 0x04 /* Auto gain enable */
682#define OV7670_COM8_BFILT 0x20 /* Band filter enable */
683#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */
684#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
685#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */
686#define OV7670_R15_COM10 0x15 /* Control 10 */
687#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */
688#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */
689#define OV7670_R19_VSTART 0x19 /* Vert start high bits */
690#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */
691#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */
692#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */
693#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
694#define OV7670_R24_AEW 0x24 /* AGC upper limit */
695#define OV7670_R25_AEB 0x25 /* AGC lower limit */
696#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */
697#define OV7670_R32_HREF 0x32 /* HREF pieces */
698#define OV7670_R3A_TSLB 0x3a /* lots of stuff */
699#define OV7670_R3B_COM11 0x3b /* Control 11 */
700#define OV7670_COM11_EXP 0x02
701#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
702#define OV7670_R3C_COM12 0x3c /* Control 12 */
703#define OV7670_R3D_COM13 0x3d /* Control 13 */
704#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */
705#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */
706#define OV7670_R3E_COM14 0x3e /* Control 14 */
707#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */
708#define OV7670_R40_COM15 0x40 /* Control 15 */
709/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */
710#define OV7670_R41_COM16 0x41 /* Control 16 */
711#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */
712/* end of ov7660 common registers */
713#define OV7670_R55_BRIGHT 0x55 /* Brightness */
714#define OV7670_R56_CONTRAS 0x56 /* Contrast control */
715#define OV7670_R69_GFIX 0x69 /* Fix gain control */
716/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */
717#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */
718#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */
719#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */
720#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */
721#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */
722#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */
723#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */
724#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */
725#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */
726
727struct ov_regvals {
728 u8 reg;
729 u8 val;
730};
731struct ov_i2c_regvals {
732 u8 reg;
733 u8 val;
734};
735
736/* Settings for OV2610 camera chip */
737static const struct ov_i2c_regvals norm_2610[] = {
738 { 0x12, 0x80 }, /* reset */
739};
740
741static const struct ov_i2c_regvals norm_2610ae[] = {
742 {0x12, 0x80}, /* reset */
743 {0x13, 0xcd},
744 {0x09, 0x01},
745 {0x0d, 0x00},
746 {0x11, 0x80},
747 {0x12, 0x20}, /* 1600x1200 */
748 {0x33, 0x0c},
749 {0x35, 0x90},
750 {0x36, 0x37},
751/* ms-win traces */
752 {0x11, 0x83}, /* clock / 3 ? */
753 {0x2d, 0x00}, /* 60 Hz filter */
754 {0x24, 0xb0}, /* normal colors */
755 {0x25, 0x90},
756 {0x10, 0x43},
757};
758
759static const struct ov_i2c_regvals norm_3620b[] = {
760 /*
761 * From the datasheet: "Note that after writing to register COMH
762 * (0x12) to change the sensor mode, registers related to the
763 * sensor’s cropping window will be reset back to their default
764 * values."
765 *
766 * "wait 4096 external clock ... to make sure the sensor is
767 * stable and ready to access registers" i.e. 160us at 24MHz
768 */
769 { 0x12, 0x80 }, /* COMH reset */
770 { 0x12, 0x00 }, /* QXGA, master */
771
772 /*
773 * 11 CLKRC "Clock Rate Control"
774 * [7] internal frequency doublers: on
775 * [6] video port mode: master
776 * [5:0] clock divider: 1
777 */
778 { 0x11, 0x80 },
779
780 /*
781 * 13 COMI "Common Control I"
782 * = 192 (0xC0) 11000000
783 * COMI[7] "AEC speed selection"
784 * = 1 (0x01) 1....... "Faster AEC correction"
785 * COMI[6] "AEC speed step selection"
786 * = 1 (0x01) .1...... "Big steps, fast"
787 * COMI[5] "Banding filter on off"
788 * = 0 (0x00) ..0..... "Off"
789 * COMI[4] "Banding filter option"
790 * = 0 (0x00) ...0.... "Main clock is 48 MHz and
791 * the PLL is ON"
792 * COMI[3] "Reserved"
793 * = 0 (0x00) ....0...
794 * COMI[2] "AGC auto manual control selection"
795 * = 0 (0x00) .....0.. "Manual"
796 * COMI[1] "AWB auto manual control selection"
797 * = 0 (0x00) ......0. "Manual"
798 * COMI[0] "Exposure control"
799 * = 0 (0x00) .......0 "Manual"
800 */
801 { 0x13, 0xc0 },
802
803 /*
804 * 09 COMC "Common Control C"
805 * = 8 (0x08) 00001000
806 * COMC[7:5] "Reserved"
807 * = 0 (0x00) 000.....
808 * COMC[4] "Sleep Mode Enable"
809 * = 0 (0x00) ...0.... "Normal mode"
810 * COMC[3:2] "Sensor sampling reset timing selection"
811 * = 2 (0x02) ....10.. "Longer reset time"
812 * COMC[1:0] "Output drive current select"
813 * = 0 (0x00) ......00 "Weakest"
814 */
815 { 0x09, 0x08 },
816
817 /*
818 * 0C COMD "Common Control D"
819 * = 8 (0x08) 00001000
820 * COMD[7] "Reserved"
821 * = 0 (0x00) 0.......
822 * COMD[6] "Swap MSB and LSB at the output port"
823 * = 0 (0x00) .0...... "False"
824 * COMD[5:3] "Reserved"
825 * = 1 (0x01) ..001...
826 * COMD[2] "Output Average On Off"
827 * = 0 (0x00) .....0.. "Output Normal"
828 * COMD[1] "Sensor precharge voltage selection"
829 * = 0 (0x00) ......0. "Selects internal
830 * reference precharge
831 * voltage"
832 * COMD[0] "Snapshot option"
833 * = 0 (0x00) .......0 "Enable live video output
834 * after snapshot sequence"
835 */
836 { 0x0c, 0x08 },
837
838 /*
839 * 0D COME "Common Control E"
840 * = 161 (0xA1) 10100001
841 * COME[7] "Output average option"
842 * = 1 (0x01) 1....... "Output average of 4 pixels"
843 * COME[6] "Anti-blooming control"
844 * = 0 (0x00) .0...... "Off"
845 * COME[5:3] "Reserved"
846 * = 4 (0x04) ..100...
847 * COME[2] "Clock output power down pin status"
848 * = 0 (0x00) .....0.. "Tri-state data output pin
849 * on power down"
850 * COME[1] "Data output pin status selection at power down"
851 * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK,
852 * HREF, and CHSYNC pins on
853 * power down"
854 * COME[0] "Auto zero circuit select"
855 * = 1 (0x01) .......1 "On"
856 */
857 { 0x0d, 0xa1 },
858
859 /*
860 * 0E COMF "Common Control F"
861 * = 112 (0x70) 01110000
862 * COMF[7] "System clock selection"
863 * = 0 (0x00) 0....... "Use 24 MHz system clock"
864 * COMF[6:4] "Reserved"
865 * = 7 (0x07) .111....
866 * COMF[3] "Manual auto negative offset canceling selection"
867 * = 0 (0x00) ....0... "Auto detect negative
868 * offset and cancel it"
869 * COMF[2:0] "Reserved"
870 * = 0 (0x00) .....000
871 */
872 { 0x0e, 0x70 },
873
874 /*
875 * 0F COMG "Common Control G"
876 * = 66 (0x42) 01000010
877 * COMG[7] "Optical black output selection"
878 * = 0 (0x00) 0....... "Disable"
879 * COMG[6] "Black level calibrate selection"
880 * = 1 (0x01) .1...... "Use optical black pixels
881 * to calibrate"
882 * COMG[5:4] "Reserved"
883 * = 0 (0x00) ..00....
884 * COMG[3] "Channel offset adjustment"
885 * = 0 (0x00) ....0... "Disable offset adjustment"
886 * COMG[2] "ADC black level calibration option"
887 * = 0 (0x00) .....0.. "Use B/G line and G/R
888 * line to calibrate each
889 * channel's black level"
890 * COMG[1] "Reserved"
891 * = 1 (0x01) ......1.
892 * COMG[0] "ADC black level calibration enable"
893 * = 0 (0x00) .......0 "Disable"
894 */
895 { 0x0f, 0x42 },
896
897 /*
898 * 14 COMJ "Common Control J"
899 * = 198 (0xC6) 11000110
900 * COMJ[7:6] "AGC gain ceiling"
901 * = 3 (0x03) 11...... "8x"
902 * COMJ[5:4] "Reserved"
903 * = 0 (0x00) ..00....
904 * COMJ[3] "Auto banding filter"
905 * = 0 (0x00) ....0... "Banding filter is always
906 * on off depending on
907 * COMI[5] setting"
908 * COMJ[2] "VSYNC drop option"
909 * = 1 (0x01) .....1.. "SYNC is dropped if frame
910 * data is dropped"
911 * COMJ[1] "Frame data drop"
912 * = 1 (0x01) ......1. "Drop frame data if
913 * exposure is not within
914 * tolerance. In AEC mode,
915 * data is normally dropped
916 * when data is out of
917 * range."
918 * COMJ[0] "Reserved"
919 * = 0 (0x00) .......0
920 */
921 { 0x14, 0xc6 },
922
923 /*
924 * 15 COMK "Common Control K"
925 * = 2 (0x02) 00000010
926 * COMK[7] "CHSYNC pin output swap"
927 * = 0 (0x00) 0....... "CHSYNC"
928 * COMK[6] "HREF pin output swap"
929 * = 0 (0x00) .0...... "HREF"
930 * COMK[5] "PCLK output selection"
931 * = 0 (0x00) ..0..... "PCLK always output"
932 * COMK[4] "PCLK edge selection"
933 * = 0 (0x00) ...0.... "Data valid on falling edge"
934 * COMK[3] "HREF output polarity"
935 * = 0 (0x00) ....0... "positive"
936 * COMK[2] "Reserved"
937 * = 0 (0x00) .....0..
938 * COMK[1] "VSYNC polarity"
939 * = 1 (0x01) ......1. "negative"
940 * COMK[0] "HSYNC polarity"
941 * = 0 (0x00) .......0 "positive"
942 */
943 { 0x15, 0x02 },
944
945 /*
946 * 33 CHLF "Current Control"
947 * = 9 (0x09) 00001001
948 * CHLF[7:6] "Sensor current control"
949 * = 0 (0x00) 00......
950 * CHLF[5] "Sensor current range control"
951 * = 0 (0x00) ..0..... "normal range"
952 * CHLF[4] "Sensor current"
953 * = 0 (0x00) ...0.... "normal current"
954 * CHLF[3] "Sensor buffer current control"
955 * = 1 (0x01) ....1... "half current"
956 * CHLF[2] "Column buffer current control"
957 * = 0 (0x00) .....0.. "normal current"
958 * CHLF[1] "Analog DSP current control"
959 * = 0 (0x00) ......0. "normal current"
960 * CHLF[1] "ADC current control"
961 * = 0 (0x00) ......0. "normal current"
962 */
963 { 0x33, 0x09 },
964
965 /*
966 * 34 VBLM "Blooming Control"
967 * = 80 (0x50) 01010000
968 * VBLM[7] "Hard soft reset switch"
969 * = 0 (0x00) 0....... "Hard reset"
970 * VBLM[6:4] "Blooming voltage selection"
971 * = 5 (0x05) .101....
972 * VBLM[3:0] "Sensor current control"
973 * = 0 (0x00) ....0000
974 */
975 { 0x34, 0x50 },
976
977 /*
978 * 36 VCHG "Sensor Precharge Voltage Control"
979 * = 0 (0x00) 00000000
980 * VCHG[7] "Reserved"
981 * = 0 (0x00) 0.......
982 * VCHG[6:4] "Sensor precharge voltage control"
983 * = 0 (0x00) .000....
984 * VCHG[3:0] "Sensor array common reference"
985 * = 0 (0x00) ....0000
986 */
987 { 0x36, 0x00 },
988
989 /*
990 * 37 ADC "ADC Reference Control"
991 * = 4 (0x04) 00000100
992 * ADC[7:4] "Reserved"
993 * = 0 (0x00) 0000....
994 * ADC[3] "ADC input signal range"
995 * = 0 (0x00) ....0... "Input signal 1.0x"
996 * ADC[2:0] "ADC range control"
997 * = 4 (0x04) .....100
998 */
999 { 0x37, 0x04 },
1000
1001 /*
1002 * 38 ACOM "Analog Common Ground"
1003 * = 82 (0x52) 01010010
1004 * ACOM[7] "Analog gain control"
1005 * = 0 (0x00) 0....... "Gain 1x"
1006 * ACOM[6] "Analog black level calibration"
1007 * = 1 (0x01) .1...... "On"
1008 * ACOM[5:0] "Reserved"
1009 * = 18 (0x12) ..010010
1010 */
1011 { 0x38, 0x52 },
1012
1013 /*
1014 * 3A FREFA "Internal Reference Adjustment"
1015 * = 0 (0x00) 00000000
1016 * FREFA[7:0] "Range"
1017 * = 0 (0x00) 00000000
1018 */
1019 { 0x3a, 0x00 },
1020
1021 /*
1022 * 3C FVOPT "Internal Reference Adjustment"
1023 * = 31 (0x1F) 00011111
1024 * FVOPT[7:0] "Range"
1025 * = 31 (0x1F) 00011111
1026 */
1027 { 0x3c, 0x1f },
1028
1029 /*
1030 * 44 Undocumented = 0 (0x00) 00000000
1031 * 44[7:0] "It's a secret"
1032 * = 0 (0x00) 00000000
1033 */
1034 { 0x44, 0x00 },
1035
1036 /*
1037 * 40 Undocumented = 0 (0x00) 00000000
1038 * 40[7:0] "It's a secret"
1039 * = 0 (0x00) 00000000
1040 */
1041 { 0x40, 0x00 },
1042
1043 /*
1044 * 41 Undocumented = 0 (0x00) 00000000
1045 * 41[7:0] "It's a secret"
1046 * = 0 (0x00) 00000000
1047 */
1048 { 0x41, 0x00 },
1049
1050 /*
1051 * 42 Undocumented = 0 (0x00) 00000000
1052 * 42[7:0] "It's a secret"
1053 * = 0 (0x00) 00000000
1054 */
1055 { 0x42, 0x00 },
1056
1057 /*
1058 * 43 Undocumented = 0 (0x00) 00000000
1059 * 43[7:0] "It's a secret"
1060 * = 0 (0x00) 00000000
1061 */
1062 { 0x43, 0x00 },
1063
1064 /*
1065 * 45 Undocumented = 128 (0x80) 10000000
1066 * 45[7:0] "It's a secret"
1067 * = 128 (0x80) 10000000
1068 */
1069 { 0x45, 0x80 },
1070
1071 /*
1072 * 48 Undocumented = 192 (0xC0) 11000000
1073 * 48[7:0] "It's a secret"
1074 * = 192 (0xC0) 11000000
1075 */
1076 { 0x48, 0xc0 },
1077
1078 /*
1079 * 49 Undocumented = 25 (0x19) 00011001
1080 * 49[7:0] "It's a secret"
1081 * = 25 (0x19) 00011001
1082 */
1083 { 0x49, 0x19 },
1084
1085 /*
1086 * 4B Undocumented = 128 (0x80) 10000000
1087 * 4B[7:0] "It's a secret"
1088 * = 128 (0x80) 10000000
1089 */
1090 { 0x4b, 0x80 },
1091
1092 /*
1093 * 4D Undocumented = 196 (0xC4) 11000100
1094 * 4D[7:0] "It's a secret"
1095 * = 196 (0xC4) 11000100
1096 */
1097 { 0x4d, 0xc4 },
1098
1099 /*
1100 * 35 VREF "Reference Voltage Control"
1101 * = 76 (0x4c) 01001100
1102 * VREF[7:5] "Column high reference control"
1103 * = 2 (0x02) 010..... "higher voltage"
1104 * VREF[4:2] "Column low reference control"
1105 * = 3 (0x03) ...011.. "Highest voltage"
1106 * VREF[1:0] "Reserved"
1107 * = 0 (0x00) ......00
1108 */
1109 { 0x35, 0x4c },
1110
1111 /*
1112 * 3D Undocumented = 0 (0x00) 00000000
1113 * 3D[7:0] "It's a secret"
1114 * = 0 (0x00) 00000000
1115 */
1116 { 0x3d, 0x00 },
1117
1118 /*
1119 * 3E Undocumented = 0 (0x00) 00000000
1120 * 3E[7:0] "It's a secret"
1121 * = 0 (0x00) 00000000
1122 */
1123 { 0x3e, 0x00 },
1124
1125 /*
1126 * 3B FREFB "Internal Reference Adjustment"
1127 * = 24 (0x18) 00011000
1128 * FREFB[7:0] "Range"
1129 * = 24 (0x18) 00011000
1130 */
1131 { 0x3b, 0x18 },
1132
1133 /*
1134 * 33 CHLF "Current Control"
1135 * = 25 (0x19) 00011001
1136 * CHLF[7:6] "Sensor current control"
1137 * = 0 (0x00) 00......
1138 * CHLF[5] "Sensor current range control"
1139 * = 0 (0x00) ..0..... "normal range"
1140 * CHLF[4] "Sensor current"
1141 * = 1 (0x01) ...1.... "double current"
1142 * CHLF[3] "Sensor buffer current control"
1143 * = 1 (0x01) ....1... "half current"
1144 * CHLF[2] "Column buffer current control"
1145 * = 0 (0x00) .....0.. "normal current"
1146 * CHLF[1] "Analog DSP current control"
1147 * = 0 (0x00) ......0. "normal current"
1148 * CHLF[1] "ADC current control"
1149 * = 0 (0x00) ......0. "normal current"
1150 */
1151 { 0x33, 0x19 },
1152
1153 /*
1154 * 34 VBLM "Blooming Control"
1155 * = 90 (0x5A) 01011010
1156 * VBLM[7] "Hard soft reset switch"
1157 * = 0 (0x00) 0....... "Hard reset"
1158 * VBLM[6:4] "Blooming voltage selection"
1159 * = 5 (0x05) .101....
1160 * VBLM[3:0] "Sensor current control"
1161 * = 10 (0x0A) ....1010
1162 */
1163 { 0x34, 0x5a },
1164
1165 /*
1166 * 3B FREFB "Internal Reference Adjustment"
1167 * = 0 (0x00) 00000000
1168 * FREFB[7:0] "Range"
1169 * = 0 (0x00) 00000000
1170 */
1171 { 0x3b, 0x00 },
1172
1173 /*
1174 * 33 CHLF "Current Control"
1175 * = 9 (0x09) 00001001
1176 * CHLF[7:6] "Sensor current control"
1177 * = 0 (0x00) 00......
1178 * CHLF[5] "Sensor current range control"
1179 * = 0 (0x00) ..0..... "normal range"
1180 * CHLF[4] "Sensor current"
1181 * = 0 (0x00) ...0.... "normal current"
1182 * CHLF[3] "Sensor buffer current control"
1183 * = 1 (0x01) ....1... "half current"
1184 * CHLF[2] "Column buffer current control"
1185 * = 0 (0x00) .....0.. "normal current"
1186 * CHLF[1] "Analog DSP current control"
1187 * = 0 (0x00) ......0. "normal current"
1188 * CHLF[1] "ADC current control"
1189 * = 0 (0x00) ......0. "normal current"
1190 */
1191 { 0x33, 0x09 },
1192
1193 /*
1194 * 34 VBLM "Blooming Control"
1195 * = 80 (0x50) 01010000
1196 * VBLM[7] "Hard soft reset switch"
1197 * = 0 (0x00) 0....... "Hard reset"
1198 * VBLM[6:4] "Blooming voltage selection"
1199 * = 5 (0x05) .101....
1200 * VBLM[3:0] "Sensor current control"
1201 * = 0 (0x00) ....0000
1202 */
1203 { 0x34, 0x50 },
1204
1205 /*
1206 * 12 COMH "Common Control H"
1207 * = 64 (0x40) 01000000
1208 * COMH[7] "SRST"
1209 * = 0 (0x00) 0....... "No-op"
1210 * COMH[6:4] "Resolution selection"
1211 * = 4 (0x04) .100.... "XGA"
1212 * COMH[3] "Master slave selection"
1213 * = 0 (0x00) ....0... "Master mode"
1214 * COMH[2] "Internal B/R channel option"
1215 * = 0 (0x00) .....0.. "B/R use same channel"
1216 * COMH[1] "Color bar test pattern"
1217 * = 0 (0x00) ......0. "Off"
1218 * COMH[0] "Reserved"
1219 * = 0 (0x00) .......0
1220 */
1221 { 0x12, 0x40 },
1222
1223 /*
1224 * 17 HREFST "Horizontal window start"
1225 * = 31 (0x1F) 00011111
1226 * HREFST[7:0] "Horizontal window start, 8 MSBs"
1227 * = 31 (0x1F) 00011111
1228 */
1229 { 0x17, 0x1f },
1230
1231 /*
1232 * 18 HREFEND "Horizontal window end"
1233 * = 95 (0x5F) 01011111
1234 * HREFEND[7:0] "Horizontal Window End, 8 MSBs"
1235 * = 95 (0x5F) 01011111
1236 */
1237 { 0x18, 0x5f },
1238
1239 /*
1240 * 19 VSTRT "Vertical window start"
1241 * = 0 (0x00) 00000000
1242 * VSTRT[7:0] "Vertical Window Start, 8 MSBs"
1243 * = 0 (0x00) 00000000
1244 */
1245 { 0x19, 0x00 },
1246
1247 /*
1248 * 1A VEND "Vertical window end"
1249 * = 96 (0x60) 01100000
1250 * VEND[7:0] "Vertical Window End, 8 MSBs"
1251 * = 96 (0x60) 01100000
1252 */
1253 { 0x1a, 0x60 },
1254
1255 /*
1256 * 32 COMM "Common Control M"
1257 * = 18 (0x12) 00010010
1258 * COMM[7:6] "Pixel clock divide option"
1259 * = 0 (0x00) 00...... "/1"
1260 * COMM[5:3] "Horizontal window end position, 3 LSBs"
1261 * = 2 (0x02) ..010...
1262 * COMM[2:0] "Horizontal window start position, 3 LSBs"
1263 * = 2 (0x02) .....010
1264 */
1265 { 0x32, 0x12 },
1266
1267 /*
1268 * 03 COMA "Common Control A"
1269 * = 74 (0x4A) 01001010
1270 * COMA[7:4] "AWB Update Threshold"
1271 * = 4 (0x04) 0100....
1272 * COMA[3:2] "Vertical window end line control 2 LSBs"
1273 * = 2 (0x02) ....10..
1274 * COMA[1:0] "Vertical window start line control 2 LSBs"
1275 * = 2 (0x02) ......10
1276 */
1277 { 0x03, 0x4a },
1278
1279 /*
1280 * 11 CLKRC "Clock Rate Control"
1281 * = 128 (0x80) 10000000
1282 * CLKRC[7] "Internal frequency doublers on off seclection"
1283 * = 1 (0x01) 1....... "On"
1284 * CLKRC[6] "Digital video master slave selection"
1285 * = 0 (0x00) .0...... "Master mode, sensor
1286 * provides PCLK"
1287 * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }"
1288 * = 0 (0x00) ..000000
1289 */
1290 { 0x11, 0x80 },
1291
1292 /*
1293 * 12 COMH "Common Control H"
1294 * = 0 (0x00) 00000000
1295 * COMH[7] "SRST"
1296 * = 0 (0x00) 0....... "No-op"
1297 * COMH[6:4] "Resolution selection"
1298 * = 0 (0x00) .000.... "QXGA"
1299 * COMH[3] "Master slave selection"
1300 * = 0 (0x00) ....0... "Master mode"
1301 * COMH[2] "Internal B/R channel option"
1302 * = 0 (0x00) .....0.. "B/R use same channel"
1303 * COMH[1] "Color bar test pattern"
1304 * = 0 (0x00) ......0. "Off"
1305 * COMH[0] "Reserved"
1306 * = 0 (0x00) .......0
1307 */
1308 { 0x12, 0x00 },
1309
1310 /*
1311 * 12 COMH "Common Control H"
1312 * = 64 (0x40) 01000000
1313 * COMH[7] "SRST"
1314 * = 0 (0x00) 0....... "No-op"
1315 * COMH[6:4] "Resolution selection"
1316 * = 4 (0x04) .100.... "XGA"
1317 * COMH[3] "Master slave selection"
1318 * = 0 (0x00) ....0... "Master mode"
1319 * COMH[2] "Internal B/R channel option"
1320 * = 0 (0x00) .....0.. "B/R use same channel"
1321 * COMH[1] "Color bar test pattern"
1322 * = 0 (0x00) ......0. "Off"
1323 * COMH[0] "Reserved"
1324 * = 0 (0x00) .......0
1325 */
1326 { 0x12, 0x40 },
1327
1328 /*
1329 * 17 HREFST "Horizontal window start"
1330 * = 31 (0x1F) 00011111
1331 * HREFST[7:0] "Horizontal window start, 8 MSBs"
1332 * = 31 (0x1F) 00011111
1333 */
1334 { 0x17, 0x1f },
1335
1336 /*
1337 * 18 HREFEND "Horizontal window end"
1338 * = 95 (0x5F) 01011111
1339 * HREFEND[7:0] "Horizontal Window End, 8 MSBs"
1340 * = 95 (0x5F) 01011111
1341 */
1342 { 0x18, 0x5f },
1343
1344 /*
1345 * 19 VSTRT "Vertical window start"
1346 * = 0 (0x00) 00000000
1347 * VSTRT[7:0] "Vertical Window Start, 8 MSBs"
1348 * = 0 (0x00) 00000000
1349 */
1350 { 0x19, 0x00 },
1351
1352 /*
1353 * 1A VEND "Vertical window end"
1354 * = 96 (0x60) 01100000
1355 * VEND[7:0] "Vertical Window End, 8 MSBs"
1356 * = 96 (0x60) 01100000
1357 */
1358 { 0x1a, 0x60 },
1359
1360 /*
1361 * 32 COMM "Common Control M"
1362 * = 18 (0x12) 00010010
1363 * COMM[7:6] "Pixel clock divide option"
1364 * = 0 (0x00) 00...... "/1"
1365 * COMM[5:3] "Horizontal window end position, 3 LSBs"
1366 * = 2 (0x02) ..010...
1367 * COMM[2:0] "Horizontal window start position, 3 LSBs"
1368 * = 2 (0x02) .....010
1369 */
1370 { 0x32, 0x12 },
1371
1372 /*
1373 * 03 COMA "Common Control A"
1374 * = 74 (0x4A) 01001010
1375 * COMA[7:4] "AWB Update Threshold"
1376 * = 4 (0x04) 0100....
1377 * COMA[3:2] "Vertical window end line control 2 LSBs"
1378 * = 2 (0x02) ....10..
1379 * COMA[1:0] "Vertical window start line control 2 LSBs"
1380 * = 2 (0x02) ......10
1381 */
1382 { 0x03, 0x4a },
1383
1384 /*
1385 * 02 RED "Red Gain Control"
1386 * = 175 (0xAF) 10101111
1387 * RED[7] "Action"
1388 * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
1389 * RED[6:0] "Value"
1390 * = 47 (0x2F) .0101111
1391 */
1392 { 0x02, 0xaf },
1393
1394 /*
1395 * 2D ADDVSL "VSYNC Pulse Width"
1396 * = 210 (0xD2) 11010010
1397 * ADDVSL[7:0] "VSYNC pulse width, LSB"
1398 * = 210 (0xD2) 11010010
1399 */
1400 { 0x2d, 0xd2 },
1401
1402 /*
1403 * 00 GAIN = 24 (0x18) 00011000
1404 * GAIN[7:6] "Reserved"
1405 * = 0 (0x00) 00......
1406 * GAIN[5] "Double"
1407 * = 0 (0x00) ..0..... "False"
1408 * GAIN[4] "Double"
1409 * = 1 (0x01) ...1.... "True"
1410 * GAIN[3:0] "Range"
1411 * = 8 (0x08) ....1000
1412 */
1413 { 0x00, 0x18 },
1414
1415 /*
1416 * 01 BLUE "Blue Gain Control"
1417 * = 240 (0xF0) 11110000
1418 * BLUE[7] "Action"
1419 * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
1420 * BLUE[6:0] "Value"
1421 * = 112 (0x70) .1110000
1422 */
1423 { 0x01, 0xf0 },
1424
1425 /*
1426 * 10 AEC "Automatic Exposure Control"
1427 * = 10 (0x0A) 00001010
1428 * AEC[7:0] "Automatic Exposure Control, 8 MSBs"
1429 * = 10 (0x0A) 00001010
1430 */
1431 { 0x10, 0x0a },
1432
1433 { 0xe1, 0x67 },
1434 { 0xe3, 0x03 },
1435 { 0xe4, 0x26 },
1436 { 0xe5, 0x3e },
1437 { 0xf8, 0x01 },
1438 { 0xff, 0x01 },
1439};
1440
1441static const struct ov_i2c_regvals norm_6x20[] = {
1442 { 0x12, 0x80 }, /* reset */
1443 { 0x11, 0x01 },
1444 { 0x03, 0x60 },
1445 { 0x05, 0x7f }, /* For when autoadjust is off */
1446 { 0x07, 0xa8 },
1447 /* The ratio of 0x0c and 0x0d controls the white point */
1448 { 0x0c, 0x24 },
1449 { 0x0d, 0x24 },
1450 { 0x0f, 0x15 }, /* COMS */
1451 { 0x10, 0x75 }, /* AEC Exposure time */
1452 { 0x12, 0x24 }, /* Enable AGC */
1453 { 0x14, 0x04 },
1454 /* 0x16: 0x06 helps frame stability with moving objects */
1455 { 0x16, 0x06 },
1456/* { 0x20, 0x30 }, * Aperture correction enable */
1457 { 0x26, 0xb2 }, /* BLC enable */
1458 /* 0x28: 0x05 Selects RGB format if RGB on */
1459 { 0x28, 0x05 },
1460 { 0x2a, 0x04 }, /* Disable framerate adjust */
1461/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
1462 { 0x2d, 0x85 },
1463 { 0x33, 0xa0 }, /* Color Processing Parameter */
1464 { 0x34, 0xd2 }, /* Max A/D range */
1465 { 0x38, 0x8b },
1466 { 0x39, 0x40 },
1467
1468 { 0x3c, 0x39 }, /* Enable AEC mode changing */
1469 { 0x3c, 0x3c }, /* Change AEC mode */
1470 { 0x3c, 0x24 }, /* Disable AEC mode changing */
1471
1472 { 0x3d, 0x80 },
1473 /* These next two registers (0x4a, 0x4b) are undocumented.
1474 * They control the color balance */
1475 { 0x4a, 0x80 },
1476 { 0x4b, 0x80 },
1477 { 0x4d, 0xd2 }, /* This reduces noise a bit */
1478 { 0x4e, 0xc1 },
1479 { 0x4f, 0x04 },
1480/* Do 50-53 have any effect? */
1481/* Toggle 0x12[2] off and on here? */
1482};
1483
1484static const struct ov_i2c_regvals norm_6x30[] = {
1485 { 0x12, 0x80 }, /* Reset */
1486 { 0x00, 0x1f }, /* Gain */
1487 { 0x01, 0x99 }, /* Blue gain */
1488 { 0x02, 0x7c }, /* Red gain */
1489 { 0x03, 0xc0 }, /* Saturation */
1490 { 0x05, 0x0a }, /* Contrast */
1491 { 0x06, 0x95 }, /* Brightness */
1492 { 0x07, 0x2d }, /* Sharpness */
1493 { 0x0c, 0x20 },
1494 { 0x0d, 0x20 },
1495 { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
1496 { 0x0f, 0x05 },
1497 { 0x10, 0x9a },
1498 { 0x11, 0x00 }, /* Pixel clock = fastest */
1499 { 0x12, 0x24 }, /* Enable AGC and AWB */
1500 { 0x13, 0x21 },
1501 { 0x14, 0x80 },
1502 { 0x15, 0x01 },
1503 { 0x16, 0x03 },
1504 { 0x17, 0x38 },
1505 { 0x18, 0xea },
1506 { 0x19, 0x04 },
1507 { 0x1a, 0x93 },
1508 { 0x1b, 0x00 },
1509 { 0x1e, 0xc4 },
1510 { 0x1f, 0x04 },
1511 { 0x20, 0x20 },
1512 { 0x21, 0x10 },
1513 { 0x22, 0x88 },
1514 { 0x23, 0xc0 }, /* Crystal circuit power level */
1515 { 0x25, 0x9a }, /* Increase AEC black ratio */
1516 { 0x26, 0xb2 }, /* BLC enable */
1517 { 0x27, 0xa2 },
1518 { 0x28, 0x00 },
1519 { 0x29, 0x00 },
1520 { 0x2a, 0x84 }, /* 60 Hz power */
1521 { 0x2b, 0xa8 }, /* 60 Hz power */
1522 { 0x2c, 0xa0 },
1523 { 0x2d, 0x95 }, /* Enable auto-brightness */
1524 { 0x2e, 0x88 },
1525 { 0x33, 0x26 },
1526 { 0x34, 0x03 },
1527 { 0x36, 0x8f },
1528 { 0x37, 0x80 },
1529 { 0x38, 0x83 },
1530 { 0x39, 0x80 },
1531 { 0x3a, 0x0f },
1532 { 0x3b, 0x3c },
1533 { 0x3c, 0x1a },
1534 { 0x3d, 0x80 },
1535 { 0x3e, 0x80 },
1536 { 0x3f, 0x0e },
1537 { 0x40, 0x00 }, /* White bal */
1538 { 0x41, 0x00 }, /* White bal */
1539 { 0x42, 0x80 },
1540 { 0x43, 0x3f }, /* White bal */
1541 { 0x44, 0x80 },
1542 { 0x45, 0x20 },
1543 { 0x46, 0x20 },
1544 { 0x47, 0x80 },
1545 { 0x48, 0x7f },
1546 { 0x49, 0x00 },
1547 { 0x4a, 0x00 },
1548 { 0x4b, 0x80 },
1549 { 0x4c, 0xd0 },
1550 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
1551 { 0x4e, 0x40 },
1552 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
1553 { 0x50, 0xff },
1554 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
1555 { 0x55, 0xff },
1556 { 0x56, 0x12 },
1557 { 0x57, 0x81 },
1558 { 0x58, 0x75 },
1559 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
1560 { 0x5a, 0x2c },
1561 { 0x5b, 0x0f }, /* AWB chrominance levels */
1562 { 0x5c, 0x10 },
1563 { 0x3d, 0x80 },
1564 { 0x27, 0xa6 },
1565 { 0x12, 0x20 }, /* Toggle AWB */
1566 { 0x12, 0x24 },
1567};
1568
1569/* Lawrence Glaister <lg@jfm.bc.ca> reports:
1570 *
1571 * Register 0x0f in the 7610 has the following effects:
1572 *
1573 * 0x85 (AEC method 1): Best overall, good contrast range
1574 * 0x45 (AEC method 2): Very overexposed
1575 * 0xa5 (spec sheet default): Ok, but the black level is
1576 * shifted resulting in loss of contrast
1577 * 0x05 (old driver setting): very overexposed, too much
1578 * contrast
1579 */
1580static const struct ov_i2c_regvals norm_7610[] = {
1581 { 0x10, 0xff },
1582 { 0x16, 0x06 },
1583 { 0x28, 0x24 },
1584 { 0x2b, 0xac },
1585 { 0x12, 0x00 },
1586 { 0x38, 0x81 },
1587 { 0x28, 0x24 }, /* 0c */
1588 { 0x0f, 0x85 }, /* lg's setting */
1589 { 0x15, 0x01 },
1590 { 0x20, 0x1c },
1591 { 0x23, 0x2a },
1592 { 0x24, 0x10 },
1593 { 0x25, 0x8a },
1594 { 0x26, 0xa2 },
1595 { 0x27, 0xc2 },
1596 { 0x2a, 0x04 },
1597 { 0x2c, 0xfe },
1598 { 0x2d, 0x93 },
1599 { 0x30, 0x71 },
1600 { 0x31, 0x60 },
1601 { 0x32, 0x26 },
1602 { 0x33, 0x20 },
1603 { 0x34, 0x48 },
1604 { 0x12, 0x24 },
1605 { 0x11, 0x01 },
1606 { 0x0c, 0x24 },
1607 { 0x0d, 0x24 },
1608};
1609
1610static const struct ov_i2c_regvals norm_7620[] = {
1611 { 0x12, 0x80 }, /* reset */
1612 { 0x00, 0x00 }, /* gain */
1613 { 0x01, 0x80 }, /* blue gain */
1614 { 0x02, 0x80 }, /* red gain */
1615 { 0x03, 0xc0 }, /* OV7670_R03_VREF */
1616 { 0x06, 0x60 },
1617 { 0x07, 0x00 },
1618 { 0x0c, 0x24 },
1619 { 0x0c, 0x24 },
1620 { 0x0d, 0x24 },
1621 { 0x11, 0x01 },
1622 { 0x12, 0x24 },
1623 { 0x13, 0x01 },
1624 { 0x14, 0x84 },
1625 { 0x15, 0x01 },
1626 { 0x16, 0x03 },
1627 { 0x17, 0x2f },
1628 { 0x18, 0xcf },
1629 { 0x19, 0x06 },
1630 { 0x1a, 0xf5 },
1631 { 0x1b, 0x00 },
1632 { 0x20, 0x18 },
1633 { 0x21, 0x80 },
1634 { 0x22, 0x80 },
1635 { 0x23, 0x00 },
1636 { 0x26, 0xa2 },
1637 { 0x27, 0xea },
1638 { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
1639 { 0x29, 0x00 },
1640 { 0x2a, 0x10 },
1641 { 0x2b, 0x00 },
1642 { 0x2c, 0x88 },
1643 { 0x2d, 0x91 },
1644 { 0x2e, 0x80 },
1645 { 0x2f, 0x44 },
1646 { 0x60, 0x27 },
1647 { 0x61, 0x02 },
1648 { 0x62, 0x5f },
1649 { 0x63, 0xd5 },
1650 { 0x64, 0x57 },
1651 { 0x65, 0x83 },
1652 { 0x66, 0x55 },
1653 { 0x67, 0x92 },
1654 { 0x68, 0xcf },
1655 { 0x69, 0x76 },
1656 { 0x6a, 0x22 },
1657 { 0x6b, 0x00 },
1658 { 0x6c, 0x02 },
1659 { 0x6d, 0x44 },
1660 { 0x6e, 0x80 },
1661 { 0x6f, 0x1d },
1662 { 0x70, 0x8b },
1663 { 0x71, 0x00 },
1664 { 0x72, 0x14 },
1665 { 0x73, 0x54 },
1666 { 0x74, 0x00 },
1667 { 0x75, 0x8e },
1668 { 0x76, 0x00 },
1669 { 0x77, 0xff },
1670 { 0x78, 0x80 },
1671 { 0x79, 0x80 },
1672 { 0x7a, 0x80 },
1673 { 0x7b, 0xe2 },
1674 { 0x7c, 0x00 },
1675};
1676
1677/* 7640 and 7648. The defaults should be OK for most registers. */
1678static const struct ov_i2c_regvals norm_7640[] = {
1679 { 0x12, 0x80 },
1680 { 0x12, 0x14 },
1681};
1682
1683static const struct ov_regvals init_519_ov7660[] = {
1684 { 0x5d, 0x03 }, /* Turn off suspend mode */
1685 { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */
1686 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
1687 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
1688 { 0xa3, 0x18 },
1689 { 0xa4, 0x04 },
1690 { 0xa5, 0x28 },
1691 { 0x37, 0x00 }, /* SetUsbInit */
1692 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
1693 /* Enable both fields, YUV Input, disable defect comp (why?) */
1694 { 0x20, 0x0c }, /* 0x0d does U <-> V swap */
1695 { 0x21, 0x38 },
1696 { 0x22, 0x1d },
1697 { 0x17, 0x50 }, /* undocumented */
1698 { 0x37, 0x00 }, /* undocumented */
1699 { 0x40, 0xff }, /* I2C timeout counter */
1700 { 0x46, 0x00 }, /* I2C clock prescaler */
1701};
1702static const struct ov_i2c_regvals norm_7660[] = {
1703 {OV7670_R12_COM7, OV7670_COM7_RESET},
1704 {OV7670_R11_CLKRC, 0x81},
1705 {0x92, 0x00}, /* DM_LNL */
1706 {0x93, 0x00}, /* DM_LNH */
1707 {0x9d, 0x4c}, /* BD50ST */
1708 {0x9e, 0x3f}, /* BD60ST */
1709 {OV7670_R3B_COM11, 0x02},
1710 {OV7670_R13_COM8, 0xf5},
1711 {OV7670_R10_AECH, 0x00},
1712 {OV7670_R00_GAIN, 0x00},
1713 {OV7670_R01_BLUE, 0x7c},
1714 {OV7670_R02_RED, 0x9d},
1715 {OV7670_R12_COM7, 0x00},
1716 {OV7670_R04_COM1, 00},
1717 {OV7670_R18_HSTOP, 0x01},
1718 {OV7670_R17_HSTART, 0x13},
1719 {OV7670_R32_HREF, 0x92},
1720 {OV7670_R19_VSTART, 0x02},
1721 {OV7670_R1A_VSTOP, 0x7a},
1722 {OV7670_R03_VREF, 0x00},
1723 {OV7670_R0E_COM5, 0x04},
1724 {OV7670_R0F_COM6, 0x62},
1725 {OV7670_R15_COM10, 0x00},
1726 {0x16, 0x02}, /* RSVD */
1727 {0x1b, 0x00}, /* PSHFT */
1728 {OV7670_R1E_MVFP, 0x01},
1729 {0x29, 0x3c}, /* RSVD */
1730 {0x33, 0x00}, /* CHLF */
1731 {0x34, 0x07}, /* ARBLM */
1732 {0x35, 0x84}, /* RSVD */
1733 {0x36, 0x00}, /* RSVD */
1734 {0x37, 0x04}, /* ADC */
1735 {0x39, 0x43}, /* OFON */
1736 {OV7670_R3A_TSLB, 0x00},
1737 {OV7670_R3C_COM12, 0x6c},
1738 {OV7670_R3D_COM13, 0x98},
1739 {OV7670_R3F_EDGE, 0x23},
1740 {OV7670_R40_COM15, 0xc1},
1741 {OV7670_R41_COM16, 0x22},
1742 {0x6b, 0x0a}, /* DBLV */
1743 {0xa1, 0x08}, /* RSVD */
1744 {0x69, 0x80}, /* HV */
1745 {0x43, 0xf0}, /* RSVD.. */
1746 {0x44, 0x10},
1747 {0x45, 0x78},
1748 {0x46, 0xa8},
1749 {0x47, 0x60},
1750 {0x48, 0x80},
1751 {0x59, 0xba},
1752 {0x5a, 0x9a},
1753 {0x5b, 0x22},
1754 {0x5c, 0xb9},
1755 {0x5d, 0x9b},
1756 {0x5e, 0x10},
1757 {0x5f, 0xe0},
1758 {0x60, 0x85},
1759 {0x61, 0x60},
1760 {0x9f, 0x9d}, /* RSVD */
1761 {0xa0, 0xa0}, /* DSPC2 */
1762 {0x4f, 0x60}, /* matrix */
1763 {0x50, 0x64},
1764 {0x51, 0x04},
1765 {0x52, 0x18},
1766 {0x53, 0x3c},
1767 {0x54, 0x54},
1768 {0x55, 0x40},
1769 {0x56, 0x40},
1770 {0x57, 0x40},
1771 {0x58, 0x0d}, /* matrix sign */
1772 {0x8b, 0xcc}, /* RSVD */
1773 {0x8c, 0xcc},
1774 {0x8d, 0xcf},
1775 {0x6c, 0x40}, /* gamma curve */
1776 {0x6d, 0xe0},
1777 {0x6e, 0xa0},
1778 {0x6f, 0x80},
1779 {0x70, 0x70},
1780 {0x71, 0x80},
1781 {0x72, 0x60},
1782 {0x73, 0x60},
1783 {0x74, 0x50},
1784 {0x75, 0x40},
1785 {0x76, 0x38},
1786 {0x77, 0x3c},
1787 {0x78, 0x32},
1788 {0x79, 0x1a},
1789 {0x7a, 0x28},
1790 {0x7b, 0x24},
1791 {0x7c, 0x04}, /* gamma curve */
1792 {0x7d, 0x12},
1793 {0x7e, 0x26},
1794 {0x7f, 0x46},
1795 {0x80, 0x54},
1796 {0x81, 0x64},
1797 {0x82, 0x70},
1798 {0x83, 0x7c},
1799 {0x84, 0x86},
1800 {0x85, 0x8e},
1801 {0x86, 0x9c},
1802 {0x87, 0xab},
1803 {0x88, 0xc4},
1804 {0x89, 0xd1},
1805 {0x8a, 0xe5},
1806 {OV7670_R14_COM9, 0x1e},
1807 {OV7670_R24_AEW, 0x80},
1808 {OV7670_R25_AEB, 0x72},
1809 {OV7670_R26_VPT, 0xb3},
1810 {0x62, 0x80}, /* LCC1 */
1811 {0x63, 0x80}, /* LCC2 */
1812 {0x64, 0x06}, /* LCC3 */
1813 {0x65, 0x00}, /* LCC4 */
1814 {0x66, 0x01}, /* LCC5 */
1815 {0x94, 0x0e}, /* RSVD.. */
1816 {0x95, 0x14},
1817 {OV7670_R13_COM8, OV7670_COM8_FASTAEC
1818 | OV7670_COM8_AECSTEP
1819 | OV7670_COM8_BFILT
1820 | 0x10
1821 | OV7670_COM8_AGC
1822 | OV7670_COM8_AWB
1823 | OV7670_COM8_AEC},
1824 {0xa1, 0xc8}
1825};
1826static const struct ov_i2c_regvals norm_9600[] = {
1827 {0x12, 0x80},
1828 {0x0c, 0x28},
1829 {0x11, 0x80},
1830 {0x13, 0xb5},
1831 {0x14, 0x3e},
1832 {0x1b, 0x04},
1833 {0x24, 0xb0},
1834 {0x25, 0x90},
1835 {0x26, 0x94},
1836 {0x35, 0x90},
1837 {0x37, 0x07},
1838 {0x38, 0x08},
1839 {0x01, 0x8e},
1840 {0x02, 0x85}
1841};
1842
1843/* 7670. Defaults taken from OmniVision provided data,
1844* as provided by Jonathan Corbet of OLPC */
1845static const struct ov_i2c_regvals norm_7670[] = {
1846 { OV7670_R12_COM7, OV7670_COM7_RESET },
1847 { OV7670_R3A_TSLB, 0x04 }, /* OV */
1848 { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
1849 { OV7670_R11_CLKRC, 0x01 },
1850/*
1851 * Set the hardware window. These values from OV don't entirely
1852 * make sense - hstop is less than hstart. But they work...
1853 */
1854 { OV7670_R17_HSTART, 0x13 },
1855 { OV7670_R18_HSTOP, 0x01 },
1856 { OV7670_R32_HREF, 0xb6 },
1857 { OV7670_R19_VSTART, 0x02 },
1858 { OV7670_R1A_VSTOP, 0x7a },
1859 { OV7670_R03_VREF, 0x0a },
1860
1861 { OV7670_R0C_COM3, 0x00 },
1862 { OV7670_R3E_COM14, 0x00 },
1863/* Mystery scaling numbers */
1864 { 0x70, 0x3a },
1865 { 0x71, 0x35 },
1866 { 0x72, 0x11 },
1867 { 0x73, 0xf0 },
1868 { 0xa2, 0x02 },
1869/* { OV7670_R15_COM10, 0x0 }, */
1870
1871/* Gamma curve values */
1872 { 0x7a, 0x20 },
1873 { 0x7b, 0x10 },
1874 { 0x7c, 0x1e },
1875 { 0x7d, 0x35 },
1876 { 0x7e, 0x5a },
1877 { 0x7f, 0x69 },
1878 { 0x80, 0x76 },
1879 { 0x81, 0x80 },
1880 { 0x82, 0x88 },
1881 { 0x83, 0x8f },
1882 { 0x84, 0x96 },
1883 { 0x85, 0xa3 },
1884 { 0x86, 0xaf },
1885 { 0x87, 0xc4 },
1886 { 0x88, 0xd7 },
1887 { 0x89, 0xe8 },
1888
1889/* AGC and AEC parameters. Note we start by disabling those features,
1890 then turn them only after tweaking the values. */
1891 { OV7670_R13_COM8, OV7670_COM8_FASTAEC
1892 | OV7670_COM8_AECSTEP
1893 | OV7670_COM8_BFILT },
1894 { OV7670_R00_GAIN, 0x00 },
1895 { OV7670_R10_AECH, 0x00 },
1896 { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
1897 { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
1898 { OV7670_RA5_BD50MAX, 0x05 },
1899 { OV7670_RAB_BD60MAX, 0x07 },
1900 { OV7670_R24_AEW, 0x95 },
1901 { OV7670_R25_AEB, 0x33 },
1902 { OV7670_R26_VPT, 0xe3 },
1903 { OV7670_R9F_HAECC1, 0x78 },
1904 { OV7670_RA0_HAECC2, 0x68 },
1905 { 0xa1, 0x03 }, /* magic */
1906 { OV7670_RA6_HAECC3, 0xd8 },
1907 { OV7670_RA7_HAECC4, 0xd8 },
1908 { OV7670_RA8_HAECC5, 0xf0 },
1909 { OV7670_RA9_HAECC6, 0x90 },
1910 { OV7670_RAA_HAECC7, 0x94 },
1911 { OV7670_R13_COM8, OV7670_COM8_FASTAEC
1912 | OV7670_COM8_AECSTEP
1913 | OV7670_COM8_BFILT
1914 | OV7670_COM8_AGC
1915 | OV7670_COM8_AEC },
1916
1917/* Almost all of these are magic "reserved" values. */
1918 { OV7670_R0E_COM5, 0x61 },
1919 { OV7670_R0F_COM6, 0x4b },
1920 { 0x16, 0x02 },
1921 { OV7670_R1E_MVFP, 0x07 },
1922 { 0x21, 0x02 },
1923 { 0x22, 0x91 },
1924 { 0x29, 0x07 },
1925 { 0x33, 0x0b },
1926 { 0x35, 0x0b },
1927 { 0x37, 0x1d },
1928 { 0x38, 0x71 },
1929 { 0x39, 0x2a },
1930 { OV7670_R3C_COM12, 0x78 },
1931 { 0x4d, 0x40 },
1932 { 0x4e, 0x20 },
1933 { OV7670_R69_GFIX, 0x00 },
1934 { 0x6b, 0x4a },
1935 { 0x74, 0x10 },
1936 { 0x8d, 0x4f },
1937 { 0x8e, 0x00 },
1938 { 0x8f, 0x00 },
1939 { 0x90, 0x00 },
1940 { 0x91, 0x00 },
1941 { 0x96, 0x00 },
1942 { 0x9a, 0x00 },
1943 { 0xb0, 0x84 },
1944 { 0xb1, 0x0c },
1945 { 0xb2, 0x0e },
1946 { 0xb3, 0x82 },
1947 { 0xb8, 0x0a },
1948
1949/* More reserved magic, some of which tweaks white balance */
1950 { 0x43, 0x0a },
1951 { 0x44, 0xf0 },
1952 { 0x45, 0x34 },
1953 { 0x46, 0x58 },
1954 { 0x47, 0x28 },
1955 { 0x48, 0x3a },
1956 { 0x59, 0x88 },
1957 { 0x5a, 0x88 },
1958 { 0x5b, 0x44 },
1959 { 0x5c, 0x67 },
1960 { 0x5d, 0x49 },
1961 { 0x5e, 0x0e },
1962 { 0x6c, 0x0a },
1963 { 0x6d, 0x55 },
1964 { 0x6e, 0x11 },
1965 { 0x6f, 0x9f }, /* "9e for advance AWB" */
1966 { 0x6a, 0x40 },
1967 { OV7670_R01_BLUE, 0x40 },
1968 { OV7670_R02_RED, 0x60 },
1969 { OV7670_R13_COM8, OV7670_COM8_FASTAEC
1970 | OV7670_COM8_AECSTEP
1971 | OV7670_COM8_BFILT
1972 | OV7670_COM8_AGC
1973 | OV7670_COM8_AEC
1974 | OV7670_COM8_AWB },
1975
1976/* Matrix coefficients */
1977 { 0x4f, 0x80 },
1978 { 0x50, 0x80 },
1979 { 0x51, 0x00 },
1980 { 0x52, 0x22 },
1981 { 0x53, 0x5e },
1982 { 0x54, 0x80 },
1983 { 0x58, 0x9e },
1984
1985 { OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
1986 { OV7670_R3F_EDGE, 0x00 },
1987 { 0x75, 0x05 },
1988 { 0x76, 0xe1 },
1989 { 0x4c, 0x00 },
1990 { 0x77, 0x01 },
1991 { OV7670_R3D_COM13, OV7670_COM13_GAMMA
1992 | OV7670_COM13_UVSAT
1993 | 2}, /* was 3 */
1994 { 0x4b, 0x09 },
1995 { 0xc9, 0x60 },
1996 { OV7670_R41_COM16, 0x38 },
1997 { 0x56, 0x40 },
1998
1999 { 0x34, 0x11 },
2000 { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
2001 { 0xa4, 0x88 },
2002 { 0x96, 0x00 },
2003 { 0x97, 0x30 },
2004 { 0x98, 0x20 },
2005 { 0x99, 0x30 },
2006 { 0x9a, 0x84 },
2007 { 0x9b, 0x29 },
2008 { 0x9c, 0x03 },
2009 { 0x9d, 0x4c },
2010 { 0x9e, 0x3f },
2011 { 0x78, 0x04 },
2012
2013/* Extra-weird stuff. Some sort of multiplexor register */
2014 { 0x79, 0x01 },
2015 { 0xc8, 0xf0 },
2016 { 0x79, 0x0f },
2017 { 0xc8, 0x00 },
2018 { 0x79, 0x10 },
2019 { 0xc8, 0x7e },
2020 { 0x79, 0x0a },
2021 { 0xc8, 0x80 },
2022 { 0x79, 0x0b },
2023 { 0xc8, 0x01 },
2024 { 0x79, 0x0c },
2025 { 0xc8, 0x0f },
2026 { 0x79, 0x0d },
2027 { 0xc8, 0x20 },
2028 { 0x79, 0x09 },
2029 { 0xc8, 0x80 },
2030 { 0x79, 0x02 },
2031 { 0xc8, 0xc0 },
2032 { 0x79, 0x03 },
2033 { 0xc8, 0x40 },
2034 { 0x79, 0x05 },
2035 { 0xc8, 0x30 },
2036 { 0x79, 0x26 },
2037};
2038
2039static const struct ov_i2c_regvals norm_8610[] = {
2040 { 0x12, 0x80 },
2041 { 0x00, 0x00 },
2042 { 0x01, 0x80 },
2043 { 0x02, 0x80 },
2044 { 0x03, 0xc0 },
2045 { 0x04, 0x30 },
2046 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
2047 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
2048 { 0x0a, 0x86 },
2049 { 0x0b, 0xb0 },
2050 { 0x0c, 0x20 },
2051 { 0x0d, 0x20 },
2052 { 0x11, 0x01 },
2053 { 0x12, 0x25 },
2054 { 0x13, 0x01 },
2055 { 0x14, 0x04 },
2056 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
2057 { 0x16, 0x03 },
2058 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
2059 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
2060 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
2061 { 0x1a, 0xf5 },
2062 { 0x1b, 0x00 },
2063 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
2064 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
2065 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
2066 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
2067 { 0x26, 0xa2 },
2068 { 0x27, 0xea },
2069 { 0x28, 0x00 },
2070 { 0x29, 0x00 },
2071 { 0x2a, 0x80 },
2072 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
2073 { 0x2c, 0xac },
2074 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
2075 { 0x2e, 0x80 },
2076 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
2077 { 0x4c, 0x00 },
2078 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
2079 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
2080 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
2081 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
2082 { 0x63, 0xff },
2083 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
2084 * maybe thats wrong */
2085 { 0x65, 0x00 },
2086 { 0x66, 0x55 },
2087 { 0x67, 0xb0 },
2088 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
2089 { 0x69, 0x02 },
2090 { 0x6a, 0x22 },
2091 { 0x6b, 0x00 },
2092 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
2093 * deleting bit7 colors the first images red */
2094 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
2095 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
2096 { 0x6f, 0x01 },
2097 { 0x70, 0x8b },
2098 { 0x71, 0x00 },
2099 { 0x72, 0x14 },
2100 { 0x73, 0x54 },
2101 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
2102 { 0x75, 0x0e },
2103 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
2104 { 0x77, 0xff },
2105 { 0x78, 0x80 },
2106 { 0x79, 0x80 },
2107 { 0x7a, 0x80 },
2108 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
2109 { 0x7c, 0x00 },
2110 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
2111 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
2112 { 0x7f, 0xfb },
2113 { 0x80, 0x28 },
2114 { 0x81, 0x00 },
2115 { 0x82, 0x23 },
2116 { 0x83, 0x0b },
2117 { 0x84, 0x00 },
2118 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
2119 { 0x86, 0xc9 },
2120 { 0x87, 0x00 },
2121 { 0x88, 0x00 },
2122 { 0x89, 0x01 },
2123 { 0x12, 0x20 },
2124 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
2125};
2126
2127static unsigned char ov7670_abs_to_sm(unsigned char v)
2128{
2129 if (v > 127)
2130 return v & 0x7f;
2131 return (128 - v) | 0x80;
2132}
2133
2134/* Write a OV519 register */
2135static void reg_w(struct sd *sd, u16 index, u16 value)
2136{
2137 int ret, req = 0;
2138
2139 if (sd->gspca_dev.usb_err < 0)
2140 return;
2141
2142 switch (sd->bridge) {
2143 case BRIDGE_OV511:
2144 case BRIDGE_OV511PLUS:
2145 req = 2;
2146 break;
2147 case BRIDGE_OVFX2:
2148 req = 0x0a;
2149 /* fall through */
2150 case BRIDGE_W9968CF:
2151 PDEBUG(D_USBO, "SET %02x %04x %04x",
2152 req, value, index);
2153 ret = usb_control_msg(sd->gspca_dev.dev,
2154 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2155 req,
2156 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2157 value, index, NULL, 0, 500);
2158 goto leave;
2159 default:
2160 req = 1;
2161 }
2162
2163 PDEBUG(D_USBO, "SET %02x 0000 %04x %02x",
2164 req, index, value);
2165 sd->gspca_dev.usb_buf[0] = value;
2166 ret = usb_control_msg(sd->gspca_dev.dev,
2167 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2168 req,
2169 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2170 0, index,
2171 sd->gspca_dev.usb_buf, 1, 500);
2172leave:
2173 if (ret < 0) {
2174 err("reg_w %02x failed %d", index, ret);
2175 sd->gspca_dev.usb_err = ret;
2176 return;
2177 }
2178}
2179
2180/* Read from a OV519 register, note not valid for the w9968cf!! */
2181/* returns: negative is error, pos or zero is data */
2182static int reg_r(struct sd *sd, u16 index)
2183{
2184 int ret;
2185 int req;
2186
2187 if (sd->gspca_dev.usb_err < 0)
2188 return -1;
2189
2190 switch (sd->bridge) {
2191 case BRIDGE_OV511:
2192 case BRIDGE_OV511PLUS:
2193 req = 3;
2194 break;
2195 case BRIDGE_OVFX2:
2196 req = 0x0b;
2197 break;
2198 default:
2199 req = 1;
2200 }
2201
2202 ret = usb_control_msg(sd->gspca_dev.dev,
2203 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
2204 req,
2205 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2206 0, index, sd->gspca_dev.usb_buf, 1, 500);
2207
2208 if (ret >= 0) {
2209 ret = sd->gspca_dev.usb_buf[0];
2210 PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
2211 req, index, ret);
2212 } else {
2213 err("reg_r %02x failed %d", index, ret);
2214 sd->gspca_dev.usb_err = ret;
2215 }
2216
2217 return ret;
2218}
2219
2220/* Read 8 values from a OV519 register */
2221static int reg_r8(struct sd *sd,
2222 u16 index)
2223{
2224 int ret;
2225
2226 if (sd->gspca_dev.usb_err < 0)
2227 return -1;
2228
2229 ret = usb_control_msg(sd->gspca_dev.dev,
2230 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
2231 1, /* REQ_IO */
2232 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2233 0, index, sd->gspca_dev.usb_buf, 8, 500);
2234
2235 if (ret >= 0) {
2236 ret = sd->gspca_dev.usb_buf[0];
2237 } else {
2238 err("reg_r8 %02x failed %d", index, ret);
2239 sd->gspca_dev.usb_err = ret;
2240 }
2241
2242 return ret;
2243}
2244
2245/*
2246 * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
2247 * the same position as 1's in "mask" are cleared and set to "value". Bits
2248 * that are in the same position as 0's in "mask" are preserved, regardless
2249 * of their respective state in "value".
2250 */
2251static void reg_w_mask(struct sd *sd,
2252 u16 index,
2253 u8 value,
2254 u8 mask)
2255{
2256 int ret;
2257 u8 oldval;
2258
2259 if (mask != 0xff) {
2260 value &= mask; /* Enforce mask on value */
2261 ret = reg_r(sd, index);
2262 if (ret < 0)
2263 return;
2264
2265 oldval = ret & ~mask; /* Clear the masked bits */
2266 value |= oldval; /* Set the desired bits */
2267 }
2268 reg_w(sd, index, value);
2269}
2270
2271/*
2272 * Writes multiple (n) byte value to a single register. Only valid with certain
2273 * registers (0x30 and 0xc4 - 0xce).
2274 */
2275static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
2276{
2277 int ret;
2278
2279 if (sd->gspca_dev.usb_err < 0)
2280 return;
2281
2282 *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
2283
2284 ret = usb_control_msg(sd->gspca_dev.dev,
2285 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2286 1 /* REG_IO */,
2287 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2288 0, index,
2289 sd->gspca_dev.usb_buf, n, 500);
2290 if (ret < 0) {
2291 err("reg_w32 %02x failed %d", index, ret);
2292 sd->gspca_dev.usb_err = ret;
2293 }
2294}
2295
2296static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
2297{
2298 int rc, retries;
2299
2300 PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
2301
2302 /* Three byte write cycle */
2303 for (retries = 6; ; ) {
2304 /* Select camera register */
2305 reg_w(sd, R51x_I2C_SADDR_3, reg);
2306
2307 /* Write "value" to I2C data port of OV511 */
2308 reg_w(sd, R51x_I2C_DATA, value);
2309
2310 /* Initiate 3-byte write cycle */
2311 reg_w(sd, R511_I2C_CTL, 0x01);
2312
2313 do {
2314 rc = reg_r(sd, R511_I2C_CTL);
2315 } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
2316
2317 if (rc < 0)
2318 return;
2319
2320 if ((rc & 2) == 0) /* Ack? */
2321 break;
2322 if (--retries < 0) {
2323 PDEBUG(D_USBO, "i2c write retries exhausted");
2324 return;
2325 }
2326 }
2327}
2328
2329static int ov511_i2c_r(struct sd *sd, u8 reg)
2330{
2331 int rc, value, retries;
2332
2333 /* Two byte write cycle */
2334 for (retries = 6; ; ) {
2335 /* Select camera register */
2336 reg_w(sd, R51x_I2C_SADDR_2, reg);
2337
2338 /* Initiate 2-byte write cycle */
2339 reg_w(sd, R511_I2C_CTL, 0x03);
2340
2341 do {
2342 rc = reg_r(sd, R511_I2C_CTL);
2343 } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
2344
2345 if (rc < 0)
2346 return rc;
2347
2348 if ((rc & 2) == 0) /* Ack? */
2349 break;
2350
2351 /* I2C abort */
2352 reg_w(sd, R511_I2C_CTL, 0x10);
2353
2354 if (--retries < 0) {
2355 PDEBUG(D_USBI, "i2c write retries exhausted");
2356 return -1;
2357 }
2358 }
2359
2360 /* Two byte read cycle */
2361 for (retries = 6; ; ) {
2362 /* Initiate 2-byte read cycle */
2363 reg_w(sd, R511_I2C_CTL, 0x05);
2364
2365 do {
2366 rc = reg_r(sd, R511_I2C_CTL);
2367 } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
2368
2369 if (rc < 0)
2370 return rc;
2371
2372 if ((rc & 2) == 0) /* Ack? */
2373 break;
2374
2375 /* I2C abort */
2376 reg_w(sd, R511_I2C_CTL, 0x10);
2377
2378 if (--retries < 0) {
2379 PDEBUG(D_USBI, "i2c read retries exhausted");
2380 return -1;
2381 }
2382 }
2383
2384 value = reg_r(sd, R51x_I2C_DATA);
2385
2386 PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value);
2387
2388 /* This is needed to make i2c_w() work */
2389 reg_w(sd, R511_I2C_CTL, 0x05);
2390
2391 return value;
2392}
2393
2394/*
2395 * The OV518 I2C I/O procedure is different, hence, this function.
2396 * This is normally only called from i2c_w(). Note that this function
2397 * always succeeds regardless of whether the sensor is present and working.
2398 */
2399static void ov518_i2c_w(struct sd *sd,
2400 u8 reg,
2401 u8 value)
2402{
2403 PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
2404
2405 /* Select camera register */
2406 reg_w(sd, R51x_I2C_SADDR_3, reg);
2407
2408 /* Write "value" to I2C data port of OV511 */
2409 reg_w(sd, R51x_I2C_DATA, value);
2410
2411 /* Initiate 3-byte write cycle */
2412 reg_w(sd, R518_I2C_CTL, 0x01);
2413
2414 /* wait for write complete */
2415 msleep(4);
2416 reg_r8(sd, R518_I2C_CTL);
2417}
2418
2419/*
2420 * returns: negative is error, pos or zero is data
2421 *
2422 * The OV518 I2C I/O procedure is different, hence, this function.
2423 * This is normally only called from i2c_r(). Note that this function
2424 * always succeeds regardless of whether the sensor is present and working.
2425 */
2426static int ov518_i2c_r(struct sd *sd, u8 reg)
2427{
2428 int value;
2429
2430 /* Select camera register */
2431 reg_w(sd, R51x_I2C_SADDR_2, reg);
2432
2433 /* Initiate 2-byte write cycle */
2434 reg_w(sd, R518_I2C_CTL, 0x03);
2435 reg_r8(sd, R518_I2C_CTL);
2436
2437 /* Initiate 2-byte read cycle */
2438 reg_w(sd, R518_I2C_CTL, 0x05);
2439 reg_r8(sd, R518_I2C_CTL);
2440
2441 value = reg_r(sd, R51x_I2C_DATA);
2442 PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
2443 return value;
2444}
2445
2446static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
2447{
2448 int ret;
2449
2450 if (sd->gspca_dev.usb_err < 0)
2451 return;
2452
2453 ret = usb_control_msg(sd->gspca_dev.dev,
2454 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
2455 0x02,
2456 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2457 (u16) value, (u16) reg, NULL, 0, 500);
2458
2459 if (ret < 0) {
2460 err("ovfx2_i2c_w %02x failed %d", reg, ret);
2461 sd->gspca_dev.usb_err = ret;
2462 }
2463
2464 PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value);
2465}
2466
2467static int ovfx2_i2c_r(struct sd *sd, u8 reg)
2468{
2469 int ret;
2470
2471 if (sd->gspca_dev.usb_err < 0)
2472 return -1;
2473
2474 ret = usb_control_msg(sd->gspca_dev.dev,
2475 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
2476 0x03,
2477 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
2478 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
2479
2480 if (ret >= 0) {
2481 ret = sd->gspca_dev.usb_buf[0];
2482 PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
2483 } else {
2484 err("ovfx2_i2c_r %02x failed %d", reg, ret);
2485 sd->gspca_dev.usb_err = ret;
2486 }
2487
2488 return ret;
2489}
2490
2491static void i2c_w(struct sd *sd, u8 reg, u8 value)
2492{
2493 if (sd->sensor_reg_cache[reg] == value)
2494 return;
2495
2496 switch (sd->bridge) {
2497 case BRIDGE_OV511:
2498 case BRIDGE_OV511PLUS:
2499 ov511_i2c_w(sd, reg, value);
2500 break;
2501 case BRIDGE_OV518:
2502 case BRIDGE_OV518PLUS:
2503 case BRIDGE_OV519:
2504 ov518_i2c_w(sd, reg, value);
2505 break;
2506 case BRIDGE_OVFX2:
2507 ovfx2_i2c_w(sd, reg, value);
2508 break;
2509 case BRIDGE_W9968CF:
2510 w9968cf_i2c_w(sd, reg, value);
2511 break;
2512 }
2513
2514 if (sd->gspca_dev.usb_err >= 0) {
2515 /* Up on sensor reset empty the register cache */
2516 if (reg == 0x12 && (value & 0x80))
2517 memset(sd->sensor_reg_cache, -1,
2518 sizeof(sd->sensor_reg_cache));
2519 else
2520 sd->sensor_reg_cache[reg] = value;
2521 }
2522}
2523
2524static int i2c_r(struct sd *sd, u8 reg)
2525{
2526 int ret = -1;
2527
2528 if (sd->sensor_reg_cache[reg] != -1)
2529 return sd->sensor_reg_cache[reg];
2530
2531 switch (sd->bridge) {
2532 case BRIDGE_OV511:
2533 case BRIDGE_OV511PLUS:
2534 ret = ov511_i2c_r(sd, reg);
2535 break;
2536 case BRIDGE_OV518:
2537 case BRIDGE_OV518PLUS:
2538 case BRIDGE_OV519:
2539 ret = ov518_i2c_r(sd, reg);
2540 break;
2541 case BRIDGE_OVFX2:
2542 ret = ovfx2_i2c_r(sd, reg);
2543 break;
2544 case BRIDGE_W9968CF:
2545 ret = w9968cf_i2c_r(sd, reg);
2546 break;
2547 }
2548
2549 if (ret >= 0)
2550 sd->sensor_reg_cache[reg] = ret;
2551
2552 return ret;
2553}
2554
2555/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
2556 * the same position as 1's in "mask" are cleared and set to "value". Bits
2557 * that are in the same position as 0's in "mask" are preserved, regardless
2558 * of their respective state in "value".
2559 */
2560static void i2c_w_mask(struct sd *sd,
2561 u8 reg,
2562 u8 value,
2563 u8 mask)
2564{
2565 int rc;
2566 u8 oldval;
2567
2568 value &= mask; /* Enforce mask on value */
2569 rc = i2c_r(sd, reg);
2570 if (rc < 0)
2571 return;
2572 oldval = rc & ~mask; /* Clear the masked bits */
2573 value |= oldval; /* Set the desired bits */
2574 i2c_w(sd, reg, value);
2575}
2576
2577/* Temporarily stops OV511 from functioning. Must do this before changing
2578 * registers while the camera is streaming */
2579static inline void ov51x_stop(struct sd *sd)
2580{
2581 PDEBUG(D_STREAM, "stopping");
2582 sd->stopped = 1;
2583 switch (sd->bridge) {
2584 case BRIDGE_OV511:
2585 case BRIDGE_OV511PLUS:
2586 reg_w(sd, R51x_SYS_RESET, 0x3d);
2587 break;
2588 case BRIDGE_OV518:
2589 case BRIDGE_OV518PLUS:
2590 reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
2591 break;
2592 case BRIDGE_OV519:
2593 reg_w(sd, OV519_R51_RESET1, 0x0f);
2594 reg_w(sd, OV519_R51_RESET1, 0x00);
2595 reg_w(sd, 0x22, 0x00); /* FRAR */
2596 break;
2597 case BRIDGE_OVFX2:
2598 reg_w_mask(sd, 0x0f, 0x00, 0x02);
2599 break;
2600 case BRIDGE_W9968CF:
2601 reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
2602 break;
2603 }
2604}
2605
2606/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
2607 * actually stopped (for performance). */
2608static inline void ov51x_restart(struct sd *sd)
2609{
2610 PDEBUG(D_STREAM, "restarting");
2611 if (!sd->stopped)
2612 return;
2613 sd->stopped = 0;
2614
2615 /* Reinitialize the stream */
2616 switch (sd->bridge) {
2617 case BRIDGE_OV511:
2618 case BRIDGE_OV511PLUS:
2619 reg_w(sd, R51x_SYS_RESET, 0x00);
2620 break;
2621 case BRIDGE_OV518:
2622 case BRIDGE_OV518PLUS:
2623 reg_w(sd, 0x2f, 0x80);
2624 reg_w(sd, R51x_SYS_RESET, 0x00);
2625 break;
2626 case BRIDGE_OV519:
2627 reg_w(sd, OV519_R51_RESET1, 0x0f);
2628 reg_w(sd, OV519_R51_RESET1, 0x00);
2629 reg_w(sd, 0x22, 0x1d); /* FRAR */
2630 break;
2631 case BRIDGE_OVFX2:
2632 reg_w_mask(sd, 0x0f, 0x02, 0x02);
2633 break;
2634 case BRIDGE_W9968CF:
2635 reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
2636 break;
2637 }
2638}
2639
2640static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
2641
2642/* This does an initial reset of an OmniVision sensor and ensures that I2C
2643 * is synchronized. Returns <0 on failure.
2644 */
2645static int init_ov_sensor(struct sd *sd, u8 slave)
2646{
2647 int i;
2648
2649 ov51x_set_slave_ids(sd, slave);
2650
2651 /* Reset the sensor */
2652 i2c_w(sd, 0x12, 0x80);
2653
2654 /* Wait for it to initialize */
2655 msleep(150);
2656
2657 for (i = 0; i < i2c_detect_tries; i++) {
2658 if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
2659 i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
2660 PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
2661 return 0;
2662 }
2663
2664 /* Reset the sensor */
2665 i2c_w(sd, 0x12, 0x80);
2666
2667 /* Wait for it to initialize */
2668 msleep(150);
2669
2670 /* Dummy read to sync I2C */
2671 if (i2c_r(sd, 0x00) < 0)
2672 return -1;
2673 }
2674 return -1;
2675}
2676
2677/* Set the read and write slave IDs. The "slave" argument is the write slave,
2678 * and the read slave will be set to (slave + 1).
2679 * This should not be called from outside the i2c I/O functions.
2680 * Sets I2C read and write slave IDs. Returns <0 for error
2681 */
2682static void ov51x_set_slave_ids(struct sd *sd,
2683 u8 slave)
2684{
2685 switch (sd->bridge) {
2686 case BRIDGE_OVFX2:
2687 reg_w(sd, OVFX2_I2C_ADDR, slave);
2688 return;
2689 case BRIDGE_W9968CF:
2690 sd->sensor_addr = slave;
2691 return;
2692 }
2693
2694 reg_w(sd, R51x_I2C_W_SID, slave);
2695 reg_w(sd, R51x_I2C_R_SID, slave + 1);
2696}
2697
2698static void write_regvals(struct sd *sd,
2699 const struct ov_regvals *regvals,
2700 int n)
2701{
2702 while (--n >= 0) {
2703 reg_w(sd, regvals->reg, regvals->val);
2704 regvals++;
2705 }
2706}
2707
2708static void write_i2c_regvals(struct sd *sd,
2709 const struct ov_i2c_regvals *regvals,
2710 int n)
2711{
2712 while (--n >= 0) {
2713 i2c_w(sd, regvals->reg, regvals->val);
2714 regvals++;
2715 }
2716}
2717
2718/****************************************************************************
2719 *
2720 * OV511 and sensor configuration
2721 *
2722 ***************************************************************************/
2723
2724/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
2725static void ov_hires_configure(struct sd *sd)
2726{
2727 int high, low;
2728
2729 if (sd->bridge != BRIDGE_OVFX2) {
2730 err("error hires sensors only supported with ovfx2");
2731 return;
2732 }
2733
2734 PDEBUG(D_PROBE, "starting ov hires configuration");
2735
2736 /* Detect sensor (sub)type */
2737 high = i2c_r(sd, 0x0a);
2738 low = i2c_r(sd, 0x0b);
2739 /* info("%x, %x", high, low); */
2740 switch (high) {
2741 case 0x96:
2742 switch (low) {
2743 case 0x40:
2744 PDEBUG(D_PROBE, "Sensor is a OV2610");
2745 sd->sensor = SEN_OV2610;
2746 return;
2747 case 0x41:
2748 PDEBUG(D_PROBE, "Sensor is a OV2610AE");
2749 sd->sensor = SEN_OV2610AE;
2750 return;
2751 case 0xb1:
2752 PDEBUG(D_PROBE, "Sensor is a OV9600");
2753 sd->sensor = SEN_OV9600;
2754 return;
2755 }
2756 break;
2757 case 0x36:
2758 if ((low & 0x0f) == 0x00) {
2759 PDEBUG(D_PROBE, "Sensor is a OV3610");
2760 sd->sensor = SEN_OV3610;
2761 return;
2762 }
2763 break;
2764 }
2765 err("Error unknown sensor type: %02x%02x", high, low);
2766}
2767
2768/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
2769 * the same register settings as the OV8610, since they are very similar.
2770 */
2771static void ov8xx0_configure(struct sd *sd)
2772{
2773 int rc;
2774
2775 PDEBUG(D_PROBE, "starting ov8xx0 configuration");
2776
2777 /* Detect sensor (sub)type */
2778 rc = i2c_r(sd, OV7610_REG_COM_I);
2779 if (rc < 0) {
2780 PDEBUG(D_ERR, "Error detecting sensor type");
2781 return;
2782 }
2783 if ((rc & 3) == 1)
2784 sd->sensor = SEN_OV8610;
2785 else
2786 err("Unknown image sensor version: %d", rc & 3);
2787}
2788
2789/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
2790 * the same register settings as the OV7610, since they are very similar.
2791 */
2792static void ov7xx0_configure(struct sd *sd)
2793{
2794 int rc, high, low;
2795
2796 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
2797
2798 /* Detect sensor (sub)type */
2799 rc = i2c_r(sd, OV7610_REG_COM_I);
2800
2801 /* add OV7670 here
2802 * it appears to be wrongly detected as a 7610 by default */
2803 if (rc < 0) {
2804 PDEBUG(D_ERR, "Error detecting sensor type");
2805 return;
2806 }
2807 if ((rc & 3) == 3) {
2808 /* quick hack to make OV7670s work */
2809 high = i2c_r(sd, 0x0a);
2810 low = i2c_r(sd, 0x0b);
2811 /* info("%x, %x", high, low); */
2812 if (high == 0x76 && (low & 0xf0) == 0x70) {
2813 PDEBUG(D_PROBE, "Sensor is an OV76%02x", low);
2814 sd->sensor = SEN_OV7670;
2815 } else {
2816 PDEBUG(D_PROBE, "Sensor is an OV7610");
2817 sd->sensor = SEN_OV7610;
2818 }
2819 } else if ((rc & 3) == 1) {
2820 /* I don't know what's different about the 76BE yet. */
2821 if (i2c_r(sd, 0x15) & 1) {
2822 PDEBUG(D_PROBE, "Sensor is an OV7620AE");
2823 sd->sensor = SEN_OV7620AE;
2824 } else {
2825 PDEBUG(D_PROBE, "Sensor is an OV76BE");
2826 sd->sensor = SEN_OV76BE;
2827 }
2828 } else if ((rc & 3) == 0) {
2829 /* try to read product id registers */
2830 high = i2c_r(sd, 0x0a);
2831 if (high < 0) {
2832 PDEBUG(D_ERR, "Error detecting camera chip PID");
2833 return;
2834 }
2835 low = i2c_r(sd, 0x0b);
2836 if (low < 0) {
2837 PDEBUG(D_ERR, "Error detecting camera chip VER");
2838 return;
2839 }
2840 if (high == 0x76) {
2841 switch (low) {
2842 case 0x30:
2843 err("Sensor is an OV7630/OV7635");
2844 err("7630 is not supported by this driver");
2845 return;
2846 case 0x40:
2847 PDEBUG(D_PROBE, "Sensor is an OV7645");
2848 sd->sensor = SEN_OV7640; /* FIXME */
2849 break;
2850 case 0x45:
2851 PDEBUG(D_PROBE, "Sensor is an OV7645B");
2852 sd->sensor = SEN_OV7640; /* FIXME */
2853 break;
2854 case 0x48:
2855 PDEBUG(D_PROBE, "Sensor is an OV7648");
2856 sd->sensor = SEN_OV7648;
2857 break;
2858 case 0x60:
2859 PDEBUG(D_PROBE, "Sensor is a OV7660");
2860 sd->sensor = SEN_OV7660;
2861 break;
2862 default:
2863 PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
2864 return;
2865 }
2866 } else {
2867 PDEBUG(D_PROBE, "Sensor is an OV7620");
2868 sd->sensor = SEN_OV7620;
2869 }
2870 } else {
2871 err("Unknown image sensor version: %d", rc & 3);
2872 }
2873}
2874
2875/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
2876static void ov6xx0_configure(struct sd *sd)
2877{
2878 int rc;
2879 PDEBUG(D_PROBE, "starting OV6xx0 configuration");
2880
2881 /* Detect sensor (sub)type */
2882 rc = i2c_r(sd, OV7610_REG_COM_I);
2883 if (rc < 0) {
2884 PDEBUG(D_ERR, "Error detecting sensor type");
2885 return;
2886 }
2887
2888 /* Ugh. The first two bits are the version bits, but
2889 * the entire register value must be used. I guess OVT
2890 * underestimated how many variants they would make. */
2891 switch (rc) {
2892 case 0x00:
2893 sd->sensor = SEN_OV6630;
2894 warn("WARNING: Sensor is an OV66308. Your camera may have");
2895 warn("been misdetected in previous driver versions.");
2896 break;
2897 case 0x01:
2898 sd->sensor = SEN_OV6620;
2899 PDEBUG(D_PROBE, "Sensor is an OV6620");
2900 break;
2901 case 0x02:
2902 sd->sensor = SEN_OV6630;
2903 PDEBUG(D_PROBE, "Sensor is an OV66308AE");
2904 break;
2905 case 0x03:
2906 sd->sensor = SEN_OV66308AF;
2907 PDEBUG(D_PROBE, "Sensor is an OV66308AF");
2908 break;
2909 case 0x90:
2910 sd->sensor = SEN_OV6630;
2911 warn("WARNING: Sensor is an OV66307. Your camera may have");
2912 warn("been misdetected in previous driver versions.");
2913 break;
2914 default:
2915 err("FATAL: Unknown sensor version: 0x%02x", rc);
2916 return;
2917 }
2918
2919 /* Set sensor-specific vars */
2920 sd->sif = 1;
2921}
2922
2923/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
2924static void ov51x_led_control(struct sd *sd, int on)
2925{
2926 if (sd->invert_led)
2927 on = !on;
2928
2929 switch (sd->bridge) {
2930 /* OV511 has no LED control */
2931 case BRIDGE_OV511PLUS:
2932 reg_w(sd, R511_SYS_LED_CTL, on);
2933 break;
2934 case BRIDGE_OV518:
2935 case BRIDGE_OV518PLUS:
2936 reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
2937 break;
2938 case BRIDGE_OV519:
2939 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
2940 break;
2941 }
2942}
2943
2944static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
2945{
2946 struct sd *sd = (struct sd *) gspca_dev;
2947
2948 if (!sd->snapshot_needs_reset)
2949 return;
2950
2951 /* Note it is important that we clear sd->snapshot_needs_reset,
2952 before actually clearing the snapshot state in the bridge
2953 otherwise we might race with the pkt_scan interrupt handler */
2954 sd->snapshot_needs_reset = 0;
2955
2956 switch (sd->bridge) {
2957 case BRIDGE_OV511:
2958 case BRIDGE_OV511PLUS:
2959 reg_w(sd, R51x_SYS_SNAP, 0x02);
2960 reg_w(sd, R51x_SYS_SNAP, 0x00);
2961 break;
2962 case BRIDGE_OV518:
2963 case BRIDGE_OV518PLUS:
2964 reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */
2965 reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */
2966 break;
2967 case BRIDGE_OV519:
2968 reg_w(sd, R51x_SYS_RESET, 0x40);
2969 reg_w(sd, R51x_SYS_RESET, 0x00);
2970 break;
2971 }
2972}
2973
2974static void ov51x_upload_quan_tables(struct sd *sd)
2975{
2976 const unsigned char yQuanTable511[] = {
2977 0, 1, 1, 2, 2, 3, 3, 4,
2978 1, 1, 1, 2, 2, 3, 4, 4,
2979 1, 1, 2, 2, 3, 4, 4, 4,
2980 2, 2, 2, 3, 4, 4, 4, 4,
2981 2, 2, 3, 4, 4, 5, 5, 5,
2982 3, 3, 4, 4, 5, 5, 5, 5,
2983 3, 4, 4, 4, 5, 5, 5, 5,
2984 4, 4, 4, 4, 5, 5, 5, 5
2985 };
2986
2987 const unsigned char uvQuanTable511[] = {
2988 0, 2, 2, 3, 4, 4, 4, 4,
2989 2, 2, 2, 4, 4, 4, 4, 4,
2990 2, 2, 3, 4, 4, 4, 4, 4,
2991 3, 4, 4, 4, 4, 4, 4, 4,
2992 4, 4, 4, 4, 4, 4, 4, 4,
2993 4, 4, 4, 4, 4, 4, 4, 4,
2994 4, 4, 4, 4, 4, 4, 4, 4,
2995 4, 4, 4, 4, 4, 4, 4, 4
2996 };
2997
2998 /* OV518 quantization tables are 8x4 (instead of 8x8) */
2999 const unsigned char yQuanTable518[] = {
3000 5, 4, 5, 6, 6, 7, 7, 7,
3001 5, 5, 5, 5, 6, 7, 7, 7,
3002 6, 6, 6, 6, 7, 7, 7, 8,
3003 7, 7, 6, 7, 7, 7, 8, 8
3004 };
3005 const unsigned char uvQuanTable518[] = {
3006 6, 6, 6, 7, 7, 7, 7, 7,
3007 6, 6, 6, 7, 7, 7, 7, 7,
3008 6, 6, 6, 7, 7, 7, 7, 8,
3009 7, 7, 7, 7, 7, 7, 8, 8
3010 };
3011
3012 const unsigned char *pYTable, *pUVTable;
3013 unsigned char val0, val1;
3014 int i, size, reg = R51x_COMP_LUT_BEGIN;
3015
3016 PDEBUG(D_PROBE, "Uploading quantization tables");
3017
3018 if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
3019 pYTable = yQuanTable511;
3020 pUVTable = uvQuanTable511;
3021 size = 32;
3022 } else {
3023 pYTable = yQuanTable518;
3024 pUVTable = uvQuanTable518;
3025 size = 16;
3026 }
3027
3028 for (i = 0; i < size; i++) {
3029 val0 = *pYTable++;
3030 val1 = *pYTable++;
3031 val0 &= 0x0f;
3032 val1 &= 0x0f;
3033 val0 |= val1 << 4;
3034 reg_w(sd, reg, val0);
3035
3036 val0 = *pUVTable++;
3037 val1 = *pUVTable++;
3038 val0 &= 0x0f;
3039 val1 &= 0x0f;
3040 val0 |= val1 << 4;
3041 reg_w(sd, reg + size, val0);
3042
3043 reg++;
3044 }
3045}
3046
3047/* This initializes the OV511/OV511+ and the sensor */
3048static void ov511_configure(struct gspca_dev *gspca_dev)
3049{
3050 struct sd *sd = (struct sd *) gspca_dev;
3051
3052 /* For 511 and 511+ */
3053 const struct ov_regvals init_511[] = {
3054 { R51x_SYS_RESET, 0x7f },
3055 { R51x_SYS_INIT, 0x01 },
3056 { R51x_SYS_RESET, 0x7f },
3057 { R51x_SYS_INIT, 0x01 },
3058 { R51x_SYS_RESET, 0x3f },
3059 { R51x_SYS_INIT, 0x01 },
3060 { R51x_SYS_RESET, 0x3d },
3061 };
3062
3063 const struct ov_regvals norm_511[] = {
3064 { R511_DRAM_FLOW_CTL, 0x01 },
3065 { R51x_SYS_SNAP, 0x00 },
3066 { R51x_SYS_SNAP, 0x02 },
3067 { R51x_SYS_SNAP, 0x00 },
3068 { R511_FIFO_OPTS, 0x1f },
3069 { R511_COMP_EN, 0x00 },
3070 { R511_COMP_LUT_EN, 0x03 },
3071 };
3072
3073 const struct ov_regvals norm_511_p[] = {
3074 { R511_DRAM_FLOW_CTL, 0xff },
3075 { R51x_SYS_SNAP, 0x00 },
3076 { R51x_SYS_SNAP, 0x02 },
3077 { R51x_SYS_SNAP, 0x00 },
3078 { R511_FIFO_OPTS, 0xff },
3079 { R511_COMP_EN, 0x00 },
3080 { R511_COMP_LUT_EN, 0x03 },
3081 };
3082
3083 const struct ov_regvals compress_511[] = {
3084 { 0x70, 0x1f },
3085 { 0x71, 0x05 },
3086 { 0x72, 0x06 },
3087 { 0x73, 0x06 },
3088 { 0x74, 0x14 },
3089 { 0x75, 0x03 },
3090 { 0x76, 0x04 },
3091 { 0x77, 0x04 },
3092 };
3093
3094 PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
3095
3096 write_regvals(sd, init_511, ARRAY_SIZE(init_511));
3097
3098 switch (sd->bridge) {
3099 case BRIDGE_OV511:
3100 write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
3101 break;
3102 case BRIDGE_OV511PLUS:
3103 write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
3104 break;
3105 }
3106
3107 /* Init compression */
3108 write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
3109
3110 ov51x_upload_quan_tables(sd);
3111}
3112
3113/* This initializes the OV518/OV518+ and the sensor */
3114static void ov518_configure(struct gspca_dev *gspca_dev)
3115{
3116 struct sd *sd = (struct sd *) gspca_dev;
3117
3118 /* For 518 and 518+ */
3119 const struct ov_regvals init_518[] = {
3120 { R51x_SYS_RESET, 0x40 },
3121 { R51x_SYS_INIT, 0xe1 },
3122 { R51x_SYS_RESET, 0x3e },
3123 { R51x_SYS_INIT, 0xe1 },
3124 { R51x_SYS_RESET, 0x00 },
3125 { R51x_SYS_INIT, 0xe1 },
3126 { 0x46, 0x00 },
3127 { 0x5d, 0x03 },
3128 };
3129
3130 const struct ov_regvals norm_518[] = {
3131 { R51x_SYS_SNAP, 0x02 }, /* Reset */
3132 { R51x_SYS_SNAP, 0x01 }, /* Enable */
3133 { 0x31, 0x0f },
3134 { 0x5d, 0x03 },
3135 { 0x24, 0x9f },
3136 { 0x25, 0x90 },
3137 { 0x20, 0x00 },
3138 { 0x51, 0x04 },
3139 { 0x71, 0x19 },
3140 { 0x2f, 0x80 },
3141 };
3142
3143 const struct ov_regvals norm_518_p[] = {
3144 { R51x_SYS_SNAP, 0x02 }, /* Reset */
3145 { R51x_SYS_SNAP, 0x01 }, /* Enable */
3146 { 0x31, 0x0f },
3147 { 0x5d, 0x03 },
3148 { 0x24, 0x9f },
3149 { 0x25, 0x90 },
3150 { 0x20, 0x60 },
3151 { 0x51, 0x02 },
3152 { 0x71, 0x19 },
3153 { 0x40, 0xff },
3154 { 0x41, 0x42 },
3155 { 0x46, 0x00 },
3156 { 0x33, 0x04 },
3157 { 0x21, 0x19 },
3158 { 0x3f, 0x10 },
3159 { 0x2f, 0x80 },
3160 };
3161
3162 /* First 5 bits of custom ID reg are a revision ID on OV518 */
3163 PDEBUG(D_PROBE, "Device revision %d",
3164 0x1f & reg_r(sd, R51x_SYS_CUST_ID));
3165
3166 write_regvals(sd, init_518, ARRAY_SIZE(init_518));
3167
3168 /* Set LED GPIO pin to output mode */
3169 reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
3170
3171 switch (sd->bridge) {
3172 case BRIDGE_OV518:
3173 write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
3174 break;
3175 case BRIDGE_OV518PLUS:
3176 write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
3177 break;
3178 }
3179
3180 ov51x_upload_quan_tables(sd);
3181
3182 reg_w(sd, 0x2f, 0x80);
3183}
3184
3185static void ov519_configure(struct sd *sd)
3186{
3187 static const struct ov_regvals init_519[] = {
3188 { 0x5a, 0x6d }, /* EnableSystem */
3189 { 0x53, 0x9b }, /* don't enable the microcontroller */
3190 { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
3191 { 0x5d, 0x03 },
3192 { 0x49, 0x01 },
3193 { 0x48, 0x00 },
3194 /* Set LED pin to output mode. Bit 4 must be cleared or sensor
3195 * detection will fail. This deserves further investigation. */
3196 { OV519_GPIO_IO_CTRL0, 0xee },
3197 { OV519_R51_RESET1, 0x0f },
3198 { OV519_R51_RESET1, 0x00 },
3199 { 0x22, 0x00 },
3200 /* windows reads 0x55 at this point*/
3201 };
3202
3203 write_regvals(sd, init_519, ARRAY_SIZE(init_519));
3204}
3205
3206static void ovfx2_configure(struct sd *sd)
3207{
3208 static const struct ov_regvals init_fx2[] = {
3209 { 0x00, 0x60 },
3210 { 0x02, 0x01 },
3211 { 0x0f, 0x1d },
3212 { 0xe9, 0x82 },
3213 { 0xea, 0xc7 },
3214 { 0xeb, 0x10 },
3215 { 0xec, 0xf6 },
3216 };
3217
3218 sd->stopped = 1;
3219
3220 write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
3221}
3222
3223/* set the mode */
3224/* This function works for ov7660 only */
3225static void ov519_set_mode(struct sd *sd)
3226{
3227 static const struct ov_regvals bridge_ov7660[2][10] = {
3228 {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
3229 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
3230 {0x25, 0x01}, {0x26, 0x00}},
3231 {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
3232 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
3233 {0x25, 0x03}, {0x26, 0x00}}
3234 };
3235 static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
3236 {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
3237 {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
3238 };
3239 static const struct ov_i2c_regvals sensor_ov7660_2[] = {
3240 {OV7670_R17_HSTART, 0x13},
3241 {OV7670_R18_HSTOP, 0x01},
3242 {OV7670_R32_HREF, 0x92},
3243 {OV7670_R19_VSTART, 0x02},
3244 {OV7670_R1A_VSTOP, 0x7a},
3245 {OV7670_R03_VREF, 0x00},
3246/* {0x33, 0x00}, */
3247/* {0x34, 0x07}, */
3248/* {0x36, 0x00}, */
3249/* {0x6b, 0x0a}, */
3250 };
3251
3252 write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
3253 ARRAY_SIZE(bridge_ov7660[0]));
3254 write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
3255 ARRAY_SIZE(sensor_ov7660[0]));
3256 write_i2c_regvals(sd, sensor_ov7660_2,
3257 ARRAY_SIZE(sensor_ov7660_2));
3258}
3259
3260/* set the frame rate */
3261/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
3262static void ov519_set_fr(struct sd *sd)
3263{
3264 int fr;
3265 u8 clock;
3266 /* frame rate table with indices:
3267 * - mode = 0: 320x240, 1: 640x480
3268 * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
3269 * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
3270 */
3271 static const u8 fr_tb[2][6][3] = {
3272 {{0x04, 0xff, 0x00},
3273 {0x04, 0x1f, 0x00},
3274 {0x04, 0x1b, 0x00},
3275 {0x04, 0x15, 0x00},
3276 {0x04, 0x09, 0x00},
3277 {0x04, 0x01, 0x00}},
3278 {{0x0c, 0xff, 0x00},
3279 {0x0c, 0x1f, 0x00},
3280 {0x0c, 0x1b, 0x00},
3281 {0x04, 0xff, 0x01},
3282 {0x04, 0x1f, 0x01},
3283 {0x04, 0x1b, 0x01}},
3284 };
3285
3286 if (frame_rate > 0)
3287 sd->frame_rate = frame_rate;
3288 if (sd->frame_rate >= 30)
3289 fr = 0;
3290 else if (sd->frame_rate >= 25)
3291 fr = 1;
3292 else if (sd->frame_rate >= 20)
3293 fr = 2;
3294 else if (sd->frame_rate >= 15)
3295 fr = 3;
3296 else if (sd->frame_rate >= 10)
3297 fr = 4;
3298 else
3299 fr = 5;
3300 reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
3301 reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
3302 clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
3303 if (sd->sensor == SEN_OV7660)
3304 clock |= 0x80; /* enable double clock */
3305 ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
3306}
3307
3308static void setautogain(struct gspca_dev *gspca_dev)
3309{
3310 struct sd *sd = (struct sd *) gspca_dev;
3311
3312 i2c_w_mask(sd, 0x13, sd->ctrls[AUTOGAIN].val ? 0x05 : 0x00, 0x05);
3313}
3314
3315/* this function is called at probe time */
3316static int sd_config(struct gspca_dev *gspca_dev,
3317 const struct usb_device_id *id)
3318{
3319 struct sd *sd = (struct sd *) gspca_dev;
3320 struct cam *cam = &gspca_dev->cam;
3321
3322 sd->bridge = id->driver_info & BRIDGE_MASK;
3323 sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
3324
3325 switch (sd->bridge) {
3326 case BRIDGE_OV511:
3327 case BRIDGE_OV511PLUS:
3328 cam->cam_mode = ov511_vga_mode;
3329 cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
3330 break;
3331 case BRIDGE_OV518:
3332 case BRIDGE_OV518PLUS:
3333 cam->cam_mode = ov518_vga_mode;
3334 cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
3335 break;
3336 case BRIDGE_OV519:
3337 cam->cam_mode = ov519_vga_mode;
3338 cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
3339 break;
3340 case BRIDGE_OVFX2:
3341 cam->cam_mode = ov519_vga_mode;
3342 cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
3343 cam->bulk_size = OVFX2_BULK_SIZE;
3344 cam->bulk_nurbs = MAX_NURBS;
3345 cam->bulk = 1;
3346 break;
3347 case BRIDGE_W9968CF:
3348 cam->cam_mode = w9968cf_vga_mode;
3349 cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
3350 cam->reverse_alts = 1;
3351 break;
3352 }
3353
3354 gspca_dev->cam.ctrls = sd->ctrls;
3355 sd->quality = QUALITY_DEF;
3356 sd->frame_rate = 15;
3357
3358 return 0;
3359}
3360
3361/* this function is called at probe and resume time */
3362static int sd_init(struct gspca_dev *gspca_dev)
3363{
3364 struct sd *sd = (struct sd *) gspca_dev;
3365 struct cam *cam = &gspca_dev->cam;
3366
3367 switch (sd->bridge) {
3368 case BRIDGE_OV511:
3369 case BRIDGE_OV511PLUS:
3370 ov511_configure(gspca_dev);
3371 break;
3372 case BRIDGE_OV518:
3373 case BRIDGE_OV518PLUS:
3374 ov518_configure(gspca_dev);
3375 break;
3376 case BRIDGE_OV519:
3377 ov519_configure(sd);
3378 break;
3379 case BRIDGE_OVFX2:
3380 ovfx2_configure(sd);
3381 break;
3382 case BRIDGE_W9968CF:
3383 w9968cf_configure(sd);
3384 break;
3385 }
3386
3387 /* The OV519 must be more aggressive about sensor detection since
3388 * I2C write will never fail if the sensor is not present. We have
3389 * to try to initialize the sensor to detect its presence */
3390 sd->sensor = -1;
3391
3392 /* Test for 76xx */
3393 if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
3394 ov7xx0_configure(sd);
3395
3396 /* Test for 6xx0 */
3397 } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
3398 ov6xx0_configure(sd);
3399
3400 /* Test for 8xx0 */
3401 } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
3402 ov8xx0_configure(sd);
3403
3404 /* Test for 3xxx / 2xxx */
3405 } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
3406 ov_hires_configure(sd);
3407 } else {
3408 err("Can't determine sensor slave IDs");
3409 goto error;
3410 }
3411
3412 if (sd->sensor < 0)
3413 goto error;
3414
3415 ov51x_led_control(sd, 0); /* turn LED off */
3416
3417 switch (sd->bridge) {
3418 case BRIDGE_OV511:
3419 case BRIDGE_OV511PLUS:
3420 if (sd->sif) {
3421 cam->cam_mode = ov511_sif_mode;
3422 cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
3423 }
3424 break;
3425 case BRIDGE_OV518:
3426 case BRIDGE_OV518PLUS:
3427 if (sd->sif) {
3428 cam->cam_mode = ov518_sif_mode;
3429 cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
3430 }
3431 break;
3432 case BRIDGE_OV519:
3433 if (sd->sif) {
3434 cam->cam_mode = ov519_sif_mode;
3435 cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
3436 }
3437 break;
3438 case BRIDGE_OVFX2:
3439 switch (sd->sensor) {
3440 case SEN_OV2610:
3441 case SEN_OV2610AE:
3442 cam->cam_mode = ovfx2_ov2610_mode;
3443 cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode);
3444 break;
3445 case SEN_OV3610:
3446 cam->cam_mode = ovfx2_ov3610_mode;
3447 cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
3448 break;
3449 case SEN_OV9600:
3450 cam->cam_mode = ovfx2_ov9600_mode;
3451 cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
3452 break;
3453 default:
3454 if (sd->sif) {
3455 cam->cam_mode = ov519_sif_mode;
3456 cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
3457 }
3458 break;
3459 }
3460 break;
3461 case BRIDGE_W9968CF:
3462 if (sd->sif)
3463 cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
3464
3465 /* w9968cf needs initialisation once the sensor is known */
3466 w9968cf_init(sd);
3467 break;
3468 }
3469
3470 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
3471
3472 /* initialize the sensor */
3473 switch (sd->sensor) {
3474 case SEN_OV2610:
3475 write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
3476
3477 /* Enable autogain, autoexpo, awb, bandfilter */
3478 i2c_w_mask(sd, 0x13, 0x27, 0x27);
3479 break;
3480 case SEN_OV2610AE:
3481 write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae));
3482
3483 /* enable autoexpo */
3484 i2c_w_mask(sd, 0x13, 0x05, 0x05);
3485 break;
3486 case SEN_OV3610:
3487 write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
3488
3489 /* Enable autogain, autoexpo, awb, bandfilter */
3490 i2c_w_mask(sd, 0x13, 0x27, 0x27);
3491 break;
3492 case SEN_OV6620:
3493 write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
3494 break;
3495 case SEN_OV6630:
3496 case SEN_OV66308AF:
3497 sd->ctrls[CONTRAST].def = 200;
3498 /* The default is too low for the ov6630 */
3499 write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
3500 break;
3501 default:
3502/* case SEN_OV7610: */
3503/* case SEN_OV76BE: */
3504 write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
3505 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
3506 break;
3507 case SEN_OV7620:
3508 case SEN_OV7620AE:
3509 write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
3510 break;
3511 case SEN_OV7640:
3512 case SEN_OV7648:
3513 write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
3514 break;
3515 case SEN_OV7660:
3516 i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
3517 msleep(14);
3518 reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
3519 write_regvals(sd, init_519_ov7660,
3520 ARRAY_SIZE(init_519_ov7660));
3521 write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
3522 sd->gspca_dev.curr_mode = 1; /* 640x480 */
3523 ov519_set_mode(sd);
3524 ov519_set_fr(sd);
3525 sd->ctrls[COLORS].max = 4; /* 0..4 */
3526 sd->ctrls[COLORS].val =
3527 sd->ctrls[COLORS].def = 2;
3528 setcolors(gspca_dev);
3529 sd->ctrls[CONTRAST].max = 6; /* 0..6 */
3530 sd->ctrls[CONTRAST].val =
3531 sd->ctrls[CONTRAST].def = 3;
3532 setcontrast(gspca_dev);
3533 sd->ctrls[BRIGHTNESS].max = 6; /* 0..6 */
3534 sd->ctrls[BRIGHTNESS].val =
3535 sd->ctrls[BRIGHTNESS].def = 3;
3536 setbrightness(gspca_dev);
3537 sd_reset_snapshot(gspca_dev);
3538 ov51x_restart(sd);
3539 ov51x_stop(sd); /* not in win traces */
3540 ov51x_led_control(sd, 0);
3541 break;
3542 case SEN_OV7670:
3543 sd->ctrls[FREQ].max = 3; /* auto */
3544 sd->ctrls[FREQ].def = 3;
3545 write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
3546 break;
3547 case SEN_OV8610:
3548 write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
3549 break;
3550 case SEN_OV9600:
3551 write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
3552
3553 /* enable autoexpo */
3554/* i2c_w_mask(sd, 0x13, 0x05, 0x05); */
3555 break;
3556 }
3557 return gspca_dev->usb_err;
3558error:
3559 PDEBUG(D_ERR, "OV519 Config failed");
3560 return -EINVAL;
3561}
3562
3563/* function called at start time before URB creation */
3564static int sd_isoc_init(struct gspca_dev *gspca_dev)
3565{
3566 struct sd *sd = (struct sd *) gspca_dev;
3567
3568 switch (sd->bridge) {
3569 case BRIDGE_OVFX2:
3570 if (gspca_dev->width != 800)
3571 gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
3572 else
3573 gspca_dev->cam.bulk_size = 7 * 4096;
3574 break;
3575 }
3576 return 0;
3577}
3578
3579/* Set up the OV511/OV511+ with the given image parameters.
3580 *
3581 * Do not put any sensor-specific code in here (including I2C I/O functions)
3582 */
3583static void ov511_mode_init_regs(struct sd *sd)
3584{
3585 int hsegs, vsegs, packet_size, fps, needed;
3586 int interlaced = 0;
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 err("Couldn't get altsetting");
3594 sd->gspca_dev.usb_err = -EIO;
3595 return;
3596 }
3597
3598 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
3599 reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
3600
3601 reg_w(sd, R511_CAM_UV_EN, 0x01);
3602 reg_w(sd, R511_SNAP_UV_EN, 0x01);
3603 reg_w(sd, R511_SNAP_OPTS, 0x03);
3604
3605 /* Here I'm assuming that snapshot size == image size.
3606 * I hope that's always true. --claudio
3607 */
3608 hsegs = (sd->gspca_dev.width >> 3) - 1;
3609 vsegs = (sd->gspca_dev.height >> 3) - 1;
3610
3611 reg_w(sd, R511_CAM_PXCNT, hsegs);
3612 reg_w(sd, R511_CAM_LNCNT, vsegs);
3613 reg_w(sd, R511_CAM_PXDIV, 0x00);
3614 reg_w(sd, R511_CAM_LNDIV, 0x00);
3615
3616 /* YUV420, low pass filter on */
3617 reg_w(sd, R511_CAM_OPTS, 0x03);
3618
3619 /* Snapshot additions */
3620 reg_w(sd, R511_SNAP_PXCNT, hsegs);
3621 reg_w(sd, R511_SNAP_LNCNT, vsegs);
3622 reg_w(sd, R511_SNAP_PXDIV, 0x00);
3623 reg_w(sd, R511_SNAP_LNDIV, 0x00);
3624
3625 /******** Set the framerate ********/
3626 if (frame_rate > 0)
3627 sd->frame_rate = frame_rate;
3628
3629 switch (sd->sensor) {
3630 case SEN_OV6620:
3631 /* No framerate control, doesn't like higher rates yet */
3632 sd->clockdiv = 3;
3633 break;
3634
3635 /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
3636 for more sensors we need to do this for them too */
3637 case SEN_OV7620:
3638 case SEN_OV7620AE:
3639 case SEN_OV7640:
3640 case SEN_OV7648:
3641 case SEN_OV76BE:
3642 if (sd->gspca_dev.width == 320)
3643 interlaced = 1;
3644 /* Fall through */
3645 case SEN_OV6630:
3646 case SEN_OV7610:
3647 case SEN_OV7670:
3648 switch (sd->frame_rate) {
3649 case 30:
3650 case 25:
3651 /* Not enough bandwidth to do 640x480 @ 30 fps */
3652 if (sd->gspca_dev.width != 640) {
3653 sd->clockdiv = 0;
3654 break;
3655 }
3656 /* Fall through for 640x480 case */
3657 default:
3658/* case 20: */
3659/* case 15: */
3660 sd->clockdiv = 1;
3661 break;
3662 case 10:
3663 sd->clockdiv = 2;
3664 break;
3665 case 5:
3666 sd->clockdiv = 5;
3667 break;
3668 }
3669 if (interlaced) {
3670 sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
3671 /* Higher then 10 does not work */
3672 if (sd->clockdiv > 10)
3673 sd->clockdiv = 10;
3674 }
3675 break;
3676
3677 case SEN_OV8610:
3678 /* No framerate control ?? */
3679 sd->clockdiv = 0;
3680 break;
3681 }
3682
3683 /* Check if we have enough bandwidth to disable compression */
3684 fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
3685 needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
3686 /* 1400 is a conservative estimate of the max nr of isoc packets/sec */
3687 if (needed > 1400 * packet_size) {
3688 /* Enable Y and UV quantization and compression */
3689 reg_w(sd, R511_COMP_EN, 0x07);
3690 reg_w(sd, R511_COMP_LUT_EN, 0x03);
3691 } else {
3692 reg_w(sd, R511_COMP_EN, 0x06);
3693 reg_w(sd, R511_COMP_LUT_EN, 0x00);
3694 }
3695
3696 reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
3697 reg_w(sd, R51x_SYS_RESET, 0);
3698}
3699
3700/* Sets up the OV518/OV518+ with the given image parameters
3701 *
3702 * OV518 needs a completely different approach, until we can figure out what
3703 * the individual registers do. Also, only 15 FPS is supported now.
3704 *
3705 * Do not put any sensor-specific code in here (including I2C I/O functions)
3706 */
3707static void ov518_mode_init_regs(struct sd *sd)
3708{
3709 int hsegs, vsegs, packet_size;
3710 struct usb_host_interface *alt;
3711 struct usb_interface *intf;
3712
3713 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
3714 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
3715 if (!alt) {
3716 err("Couldn't get altsetting");
3717 sd->gspca_dev.usb_err = -EIO;
3718 return;
3719 }
3720
3721 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
3722 ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
3723
3724 /******** Set the mode ********/
3725 reg_w(sd, 0x2b, 0);
3726 reg_w(sd, 0x2c, 0);
3727 reg_w(sd, 0x2d, 0);
3728 reg_w(sd, 0x2e, 0);
3729 reg_w(sd, 0x3b, 0);
3730 reg_w(sd, 0x3c, 0);
3731 reg_w(sd, 0x3d, 0);
3732 reg_w(sd, 0x3e, 0);
3733
3734 if (sd->bridge == BRIDGE_OV518) {
3735 /* Set 8-bit (YVYU) input format */
3736 reg_w_mask(sd, 0x20, 0x08, 0x08);
3737
3738 /* Set 12-bit (4:2:0) output format */
3739 reg_w_mask(sd, 0x28, 0x80, 0xf0);
3740 reg_w_mask(sd, 0x38, 0x80, 0xf0);
3741 } else {
3742 reg_w(sd, 0x28, 0x80);
3743 reg_w(sd, 0x38, 0x80);
3744 }
3745
3746 hsegs = sd->gspca_dev.width / 16;
3747 vsegs = sd->gspca_dev.height / 4;
3748
3749 reg_w(sd, 0x29, hsegs);
3750 reg_w(sd, 0x2a, vsegs);
3751
3752 reg_w(sd, 0x39, hsegs);
3753 reg_w(sd, 0x3a, vsegs);
3754
3755 /* Windows driver does this here; who knows why */
3756 reg_w(sd, 0x2f, 0x80);
3757
3758 /******** Set the framerate ********/
3759 sd->clockdiv = 1;
3760
3761 /* Mode independent, but framerate dependent, regs */
3762 /* 0x51: Clock divider; Only works on some cams which use 2 crystals */
3763 reg_w(sd, 0x51, 0x04);
3764 reg_w(sd, 0x22, 0x18);
3765 reg_w(sd, 0x23, 0xff);
3766
3767 if (sd->bridge == BRIDGE_OV518PLUS) {
3768 switch (sd->sensor) {
3769 case SEN_OV7620AE:
3770 if (sd->gspca_dev.width == 320) {
3771 reg_w(sd, 0x20, 0x00);
3772 reg_w(sd, 0x21, 0x19);
3773 } else {
3774 reg_w(sd, 0x20, 0x60);
3775 reg_w(sd, 0x21, 0x1f);
3776 }
3777 break;
3778 case SEN_OV7620:
3779 reg_w(sd, 0x20, 0x00);
3780 reg_w(sd, 0x21, 0x19);
3781 break;
3782 default:
3783 reg_w(sd, 0x21, 0x19);
3784 }
3785 } else
3786 reg_w(sd, 0x71, 0x17); /* Compression-related? */
3787
3788 /* FIXME: Sensor-specific */
3789 /* Bit 5 is what matters here. Of course, it is "reserved" */
3790 i2c_w(sd, 0x54, 0x23);
3791
3792 reg_w(sd, 0x2f, 0x80);
3793
3794 if (sd->bridge == BRIDGE_OV518PLUS) {
3795 reg_w(sd, 0x24, 0x94);
3796 reg_w(sd, 0x25, 0x90);
3797 ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
3798 ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */
3799 ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */
3800 ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */
3801 ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */
3802 ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */
3803 ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */
3804 ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */
3805 ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */
3806 } else {
3807 reg_w(sd, 0x24, 0x9f);
3808 reg_w(sd, 0x25, 0x90);
3809 ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */
3810 ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */
3811 ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */
3812 ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */
3813 ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */
3814 ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */
3815 ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */
3816 ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */
3817 ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */
3818 }
3819
3820 reg_w(sd, 0x2f, 0x80);
3821}
3822
3823/* Sets up the OV519 with the given image parameters
3824 *
3825 * OV519 needs a completely different approach, until we can figure out what
3826 * the individual registers do.
3827 *
3828 * Do not put any sensor-specific code in here (including I2C I/O functions)
3829 */
3830static void ov519_mode_init_regs(struct sd *sd)
3831{
3832 static const struct ov_regvals mode_init_519_ov7670[] = {
3833 { 0x5d, 0x03 }, /* Turn off suspend mode */
3834 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
3835 { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
3836 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
3837 { 0xa3, 0x18 },
3838 { 0xa4, 0x04 },
3839 { 0xa5, 0x28 },
3840 { 0x37, 0x00 }, /* SetUsbInit */
3841 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
3842 /* Enable both fields, YUV Input, disable defect comp (why?) */
3843 { 0x20, 0x0c },
3844 { 0x21, 0x38 },
3845 { 0x22, 0x1d },
3846 { 0x17, 0x50 }, /* undocumented */
3847 { 0x37, 0x00 }, /* undocumented */
3848 { 0x40, 0xff }, /* I2C timeout counter */
3849 { 0x46, 0x00 }, /* I2C clock prescaler */
3850 { 0x59, 0x04 }, /* new from windrv 090403 */
3851 { 0xff, 0x00 }, /* undocumented */
3852 /* windows reads 0x55 at this point, why? */
3853 };
3854
3855 static const struct ov_regvals mode_init_519[] = {
3856 { 0x5d, 0x03 }, /* Turn off suspend mode */
3857 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
3858 { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
3859 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
3860 { 0xa3, 0x18 },
3861 { 0xa4, 0x04 },
3862 { 0xa5, 0x28 },
3863 { 0x37, 0x00 }, /* SetUsbInit */
3864 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
3865 /* Enable both fields, YUV Input, disable defect comp (why?) */
3866 { 0x22, 0x1d },
3867 { 0x17, 0x50 }, /* undocumented */
3868 { 0x37, 0x00 }, /* undocumented */
3869 { 0x40, 0xff }, /* I2C timeout counter */
3870 { 0x46, 0x00 }, /* I2C clock prescaler */
3871 { 0x59, 0x04 }, /* new from windrv 090403 */
3872 { 0xff, 0x00 }, /* undocumented */
3873 /* windows reads 0x55 at this point, why? */
3874 };
3875
3876 /******** Set the mode ********/
3877 switch (sd->sensor) {
3878 default:
3879 write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
3880 if (sd->sensor == SEN_OV7640 ||
3881 sd->sensor == SEN_OV7648) {
3882 /* Select 8-bit input mode */
3883 reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
3884 }
3885 break;
3886 case SEN_OV7660:
3887 return; /* done by ov519_set_mode/fr() */
3888 case SEN_OV7670:
3889 write_regvals(sd, mode_init_519_ov7670,
3890 ARRAY_SIZE(mode_init_519_ov7670));
3891 break;
3892 }
3893
3894 reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
3895 reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3);
3896 if (sd->sensor == SEN_OV7670 &&
3897 sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
3898 reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
3899 else if (sd->sensor == SEN_OV7648 &&
3900 sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
3901 reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
3902 else
3903 reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
3904 reg_w(sd, OV519_R13_X_OFFSETH, 0x00);
3905 reg_w(sd, OV519_R14_Y_OFFSETL, 0x00);
3906 reg_w(sd, OV519_R15_Y_OFFSETH, 0x00);
3907 reg_w(sd, OV519_R16_DIVIDER, 0x00);
3908 reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */
3909 reg_w(sd, 0x26, 0x00); /* Undocumented */
3910
3911 /******** Set the framerate ********/
3912 if (frame_rate > 0)
3913 sd->frame_rate = frame_rate;
3914
3915/* FIXME: These are only valid at the max resolution. */
3916 sd->clockdiv = 0;
3917 switch (sd->sensor) {
3918 case SEN_OV7640:
3919 case SEN_OV7648:
3920 switch (sd->frame_rate) {
3921 default:
3922/* case 30: */
3923 reg_w(sd, 0xa4, 0x0c);
3924 reg_w(sd, 0x23, 0xff);
3925 break;
3926 case 25:
3927 reg_w(sd, 0xa4, 0x0c);
3928 reg_w(sd, 0x23, 0x1f);
3929 break;
3930 case 20:
3931 reg_w(sd, 0xa4, 0x0c);
3932 reg_w(sd, 0x23, 0x1b);
3933 break;
3934 case 15:
3935 reg_w(sd, 0xa4, 0x04);
3936 reg_w(sd, 0x23, 0xff);
3937 sd->clockdiv = 1;
3938 break;
3939 case 10:
3940 reg_w(sd, 0xa4, 0x04);
3941 reg_w(sd, 0x23, 0x1f);
3942 sd->clockdiv = 1;
3943 break;
3944 case 5:
3945 reg_w(sd, 0xa4, 0x04);
3946 reg_w(sd, 0x23, 0x1b);
3947 sd->clockdiv = 1;
3948 break;
3949 }
3950 break;
3951 case SEN_OV8610:
3952 switch (sd->frame_rate) {
3953 default: /* 15 fps */
3954/* case 15: */
3955 reg_w(sd, 0xa4, 0x06);
3956 reg_w(sd, 0x23, 0xff);
3957 break;
3958 case 10:
3959 reg_w(sd, 0xa4, 0x06);
3960 reg_w(sd, 0x23, 0x1f);
3961 break;
3962 case 5:
3963 reg_w(sd, 0xa4, 0x06);
3964 reg_w(sd, 0x23, 0x1b);
3965 break;
3966 }
3967 break;
3968 case SEN_OV7670: /* guesses, based on 7640 */
3969 PDEBUG(D_STREAM, "Setting framerate to %d fps",
3970 (sd->frame_rate == 0) ? 15 : sd->frame_rate);
3971 reg_w(sd, 0xa4, 0x10);
3972 switch (sd->frame_rate) {
3973 case 30:
3974 reg_w(sd, 0x23, 0xff);
3975 break;
3976 case 20:
3977 reg_w(sd, 0x23, 0x1b);
3978 break;
3979 default:
3980/* case 15: */
3981 reg_w(sd, 0x23, 0xff);
3982 sd->clockdiv = 1;
3983 break;
3984 }
3985 break;
3986 }
3987}
3988
3989static void mode_init_ov_sensor_regs(struct sd *sd)
3990{
3991 struct gspca_dev *gspca_dev;
3992 int qvga, xstart, xend, ystart, yend;
3993 u8 v;
3994
3995 gspca_dev = &sd->gspca_dev;
3996 qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
3997
3998 /******** Mode (VGA/QVGA) and sensor specific regs ********/
3999 switch (sd->sensor) {
4000 case SEN_OV2610:
4001 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4002 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
4003 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
4004 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
4005 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
4006 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
4007 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
4008 return;
4009 case SEN_OV2610AE: {
4010 u8 v;
4011
4012 /* frame rates:
4013 * 10fps / 5 fps for 1600x1200
4014 * 40fps / 20fps for 800x600
4015 */
4016 v = 80;
4017 if (qvga) {
4018 if (sd->frame_rate < 25)
4019 v = 0x81;
4020 } else {
4021 if (sd->frame_rate < 10)
4022 v = 0x81;
4023 }
4024 i2c_w(sd, 0x11, v);
4025 i2c_w(sd, 0x12, qvga ? 0x60 : 0x20);
4026 return;
4027 }
4028 case SEN_OV3610:
4029 if (qvga) {
4030 xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
4031 ystart = (776 - gspca_dev->height) / 2;
4032 } else {
4033 xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4);
4034 ystart = (1544 - gspca_dev->height) / 2;
4035 }
4036 xend = xstart + gspca_dev->width;
4037 yend = ystart + gspca_dev->height;
4038 /* Writing to the COMH register resets the other windowing regs
4039 to their default values, so we must do this first. */
4040 i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0);
4041 i2c_w_mask(sd, 0x32,
4042 (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7),
4043 0x3f);
4044 i2c_w_mask(sd, 0x03,
4045 (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3),
4046 0x0f);
4047 i2c_w(sd, 0x17, xstart >> 4);
4048 i2c_w(sd, 0x18, xend >> 4);
4049 i2c_w(sd, 0x19, ystart >> 3);
4050 i2c_w(sd, 0x1a, yend >> 3);
4051 return;
4052 case SEN_OV8610:
4053 /* For OV8610 qvga means qsvga */
4054 i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
4055 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
4056 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4057 i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */
4058 i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */
4059 break;
4060 case SEN_OV7610:
4061 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4062 i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
4063 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
4064 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4065 break;
4066 case SEN_OV7620:
4067 case SEN_OV7620AE:
4068 case SEN_OV76BE:
4069 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4070 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
4071 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
4072 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
4073 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
4074 i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
4075 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
4076 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
4077 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4078 if (sd->sensor == SEN_OV76BE)
4079 i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
4080 break;
4081 case SEN_OV7640:
4082 case SEN_OV7648:
4083 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4084 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
4085 /* Setting this undocumented bit in qvga mode removes a very
4086 annoying vertical shaking of the image */
4087 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
4088 /* Unknown */
4089 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
4090 /* Allow higher automatic gain (to allow higher framerates) */
4091 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
4092 i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
4093 break;
4094 case SEN_OV7670:
4095 /* set COM7_FMT_VGA or COM7_FMT_QVGA
4096 * do we need to set anything else?
4097 * HSTART etc are set in set_ov_sensor_window itself */
4098 i2c_w_mask(sd, OV7670_R12_COM7,
4099 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
4100 OV7670_COM7_FMT_MASK);
4101 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
4102 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
4103 OV7670_COM8_AWB);
4104 if (qvga) { /* QVGA from ov7670.c by
4105 * Jonathan Corbet */
4106 xstart = 164;
4107 xend = 28;
4108 ystart = 14;
4109 yend = 494;
4110 } else { /* VGA */
4111 xstart = 158;
4112 xend = 14;
4113 ystart = 10;
4114 yend = 490;
4115 }
4116 /* OV7670 hardware window registers are split across
4117 * multiple locations */
4118 i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
4119 i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
4120 v = i2c_r(sd, OV7670_R32_HREF);
4121 v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
4122 msleep(10); /* need to sleep between read and write to
4123 * same reg! */
4124 i2c_w(sd, OV7670_R32_HREF, v);
4125
4126 i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
4127 i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
4128 v = i2c_r(sd, OV7670_R03_VREF);
4129 v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
4130 msleep(10); /* need to sleep between read and write to
4131 * same reg! */
4132 i2c_w(sd, OV7670_R03_VREF, v);
4133 break;
4134 case SEN_OV6620:
4135 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4136 i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
4137 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4138 break;
4139 case SEN_OV6630:
4140 case SEN_OV66308AF:
4141 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
4142 i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
4143 break;
4144 case SEN_OV9600: {
4145 const struct ov_i2c_regvals *vals;
4146 static const struct ov_i2c_regvals sxga_15[] = {
4147 {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
4148 };
4149 static const struct ov_i2c_regvals sxga_7_5[] = {
4150 {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
4151 };
4152 static const struct ov_i2c_regvals vga_30[] = {
4153 {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
4154 };
4155 static const struct ov_i2c_regvals vga_15[] = {
4156 {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
4157 };
4158
4159 /* frame rates:
4160 * 15fps / 7.5 fps for 1280x1024
4161 * 30fps / 15fps for 640x480
4162 */
4163 i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
4164 if (qvga)
4165 vals = sd->frame_rate < 30 ? vga_15 : vga_30;
4166 else
4167 vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
4168 write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
4169 return;
4170 }
4171 default:
4172 return;
4173 }
4174
4175 /******** Clock programming ********/
4176 i2c_w(sd, 0x11, sd->clockdiv);
4177}
4178
4179/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
4180static void sethvflip(struct gspca_dev *gspca_dev)
4181{
4182 struct sd *sd = (struct sd *) gspca_dev;
4183
4184 if (sd->gspca_dev.streaming)
4185 reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */
4186 i2c_w_mask(sd, OV7670_R1E_MVFP,
4187 OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val
4188 | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val,
4189 OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
4190 if (sd->gspca_dev.streaming)
4191 reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */
4192}
4193
4194static void set_ov_sensor_window(struct sd *sd)
4195{
4196 struct gspca_dev *gspca_dev;
4197 int qvga, crop;
4198 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
4199
4200 /* mode setup is fully handled in mode_init_ov_sensor_regs for these */
4201 switch (sd->sensor) {
4202 case SEN_OV2610:
4203 case SEN_OV2610AE:
4204 case SEN_OV3610:
4205 case SEN_OV7670:
4206 case SEN_OV9600:
4207 mode_init_ov_sensor_regs(sd);
4208 return;
4209 case SEN_OV7660:
4210 ov519_set_mode(sd);
4211 ov519_set_fr(sd);
4212 return;
4213 }
4214
4215 gspca_dev = &sd->gspca_dev;
4216 qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
4217 crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
4218
4219 /* The different sensor ICs handle setting up of window differently.
4220 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
4221 switch (sd->sensor) {
4222 case SEN_OV8610:
4223 hwsbase = 0x1e;
4224 hwebase = 0x1e;
4225 vwsbase = 0x02;
4226 vwebase = 0x02;
4227 break;
4228 case SEN_OV7610:
4229 case SEN_OV76BE:
4230 hwsbase = 0x38;
4231 hwebase = 0x3a;
4232 vwsbase = vwebase = 0x05;
4233 break;
4234 case SEN_OV6620:
4235 case SEN_OV6630:
4236 case SEN_OV66308AF:
4237 hwsbase = 0x38;
4238 hwebase = 0x3a;
4239 vwsbase = 0x05;
4240 vwebase = 0x06;
4241 if (sd->sensor == SEN_OV66308AF && qvga)
4242 /* HDG: this fixes U and V getting swapped */
4243 hwsbase++;
4244 if (crop) {
4245 hwsbase += 8;
4246 hwebase += 8;
4247 vwsbase += 11;
4248 vwebase += 11;
4249 }
4250 break;
4251 case SEN_OV7620:
4252 case SEN_OV7620AE:
4253 hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
4254 hwebase = 0x2f;
4255 vwsbase = vwebase = 0x05;
4256 break;
4257 case SEN_OV7640:
4258 case SEN_OV7648:
4259 hwsbase = 0x1a;
4260 hwebase = 0x1a;
4261 vwsbase = vwebase = 0x03;
4262 break;
4263 default:
4264 return;
4265 }
4266
4267 switch (sd->sensor) {
4268 case SEN_OV6620:
4269 case SEN_OV6630:
4270 case SEN_OV66308AF:
4271 if (qvga) { /* QCIF */
4272 hwscale = 0;
4273 vwscale = 0;
4274 } else { /* CIF */
4275 hwscale = 1;
4276 vwscale = 1; /* The datasheet says 0;
4277 * it's wrong */
4278 }
4279 break;
4280 case SEN_OV8610:
4281 if (qvga) { /* QSVGA */
4282 hwscale = 1;
4283 vwscale = 1;
4284 } else { /* SVGA */
4285 hwscale = 2;
4286 vwscale = 2;
4287 }
4288 break;
4289 default: /* SEN_OV7xx0 */
4290 if (qvga) { /* QVGA */
4291 hwscale = 1;
4292 vwscale = 0;
4293 } else { /* VGA */
4294 hwscale = 2;
4295 vwscale = 1;
4296 }
4297 }
4298
4299 mode_init_ov_sensor_regs(sd);
4300
4301 i2c_w(sd, 0x17, hwsbase);
4302 i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
4303 i2c_w(sd, 0x19, vwsbase);
4304 i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
4305}
4306
4307/* -- start the camera -- */
4308static int sd_start(struct gspca_dev *gspca_dev)
4309{
4310 struct sd *sd = (struct sd *) gspca_dev;
4311
4312 /* Default for most bridges, allow bridge_mode_init_regs to override */
4313 sd->sensor_width = sd->gspca_dev.width;
4314 sd->sensor_height = sd->gspca_dev.height;
4315
4316 switch (sd->bridge) {
4317 case BRIDGE_OV511:
4318 case BRIDGE_OV511PLUS:
4319 ov511_mode_init_regs(sd);
4320 break;
4321 case BRIDGE_OV518:
4322 case BRIDGE_OV518PLUS:
4323 ov518_mode_init_regs(sd);
4324 break;
4325 case BRIDGE_OV519:
4326 ov519_mode_init_regs(sd);
4327 break;
4328 /* case BRIDGE_OVFX2: nothing to do */
4329 case BRIDGE_W9968CF:
4330 w9968cf_mode_init_regs(sd);
4331 break;
4332 }
4333
4334 set_ov_sensor_window(sd);
4335
4336 if (!(sd->gspca_dev.ctrl_dis & (1 << CONTRAST)))
4337 setcontrast(gspca_dev);
4338 if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS)))
4339 setbrightness(gspca_dev);
4340 if (!(sd->gspca_dev.ctrl_dis & (1 << EXPOSURE)))
4341 setexposure(gspca_dev);
4342 if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS)))
4343 setcolors(gspca_dev);
4344 if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP))))
4345 sethvflip(gspca_dev);
4346 if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT)))
4347 setautobright(gspca_dev);
4348 if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOGAIN)))
4349 setautogain(gspca_dev);
4350 if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ)))
4351 setfreq_i(sd);
4352
4353 /* Force clear snapshot state in case the snapshot button was
4354 pressed while we weren't streaming */
4355 sd->snapshot_needs_reset = 1;
4356 sd_reset_snapshot(gspca_dev);
4357
4358 sd->first_frame = 3;
4359
4360 ov51x_restart(sd);
4361 ov51x_led_control(sd, 1);
4362 return gspca_dev->usb_err;
4363}
4364
4365static void sd_stopN(struct gspca_dev *gspca_dev)
4366{
4367 struct sd *sd = (struct sd *) gspca_dev;
4368
4369 ov51x_stop(sd);
4370 ov51x_led_control(sd, 0);
4371}
4372
4373static void sd_stop0(struct gspca_dev *gspca_dev)
4374{
4375 struct sd *sd = (struct sd *) gspca_dev;
4376
4377 if (!sd->gspca_dev.present)
4378 return;
4379 if (sd->bridge == BRIDGE_W9968CF)
4380 w9968cf_stop0(sd);
4381
4382#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
4383 /* If the last button state is pressed, release it now! */
4384 if (sd->snapshot_pressed) {
4385 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
4386 input_sync(gspca_dev->input_dev);
4387 sd->snapshot_pressed = 0;
4388 }
4389#endif
4390 if (sd->bridge == BRIDGE_OV519)
4391 reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
4392}
4393
4394static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
4395{
4396 struct sd *sd = (struct sd *) gspca_dev;
4397
4398 if (sd->snapshot_pressed != state) {
4399#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
4400 input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
4401 input_sync(gspca_dev->input_dev);
4402#endif
4403 if (state)
4404 sd->snapshot_needs_reset = 1;
4405
4406 sd->snapshot_pressed = state;
4407 } else {
4408 /* On the ov511 / ov519 we need to reset the button state
4409 multiple times, as resetting does not work as long as the
4410 button stays pressed */
4411 switch (sd->bridge) {
4412 case BRIDGE_OV511:
4413 case BRIDGE_OV511PLUS:
4414 case BRIDGE_OV519:
4415 if (state)
4416 sd->snapshot_needs_reset = 1;
4417 break;
4418 }
4419 }
4420}
4421
4422static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
4423 u8 *in, /* isoc packet */
4424 int len) /* iso packet length */
4425{
4426 struct sd *sd = (struct sd *) gspca_dev;
4427
4428 /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
4429 * byte non-zero. The EOF packet has image width/height in the
4430 * 10th and 11th bytes. The 9th byte is given as follows:
4431 *
4432 * bit 7: EOF
4433 * 6: compression enabled
4434 * 5: 422/420/400 modes
4435 * 4: 422/420/400 modes
4436 * 3: 1
4437 * 2: snapshot button on
4438 * 1: snapshot frame
4439 * 0: even/odd field
4440 */
4441 if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
4442 (in[8] & 0x08)) {
4443 ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
4444 if (in[8] & 0x80) {
4445 /* Frame end */
4446 if ((in[9] + 1) * 8 != gspca_dev->width ||
4447 (in[10] + 1) * 8 != gspca_dev->height) {
4448 PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
4449 " requested: %dx%d\n",
4450 (in[9] + 1) * 8, (in[10] + 1) * 8,
4451 gspca_dev->width, gspca_dev->height);
4452 gspca_dev->last_packet_type = DISCARD_PACKET;
4453 return;
4454 }
4455 /* Add 11 byte footer to frame, might be useful */
4456 gspca_frame_add(gspca_dev, LAST_PACKET, in, 11);
4457 return;
4458 } else {
4459 /* Frame start */
4460 gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0);
4461 sd->packet_nr = 0;
4462 }
4463 }
4464
4465 /* Ignore the packet number */
4466 len--;
4467
4468 /* intermediate packet */
4469 gspca_frame_add(gspca_dev, INTER_PACKET, in, len);
4470}
4471
4472static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
4473 u8 *data, /* isoc packet */
4474 int len) /* iso packet length */
4475{
4476 struct sd *sd = (struct sd *) gspca_dev;
4477
4478 /* A false positive here is likely, until OVT gives me
4479 * the definitive SOF/EOF format */
4480 if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
4481 ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1);
4482 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
4483 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
4484 sd->packet_nr = 0;
4485 }
4486
4487 if (gspca_dev->last_packet_type == DISCARD_PACKET)
4488 return;
4489
4490 /* Does this device use packet numbers ? */
4491 if (len & 7) {
4492 len--;
4493 if (sd->packet_nr == data[len])
4494 sd->packet_nr++;
4495 /* The last few packets of the frame (which are all 0's
4496 except that they may contain part of the footer), are
4497 numbered 0 */
4498 else if (sd->packet_nr == 0 || data[len]) {
4499 PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
4500 (int)data[len], (int)sd->packet_nr);
4501 gspca_dev->last_packet_type = DISCARD_PACKET;
4502 return;
4503 }
4504 }
4505
4506 /* intermediate packet */
4507 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4508}
4509
4510static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
4511 u8 *data, /* isoc packet */
4512 int len) /* iso packet length */
4513{
4514 /* Header of ov519 is 16 bytes:
4515 * Byte Value Description
4516 * 0 0xff magic
4517 * 1 0xff magic
4518 * 2 0xff magic
4519 * 3 0xXX 0x50 = SOF, 0x51 = EOF
4520 * 9 0xXX 0x01 initial frame without data,
4521 * 0x00 standard frame with image
4522 * 14 Lo in EOF: length of image data / 8
4523 * 15 Hi
4524 */
4525
4526 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
4527 switch (data[3]) {
4528 case 0x50: /* start of frame */
4529 /* Don't check the button state here, as the state
4530 usually (always ?) changes at EOF and checking it
4531 here leads to unnecessary snapshot state resets. */
4532#define HDRSZ 16
4533 data += HDRSZ;
4534 len -= HDRSZ;
4535#undef HDRSZ
4536 if (data[0] == 0xff || data[1] == 0xd8)
4537 gspca_frame_add(gspca_dev, FIRST_PACKET,
4538 data, len);
4539 else
4540 gspca_dev->last_packet_type = DISCARD_PACKET;
4541 return;
4542 case 0x51: /* end of frame */
4543 ov51x_handle_button(gspca_dev, data[11] & 1);
4544 if (data[9] != 0)
4545 gspca_dev->last_packet_type = DISCARD_PACKET;
4546 gspca_frame_add(gspca_dev, LAST_PACKET,
4547 NULL, 0);
4548 return;
4549 }
4550 }
4551
4552 /* intermediate packet */
4553 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4554}
4555
4556static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
4557 u8 *data, /* isoc packet */
4558 int len) /* iso packet length */
4559{
4560 struct sd *sd = (struct sd *) gspca_dev;
4561
4562 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4563
4564 /* A short read signals EOF */
4565 if (len < gspca_dev->cam.bulk_size) {
4566 /* If the frame is short, and it is one of the first ones
4567 the sensor and bridge are still syncing, so drop it. */
4568 if (sd->first_frame) {
4569 sd->first_frame--;
4570 if (gspca_dev->image_len <
4571 sd->gspca_dev.width * sd->gspca_dev.height)
4572 gspca_dev->last_packet_type = DISCARD_PACKET;
4573 }
4574 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
4575 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
4576 }
4577}
4578
4579static void sd_pkt_scan(struct gspca_dev *gspca_dev,
4580 u8 *data, /* isoc packet */
4581 int len) /* iso packet length */
4582{
4583 struct sd *sd = (struct sd *) gspca_dev;
4584
4585 switch (sd->bridge) {
4586 case BRIDGE_OV511:
4587 case BRIDGE_OV511PLUS:
4588 ov511_pkt_scan(gspca_dev, data, len);
4589 break;
4590 case BRIDGE_OV518:
4591 case BRIDGE_OV518PLUS:
4592 ov518_pkt_scan(gspca_dev, data, len);
4593 break;
4594 case BRIDGE_OV519:
4595 ov519_pkt_scan(gspca_dev, data, len);
4596 break;
4597 case BRIDGE_OVFX2:
4598 ovfx2_pkt_scan(gspca_dev, data, len);
4599 break;
4600 case BRIDGE_W9968CF:
4601 w9968cf_pkt_scan(gspca_dev, data, len);
4602 break;
4603 }
4604}
4605
4606/* -- management routines -- */
4607
4608static void setbrightness(struct gspca_dev *gspca_dev)
4609{
4610 struct sd *sd = (struct sd *) gspca_dev;
4611 int val;
4612 static const struct ov_i2c_regvals brit_7660[][7] = {
4613 {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
4614 {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
4615 {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
4616 {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
4617 {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
4618 {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
4619 {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
4620 {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
4621 {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
4622 {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
4623 {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
4624 {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
4625 {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
4626 {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
4627 };
4628
4629 val = sd->ctrls[BRIGHTNESS].val;
4630 switch (sd->sensor) {
4631 case SEN_OV8610:
4632 case SEN_OV7610:
4633 case SEN_OV76BE:
4634 case SEN_OV6620:
4635 case SEN_OV6630:
4636 case SEN_OV66308AF:
4637 case SEN_OV7640:
4638 case SEN_OV7648:
4639 i2c_w(sd, OV7610_REG_BRT, val);
4640 break;
4641 case SEN_OV7620:
4642 case SEN_OV7620AE:
4643 /* 7620 doesn't like manual changes when in auto mode */
4644 if (!sd->ctrls[AUTOBRIGHT].val)
4645 i2c_w(sd, OV7610_REG_BRT, val);
4646 break;
4647 case SEN_OV7660:
4648 write_i2c_regvals(sd, brit_7660[val],
4649 ARRAY_SIZE(brit_7660[0]));
4650 break;
4651 case SEN_OV7670:
4652/*win trace
4653 * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
4654 i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
4655 break;
4656 }
4657}
4658
4659static void setcontrast(struct gspca_dev *gspca_dev)
4660{
4661 struct sd *sd = (struct sd *) gspca_dev;
4662 int val;
4663 static const struct ov_i2c_regvals contrast_7660[][31] = {
4664 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
4665 {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
4666 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
4667 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
4668 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
4669 {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
4670 {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
4671 {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
4672 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
4673 {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
4674 {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
4675 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
4676 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
4677 {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
4678 {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
4679 {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
4680 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
4681 {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
4682 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
4683 {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
4684 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
4685 {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
4686 {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
4687 {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
4688 {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
4689 {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
4690 {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
4691 {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
4692 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
4693 {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
4694 {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
4695 {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
4696 {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
4697 {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
4698 {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
4699 {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
4700 {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
4701 {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
4702 {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
4703 {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
4704 {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
4705 {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
4706 {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
4707 {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
4708 {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
4709 {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
4710 {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
4711 {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
4712 {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
4713 {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
4714 {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
4715 {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
4716 {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
4717 {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
4718 {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
4719 {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
4720 };
4721
4722 val = sd->ctrls[CONTRAST].val;
4723 switch (sd->sensor) {
4724 case SEN_OV7610:
4725 case SEN_OV6620:
4726 i2c_w(sd, OV7610_REG_CNT, val);
4727 break;
4728 case SEN_OV6630:
4729 case SEN_OV66308AF:
4730 i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
4731 break;
4732 case SEN_OV8610: {
4733 static const u8 ctab[] = {
4734 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
4735 };
4736
4737 /* Use Y gamma control instead. Bit 0 enables it. */
4738 i2c_w(sd, 0x64, ctab[val >> 5]);
4739 break;
4740 }
4741 case SEN_OV7620:
4742 case SEN_OV7620AE: {
4743 static const u8 ctab[] = {
4744 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
4745 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
4746 };
4747
4748 /* Use Y gamma control instead. Bit 0 enables it. */
4749 i2c_w(sd, 0x64, ctab[val >> 4]);
4750 break;
4751 }
4752 case SEN_OV7660:
4753 write_i2c_regvals(sd, contrast_7660[val],
4754 ARRAY_SIZE(contrast_7660[0]));
4755 break;
4756 case SEN_OV7670:
4757 /* check that this isn't just the same as ov7610 */
4758 i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
4759 break;
4760 }
4761}
4762
4763static void setexposure(struct gspca_dev *gspca_dev)
4764{
4765 struct sd *sd = (struct sd *) gspca_dev;
4766
4767 if (!sd->ctrls[AUTOGAIN].val)
4768 i2c_w(sd, 0x10, sd->ctrls[EXPOSURE].val);
4769}
4770
4771static void setcolors(struct gspca_dev *gspca_dev)
4772{
4773 struct sd *sd = (struct sd *) gspca_dev;
4774 int val;
4775 static const struct ov_i2c_regvals colors_7660[][6] = {
4776 {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
4777 {0x53, 0x19}, {0x54, 0x23}},
4778 {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
4779 {0x53, 0x2c}, {0x54, 0x3e}},
4780 {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
4781 {0x53, 0x40}, {0x54, 0x59}},
4782 {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
4783 {0x53, 0x53}, {0x54, 0x73}},
4784 {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
4785 {0x53, 0x66}, {0x54, 0x8e}},
4786 };
4787
4788 val = sd->ctrls[COLORS].val;
4789 switch (sd->sensor) {
4790 case SEN_OV8610:
4791 case SEN_OV7610:
4792 case SEN_OV76BE:
4793 case SEN_OV6620:
4794 case SEN_OV6630:
4795 case SEN_OV66308AF:
4796 i2c_w(sd, OV7610_REG_SAT, val);
4797 break;
4798 case SEN_OV7620:
4799 case SEN_OV7620AE:
4800 /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
4801/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
4802 if (rc < 0)
4803 goto out; */
4804 i2c_w(sd, OV7610_REG_SAT, val);
4805 break;
4806 case SEN_OV7640:
4807 case SEN_OV7648:
4808 i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
4809 break;
4810 case SEN_OV7660:
4811 write_i2c_regvals(sd, colors_7660[val],
4812 ARRAY_SIZE(colors_7660[0]));
4813 break;
4814 case SEN_OV7670:
4815 /* supported later once I work out how to do it
4816 * transparently fail now! */
4817 /* set REG_COM13 values for UV sat auto mode */
4818 break;
4819 }
4820}
4821
4822static void setautobright(struct gspca_dev *gspca_dev)
4823{
4824 struct sd *sd = (struct sd *) gspca_dev;
4825
4826 i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10);
4827}
4828
4829static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
4830{
4831 struct sd *sd = (struct sd *) gspca_dev;
4832
4833 sd->ctrls[AUTOGAIN].val = val;
4834 if (val) {
4835 gspca_dev->ctrl_inac |= (1 << EXPOSURE);
4836 } else {
4837 gspca_dev->ctrl_inac &= ~(1 << EXPOSURE);
4838 sd->ctrls[EXPOSURE].val = i2c_r(sd, 0x10);
4839 }
4840 if (gspca_dev->streaming)
4841 setautogain(gspca_dev);
4842 return gspca_dev->usb_err;
4843}
4844
4845static void setfreq_i(struct sd *sd)
4846{
4847 if (sd->sensor == SEN_OV7660
4848 || sd->sensor == SEN_OV7670) {
4849 switch (sd->ctrls[FREQ].val) {
4850 case 0: /* Banding filter disabled */
4851 i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
4852 break;
4853 case 1: /* 50 hz */
4854 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
4855 OV7670_COM8_BFILT);
4856 i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
4857 break;
4858 case 2: /* 60 hz */
4859 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
4860 OV7670_COM8_BFILT);
4861 i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
4862 break;
4863 case 3: /* Auto hz - ov7670 only */
4864 i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
4865 OV7670_COM8_BFILT);
4866 i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
4867 0x18);
4868 break;
4869 }
4870 } else {
4871 switch (sd->ctrls[FREQ].val) {
4872 case 0: /* Banding filter disabled */
4873 i2c_w_mask(sd, 0x2d, 0x00, 0x04);
4874 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
4875 break;
4876 case 1: /* 50 hz (filter on and framerate adj) */
4877 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
4878 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
4879 /* 20 fps -> 16.667 fps */
4880 if (sd->sensor == SEN_OV6620 ||
4881 sd->sensor == SEN_OV6630 ||
4882 sd->sensor == SEN_OV66308AF)
4883 i2c_w(sd, 0x2b, 0x5e);
4884 else
4885 i2c_w(sd, 0x2b, 0xac);
4886 break;
4887 case 2: /* 60 hz (filter on, ...) */
4888 i2c_w_mask(sd, 0x2d, 0x04, 0x04);
4889 if (sd->sensor == SEN_OV6620 ||
4890 sd->sensor == SEN_OV6630 ||
4891 sd->sensor == SEN_OV66308AF) {
4892 /* 20 fps -> 15 fps */
4893 i2c_w_mask(sd, 0x2a, 0x80, 0x80);
4894 i2c_w(sd, 0x2b, 0xa8);
4895 } else {
4896 /* no framerate adj. */
4897 i2c_w_mask(sd, 0x2a, 0x00, 0x80);
4898 }
4899 break;
4900 }
4901 }
4902}
4903static void setfreq(struct gspca_dev *gspca_dev)
4904{
4905 struct sd *sd = (struct sd *) gspca_dev;
4906
4907 setfreq_i(sd);
4908
4909 /* Ugly but necessary */
4910 if (sd->bridge == BRIDGE_W9968CF)
4911 w9968cf_set_crop_window(sd);
4912}
4913
4914static int sd_querymenu(struct gspca_dev *gspca_dev,
4915 struct v4l2_querymenu *menu)
4916{
4917 struct sd *sd = (struct sd *) gspca_dev;
4918
4919 switch (menu->id) {
4920 case V4L2_CID_POWER_LINE_FREQUENCY:
4921 switch (menu->index) {
4922 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
4923 strcpy((char *) menu->name, "NoFliker");
4924 return 0;
4925 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
4926 strcpy((char *) menu->name, "50 Hz");
4927 return 0;
4928 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
4929 strcpy((char *) menu->name, "60 Hz");
4930 return 0;
4931 case 3:
4932 if (sd->sensor != SEN_OV7670)
4933 return -EINVAL;
4934
4935 strcpy((char *) menu->name, "Automatic");
4936 return 0;
4937 }
4938 break;
4939 }
4940 return -EINVAL;
4941}
4942
4943static int sd_get_jcomp(struct gspca_dev *gspca_dev,
4944 struct v4l2_jpegcompression *jcomp)
4945{
4946 struct sd *sd = (struct sd *) gspca_dev;
4947
4948 if (sd->bridge != BRIDGE_W9968CF)
4949 return -EINVAL;
4950
4951 memset(jcomp, 0, sizeof *jcomp);
4952 jcomp->quality = sd->quality;
4953 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
4954 V4L2_JPEG_MARKER_DRI;
4955 return 0;
4956}
4957
4958static int sd_set_jcomp(struct gspca_dev *gspca_dev,
4959 struct v4l2_jpegcompression *jcomp)
4960{
4961 struct sd *sd = (struct sd *) gspca_dev;
4962
4963 if (sd->bridge != BRIDGE_W9968CF)
4964 return -EINVAL;
4965
4966 if (gspca_dev->streaming)
4967 return -EBUSY;
4968
4969 if (jcomp->quality < QUALITY_MIN)
4970 sd->quality = QUALITY_MIN;
4971 else if (jcomp->quality > QUALITY_MAX)
4972 sd->quality = QUALITY_MAX;
4973 else
4974 sd->quality = jcomp->quality;
4975
4976 /* Return resulting jcomp params to app */
4977 sd_get_jcomp(gspca_dev, jcomp);
4978
4979 return 0;
4980}
4981
4982/* sub-driver description */
4983static const struct sd_desc sd_desc = {
4984 .name = MODULE_NAME,
4985 .ctrls = sd_ctrls,
4986 .nctrls = ARRAY_SIZE(sd_ctrls),
4987 .config = sd_config,
4988 .init = sd_init,
4989 .isoc_init = sd_isoc_init,
4990 .start = sd_start,
4991 .stopN = sd_stopN,
4992 .stop0 = sd_stop0,
4993 .pkt_scan = sd_pkt_scan,
4994 .dq_callback = sd_reset_snapshot,
4995 .querymenu = sd_querymenu,
4996 .get_jcomp = sd_get_jcomp,
4997 .set_jcomp = sd_set_jcomp,
4998#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
4999 .other_input = 1,
5000#endif
5001};
5002
5003/* -- module initialisation -- */
5004static const struct usb_device_id device_table[] = {
5005 {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
5006 {USB_DEVICE(0x041e, 0x4052),
5007 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
5008 {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
5009 {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
5010 {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
5011 {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
5012 {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
5013 {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
5014 {USB_DEVICE(0x045e, 0x028c),
5015 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
5016 {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
5017 {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
5018 {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
5019 {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
5020 {USB_DEVICE(0x05a9, 0x0519),
5021 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
5022 {USB_DEVICE(0x05a9, 0x0530),
5023 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
5024 {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
5025 {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
5026 {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
5027 {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
5028 {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
5029 {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
5030 {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
5031 {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
5032 {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
5033 {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
5034 {}
5035};
5036
5037MODULE_DEVICE_TABLE(usb, device_table);
5038
5039/* -- device connect -- */
5040static int sd_probe(struct usb_interface *intf,
5041 const struct usb_device_id *id)
5042{
5043 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
5044 THIS_MODULE);
5045}
5046
5047static struct usb_driver sd_driver = {
5048 .name = MODULE_NAME,
5049 .id_table = device_table,
5050 .probe = sd_probe,
5051 .disconnect = gspca_disconnect,
5052#ifdef CONFIG_PM
5053 .suspend = gspca_suspend,
5054 .resume = gspca_resume,
5055#endif
5056};
5057
5058/* -- module insert / remove -- */
5059static int __init sd_mod_init(void)
5060{
5061 return usb_register(&sd_driver);
5062}
5063static void __exit sd_mod_exit(void)
5064{
5065 usb_deregister(&sd_driver);
5066}
5067
5068module_init(sd_mod_init);
5069module_exit(sd_mod_exit);
5070
5071module_param(frame_rate, int, 0644);
5072MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
new file mode 100644
index 00000000000..0c6369b7fe1
--- /dev/null
+++ b/drivers/media/video/gspca/ov534.c
@@ -0,0 +1,1546 @@
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 MODULE_NAME "ov534"
32
33#include "gspca.h"
34
35#define OV534_REG_ADDRESS 0xf1 /* sensor address */
36#define OV534_REG_SUBADDR 0xf2
37#define OV534_REG_WRITE 0xf3
38#define OV534_REG_READ 0xf4
39#define OV534_REG_OPERATION 0xf5
40#define OV534_REG_STATUS 0xf6
41
42#define OV534_OP_WRITE_3 0x37
43#define OV534_OP_WRITE_2 0x33
44#define OV534_OP_READ_2 0xf9
45
46#define CTRL_TIMEOUT 500
47
48MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
49MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
50MODULE_LICENSE("GPL");
51
52/* controls */
53enum e_ctrl {
54 BRIGHTNESS,
55 CONTRAST,
56 GAIN,
57 EXPOSURE,
58 AGC,
59 AWB,
60 AEC,
61 SHARPNESS,
62 HFLIP,
63 VFLIP,
64 COLORS,
65 LIGHTFREQ,
66 NCTRLS /* number of controls */
67};
68
69/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev; /* !! must be the first item */
72
73 struct gspca_ctrl ctrls[NCTRLS];
74
75 __u32 last_pts;
76 u16 last_fid;
77 u8 frame_rate;
78
79 u8 sensor;
80};
81enum sensors {
82 SENSOR_OV767x,
83 SENSOR_OV772x,
84 NSENSORS
85};
86
87/* V4L2 controls supported by the driver */
88static void setbrightness(struct gspca_dev *gspca_dev);
89static void setcontrast(struct gspca_dev *gspca_dev);
90static void setgain(struct gspca_dev *gspca_dev);
91static void setexposure(struct gspca_dev *gspca_dev);
92static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val);
93static void setawb(struct gspca_dev *gspca_dev);
94static void setaec(struct gspca_dev *gspca_dev);
95static void setsharpness(struct gspca_dev *gspca_dev);
96static void sethvflip(struct gspca_dev *gspca_dev);
97static void setcolors(struct gspca_dev *gspca_dev);
98static void setlightfreq(struct gspca_dev *gspca_dev);
99
100static int sd_start(struct gspca_dev *gspca_dev);
101static void sd_stopN(struct gspca_dev *gspca_dev);
102
103static const struct ctrl sd_ctrls[] = {
104[BRIGHTNESS] = {
105 {
106 .id = V4L2_CID_BRIGHTNESS,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Brightness",
109 .minimum = 0,
110 .maximum = 255,
111 .step = 1,
112 .default_value = 0,
113 },
114 .set_control = setbrightness
115 },
116[CONTRAST] = {
117 {
118 .id = V4L2_CID_CONTRAST,
119 .type = V4L2_CTRL_TYPE_INTEGER,
120 .name = "Contrast",
121 .minimum = 0,
122 .maximum = 255,
123 .step = 1,
124 .default_value = 32,
125 },
126 .set_control = setcontrast
127 },
128[GAIN] = {
129 {
130 .id = V4L2_CID_GAIN,
131 .type = V4L2_CTRL_TYPE_INTEGER,
132 .name = "Main Gain",
133 .minimum = 0,
134 .maximum = 63,
135 .step = 1,
136 .default_value = 20,
137 },
138 .set_control = setgain
139 },
140[EXPOSURE] = {
141 {
142 .id = V4L2_CID_EXPOSURE,
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Exposure",
145 .minimum = 0,
146 .maximum = 255,
147 .step = 1,
148 .default_value = 120,
149 },
150 .set_control = setexposure
151 },
152[AGC] = {
153 {
154 .id = V4L2_CID_AUTOGAIN,
155 .type = V4L2_CTRL_TYPE_BOOLEAN,
156 .name = "Auto Gain",
157 .minimum = 0,
158 .maximum = 1,
159 .step = 1,
160 .default_value = 1,
161 },
162 .set = sd_setagc
163 },
164[AWB] = {
165 {
166 .id = V4L2_CID_AUTO_WHITE_BALANCE,
167 .type = V4L2_CTRL_TYPE_BOOLEAN,
168 .name = "Auto White Balance",
169 .minimum = 0,
170 .maximum = 1,
171 .step = 1,
172 .default_value = 1,
173 },
174 .set_control = setawb
175 },
176[AEC] = {
177 {
178 .id = V4L2_CID_EXPOSURE_AUTO,
179 .type = V4L2_CTRL_TYPE_BOOLEAN,
180 .name = "Auto Exposure",
181 .minimum = 0,
182 .maximum = 1,
183 .step = 1,
184 .default_value = 1,
185 },
186 .set_control = setaec
187 },
188[SHARPNESS] = {
189 {
190 .id = V4L2_CID_SHARPNESS,
191 .type = V4L2_CTRL_TYPE_INTEGER,
192 .name = "Sharpness",
193 .minimum = 0,
194 .maximum = 63,
195 .step = 1,
196 .default_value = 0,
197 },
198 .set_control = setsharpness
199 },
200[HFLIP] = {
201 {
202 .id = V4L2_CID_HFLIP,
203 .type = V4L2_CTRL_TYPE_BOOLEAN,
204 .name = "HFlip",
205 .minimum = 0,
206 .maximum = 1,
207 .step = 1,
208 .default_value = 0,
209 },
210 .set_control = sethvflip
211 },
212[VFLIP] = {
213 {
214 .id = V4L2_CID_VFLIP,
215 .type = V4L2_CTRL_TYPE_BOOLEAN,
216 .name = "VFlip",
217 .minimum = 0,
218 .maximum = 1,
219 .step = 1,
220 .default_value = 0,
221 },
222 .set_control = sethvflip
223 },
224[COLORS] = {
225 {
226 .id = V4L2_CID_SATURATION,
227 .type = V4L2_CTRL_TYPE_INTEGER,
228 .name = "Saturation",
229 .minimum = 0,
230 .maximum = 6,
231 .step = 1,
232 .default_value = 3,
233 },
234 .set_control = setcolors
235 },
236[LIGHTFREQ] = {
237 {
238 .id = V4L2_CID_POWER_LINE_FREQUENCY,
239 .type = V4L2_CTRL_TYPE_MENU,
240 .name = "Light Frequency Filter",
241 .minimum = 0,
242 .maximum = 1,
243 .step = 1,
244 .default_value = 0,
245 },
246 .set_control = setlightfreq
247 },
248};
249
250static const struct v4l2_pix_format ov772x_mode[] = {
251 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
252 .bytesperline = 320 * 2,
253 .sizeimage = 320 * 240 * 2,
254 .colorspace = V4L2_COLORSPACE_SRGB,
255 .priv = 1},
256 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
257 .bytesperline = 640 * 2,
258 .sizeimage = 640 * 480 * 2,
259 .colorspace = V4L2_COLORSPACE_SRGB,
260 .priv = 0},
261};
262static const struct v4l2_pix_format ov767x_mode[] = {
263 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
264 .bytesperline = 320,
265 .sizeimage = 320 * 240 * 3 / 8 + 590,
266 .colorspace = V4L2_COLORSPACE_JPEG},
267 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
268 .bytesperline = 640,
269 .sizeimage = 640 * 480 * 3 / 8 + 590,
270 .colorspace = V4L2_COLORSPACE_JPEG},
271};
272
273static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
274static const u8 vga_rates[] = {60, 50, 40, 30, 15};
275
276static const struct framerates ov772x_framerates[] = {
277 { /* 320x240 */
278 .rates = qvga_rates,
279 .nrates = ARRAY_SIZE(qvga_rates),
280 },
281 { /* 640x480 */
282 .rates = vga_rates,
283 .nrates = ARRAY_SIZE(vga_rates),
284 },
285};
286
287struct reg_array {
288 const u8 (*val)[2];
289 int len;
290};
291
292static const u8 bridge_init_767x[][2] = {
293/* comments from the ms-win file apollo7670.set */
294/* str1 */
295 {0xf1, 0x42},
296 {0x88, 0xf8},
297 {0x89, 0xff},
298 {0x76, 0x03},
299 {0x92, 0x03},
300 {0x95, 0x10},
301 {0xe2, 0x00},
302 {0xe7, 0x3e},
303 {0x8d, 0x1c},
304 {0x8e, 0x00},
305 {0x8f, 0x00},
306 {0x1f, 0x00},
307 {0xc3, 0xf9},
308 {0x89, 0xff},
309 {0x88, 0xf8},
310 {0x76, 0x03},
311 {0x92, 0x01},
312 {0x93, 0x18},
313 {0x1c, 0x00},
314 {0x1d, 0x48},
315 {0x1d, 0x00},
316 {0x1d, 0xff},
317 {0x1d, 0x02},
318 {0x1d, 0x58},
319 {0x1d, 0x00},
320 {0x1c, 0x0a},
321 {0x1d, 0x0a},
322 {0x1d, 0x0e},
323 {0xc0, 0x50}, /* HSize 640 */
324 {0xc1, 0x3c}, /* VSize 480 */
325 {0x34, 0x05}, /* enable Audio Suspend mode */
326 {0xc2, 0x0c}, /* Input YUV */
327 {0xc3, 0xf9}, /* enable PRE */
328 {0x34, 0x05}, /* enable Audio Suspend mode */
329 {0xe7, 0x2e}, /* this solves failure of "SuspendResumeTest" */
330 {0x31, 0xf9}, /* enable 1.8V Suspend */
331 {0x35, 0x02}, /* turn on JPEG */
332 {0xd9, 0x10},
333 {0x25, 0x42}, /* GPIO[8]:Input */
334 {0x94, 0x11}, /* If the default setting is loaded when
335 * system boots up, this flag is closed here */
336};
337static const u8 sensor_init_767x[][2] = {
338 {0x12, 0x80},
339 {0x11, 0x03},
340 {0x3a, 0x04},
341 {0x12, 0x00},
342 {0x17, 0x13},
343 {0x18, 0x01},
344 {0x32, 0xb6},
345 {0x19, 0x02},
346 {0x1a, 0x7a},
347 {0x03, 0x0a},
348 {0x0c, 0x00},
349 {0x3e, 0x00},
350 {0x70, 0x3a},
351 {0x71, 0x35},
352 {0x72, 0x11},
353 {0x73, 0xf0},
354 {0xa2, 0x02},
355 {0x7a, 0x2a}, /* set Gamma=1.6 below */
356 {0x7b, 0x12},
357 {0x7c, 0x1d},
358 {0x7d, 0x2d},
359 {0x7e, 0x45},
360 {0x7f, 0x50},
361 {0x80, 0x59},
362 {0x81, 0x62},
363 {0x82, 0x6b},
364 {0x83, 0x73},
365 {0x84, 0x7b},
366 {0x85, 0x8a},
367 {0x86, 0x98},
368 {0x87, 0xb2},
369 {0x88, 0xca},
370 {0x89, 0xe0},
371 {0x13, 0xe0},
372 {0x00, 0x00},
373 {0x10, 0x00},
374 {0x0d, 0x40},
375 {0x14, 0x38}, /* gain max 16x */
376 {0xa5, 0x05},
377 {0xab, 0x07},
378 {0x24, 0x95},
379 {0x25, 0x33},
380 {0x26, 0xe3},
381 {0x9f, 0x78},
382 {0xa0, 0x68},
383 {0xa1, 0x03},
384 {0xa6, 0xd8},
385 {0xa7, 0xd8},
386 {0xa8, 0xf0},
387 {0xa9, 0x90},
388 {0xaa, 0x94},
389 {0x13, 0xe5},
390 {0x0e, 0x61},
391 {0x0f, 0x4b},
392 {0x16, 0x02},
393 {0x21, 0x02},
394 {0x22, 0x91},
395 {0x29, 0x07},
396 {0x33, 0x0b},
397 {0x35, 0x0b},
398 {0x37, 0x1d},
399 {0x38, 0x71},
400 {0x39, 0x2a},
401 {0x3c, 0x78},
402 {0x4d, 0x40},
403 {0x4e, 0x20},
404 {0x69, 0x00},
405 {0x6b, 0x4a},
406 {0x74, 0x10},
407 {0x8d, 0x4f},
408 {0x8e, 0x00},
409 {0x8f, 0x00},
410 {0x90, 0x00},
411 {0x91, 0x00},
412 {0x96, 0x00},
413 {0x9a, 0x80},
414 {0xb0, 0x84},
415 {0xb1, 0x0c},
416 {0xb2, 0x0e},
417 {0xb3, 0x82},
418 {0xb8, 0x0a},
419 {0x43, 0x0a},
420 {0x44, 0xf0},
421 {0x45, 0x34},
422 {0x46, 0x58},
423 {0x47, 0x28},
424 {0x48, 0x3a},
425 {0x59, 0x88},
426 {0x5a, 0x88},
427 {0x5b, 0x44},
428 {0x5c, 0x67},
429 {0x5d, 0x49},
430 {0x5e, 0x0e},
431 {0x6c, 0x0a},
432 {0x6d, 0x55},
433 {0x6e, 0x11},
434 {0x6f, 0x9f},
435 {0x6a, 0x40},
436 {0x01, 0x40},
437 {0x02, 0x40},
438 {0x13, 0xe7},
439 {0x4f, 0x80},
440 {0x50, 0x80},
441 {0x51, 0x00},
442 {0x52, 0x22},
443 {0x53, 0x5e},
444 {0x54, 0x80},
445 {0x58, 0x9e},
446 {0x41, 0x08},
447 {0x3f, 0x00},
448 {0x75, 0x04},
449 {0x76, 0xe1},
450 {0x4c, 0x00},
451 {0x77, 0x01},
452 {0x3d, 0xc2},
453 {0x4b, 0x09},
454 {0xc9, 0x60},
455 {0x41, 0x38}, /* jfm: auto sharpness + auto de-noise */
456 {0x56, 0x40},
457 {0x34, 0x11},
458 {0x3b, 0xc2},
459 {0xa4, 0x8a}, /* Night mode trigger point */
460 {0x96, 0x00},
461 {0x97, 0x30},
462 {0x98, 0x20},
463 {0x99, 0x20},
464 {0x9a, 0x84},
465 {0x9b, 0x29},
466 {0x9c, 0x03},
467 {0x9d, 0x4c},
468 {0x9e, 0x3f},
469 {0x78, 0x04},
470 {0x79, 0x01},
471 {0xc8, 0xf0},
472 {0x79, 0x0f},
473 {0xc8, 0x00},
474 {0x79, 0x10},
475 {0xc8, 0x7e},
476 {0x79, 0x0a},
477 {0xc8, 0x80},
478 {0x79, 0x0b},
479 {0xc8, 0x01},
480 {0x79, 0x0c},
481 {0xc8, 0x0f},
482 {0x79, 0x0d},
483 {0xc8, 0x20},
484 {0x79, 0x09},
485 {0xc8, 0x80},
486 {0x79, 0x02},
487 {0xc8, 0xc0},
488 {0x79, 0x03},
489 {0xc8, 0x20},
490 {0x79, 0x26},
491};
492static const u8 bridge_start_vga_767x[][2] = {
493/* str59 JPG */
494 {0x94, 0xaa},
495 {0xf1, 0x42},
496 {0xe5, 0x04},
497 {0xc0, 0x50},
498 {0xc1, 0x3c},
499 {0xc2, 0x0c},
500 {0x35, 0x02}, /* turn on JPEG */
501 {0xd9, 0x10},
502 {0xda, 0x00}, /* for higher clock rate(30fps) */
503 {0x34, 0x05}, /* enable Audio Suspend mode */
504 {0xc3, 0xf9}, /* enable PRE */
505 {0x8c, 0x00}, /* CIF VSize LSB[2:0] */
506 {0x8d, 0x1c}, /* output YUV */
507/* {0x34, 0x05}, * enable Audio Suspend mode (?) */
508 {0x50, 0x00}, /* H/V divider=0 */
509 {0x51, 0xa0}, /* input H=640/4 */
510 {0x52, 0x3c}, /* input V=480/4 */
511 {0x53, 0x00}, /* offset X=0 */
512 {0x54, 0x00}, /* offset Y=0 */
513 {0x55, 0x00}, /* H/V size[8]=0 */
514 {0x57, 0x00}, /* H-size[9]=0 */
515 {0x5c, 0x00}, /* output size[9:8]=0 */
516 {0x5a, 0xa0}, /* output H=640/4 */
517 {0x5b, 0x78}, /* output V=480/4 */
518 {0x1c, 0x0a},
519 {0x1d, 0x0a},
520 {0x94, 0x11},
521};
522static const u8 sensor_start_vga_767x[][2] = {
523 {0x11, 0x01},
524 {0x1e, 0x04},
525 {0x19, 0x02},
526 {0x1a, 0x7a},
527};
528static const u8 bridge_start_qvga_767x[][2] = {
529/* str86 JPG */
530 {0x94, 0xaa},
531 {0xf1, 0x42},
532 {0xe5, 0x04},
533 {0xc0, 0x80},
534 {0xc1, 0x60},
535 {0xc2, 0x0c},
536 {0x35, 0x02}, /* turn on JPEG */
537 {0xd9, 0x10},
538 {0xc0, 0x50}, /* CIF HSize 640 */
539 {0xc1, 0x3c}, /* CIF VSize 480 */
540 {0x8c, 0x00}, /* CIF VSize LSB[2:0] */
541 {0x8d, 0x1c}, /* output YUV */
542 {0x34, 0x05}, /* enable Audio Suspend mode */
543 {0xc2, 0x4c}, /* output YUV and Enable DCW */
544 {0xc3, 0xf9}, /* enable PRE */
545 {0x1c, 0x00}, /* indirect addressing */
546 {0x1d, 0x48}, /* output YUV422 */
547 {0x50, 0x89}, /* H/V divider=/2; plus DCW AVG */
548 {0x51, 0xa0}, /* DCW input H=640/4 */
549 {0x52, 0x78}, /* DCW input V=480/4 */
550 {0x53, 0x00}, /* offset X=0 */
551 {0x54, 0x00}, /* offset Y=0 */
552 {0x55, 0x00}, /* H/V size[8]=0 */
553 {0x57, 0x00}, /* H-size[9]=0 */
554 {0x5c, 0x00}, /* DCW output size[9:8]=0 */
555 {0x5a, 0x50}, /* DCW output H=320/4 */
556 {0x5b, 0x3c}, /* DCW output V=240/4 */
557 {0x1c, 0x0a},
558 {0x1d, 0x0a},
559 {0x94, 0x11},
560};
561static const u8 sensor_start_qvga_767x[][2] = {
562 {0x11, 0x01},
563 {0x1e, 0x04},
564 {0x19, 0x02},
565 {0x1a, 0x7a},
566};
567
568static const u8 bridge_init_772x[][2] = {
569 { 0xc2, 0x0c },
570 { 0x88, 0xf8 },
571 { 0xc3, 0x69 },
572 { 0x89, 0xff },
573 { 0x76, 0x03 },
574 { 0x92, 0x01 },
575 { 0x93, 0x18 },
576 { 0x94, 0x10 },
577 { 0x95, 0x10 },
578 { 0xe2, 0x00 },
579 { 0xe7, 0x3e },
580
581 { 0x96, 0x00 },
582
583 { 0x97, 0x20 },
584 { 0x97, 0x20 },
585 { 0x97, 0x20 },
586 { 0x97, 0x0a },
587 { 0x97, 0x3f },
588 { 0x97, 0x4a },
589 { 0x97, 0x20 },
590 { 0x97, 0x15 },
591 { 0x97, 0x0b },
592
593 { 0x8e, 0x40 },
594 { 0x1f, 0x81 },
595 { 0x34, 0x05 },
596 { 0xe3, 0x04 },
597 { 0x88, 0x00 },
598 { 0x89, 0x00 },
599 { 0x76, 0x00 },
600 { 0xe7, 0x2e },
601 { 0x31, 0xf9 },
602 { 0x25, 0x42 },
603 { 0x21, 0xf0 },
604
605 { 0x1c, 0x00 },
606 { 0x1d, 0x40 },
607 { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
608 { 0x1d, 0x00 }, /* payload size */
609
610 { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
611 { 0x1d, 0x58 }, /* frame size */
612 { 0x1d, 0x00 }, /* frame size */
613
614 { 0x1c, 0x0a },
615 { 0x1d, 0x08 }, /* turn on UVC header */
616 { 0x1d, 0x0e }, /* .. */
617
618 { 0x8d, 0x1c },
619 { 0x8e, 0x80 },
620 { 0xe5, 0x04 },
621
622 { 0xc0, 0x50 },
623 { 0xc1, 0x3c },
624 { 0xc2, 0x0c },
625};
626static const u8 sensor_init_772x[][2] = {
627 { 0x12, 0x80 },
628 { 0x11, 0x01 },
629/*fixme: better have a delay?*/
630 { 0x11, 0x01 },
631 { 0x11, 0x01 },
632 { 0x11, 0x01 },
633 { 0x11, 0x01 },
634 { 0x11, 0x01 },
635 { 0x11, 0x01 },
636 { 0x11, 0x01 },
637 { 0x11, 0x01 },
638 { 0x11, 0x01 },
639 { 0x11, 0x01 },
640
641 { 0x3d, 0x03 },
642 { 0x17, 0x26 },
643 { 0x18, 0xa0 },
644 { 0x19, 0x07 },
645 { 0x1a, 0xf0 },
646 { 0x32, 0x00 },
647 { 0x29, 0xa0 },
648 { 0x2c, 0xf0 },
649 { 0x65, 0x20 },
650 { 0x11, 0x01 },
651 { 0x42, 0x7f },
652 { 0x63, 0xaa }, /* AWB - was e0 */
653 { 0x64, 0xff },
654 { 0x66, 0x00 },
655 { 0x13, 0xf0 }, /* com8 */
656 { 0x0d, 0x41 },
657 { 0x0f, 0xc5 },
658 { 0x14, 0x11 },
659
660 { 0x22, 0x7f },
661 { 0x23, 0x03 },
662 { 0x24, 0x40 },
663 { 0x25, 0x30 },
664 { 0x26, 0xa1 },
665 { 0x2a, 0x00 },
666 { 0x2b, 0x00 },
667 { 0x6b, 0xaa },
668 { 0x13, 0xff }, /* AWB */
669
670 { 0x90, 0x05 },
671 { 0x91, 0x01 },
672 { 0x92, 0x03 },
673 { 0x93, 0x00 },
674 { 0x94, 0x60 },
675 { 0x95, 0x3c },
676 { 0x96, 0x24 },
677 { 0x97, 0x1e },
678 { 0x98, 0x62 },
679 { 0x99, 0x80 },
680 { 0x9a, 0x1e },
681 { 0x9b, 0x08 },
682 { 0x9c, 0x20 },
683 { 0x9e, 0x81 },
684
685 { 0xa6, 0x04 },
686 { 0x7e, 0x0c },
687 { 0x7f, 0x16 },
688 { 0x80, 0x2a },
689 { 0x81, 0x4e },
690 { 0x82, 0x61 },
691 { 0x83, 0x6f },
692 { 0x84, 0x7b },
693 { 0x85, 0x86 },
694 { 0x86, 0x8e },
695 { 0x87, 0x97 },
696 { 0x88, 0xa4 },
697 { 0x89, 0xaf },
698 { 0x8a, 0xc5 },
699 { 0x8b, 0xd7 },
700 { 0x8c, 0xe8 },
701 { 0x8d, 0x20 },
702
703 { 0x0c, 0x90 },
704
705 { 0x2b, 0x00 },
706 { 0x22, 0x7f },
707 { 0x23, 0x03 },
708 { 0x11, 0x01 },
709 { 0x0c, 0xd0 },
710 { 0x64, 0xff },
711 { 0x0d, 0x41 },
712
713 { 0x14, 0x41 },
714 { 0x0e, 0xcd },
715 { 0xac, 0xbf },
716 { 0x8e, 0x00 }, /* De-noise threshold */
717 { 0x0c, 0xd0 }
718};
719static const u8 bridge_start_vga_772x[][2] = {
720 {0x1c, 0x00},
721 {0x1d, 0x40},
722 {0x1d, 0x02},
723 {0x1d, 0x00},
724 {0x1d, 0x02},
725 {0x1d, 0x58},
726 {0x1d, 0x00},
727 {0xc0, 0x50},
728 {0xc1, 0x3c},
729};
730static const u8 sensor_start_vga_772x[][2] = {
731 {0x12, 0x00},
732 {0x17, 0x26},
733 {0x18, 0xa0},
734 {0x19, 0x07},
735 {0x1a, 0xf0},
736 {0x29, 0xa0},
737 {0x2c, 0xf0},
738 {0x65, 0x20},
739};
740static const u8 bridge_start_qvga_772x[][2] = {
741 {0x1c, 0x00},
742 {0x1d, 0x40},
743 {0x1d, 0x02},
744 {0x1d, 0x00},
745 {0x1d, 0x01},
746 {0x1d, 0x4b},
747 {0x1d, 0x00},
748 {0xc0, 0x28},
749 {0xc1, 0x1e},
750};
751static const u8 sensor_start_qvga_772x[][2] = {
752 {0x12, 0x40},
753 {0x17, 0x3f},
754 {0x18, 0x50},
755 {0x19, 0x03},
756 {0x1a, 0x78},
757 {0x29, 0x50},
758 {0x2c, 0x78},
759 {0x65, 0x2f},
760};
761
762static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
763{
764 struct usb_device *udev = gspca_dev->dev;
765 int ret;
766
767 if (gspca_dev->usb_err < 0)
768 return;
769
770 PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
771 gspca_dev->usb_buf[0] = val;
772 ret = usb_control_msg(udev,
773 usb_sndctrlpipe(udev, 0),
774 0x01,
775 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
776 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
777 if (ret < 0) {
778 err("write failed %d", ret);
779 gspca_dev->usb_err = ret;
780 }
781}
782
783static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
784{
785 struct usb_device *udev = gspca_dev->dev;
786 int ret;
787
788 if (gspca_dev->usb_err < 0)
789 return 0;
790 ret = usb_control_msg(udev,
791 usb_rcvctrlpipe(udev, 0),
792 0x01,
793 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
794 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
795 PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
796 if (ret < 0) {
797 err("read failed %d", ret);
798 gspca_dev->usb_err = ret;
799 }
800 return gspca_dev->usb_buf[0];
801}
802
803/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
804 * (direction and output)? */
805static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
806{
807 u8 data;
808
809 PDEBUG(D_CONF, "led status: %d", status);
810
811 data = ov534_reg_read(gspca_dev, 0x21);
812 data |= 0x80;
813 ov534_reg_write(gspca_dev, 0x21, data);
814
815 data = ov534_reg_read(gspca_dev, 0x23);
816 if (status)
817 data |= 0x80;
818 else
819 data &= ~0x80;
820
821 ov534_reg_write(gspca_dev, 0x23, data);
822
823 if (!status) {
824 data = ov534_reg_read(gspca_dev, 0x21);
825 data &= ~0x80;
826 ov534_reg_write(gspca_dev, 0x21, data);
827 }
828}
829
830static int sccb_check_status(struct gspca_dev *gspca_dev)
831{
832 u8 data;
833 int i;
834
835 for (i = 0; i < 5; i++) {
836 data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
837
838 switch (data) {
839 case 0x00:
840 return 1;
841 case 0x04:
842 return 0;
843 case 0x03:
844 break;
845 default:
846 PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
847 data, i + 1);
848 }
849 }
850 return 0;
851}
852
853static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
854{
855 PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
856 ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
857 ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
858 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
859
860 if (!sccb_check_status(gspca_dev)) {
861 err("sccb_reg_write failed");
862 gspca_dev->usb_err = -EIO;
863 }
864}
865
866static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
867{
868 ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
869 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
870 if (!sccb_check_status(gspca_dev))
871 err("sccb_reg_read failed 1");
872
873 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
874 if (!sccb_check_status(gspca_dev))
875 err("sccb_reg_read failed 2");
876
877 return ov534_reg_read(gspca_dev, OV534_REG_READ);
878}
879
880/* output a bridge sequence (reg - val) */
881static void reg_w_array(struct gspca_dev *gspca_dev,
882 const u8 (*data)[2], int len)
883{
884 while (--len >= 0) {
885 ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
886 data++;
887 }
888}
889
890/* output a sensor sequence (reg - val) */
891static void sccb_w_array(struct gspca_dev *gspca_dev,
892 const u8 (*data)[2], int len)
893{
894 while (--len >= 0) {
895 if ((*data)[0] != 0xff) {
896 sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
897 } else {
898 sccb_reg_read(gspca_dev, (*data)[1]);
899 sccb_reg_write(gspca_dev, 0xff, 0x00);
900 }
901 data++;
902 }
903}
904
905/* ov772x specific controls */
906static void set_frame_rate(struct gspca_dev *gspca_dev)
907{
908 struct sd *sd = (struct sd *) gspca_dev;
909 int i;
910 struct rate_s {
911 u8 fps;
912 u8 r11;
913 u8 r0d;
914 u8 re5;
915 };
916 const struct rate_s *r;
917 static const struct rate_s rate_0[] = { /* 640x480 */
918 {60, 0x01, 0xc1, 0x04},
919 {50, 0x01, 0x41, 0x02},
920 {40, 0x02, 0xc1, 0x04},
921 {30, 0x04, 0x81, 0x02},
922 {15, 0x03, 0x41, 0x04},
923 };
924 static const struct rate_s rate_1[] = { /* 320x240 */
925 {125, 0x02, 0x81, 0x02},
926 {100, 0x02, 0xc1, 0x04},
927 {75, 0x03, 0xc1, 0x04},
928 {60, 0x04, 0xc1, 0x04},
929 {50, 0x02, 0x41, 0x04},
930 {40, 0x03, 0x41, 0x04},
931 {30, 0x04, 0x41, 0x04},
932 };
933
934 if (sd->sensor != SENSOR_OV772x)
935 return;
936 if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
937 r = rate_0;
938 i = ARRAY_SIZE(rate_0);
939 } else {
940 r = rate_1;
941 i = ARRAY_SIZE(rate_1);
942 }
943 while (--i > 0) {
944 if (sd->frame_rate >= r->fps)
945 break;
946 r++;
947 }
948
949 sccb_reg_write(gspca_dev, 0x11, r->r11);
950 sccb_reg_write(gspca_dev, 0x0d, r->r0d);
951 ov534_reg_write(gspca_dev, 0xe5, r->re5);
952
953 PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
954}
955
956static void setbrightness(struct gspca_dev *gspca_dev)
957{
958 struct sd *sd = (struct sd *) gspca_dev;
959 int val;
960
961 val = sd->ctrls[BRIGHTNESS].val;
962 if (sd->sensor == SENSOR_OV767x) {
963 if (val < 0)
964 val = 0x80 - val;
965 sccb_reg_write(gspca_dev, 0x55, val); /* bright */
966 } else {
967 sccb_reg_write(gspca_dev, 0x9b, val);
968 }
969}
970
971static void setcontrast(struct gspca_dev *gspca_dev)
972{
973 struct sd *sd = (struct sd *) gspca_dev;
974 u8 val;
975
976 val = sd->ctrls[CONTRAST].val;
977 if (sd->sensor == SENSOR_OV767x)
978 sccb_reg_write(gspca_dev, 0x56, val); /* contras */
979 else
980 sccb_reg_write(gspca_dev, 0x9c, val);
981}
982
983static void setgain(struct gspca_dev *gspca_dev)
984{
985 struct sd *sd = (struct sd *) gspca_dev;
986 u8 val;
987
988 if (sd->ctrls[AGC].val)
989 return;
990
991 val = sd->ctrls[GAIN].val;
992 switch (val & 0x30) {
993 case 0x00:
994 val &= 0x0f;
995 break;
996 case 0x10:
997 val &= 0x0f;
998 val |= 0x30;
999 break;
1000 case 0x20:
1001 val &= 0x0f;
1002 val |= 0x70;
1003 break;
1004 default:
1005/* case 0x30: */
1006 val &= 0x0f;
1007 val |= 0xf0;
1008 break;
1009 }
1010 sccb_reg_write(gspca_dev, 0x00, val);
1011}
1012
1013static void setexposure(struct gspca_dev *gspca_dev)
1014{
1015 struct sd *sd = (struct sd *) gspca_dev;
1016 u8 val;
1017
1018 if (sd->ctrls[AEC].val)
1019 return;
1020
1021 val = sd->ctrls[EXPOSURE].val;
1022 if (sd->sensor == SENSOR_OV767x) {
1023
1024 /* set only aec[9:2] */
1025 sccb_reg_write(gspca_dev, 0x10, val); /* aech */
1026 } else {
1027
1028 /* 'val' is one byte and represents half of the exposure value
1029 * we are going to set into registers, a two bytes value:
1030 *
1031 * MSB: ((u16) val << 1) >> 8 == val >> 7
1032 * LSB: ((u16) val << 1) & 0xff == val << 1
1033 */
1034 sccb_reg_write(gspca_dev, 0x08, val >> 7);
1035 sccb_reg_write(gspca_dev, 0x10, val << 1);
1036 }
1037}
1038
1039static void setagc(struct gspca_dev *gspca_dev)
1040{
1041 struct sd *sd = (struct sd *) gspca_dev;
1042
1043 if (sd->ctrls[AGC].val) {
1044 sccb_reg_write(gspca_dev, 0x13,
1045 sccb_reg_read(gspca_dev, 0x13) | 0x04);
1046 sccb_reg_write(gspca_dev, 0x64,
1047 sccb_reg_read(gspca_dev, 0x64) | 0x03);
1048 } else {
1049 sccb_reg_write(gspca_dev, 0x13,
1050 sccb_reg_read(gspca_dev, 0x13) & ~0x04);
1051 sccb_reg_write(gspca_dev, 0x64,
1052 sccb_reg_read(gspca_dev, 0x64) & ~0x03);
1053
1054 setgain(gspca_dev);
1055 }
1056}
1057
1058static void setawb(struct gspca_dev *gspca_dev)
1059{
1060 struct sd *sd = (struct sd *) gspca_dev;
1061
1062 if (sd->ctrls[AWB].val) {
1063 sccb_reg_write(gspca_dev, 0x13,
1064 sccb_reg_read(gspca_dev, 0x13) | 0x02);
1065 if (sd->sensor == SENSOR_OV772x)
1066 sccb_reg_write(gspca_dev, 0x63,
1067 sccb_reg_read(gspca_dev, 0x63) | 0xc0);
1068 } else {
1069 sccb_reg_write(gspca_dev, 0x13,
1070 sccb_reg_read(gspca_dev, 0x13) & ~0x02);
1071 if (sd->sensor == SENSOR_OV772x)
1072 sccb_reg_write(gspca_dev, 0x63,
1073 sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
1074 }
1075}
1076
1077static void setaec(struct gspca_dev *gspca_dev)
1078{
1079 struct sd *sd = (struct sd *) gspca_dev;
1080 u8 data;
1081
1082 data = sd->sensor == SENSOR_OV767x ?
1083 0x05 : /* agc + aec */
1084 0x01; /* agc */
1085 if (sd->ctrls[AEC].val)
1086 sccb_reg_write(gspca_dev, 0x13,
1087 sccb_reg_read(gspca_dev, 0x13) | data);
1088 else {
1089 sccb_reg_write(gspca_dev, 0x13,
1090 sccb_reg_read(gspca_dev, 0x13) & ~data);
1091 if (sd->sensor == SENSOR_OV767x)
1092 sd->ctrls[EXPOSURE].val =
1093 sccb_reg_read(gspca_dev, 10); /* aech */
1094 else
1095 setexposure(gspca_dev);
1096 }
1097}
1098
1099static void setsharpness(struct gspca_dev *gspca_dev)
1100{
1101 struct sd *sd = (struct sd *) gspca_dev;
1102 u8 val;
1103
1104 val = sd->ctrls[SHARPNESS].val;
1105 sccb_reg_write(gspca_dev, 0x91, val); /* Auto de-noise threshold */
1106 sccb_reg_write(gspca_dev, 0x8e, val); /* De-noise threshold */
1107}
1108
1109static void sethvflip(struct gspca_dev *gspca_dev)
1110{
1111 struct sd *sd = (struct sd *) gspca_dev;
1112 u8 val;
1113
1114 if (sd->sensor == SENSOR_OV767x) {
1115 val = sccb_reg_read(gspca_dev, 0x1e); /* mvfp */
1116 val &= ~0x30;
1117 if (sd->ctrls[HFLIP].val)
1118 val |= 0x20;
1119 if (sd->ctrls[VFLIP].val)
1120 val |= 0x10;
1121 sccb_reg_write(gspca_dev, 0x1e, val);
1122 } else {
1123 val = sccb_reg_read(gspca_dev, 0x0c);
1124 val &= ~0xc0;
1125 if (sd->ctrls[HFLIP].val == 0)
1126 val |= 0x40;
1127 if (sd->ctrls[VFLIP].val == 0)
1128 val |= 0x80;
1129 sccb_reg_write(gspca_dev, 0x0c, val);
1130 }
1131}
1132
1133static void setcolors(struct gspca_dev *gspca_dev)
1134{
1135 struct sd *sd = (struct sd *) gspca_dev;
1136 u8 val;
1137 int i;
1138 static u8 color_tb[][6] = {
1139 {0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
1140 {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
1141 {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
1142 {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
1143 {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
1144 {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
1145 {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
1146 };
1147
1148 val = sd->ctrls[COLORS].val;
1149 for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
1150 sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
1151}
1152
1153static void setlightfreq(struct gspca_dev *gspca_dev)
1154{
1155 struct sd *sd = (struct sd *) gspca_dev;
1156 u8 val;
1157
1158 val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00;
1159 if (sd->sensor == SENSOR_OV767x) {
1160 sccb_reg_write(gspca_dev, 0x2a, 0x00);
1161 if (val)
1162 val = 0x9d; /* insert dummy to 25fps for 50Hz */
1163 }
1164 sccb_reg_write(gspca_dev, 0x2b, val);
1165}
1166
1167
1168/* this function is called at probe time */
1169static int sd_config(struct gspca_dev *gspca_dev,
1170 const struct usb_device_id *id)
1171{
1172 struct sd *sd = (struct sd *) gspca_dev;
1173 struct cam *cam;
1174
1175 cam = &gspca_dev->cam;
1176
1177 cam->ctrls = sd->ctrls;
1178
1179 /* the auto white balance control works only when auto gain is set */
1180 if (sd_ctrls[AGC].qctrl.default_value == 0)
1181 gspca_dev->ctrl_inac |= (1 << AWB);
1182
1183 cam->cam_mode = ov772x_mode;
1184 cam->nmodes = ARRAY_SIZE(ov772x_mode);
1185
1186 sd->frame_rate = 30;
1187
1188 return 0;
1189}
1190
1191/* this function is called at probe and resume time */
1192static int sd_init(struct gspca_dev *gspca_dev)
1193{
1194 struct sd *sd = (struct sd *) gspca_dev;
1195 u16 sensor_id;
1196 static const struct reg_array bridge_init[NSENSORS] = {
1197 [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
1198 [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
1199 };
1200 static const struct reg_array sensor_init[NSENSORS] = {
1201 [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
1202 [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
1203 };
1204
1205 /* reset bridge */
1206 ov534_reg_write(gspca_dev, 0xe7, 0x3a);
1207 ov534_reg_write(gspca_dev, 0xe0, 0x08);
1208 msleep(100);
1209
1210 /* initialize the sensor address */
1211 ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
1212
1213 /* reset sensor */
1214 sccb_reg_write(gspca_dev, 0x12, 0x80);
1215 msleep(10);
1216
1217 /* probe the sensor */
1218 sccb_reg_read(gspca_dev, 0x0a);
1219 sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
1220 sccb_reg_read(gspca_dev, 0x0b);
1221 sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
1222 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1223
1224 if ((sensor_id & 0xfff0) == 0x7670) {
1225 sd->sensor = SENSOR_OV767x;
1226 gspca_dev->ctrl_dis = (1 << GAIN) |
1227 (1 << AGC) |
1228 (1 << SHARPNESS); /* auto */
1229 sd->ctrls[BRIGHTNESS].min = -127;
1230 sd->ctrls[BRIGHTNESS].max = 127;
1231 sd->ctrls[BRIGHTNESS].def = 0;
1232 sd->ctrls[CONTRAST].max = 0x80;
1233 sd->ctrls[CONTRAST].def = 0x40;
1234 sd->ctrls[EXPOSURE].min = 0x08;
1235 sd->ctrls[EXPOSURE].max = 0x60;
1236 sd->ctrls[EXPOSURE].def = 0x13;
1237 sd->ctrls[SHARPNESS].max = 9;
1238 sd->ctrls[SHARPNESS].def = 4;
1239 sd->ctrls[HFLIP].def = 1;
1240 gspca_dev->cam.cam_mode = ov767x_mode;
1241 gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
1242 } else {
1243 sd->sensor = SENSOR_OV772x;
1244 gspca_dev->ctrl_dis = (1 << COLORS);
1245 gspca_dev->cam.bulk = 1;
1246 gspca_dev->cam.bulk_size = 16384;
1247 gspca_dev->cam.bulk_nurbs = 2;
1248 gspca_dev->cam.mode_framerates = ov772x_framerates;
1249 }
1250
1251 /* initialize */
1252 reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
1253 bridge_init[sd->sensor].len);
1254 ov534_set_led(gspca_dev, 1);
1255 sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
1256 sensor_init[sd->sensor].len);
1257 if (sd->sensor == SENSOR_OV767x)
1258 sd_start(gspca_dev);
1259 sd_stopN(gspca_dev);
1260/* set_frame_rate(gspca_dev); */
1261
1262 return gspca_dev->usb_err;
1263}
1264
1265static int sd_start(struct gspca_dev *gspca_dev)
1266{
1267 struct sd *sd = (struct sd *) gspca_dev;
1268 int mode;
1269 static const struct reg_array bridge_start[NSENSORS][2] = {
1270 [SENSOR_OV767x] = {{bridge_start_qvga_767x,
1271 ARRAY_SIZE(bridge_start_qvga_767x)},
1272 {bridge_start_vga_767x,
1273 ARRAY_SIZE(bridge_start_vga_767x)}},
1274 [SENSOR_OV772x] = {{bridge_start_qvga_772x,
1275 ARRAY_SIZE(bridge_start_qvga_772x)},
1276 {bridge_start_vga_772x,
1277 ARRAY_SIZE(bridge_start_vga_772x)}},
1278 };
1279 static const struct reg_array sensor_start[NSENSORS][2] = {
1280 [SENSOR_OV767x] = {{sensor_start_qvga_767x,
1281 ARRAY_SIZE(sensor_start_qvga_767x)},
1282 {sensor_start_vga_767x,
1283 ARRAY_SIZE(sensor_start_vga_767x)}},
1284 [SENSOR_OV772x] = {{sensor_start_qvga_772x,
1285 ARRAY_SIZE(sensor_start_qvga_772x)},
1286 {sensor_start_vga_772x,
1287 ARRAY_SIZE(sensor_start_vga_772x)}},
1288 };
1289
1290 /* (from ms-win trace) */
1291 if (sd->sensor == SENSOR_OV767x)
1292 sccb_reg_write(gspca_dev, 0x1e, 0x04);
1293 /* black sun enable ? */
1294
1295 mode = gspca_dev->curr_mode; /* 0: 320x240, 1: 640x480 */
1296 reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
1297 bridge_start[sd->sensor][mode].len);
1298 sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
1299 sensor_start[sd->sensor][mode].len);
1300
1301 set_frame_rate(gspca_dev);
1302
1303 if (!(gspca_dev->ctrl_dis & (1 << AGC)))
1304 setagc(gspca_dev);
1305 setawb(gspca_dev);
1306 setaec(gspca_dev);
1307 if (!(gspca_dev->ctrl_dis & (1 << GAIN)))
1308 setgain(gspca_dev);
1309 setexposure(gspca_dev);
1310 setbrightness(gspca_dev);
1311 setcontrast(gspca_dev);
1312 if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS)))
1313 setsharpness(gspca_dev);
1314 sethvflip(gspca_dev);
1315 if (!(gspca_dev->ctrl_dis & (1 << COLORS)))
1316 setcolors(gspca_dev);
1317 setlightfreq(gspca_dev);
1318
1319 ov534_set_led(gspca_dev, 1);
1320 ov534_reg_write(gspca_dev, 0xe0, 0x00);
1321 return gspca_dev->usb_err;
1322}
1323
1324static void sd_stopN(struct gspca_dev *gspca_dev)
1325{
1326 ov534_reg_write(gspca_dev, 0xe0, 0x09);
1327 ov534_set_led(gspca_dev, 0);
1328}
1329
1330/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1331#define UVC_STREAM_EOH (1 << 7)
1332#define UVC_STREAM_ERR (1 << 6)
1333#define UVC_STREAM_STI (1 << 5)
1334#define UVC_STREAM_RES (1 << 4)
1335#define UVC_STREAM_SCR (1 << 3)
1336#define UVC_STREAM_PTS (1 << 2)
1337#define UVC_STREAM_EOF (1 << 1)
1338#define UVC_STREAM_FID (1 << 0)
1339
1340static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1341 u8 *data, int len)
1342{
1343 struct sd *sd = (struct sd *) gspca_dev;
1344 __u32 this_pts;
1345 u16 this_fid;
1346 int remaining_len = len;
1347 int payload_len;
1348
1349 payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
1350 do {
1351 len = min(remaining_len, payload_len);
1352
1353 /* Payloads are prefixed with a UVC-style header. We
1354 consider a frame to start when the FID toggles, or the PTS
1355 changes. A frame ends when EOF is set, and we've received
1356 the correct number of bytes. */
1357
1358 /* Verify UVC header. Header length is always 12 */
1359 if (data[0] != 12 || len < 12) {
1360 PDEBUG(D_PACK, "bad header");
1361 goto discard;
1362 }
1363
1364 /* Check errors */
1365 if (data[1] & UVC_STREAM_ERR) {
1366 PDEBUG(D_PACK, "payload error");
1367 goto discard;
1368 }
1369
1370 /* Extract PTS and FID */
1371 if (!(data[1] & UVC_STREAM_PTS)) {
1372 PDEBUG(D_PACK, "PTS not present");
1373 goto discard;
1374 }
1375 this_pts = (data[5] << 24) | (data[4] << 16)
1376 | (data[3] << 8) | data[2];
1377 this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
1378
1379 /* If PTS or FID has changed, start a new frame. */
1380 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1381 if (gspca_dev->last_packet_type == INTER_PACKET)
1382 gspca_frame_add(gspca_dev, LAST_PACKET,
1383 NULL, 0);
1384 sd->last_pts = this_pts;
1385 sd->last_fid = this_fid;
1386 gspca_frame_add(gspca_dev, FIRST_PACKET,
1387 data + 12, len - 12);
1388 /* If this packet is marked as EOF, end the frame */
1389 } else if (data[1] & UVC_STREAM_EOF) {
1390 sd->last_pts = 0;
1391 if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
1392 && gspca_dev->image_len + len - 12 !=
1393 gspca_dev->width * gspca_dev->height * 2) {
1394 PDEBUG(D_PACK, "wrong sized frame");
1395 goto discard;
1396 }
1397 gspca_frame_add(gspca_dev, LAST_PACKET,
1398 data + 12, len - 12);
1399 } else {
1400
1401 /* Add the data from this payload */
1402 gspca_frame_add(gspca_dev, INTER_PACKET,
1403 data + 12, len - 12);
1404 }
1405
1406 /* Done this payload */
1407 goto scan_next;
1408
1409discard:
1410 /* Discard data until a new frame starts. */
1411 gspca_dev->last_packet_type = DISCARD_PACKET;
1412
1413scan_next:
1414 remaining_len -= len;
1415 data += len;
1416 } while (remaining_len > 0);
1417}
1418
1419static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val)
1420{
1421 struct sd *sd = (struct sd *) gspca_dev;
1422
1423 sd->ctrls[AGC].val = val;
1424
1425 /* the auto white balance control works only
1426 * when auto gain is set */
1427 if (val) {
1428 gspca_dev->ctrl_inac &= ~(1 << AWB);
1429 } else {
1430 gspca_dev->ctrl_inac |= (1 << AWB);
1431 if (sd->ctrls[AWB].val) {
1432 sd->ctrls[AWB].val = 0;
1433 if (gspca_dev->streaming)
1434 setawb(gspca_dev);
1435 }
1436 }
1437 if (gspca_dev->streaming)
1438 setagc(gspca_dev);
1439 return gspca_dev->usb_err;
1440}
1441
1442static int sd_querymenu(struct gspca_dev *gspca_dev,
1443 struct v4l2_querymenu *menu)
1444{
1445 switch (menu->id) {
1446 case V4L2_CID_POWER_LINE_FREQUENCY:
1447 switch (menu->index) {
1448 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1449 strcpy((char *) menu->name, "Disabled");
1450 return 0;
1451 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1452 strcpy((char *) menu->name, "50 Hz");
1453 return 0;
1454 }
1455 break;
1456 }
1457
1458 return -EINVAL;
1459}
1460
1461/* get stream parameters (framerate) */
1462static void sd_get_streamparm(struct gspca_dev *gspca_dev,
1463 struct v4l2_streamparm *parm)
1464{
1465 struct v4l2_captureparm *cp = &parm->parm.capture;
1466 struct v4l2_fract *tpf = &cp->timeperframe;
1467 struct sd *sd = (struct sd *) gspca_dev;
1468
1469 cp->capability |= V4L2_CAP_TIMEPERFRAME;
1470 tpf->numerator = 1;
1471 tpf->denominator = sd->frame_rate;
1472}
1473
1474/* set stream parameters (framerate) */
1475static void sd_set_streamparm(struct gspca_dev *gspca_dev,
1476 struct v4l2_streamparm *parm)
1477{
1478 struct v4l2_captureparm *cp = &parm->parm.capture;
1479 struct v4l2_fract *tpf = &cp->timeperframe;
1480 struct sd *sd = (struct sd *) gspca_dev;
1481
1482 /* Set requested framerate */
1483 sd->frame_rate = tpf->denominator / tpf->numerator;
1484 if (gspca_dev->streaming)
1485 set_frame_rate(gspca_dev);
1486
1487 /* Return the actual framerate */
1488 tpf->numerator = 1;
1489 tpf->denominator = sd->frame_rate;
1490}
1491
1492/* sub-driver description */
1493static const struct sd_desc sd_desc = {
1494 .name = MODULE_NAME,
1495 .ctrls = sd_ctrls,
1496 .nctrls = ARRAY_SIZE(sd_ctrls),
1497 .config = sd_config,
1498 .init = sd_init,
1499 .start = sd_start,
1500 .stopN = sd_stopN,
1501 .pkt_scan = sd_pkt_scan,
1502 .querymenu = sd_querymenu,
1503 .get_streamparm = sd_get_streamparm,
1504 .set_streamparm = sd_set_streamparm,
1505};
1506
1507/* -- module initialisation -- */
1508static const struct usb_device_id device_table[] = {
1509 {USB_DEVICE(0x1415, 0x2000)},
1510 {USB_DEVICE(0x06f8, 0x3002)},
1511 {}
1512};
1513
1514MODULE_DEVICE_TABLE(usb, device_table);
1515
1516/* -- device connect -- */
1517static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1518{
1519 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1520 THIS_MODULE);
1521}
1522
1523static struct usb_driver sd_driver = {
1524 .name = MODULE_NAME,
1525 .id_table = device_table,
1526 .probe = sd_probe,
1527 .disconnect = gspca_disconnect,
1528#ifdef CONFIG_PM
1529 .suspend = gspca_suspend,
1530 .resume = gspca_resume,
1531#endif
1532};
1533
1534/* -- module insert / remove -- */
1535static int __init sd_mod_init(void)
1536{
1537 return usb_register(&sd_driver);
1538}
1539
1540static void __exit sd_mod_exit(void)
1541{
1542 usb_deregister(&sd_driver);
1543}
1544
1545module_init(sd_mod_init);
1546module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
new file mode 100644
index 00000000000..aaf5428c57f
--- /dev/null
+++ b/drivers/media/video/gspca/ov534_9.c
@@ -0,0 +1,1469 @@
1/*
2 * ov534-ov965x gspca driver
3 *
4 * Copyright (C) 2009-2010 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 MODULE_NAME "ov534_9"
28
29#include "gspca.h"
30
31#define OV534_REG_ADDRESS 0xf1 /* sensor address */
32#define OV534_REG_SUBADDR 0xf2
33#define OV534_REG_WRITE 0xf3
34#define OV534_REG_READ 0xf4
35#define OV534_REG_OPERATION 0xf5
36#define OV534_REG_STATUS 0xf6
37
38#define OV534_OP_WRITE_3 0x37
39#define OV534_OP_WRITE_2 0x33
40#define OV534_OP_READ_2 0xf9
41
42#define CTRL_TIMEOUT 500
43
44MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
45MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
46MODULE_LICENSE("GPL");
47
48/* specific webcam descriptor */
49struct sd {
50 struct gspca_dev gspca_dev; /* !! must be the first item */
51 __u32 last_pts;
52 u8 last_fid;
53
54 u8 brightness;
55 u8 contrast;
56 u8 autogain;
57 u8 exposure;
58 s8 sharpness;
59 u8 satur;
60 u8 freq;
61};
62
63/* V4L2 controls supported by the driver */
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
76static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
78
79static const struct ctrl sd_ctrls[] = {
80 { /* 0 */
81 {
82 .id = V4L2_CID_BRIGHTNESS,
83 .type = V4L2_CTRL_TYPE_INTEGER,
84 .name = "Brightness",
85 .minimum = 0,
86 .maximum = 15,
87 .step = 1,
88#define BRIGHTNESS_DEF 7
89 .default_value = BRIGHTNESS_DEF,
90 },
91 .set = sd_setbrightness,
92 .get = sd_getbrightness,
93 },
94 { /* 1 */
95 {
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
100 .maximum = 15,
101 .step = 1,
102#define CONTRAST_DEF 3
103 .default_value = CONTRAST_DEF,
104 },
105 .set = sd_setcontrast,
106 .get = sd_getcontrast,
107 },
108 { /* 2 */
109 {
110 .id = V4L2_CID_AUTOGAIN,
111 .type = V4L2_CTRL_TYPE_BOOLEAN,
112 .name = "Autogain",
113 .minimum = 0,
114 .maximum = 1,
115 .step = 1,
116#define AUTOGAIN_DEF 1
117 .default_value = AUTOGAIN_DEF,
118 },
119 .set = sd_setautogain,
120 .get = sd_getautogain,
121 },
122#define EXPO_IDX 3
123 { /* 3 */
124 {
125 .id = V4L2_CID_EXPOSURE,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Exposure",
128 .minimum = 0,
129 .maximum = 3,
130 .step = 1,
131#define EXPO_DEF 0
132 .default_value = EXPO_DEF,
133 },
134 .set = sd_setexposure,
135 .get = sd_getexposure,
136 },
137 { /* 4 */
138 {
139 .id = V4L2_CID_SHARPNESS,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Sharpness",
142 .minimum = -1, /* -1 = auto */
143 .maximum = 4,
144 .step = 1,
145#define SHARPNESS_DEF -1
146 .default_value = SHARPNESS_DEF,
147 },
148 .set = sd_setsharpness,
149 .get = sd_getsharpness,
150 },
151 { /* 5 */
152 {
153 .id = V4L2_CID_SATURATION,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .name = "Saturation",
156 .minimum = 0,
157 .maximum = 4,
158 .step = 1,
159#define SATUR_DEF 2
160 .default_value = SATUR_DEF,
161 },
162 .set = sd_setsatur,
163 .get = sd_getsatur,
164 },
165 {
166 {
167 .id = V4L2_CID_POWER_LINE_FREQUENCY,
168 .type = V4L2_CTRL_TYPE_MENU,
169 .name = "Light frequency filter",
170 .minimum = 0,
171 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
172 .step = 1,
173#define FREQ_DEF 0
174 .default_value = FREQ_DEF,
175 },
176 .set = sd_setfreq,
177 .get = sd_getfreq,
178 },
179};
180
181static const struct v4l2_pix_format ov965x_mode[] = {
182#define QVGA_MODE 0
183 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
184 .bytesperline = 320,
185 .sizeimage = 320 * 240 * 3 / 8 + 590,
186 .colorspace = V4L2_COLORSPACE_JPEG},
187#define VGA_MODE 1
188 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
189 .bytesperline = 640,
190 .sizeimage = 640 * 480 * 3 / 8 + 590,
191 .colorspace = V4L2_COLORSPACE_JPEG},
192#define SVGA_MODE 2
193 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
194 .bytesperline = 800,
195 .sizeimage = 800 * 600 * 3 / 8 + 590,
196 .colorspace = V4L2_COLORSPACE_JPEG},
197#define XGA_MODE 3
198 {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
199 .bytesperline = 1024,
200 .sizeimage = 1024 * 768 * 3 / 8 + 590,
201 .colorspace = V4L2_COLORSPACE_JPEG},
202#define SXGA_MODE 4
203 {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
204 .bytesperline = 1280,
205 .sizeimage = 1280 * 1024 * 3 / 8 + 590,
206 .colorspace = V4L2_COLORSPACE_JPEG},
207};
208
209static const u8 bridge_init[][2] = {
210 {0x88, 0xf8},
211 {0x89, 0xff},
212 {0x76, 0x03},
213 {0x92, 0x03},
214 {0x95, 0x10},
215 {0xe2, 0x00},
216 {0xe7, 0x3e},
217 {0x8d, 0x1c},
218 {0x8e, 0x00},
219 {0x8f, 0x00},
220 {0x1f, 0x00},
221 {0xc3, 0xf9},
222 {0x89, 0xff},
223 {0x88, 0xf8},
224 {0x76, 0x03},
225 {0x92, 0x01},
226 {0x93, 0x18},
227 {0x1c, 0x0a},
228 {0x1d, 0x48},
229 {0xc0, 0x50},
230 {0xc1, 0x3c},
231 {0x34, 0x05},
232 {0xc2, 0x0c},
233 {0xc3, 0xf9},
234 {0x34, 0x05},
235 {0xe7, 0x2e},
236 {0x31, 0xf9},
237 {0x35, 0x02},
238 {0xd9, 0x10},
239 {0x25, 0x42},
240 {0x94, 0x11},
241};
242
243static const u8 sensor_init[][2] = {
244 {0x12, 0x80}, /* com7 - SSCB reset */
245 {0x00, 0x00}, /* gain */
246 {0x01, 0x80}, /* blue */
247 {0x02, 0x80}, /* red */
248 {0x03, 0x1b}, /* vref */
249 {0x04, 0x03}, /* com1 - exposure low bits */
250 {0x0b, 0x57}, /* ver */
251 {0x0e, 0x61}, /* com5 */
252 {0x0f, 0x42}, /* com6 */
253 {0x11, 0x00}, /* clkrc */
254 {0x12, 0x02}, /* com7 - 15fps VGA YUYV */
255 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
256 {0x14, 0x28}, /* com9 */
257 {0x16, 0x24}, /* reg16 */
258 {0x17, 0x1d}, /* hstart*/
259 {0x18, 0xbd}, /* hstop */
260 {0x19, 0x01}, /* vstrt */
261 {0x1a, 0x81}, /* vstop*/
262 {0x1e, 0x04}, /* mvfp */
263 {0x24, 0x3c}, /* aew */
264 {0x25, 0x36}, /* aeb */
265 {0x26, 0x71}, /* vpt */
266 {0x27, 0x08}, /* bbias */
267 {0x28, 0x08}, /* gbbias */
268 {0x29, 0x15}, /* gr com */
269 {0x2a, 0x00}, /* exhch */
270 {0x2b, 0x00}, /* exhcl */
271 {0x2c, 0x08}, /* rbias */
272 {0x32, 0xff}, /* href */
273 {0x33, 0x00}, /* chlf */
274 {0x34, 0x3f}, /* aref1 */
275 {0x35, 0x00}, /* aref2 */
276 {0x36, 0xf8}, /* aref3 */
277 {0x38, 0x72}, /* adc2 */
278 {0x39, 0x57}, /* aref4 */
279 {0x3a, 0x80}, /* tslb - yuyv */
280 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
281 {0x3d, 0x99}, /* com13 */
282 {0x3f, 0xc1}, /* edge */
283 {0x40, 0xc0}, /* com15 */
284 {0x41, 0x40}, /* com16 */
285 {0x42, 0xc0}, /* com17 */
286 {0x43, 0x0a}, /* rsvd */
287 {0x44, 0xf0},
288 {0x45, 0x46},
289 {0x46, 0x62},
290 {0x47, 0x2a},
291 {0x48, 0x3c},
292 {0x4a, 0xfc},
293 {0x4b, 0xfc},
294 {0x4c, 0x7f},
295 {0x4d, 0x7f},
296 {0x4e, 0x7f},
297 {0x4f, 0x98}, /* matrix */
298 {0x50, 0x98},
299 {0x51, 0x00},
300 {0x52, 0x28},
301 {0x53, 0x70},
302 {0x54, 0x98},
303 {0x58, 0x1a}, /* matrix coef sign */
304 {0x59, 0x85}, /* AWB control */
305 {0x5a, 0xa9},
306 {0x5b, 0x64},
307 {0x5c, 0x84},
308 {0x5d, 0x53},
309 {0x5e, 0x0e},
310 {0x5f, 0xf0}, /* AWB blue limit */
311 {0x60, 0xf0}, /* AWB red limit */
312 {0x61, 0xf0}, /* AWB green limit */
313 {0x62, 0x00}, /* lcc1 */
314 {0x63, 0x00}, /* lcc2 */
315 {0x64, 0x02}, /* lcc3 */
316 {0x65, 0x16}, /* lcc4 */
317 {0x66, 0x01}, /* lcc5 */
318 {0x69, 0x02}, /* hv */
319 {0x6b, 0x5a}, /* dbvl */
320 {0x6c, 0x04},
321 {0x6d, 0x55},
322 {0x6e, 0x00},
323 {0x6f, 0x9d},
324 {0x70, 0x21}, /* dnsth */
325 {0x71, 0x78},
326 {0x72, 0x00}, /* poidx */
327 {0x73, 0x01}, /* pckdv */
328 {0x74, 0x3a}, /* xindx */
329 {0x75, 0x35}, /* yindx */
330 {0x76, 0x01},
331 {0x77, 0x02},
332 {0x7a, 0x12}, /* gamma curve */
333 {0x7b, 0x08},
334 {0x7c, 0x16},
335 {0x7d, 0x30},
336 {0x7e, 0x5e},
337 {0x7f, 0x72},
338 {0x80, 0x82},
339 {0x81, 0x8e},
340 {0x82, 0x9a},
341 {0x83, 0xa4},
342 {0x84, 0xac},
343 {0x85, 0xb8},
344 {0x86, 0xc3},
345 {0x87, 0xd6},
346 {0x88, 0xe6},
347 {0x89, 0xf2},
348 {0x8a, 0x03},
349 {0x8c, 0x89}, /* com19 */
350 {0x14, 0x28}, /* com9 */
351 {0x90, 0x7d},
352 {0x91, 0x7b},
353 {0x9d, 0x03}, /* lcc6 */
354 {0x9e, 0x04}, /* lcc7 */
355 {0x9f, 0x7a},
356 {0xa0, 0x79},
357 {0xa1, 0x40}, /* aechm */
358 {0xa4, 0x50}, /* com21 */
359 {0xa5, 0x68}, /* com26 */
360 {0xa6, 0x4a}, /* AWB green */
361 {0xa8, 0xc1}, /* refa8 */
362 {0xa9, 0xef}, /* refa9 */
363 {0xaa, 0x92},
364 {0xab, 0x04},
365 {0xac, 0x80}, /* black level control */
366 {0xad, 0x80},
367 {0xae, 0x80},
368 {0xaf, 0x80},
369 {0xb2, 0xf2},
370 {0xb3, 0x20},
371 {0xb4, 0x20}, /* ctrlb4 */
372 {0xb5, 0x00},
373 {0xb6, 0xaf},
374 {0xbb, 0xae},
375 {0xbc, 0x7f}, /* ADC channel offsets */
376 {0xdb, 0x7f},
377 {0xbe, 0x7f},
378 {0xbf, 0x7f},
379 {0xc0, 0xe2},
380 {0xc1, 0xc0},
381 {0xc2, 0x01},
382 {0xc3, 0x4e},
383 {0xc6, 0x85},
384 {0xc7, 0x80}, /* com24 */
385 {0xc9, 0xe0},
386 {0xca, 0xe8},
387 {0xcb, 0xf0},
388 {0xcc, 0xd8},
389 {0xcd, 0xf1},
390 {0x4f, 0x98}, /* matrix */
391 {0x50, 0x98},
392 {0x51, 0x00},
393 {0x52, 0x28},
394 {0x53, 0x70},
395 {0x54, 0x98},
396 {0x58, 0x1a},
397 {0xff, 0x41}, /* read 41, write ff 00 */
398 {0x41, 0x40}, /* com16 */
399
400 {0xc5, 0x03}, /* 60 Hz banding filter */
401 {0x6a, 0x02}, /* 50 Hz banding filter */
402
403 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
404 {0x36, 0xfa}, /* aref3 */
405 {0x69, 0x0a}, /* hv */
406 {0x8c, 0x89}, /* com22 */
407 {0x14, 0x28}, /* com9 */
408 {0x3e, 0x0c},
409 {0x41, 0x40}, /* com16 */
410 {0x72, 0x00},
411 {0x73, 0x00},
412 {0x74, 0x3a},
413 {0x75, 0x35},
414 {0x76, 0x01},
415 {0xc7, 0x80},
416 {0x03, 0x12}, /* vref */
417 {0x17, 0x16}, /* hstart */
418 {0x18, 0x02}, /* hstop */
419 {0x19, 0x01}, /* vstrt */
420 {0x1a, 0x3d}, /* vstop */
421 {0x32, 0xff}, /* href */
422 {0xc0, 0xaa},
423};
424
425static const u8 bridge_init_2[][2] = {
426 {0x94, 0xaa},
427 {0xf1, 0x60},
428 {0xe5, 0x04},
429 {0xc0, 0x50},
430 {0xc1, 0x3c},
431 {0x8c, 0x00},
432 {0x8d, 0x1c},
433 {0x34, 0x05},
434
435 {0xc2, 0x0c},
436 {0xc3, 0xf9},
437 {0xda, 0x01},
438 {0x50, 0x00},
439 {0x51, 0xa0},
440 {0x52, 0x3c},
441 {0x53, 0x00},
442 {0x54, 0x00},
443 {0x55, 0x00},
444 {0x57, 0x00},
445 {0x5c, 0x00},
446 {0x5a, 0xa0},
447 {0x5b, 0x78},
448 {0x35, 0x02},
449 {0xd9, 0x10},
450 {0x94, 0x11},
451};
452
453static const u8 sensor_init_2[][2] = {
454 {0x3b, 0xc4},
455 {0x1e, 0x04}, /* mvfp */
456 {0x13, 0xe0}, /* com8 */
457 {0x00, 0x00}, /* gain */
458 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
459 {0x11, 0x03}, /* clkrc */
460 {0x6b, 0x5a}, /* dblv */
461 {0x6a, 0x05},
462 {0xc5, 0x07},
463 {0xa2, 0x4b},
464 {0xa3, 0x3e},
465 {0x2d, 0x00},
466 {0xff, 0x42}, /* read 42, write ff 00 */
467 {0x42, 0xc0}, /* com17 */
468 {0x2d, 0x00},
469 {0xff, 0x42}, /* read 42, write ff 00 */
470 {0x42, 0xc1}, /* com17 */
471/* sharpness */
472 {0x3f, 0x01},
473 {0xff, 0x42}, /* read 42, write ff 00 */
474 {0x42, 0xc1}, /* com17 */
475/* saturation */
476 {0x4f, 0x98}, /* matrix */
477 {0x50, 0x98},
478 {0x51, 0x00},
479 {0x52, 0x28},
480 {0x53, 0x70},
481 {0x54, 0x98},
482 {0x58, 0x1a},
483 {0xff, 0x41}, /* read 41, write ff 00 */
484 {0x41, 0x40}, /* com16 */
485/* contrast */
486 {0x56, 0x40},
487/* brightness */
488 {0x55, 0x8f},
489/* expo */
490 {0x10, 0x25}, /* aech - exposure high bits */
491 {0xff, 0x13}, /* read 13, write ff 00 */
492 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
493};
494
495static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
496 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
497 {0x36, 0xfa}, /* aref3 */
498 {0x69, 0x0a}, /* hv */
499 {0x8c, 0x89}, /* com22 */
500 {0x14, 0x28}, /* com9 */
501 {0x3e, 0x0c}, /* com14 */
502 {0x41, 0x40}, /* com16 */
503 {0x72, 0x00},
504 {0x73, 0x00},
505 {0x74, 0x3a},
506 {0x75, 0x35},
507 {0x76, 0x01},
508 {0xc7, 0x80}, /* com24 */
509 {0x03, 0x12}, /* vref */
510 {0x17, 0x16}, /* hstart */
511 {0x18, 0x02}, /* hstop */
512 {0x19, 0x01}, /* vstrt */
513 {0x1a, 0x3d}, /* vstop */
514 {0x32, 0xff}, /* href */
515 {0xc0, 0xaa},
516};
517
518static const u8 sensor_start_1_svga[][2] = {
519 {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
520 {0x36, 0xf8}, /* aref3 */
521 {0x69, 0x02}, /* hv */
522 {0x8c, 0x0d}, /* com22 */
523 {0x3e, 0x0c}, /* com14 */
524 {0x41, 0x40}, /* com16 */
525 {0x72, 0x00},
526 {0x73, 0x01},
527 {0x74, 0x3a},
528 {0x75, 0x35},
529 {0x76, 0x01},
530 {0xc7, 0x80}, /* com24 */
531 {0x03, 0x1b}, /* vref */
532 {0x17, 0x1d}, /* hstart */
533 {0x18, 0xbd}, /* hstop */
534 {0x19, 0x01}, /* vstrt */
535 {0x1a, 0x81}, /* vstop */
536 {0x32, 0xff}, /* href */
537 {0xc0, 0xe2},
538};
539
540static const u8 sensor_start_1_xga[][2] = {
541 {0x12, 0x02}, /* com7 */
542 {0x36, 0xf8}, /* aref3 */
543 {0x69, 0x02}, /* hv */
544 {0x8c, 0x89}, /* com22 */
545 {0x14, 0x28}, /* com9 */
546 {0x3e, 0x0c}, /* com14 */
547 {0x41, 0x40}, /* com16 */
548 {0x72, 0x00},
549 {0x73, 0x01},
550 {0x74, 0x3a},
551 {0x75, 0x35},
552 {0x76, 0x01},
553 {0xc7, 0x80}, /* com24 */
554 {0x03, 0x1b}, /* vref */
555 {0x17, 0x1d}, /* hstart */
556 {0x18, 0xbd}, /* hstop */
557 {0x19, 0x01}, /* vstrt */
558 {0x1a, 0x81}, /* vstop */
559 {0x32, 0xff}, /* href */
560 {0xc0, 0xe2},
561};
562
563static const u8 sensor_start_1_sxga[][2] = {
564 {0x12, 0x02}, /* com7 */
565 {0x36, 0xf8}, /* aref3 */
566 {0x69, 0x02}, /* hv */
567 {0x8c, 0x89}, /* com22 */
568 {0x14, 0x28}, /* com9 */
569 {0x3e, 0x0c}, /* com14 */
570 {0x41, 0x40}, /* com16 */
571 {0x72, 0x00},
572 {0x73, 0x01},
573 {0x74, 0x3a},
574 {0x75, 0x35},
575 {0x76, 0x01},
576 {0xc7, 0x80}, /* com24 */
577 {0x03, 0x1b}, /* vref */
578 {0x17, 0x1d}, /* hstart */
579 {0x18, 0x02}, /* hstop */
580 {0x19, 0x01}, /* vstrt */
581 {0x1a, 0x81}, /* vstop */
582 {0x32, 0xff}, /* href */
583 {0xc0, 0xe2},
584};
585
586static const u8 bridge_start_qvga[][2] = {
587 {0x94, 0xaa},
588 {0xf1, 0x60},
589 {0xe5, 0x04},
590 {0xc0, 0x50},
591 {0xc1, 0x3c},
592 {0x8c, 0x00},
593 {0x8d, 0x1c},
594 {0x34, 0x05},
595
596 {0xc2, 0x4c},
597 {0xc3, 0xf9},
598 {0xda, 0x00},
599 {0x50, 0x00},
600 {0x51, 0xa0},
601 {0x52, 0x78},
602 {0x53, 0x00},
603 {0x54, 0x00},
604 {0x55, 0x00},
605 {0x57, 0x00},
606 {0x5c, 0x00},
607 {0x5a, 0x50},
608 {0x5b, 0x3c},
609 {0x35, 0x02},
610 {0xd9, 0x10},
611 {0x94, 0x11},
612};
613
614static const u8 bridge_start_vga[][2] = {
615 {0x94, 0xaa},
616 {0xf1, 0x60},
617 {0xe5, 0x04},
618 {0xc0, 0x50},
619 {0xc1, 0x3c},
620 {0x8c, 0x00},
621 {0x8d, 0x1c},
622 {0x34, 0x05},
623 {0xc2, 0x0c},
624 {0xc3, 0xf9},
625 {0xda, 0x01},
626 {0x50, 0x00},
627 {0x51, 0xa0},
628 {0x52, 0x3c},
629 {0x53, 0x00},
630 {0x54, 0x00},
631 {0x55, 0x00},
632 {0x57, 0x00},
633 {0x5c, 0x00},
634 {0x5a, 0xa0},
635 {0x5b, 0x78},
636 {0x35, 0x02},
637 {0xd9, 0x10},
638 {0x94, 0x11},
639};
640
641static const u8 bridge_start_svga[][2] = {
642 {0x94, 0xaa},
643 {0xf1, 0x60},
644 {0xe5, 0x04},
645 {0xc0, 0xa0},
646 {0xc1, 0x80},
647 {0x8c, 0x00},
648 {0x8d, 0x1c},
649 {0x34, 0x05},
650 {0xc2, 0x4c},
651 {0xc3, 0xf9},
652 {0x50, 0x00},
653 {0x51, 0x40},
654 {0x52, 0x00},
655 {0x53, 0x00},
656 {0x54, 0x00},
657 {0x55, 0x88},
658 {0x57, 0x00},
659 {0x5c, 0x00},
660 {0x5a, 0xc8},
661 {0x5b, 0x96},
662 {0x35, 0x02},
663 {0xd9, 0x10},
664 {0xda, 0x00},
665 {0x94, 0x11},
666};
667
668static const u8 bridge_start_xga[][2] = {
669 {0x94, 0xaa},
670 {0xf1, 0x60},
671 {0xe5, 0x04},
672 {0xc0, 0xa0},
673 {0xc1, 0x80},
674 {0x8c, 0x00},
675 {0x8d, 0x1c},
676 {0x34, 0x05},
677 {0xc2, 0x4c},
678 {0xc3, 0xf9},
679 {0x50, 0x00},
680 {0x51, 0x40},
681 {0x52, 0x00},
682 {0x53, 0x00},
683 {0x54, 0x00},
684 {0x55, 0x88},
685 {0x57, 0x00},
686 {0x5c, 0x01},
687 {0x5a, 0x00},
688 {0x5b, 0xc0},
689 {0x35, 0x02},
690 {0xd9, 0x10},
691 {0xda, 0x01},
692 {0x94, 0x11},
693};
694
695static const u8 bridge_start_sxga[][2] = {
696 {0x94, 0xaa},
697 {0xf1, 0x60},
698 {0xe5, 0x04},
699 {0xc0, 0xa0},
700 {0xc1, 0x80},
701 {0x8c, 0x00},
702 {0x8d, 0x1c},
703 {0x34, 0x05},
704 {0xc2, 0x0c},
705 {0xc3, 0xf9},
706 {0xda, 0x00},
707 {0x35, 0x02},
708 {0xd9, 0x10},
709 {0x94, 0x11},
710};
711
712static const u8 sensor_start_2_qvga[][2] = {
713 {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
714 {0x1e, 0x04}, /* mvfp */
715 {0x13, 0xe0}, /* com8 */
716 {0x00, 0x00},
717 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
718 {0x11, 0x01}, /* clkrc */
719 {0x6b, 0x5a}, /* dblv */
720 {0x6a, 0x02}, /* 50 Hz banding filter */
721 {0xc5, 0x03}, /* 60 Hz banding filter */
722 {0xa2, 0x96}, /* bd50 */
723 {0xa3, 0x7d}, /* bd60 */
724
725 {0xff, 0x13}, /* read 13, write ff 00 */
726 {0x13, 0xe7},
727 {0x3a, 0x80}, /* tslb - yuyv */
728};
729
730static const u8 sensor_start_2_vga[][2] = {
731 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
732 {0x1e, 0x04}, /* mvfp */
733 {0x13, 0xe0}, /* com8 */
734 {0x00, 0x00},
735 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
736 {0x11, 0x03}, /* clkrc */
737 {0x6b, 0x5a}, /* dblv */
738 {0x6a, 0x05}, /* 50 Hz banding filter */
739 {0xc5, 0x07}, /* 60 Hz banding filter */
740 {0xa2, 0x4b}, /* bd50 */
741 {0xa3, 0x3e}, /* bd60 */
742
743 {0x2d, 0x00}, /* advfl */
744};
745
746static const u8 sensor_start_2_svga[][2] = { /* same for xga */
747 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
748 {0x1e, 0x04}, /* mvfp */
749 {0x13, 0xe0}, /* com8 */
750 {0x00, 0x00},
751 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
752 {0x11, 0x01}, /* clkrc */
753 {0x6b, 0x5a}, /* dblv */
754 {0x6a, 0x0c}, /* 50 Hz banding filter */
755 {0xc5, 0x0f}, /* 60 Hz banding filter */
756 {0xa2, 0x4e}, /* bd50 */
757 {0xa3, 0x41}, /* bd60 */
758};
759
760static const u8 sensor_start_2_sxga[][2] = {
761 {0x13, 0xe0}, /* com8 */
762 {0x00, 0x00},
763 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
764 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
765 {0x1e, 0x04}, /* mvfp */
766 {0x11, 0x01}, /* clkrc */
767 {0x6b, 0x5a}, /* dblv */
768 {0x6a, 0x0c}, /* 50 Hz banding filter */
769 {0xc5, 0x0f}, /* 60 Hz banding filter */
770 {0xa2, 0x4e}, /* bd50 */
771 {0xa3, 0x41}, /* bd60 */
772};
773
774static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
775{
776 struct usb_device *udev = gspca_dev->dev;
777 int ret;
778
779 if (gspca_dev->usb_err < 0)
780 return;
781 gspca_dev->usb_buf[0] = val;
782 ret = usb_control_msg(udev,
783 usb_sndctrlpipe(udev, 0),
784 0x01,
785 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
786 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
787 if (ret < 0) {
788 err("reg_w failed %d", ret);
789 gspca_dev->usb_err = ret;
790 }
791}
792
793static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
794{
795 PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
796 reg_w_i(gspca_dev, reg, val);
797}
798
799static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
800{
801 struct usb_device *udev = gspca_dev->dev;
802 int ret;
803
804 if (gspca_dev->usb_err < 0)
805 return 0;
806 ret = usb_control_msg(udev,
807 usb_rcvctrlpipe(udev, 0),
808 0x01,
809 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
810 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
811 PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
812 if (ret < 0) {
813 err("reg_r err %d", ret);
814 gspca_dev->usb_err = ret;
815 }
816 return gspca_dev->usb_buf[0];
817}
818
819static int sccb_check_status(struct gspca_dev *gspca_dev)
820{
821 u8 data;
822 int i;
823
824 for (i = 0; i < 5; i++) {
825 data = reg_r(gspca_dev, OV534_REG_STATUS);
826
827 switch (data) {
828 case 0x00:
829 return 1;
830 case 0x04:
831 return 0;
832 case 0x03:
833 break;
834 default:
835 PDEBUG(D_USBI|D_USBO,
836 "sccb status 0x%02x, attempt %d/5",
837 data, i + 1);
838 }
839 }
840 return 0;
841}
842
843static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
844{
845 PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
846 reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
847 reg_w_i(gspca_dev, OV534_REG_WRITE, val);
848 reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
849
850 if (!sccb_check_status(gspca_dev))
851 err("sccb_write failed");
852}
853
854static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
855{
856 reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
857 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
858 if (!sccb_check_status(gspca_dev))
859 err("sccb_read failed 1");
860
861 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
862 if (!sccb_check_status(gspca_dev))
863 err("sccb_read failed 2");
864
865 return reg_r(gspca_dev, OV534_REG_READ);
866}
867
868/* output a bridge sequence (reg - val) */
869static void reg_w_array(struct gspca_dev *gspca_dev,
870 const u8 (*data)[2], int len)
871{
872 while (--len >= 0) {
873 reg_w(gspca_dev, (*data)[0], (*data)[1]);
874 data++;
875 }
876}
877
878/* output a sensor sequence (reg - val) */
879static void sccb_w_array(struct gspca_dev *gspca_dev,
880 const u8 (*data)[2], int len)
881{
882 while (--len >= 0) {
883 if ((*data)[0] != 0xff) {
884 sccb_write(gspca_dev, (*data)[0], (*data)[1]);
885 } else {
886 sccb_read(gspca_dev, (*data)[1]);
887 sccb_write(gspca_dev, 0xff, 0x00);
888 }
889 data++;
890 }
891}
892
893/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
894 * (direction and output)? */
895static void set_led(struct gspca_dev *gspca_dev, int status)
896{
897 u8 data;
898
899 PDEBUG(D_CONF, "led status: %d", status);
900
901 data = reg_r(gspca_dev, 0x21);
902 data |= 0x80;
903 reg_w(gspca_dev, 0x21, data);
904
905 data = reg_r(gspca_dev, 0x23);
906 if (status)
907 data |= 0x80;
908 else
909 data &= ~0x80;
910
911 reg_w(gspca_dev, 0x23, data);
912
913 if (!status) {
914 data = reg_r(gspca_dev, 0x21);
915 data &= ~0x80;
916 reg_w(gspca_dev, 0x21, data);
917 }
918}
919
920static void setbrightness(struct gspca_dev *gspca_dev)
921{
922 struct sd *sd = (struct sd *) gspca_dev;
923 u8 val;
924
925 val = sd->brightness;
926 if (val < 8)
927 val = 15 - val; /* f .. 8 */
928 else
929 val = val - 8; /* 0 .. 7 */
930 sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */
931 0x0f | (val << 4));
932}
933
934static void setcontrast(struct gspca_dev *gspca_dev)
935{
936 struct sd *sd = (struct sd *) gspca_dev;
937
938 sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
939 sd->contrast << 4);
940}
941
942static void setautogain(struct gspca_dev *gspca_dev)
943{
944 struct sd *sd = (struct sd *) gspca_dev;
945 u8 val;
946
947/*fixme: should adjust agc/awb/aec by different controls */
948 val = sccb_read(gspca_dev, 0x13); /* com8 */
949 sccb_write(gspca_dev, 0xff, 0x00);
950 if (sd->autogain)
951 val |= 0x05; /* agc & aec */
952 else
953 val &= 0xfa;
954 sccb_write(gspca_dev, 0x13, val);
955}
956
957static void setexposure(struct gspca_dev *gspca_dev)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
960 u8 val;
961 static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
962
963 sccb_write(gspca_dev, 0x10, /* aec[9:2] */
964 expo[sd->exposure]);
965
966 val = sccb_read(gspca_dev, 0x13); /* com8 */
967 sccb_write(gspca_dev, 0xff, 0x00);
968 sccb_write(gspca_dev, 0x13, val);
969
970 val = sccb_read(gspca_dev, 0xa1); /* aech */
971 sccb_write(gspca_dev, 0xff, 0x00);
972 sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */
973}
974
975static void setsharpness(struct gspca_dev *gspca_dev)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978 s8 val;
979
980 val = sd->sharpness;
981 if (val < 0) { /* auto */
982 val = sccb_read(gspca_dev, 0x42); /* com17 */
983 sccb_write(gspca_dev, 0xff, 0x00);
984 sccb_write(gspca_dev, 0x42, val | 0x40);
985 /* Edge enhancement strength auto adjust */
986 return;
987 }
988 if (val != 0)
989 val = 1 << (val - 1);
990 sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */
991 val);
992 val = sccb_read(gspca_dev, 0x42); /* com17 */
993 sccb_write(gspca_dev, 0xff, 0x00);
994 sccb_write(gspca_dev, 0x42, val & 0xbf);
995}
996
997static void setsatur(struct gspca_dev *gspca_dev)
998{
999 struct sd *sd = (struct sd *) gspca_dev;
1000 u8 val1, val2, val3;
1001 static const u8 matrix[5][2] = {
1002 {0x14, 0x38},
1003 {0x1e, 0x54},
1004 {0x28, 0x70},
1005 {0x32, 0x8c},
1006 {0x48, 0x90}
1007 };
1008
1009 val1 = matrix[sd->satur][0];
1010 val2 = matrix[sd->satur][1];
1011 val3 = val1 + val2;
1012 sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */
1013 sccb_write(gspca_dev, 0x50, val3);
1014 sccb_write(gspca_dev, 0x51, 0x00);
1015 sccb_write(gspca_dev, 0x52, val1);
1016 sccb_write(gspca_dev, 0x53, val2);
1017 sccb_write(gspca_dev, 0x54, val3);
1018 sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */
1019
1020 val1 = sccb_read(gspca_dev, 0x41); /* com16 */
1021 sccb_write(gspca_dev, 0xff, 0x00);
1022 sccb_write(gspca_dev, 0x41, val1);
1023}
1024
1025static void setfreq(struct gspca_dev *gspca_dev)
1026{
1027 struct sd *sd = (struct sd *) gspca_dev;
1028 u8 val;
1029
1030 val = sccb_read(gspca_dev, 0x13); /* com8 */
1031 sccb_write(gspca_dev, 0xff, 0x00);
1032 if (sd->freq == 0) {
1033 sccb_write(gspca_dev, 0x13, val & 0xdf);
1034 return;
1035 }
1036 sccb_write(gspca_dev, 0x13, val | 0x20);
1037
1038 val = sccb_read(gspca_dev, 0x42); /* com17 */
1039 sccb_write(gspca_dev, 0xff, 0x00);
1040 if (sd->freq == 1)
1041 val |= 0x01;
1042 else
1043 val &= 0xfe;
1044 sccb_write(gspca_dev, 0x42, val);
1045}
1046
1047/* this function is called at probe time */
1048static int sd_config(struct gspca_dev *gspca_dev,
1049 const struct usb_device_id *id)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052 struct cam *cam;
1053
1054 cam = &gspca_dev->cam;
1055
1056 cam->cam_mode = ov965x_mode;
1057 cam->nmodes = ARRAY_SIZE(ov965x_mode);
1058
1059 sd->brightness = BRIGHTNESS_DEF;
1060 sd->contrast = CONTRAST_DEF;
1061#if AUTOGAIN_DEF != 0
1062 sd->autogain = AUTOGAIN_DEF;
1063 gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
1064#endif
1065#if EXPO_DEF != 0
1066 sd->exposure = EXPO_DEF;
1067#endif
1068#if SHARPNESS_DEF != 0
1069 sd->sharpness = SHARPNESS_DEF;
1070#endif
1071 sd->satur = SATUR_DEF;
1072 sd->freq = FREQ_DEF;
1073
1074 return 0;
1075}
1076
1077/* this function is called at probe and resume time */
1078static int sd_init(struct gspca_dev *gspca_dev)
1079{
1080 u16 sensor_id;
1081
1082 /* reset bridge */
1083 reg_w(gspca_dev, 0xe7, 0x3a);
1084 reg_w(gspca_dev, 0xe0, 0x08);
1085 msleep(100);
1086
1087 /* initialize the sensor address */
1088 reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
1089
1090 /* reset sensor */
1091 sccb_write(gspca_dev, 0x12, 0x80);
1092 msleep(10);
1093
1094 /* probe the sensor */
1095 sccb_read(gspca_dev, 0x0a);
1096 sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
1097 sccb_read(gspca_dev, 0x0b);
1098 sensor_id |= sccb_read(gspca_dev, 0x0b);
1099 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1100
1101 /* initialize */
1102 reg_w_array(gspca_dev, bridge_init,
1103 ARRAY_SIZE(bridge_init));
1104 sccb_w_array(gspca_dev, sensor_init,
1105 ARRAY_SIZE(sensor_init));
1106 reg_w_array(gspca_dev, bridge_init_2,
1107 ARRAY_SIZE(bridge_init_2));
1108 sccb_w_array(gspca_dev, sensor_init_2,
1109 ARRAY_SIZE(sensor_init_2));
1110 reg_w(gspca_dev, 0xe0, 0x00);
1111 reg_w(gspca_dev, 0xe0, 0x01);
1112 set_led(gspca_dev, 0);
1113 reg_w(gspca_dev, 0xe0, 0x00);
1114
1115 return gspca_dev->usb_err;
1116}
1117
1118static int sd_start(struct gspca_dev *gspca_dev)
1119{
1120 switch (gspca_dev->curr_mode) {
1121 case QVGA_MODE: /* 320x240 */
1122 sccb_w_array(gspca_dev, sensor_start_1_vga,
1123 ARRAY_SIZE(sensor_start_1_vga));
1124 reg_w_array(gspca_dev, bridge_start_qvga,
1125 ARRAY_SIZE(bridge_start_qvga));
1126 sccb_w_array(gspca_dev, sensor_start_2_qvga,
1127 ARRAY_SIZE(sensor_start_2_qvga));
1128 break;
1129 case VGA_MODE: /* 640x480 */
1130 sccb_w_array(gspca_dev, sensor_start_1_vga,
1131 ARRAY_SIZE(sensor_start_1_vga));
1132 reg_w_array(gspca_dev, bridge_start_vga,
1133 ARRAY_SIZE(bridge_start_vga));
1134 sccb_w_array(gspca_dev, sensor_start_2_vga,
1135 ARRAY_SIZE(sensor_start_2_vga));
1136 break;
1137 case SVGA_MODE: /* 800x600 */
1138 sccb_w_array(gspca_dev, sensor_start_1_svga,
1139 ARRAY_SIZE(sensor_start_1_svga));
1140 reg_w_array(gspca_dev, bridge_start_svga,
1141 ARRAY_SIZE(bridge_start_svga));
1142 sccb_w_array(gspca_dev, sensor_start_2_svga,
1143 ARRAY_SIZE(sensor_start_2_svga));
1144 break;
1145 case XGA_MODE: /* 1024x768 */
1146 sccb_w_array(gspca_dev, sensor_start_1_xga,
1147 ARRAY_SIZE(sensor_start_1_xga));
1148 reg_w_array(gspca_dev, bridge_start_xga,
1149 ARRAY_SIZE(bridge_start_xga));
1150 sccb_w_array(gspca_dev, sensor_start_2_svga,
1151 ARRAY_SIZE(sensor_start_2_svga));
1152 break;
1153 default:
1154/* case SXGA_MODE: * 1280x1024 */
1155 sccb_w_array(gspca_dev, sensor_start_1_sxga,
1156 ARRAY_SIZE(sensor_start_1_sxga));
1157 reg_w_array(gspca_dev, bridge_start_sxga,
1158 ARRAY_SIZE(bridge_start_sxga));
1159 sccb_w_array(gspca_dev, sensor_start_2_sxga,
1160 ARRAY_SIZE(sensor_start_2_sxga));
1161 break;
1162 }
1163 setfreq(gspca_dev);
1164 setautogain(gspca_dev);
1165 setbrightness(gspca_dev);
1166 setcontrast(gspca_dev);
1167 setexposure(gspca_dev);
1168 setsharpness(gspca_dev);
1169 setsatur(gspca_dev);
1170
1171 reg_w(gspca_dev, 0xe0, 0x00);
1172 reg_w(gspca_dev, 0xe0, 0x00);
1173 set_led(gspca_dev, 1);
1174 return gspca_dev->usb_err;
1175}
1176
1177static void sd_stopN(struct gspca_dev *gspca_dev)
1178{
1179 reg_w(gspca_dev, 0xe0, 0x01);
1180 set_led(gspca_dev, 0);
1181 reg_w(gspca_dev, 0xe0, 0x00);
1182}
1183
1184/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1185#define UVC_STREAM_EOH (1 << 7)
1186#define UVC_STREAM_ERR (1 << 6)
1187#define UVC_STREAM_STI (1 << 5)
1188#define UVC_STREAM_RES (1 << 4)
1189#define UVC_STREAM_SCR (1 << 3)
1190#define UVC_STREAM_PTS (1 << 2)
1191#define UVC_STREAM_EOF (1 << 1)
1192#define UVC_STREAM_FID (1 << 0)
1193
1194static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1195 u8 *data, int len)
1196{
1197 struct sd *sd = (struct sd *) gspca_dev;
1198 __u32 this_pts;
1199 u8 this_fid;
1200 int remaining_len = len;
1201
1202 do {
1203 len = min(remaining_len, 2040);
1204
1205 /* Payloads are prefixed with a UVC-style header. We
1206 consider a frame to start when the FID toggles, or the PTS
1207 changes. A frame ends when EOF is set, and we've received
1208 the correct number of bytes. */
1209
1210 /* Verify UVC header. Header length is always 12 */
1211 if (data[0] != 12 || len < 12) {
1212 PDEBUG(D_PACK, "bad header");
1213 goto discard;
1214 }
1215
1216 /* Check errors */
1217 if (data[1] & UVC_STREAM_ERR) {
1218 PDEBUG(D_PACK, "payload error");
1219 goto discard;
1220 }
1221
1222 /* Extract PTS and FID */
1223 if (!(data[1] & UVC_STREAM_PTS)) {
1224 PDEBUG(D_PACK, "PTS not present");
1225 goto discard;
1226 }
1227 this_pts = (data[5] << 24) | (data[4] << 16)
1228 | (data[3] << 8) | data[2];
1229 this_fid = data[1] & UVC_STREAM_FID;
1230
1231 /* If PTS or FID has changed, start a new frame. */
1232 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1233 if (gspca_dev->last_packet_type == INTER_PACKET)
1234 gspca_frame_add(gspca_dev, LAST_PACKET,
1235 NULL, 0);
1236 sd->last_pts = this_pts;
1237 sd->last_fid = this_fid;
1238 gspca_frame_add(gspca_dev, FIRST_PACKET,
1239 data + 12, len - 12);
1240 /* If this packet is marked as EOF, end the frame */
1241 } else if (data[1] & UVC_STREAM_EOF) {
1242 sd->last_pts = 0;
1243 gspca_frame_add(gspca_dev, LAST_PACKET,
1244 data + 12, len - 12);
1245 } else {
1246
1247 /* Add the data from this payload */
1248 gspca_frame_add(gspca_dev, INTER_PACKET,
1249 data + 12, len - 12);
1250 }
1251
1252 /* Done this payload */
1253 goto scan_next;
1254
1255discard:
1256 /* Discard data until a new frame starts. */
1257 gspca_dev->last_packet_type = DISCARD_PACKET;
1258
1259scan_next:
1260 remaining_len -= len;
1261 data += len;
1262 } while (remaining_len > 0);
1263}
1264
1265/* controls */
1266static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1267{
1268 struct sd *sd = (struct sd *) gspca_dev;
1269
1270 sd->brightness = val;
1271 if (gspca_dev->streaming)
1272 setbrightness(gspca_dev);
1273 return gspca_dev->usb_err;
1274}
1275
1276static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1277{
1278 struct sd *sd = (struct sd *) gspca_dev;
1279
1280 *val = sd->brightness;
1281 return 0;
1282}
1283
1284static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287
1288 sd->contrast = val;
1289 if (gspca_dev->streaming)
1290 setcontrast(gspca_dev);
1291 return gspca_dev->usb_err;
1292}
1293
1294static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1295{
1296 struct sd *sd = (struct sd *) gspca_dev;
1297
1298 *val = sd->contrast;
1299 return 0;
1300}
1301
1302static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1303{
1304 struct sd *sd = (struct sd *) gspca_dev;
1305
1306 sd->autogain = val;
1307
1308 if (gspca_dev->streaming) {
1309 if (val)
1310 gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
1311 else
1312 gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
1313 setautogain(gspca_dev);
1314 }
1315 return gspca_dev->usb_err;
1316}
1317
1318static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1319{
1320 struct sd *sd = (struct sd *) gspca_dev;
1321
1322 *val = sd->autogain;
1323 return 0;
1324}
1325
1326static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1327{
1328 struct sd *sd = (struct sd *) gspca_dev;
1329
1330 sd->exposure = val;
1331 if (gspca_dev->streaming)
1332 setexposure(gspca_dev);
1333 return gspca_dev->usb_err;
1334}
1335
1336static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1337{
1338 struct sd *sd = (struct sd *) gspca_dev;
1339
1340 *val = sd->exposure;
1341 return 0;
1342}
1343
1344static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1345{
1346 struct sd *sd = (struct sd *) gspca_dev;
1347
1348 sd->sharpness = val;
1349 if (gspca_dev->streaming)
1350 setsharpness(gspca_dev);
1351 return gspca_dev->usb_err;
1352}
1353
1354static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1355{
1356 struct sd *sd = (struct sd *) gspca_dev;
1357
1358 *val = sd->sharpness;
1359 return 0;
1360}
1361
1362static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
1363{
1364 struct sd *sd = (struct sd *) gspca_dev;
1365
1366 sd->satur = val;
1367 if (gspca_dev->streaming)
1368 setsatur(gspca_dev);
1369 return gspca_dev->usb_err;
1370}
1371
1372static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
1373{
1374 struct sd *sd = (struct sd *) gspca_dev;
1375
1376 *val = sd->satur;
1377 return 0;
1378}
1379static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1380{
1381 struct sd *sd = (struct sd *) gspca_dev;
1382
1383 sd->freq = val;
1384 if (gspca_dev->streaming)
1385 setfreq(gspca_dev);
1386 return gspca_dev->usb_err;
1387}
1388
1389static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1390{
1391 struct sd *sd = (struct sd *) gspca_dev;
1392
1393 *val = sd->freq;
1394 return 0;
1395}
1396
1397static int sd_querymenu(struct gspca_dev *gspca_dev,
1398 struct v4l2_querymenu *menu)
1399{
1400 switch (menu->id) {
1401 case V4L2_CID_POWER_LINE_FREQUENCY:
1402 switch (menu->index) {
1403 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1404 strcpy((char *) menu->name, "NoFliker");
1405 return 0;
1406 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1407 strcpy((char *) menu->name, "50 Hz");
1408 return 0;
1409 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1410 strcpy((char *) menu->name, "60 Hz");
1411 return 0;
1412 }
1413 break;
1414 }
1415 return -EINVAL;
1416}
1417
1418/* sub-driver description */
1419static const struct sd_desc sd_desc = {
1420 .name = MODULE_NAME,
1421 .ctrls = sd_ctrls,
1422 .nctrls = ARRAY_SIZE(sd_ctrls),
1423 .config = sd_config,
1424 .init = sd_init,
1425 .start = sd_start,
1426 .stopN = sd_stopN,
1427 .pkt_scan = sd_pkt_scan,
1428 .querymenu = sd_querymenu,
1429};
1430
1431/* -- module initialisation -- */
1432static const struct usb_device_id device_table[] = {
1433 {USB_DEVICE(0x06f8, 0x3003)},
1434 {}
1435};
1436
1437MODULE_DEVICE_TABLE(usb, device_table);
1438
1439/* -- device connect -- */
1440static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1441{
1442 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1443 THIS_MODULE);
1444}
1445
1446static struct usb_driver sd_driver = {
1447 .name = MODULE_NAME,
1448 .id_table = device_table,
1449 .probe = sd_probe,
1450 .disconnect = gspca_disconnect,
1451#ifdef CONFIG_PM
1452 .suspend = gspca_suspend,
1453 .resume = gspca_resume,
1454#endif
1455};
1456
1457/* -- module insert / remove -- */
1458static int __init sd_mod_init(void)
1459{
1460 return usb_register(&sd_driver);
1461}
1462
1463static void __exit sd_mod_exit(void)
1464{
1465 usb_deregister(&sd_driver);
1466}
1467
1468module_init(sd_mod_init);
1469module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
new file mode 100644
index 00000000000..81739a2f205
--- /dev/null
+++ b/drivers/media/video/gspca/pac207.c
@@ -0,0 +1,581 @@
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 MODULE_NAME "pac207"
27
28#include <linux/input.h>
29#include "gspca.h"
30
31MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
32MODULE_DESCRIPTION("Pixart PAC207");
33MODULE_LICENSE("GPL");
34
35#define PAC207_CTRL_TIMEOUT 100 /* ms */
36
37#define PAC207_BRIGHTNESS_MIN 0
38#define PAC207_BRIGHTNESS_MAX 255
39#define PAC207_BRIGHTNESS_DEFAULT 46
40
41#define PAC207_EXPOSURE_MIN 3
42#define PAC207_EXPOSURE_MAX 26
43#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */
44#define PAC207_EXPOSURE_KNEE 8 /* 4 = 30 fps, 11 = 8, 15 = 6 */
45
46#define PAC207_GAIN_MIN 0
47#define PAC207_GAIN_MAX 31
48#define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
49#define PAC207_GAIN_KNEE 31
50
51#define PAC207_AUTOGAIN_DEADZONE 30
52
53/* specific webcam descriptor */
54struct sd {
55 struct gspca_dev gspca_dev; /* !! must be the first item */
56
57 u8 mode;
58
59 u8 brightness;
60 u8 exposure;
61 u8 autogain;
62 u8 gain;
63
64 u8 sof_read;
65 u8 header_read;
66 u8 autogain_ignore_frames;
67
68 atomic_t avg_lum;
69};
70
71/* V4L2 controls supported by the driver */
72static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
76static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
78static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
79static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
80
81static const struct ctrl sd_ctrls[] = {
82#define SD_BRIGHTNESS 0
83 {
84 {
85 .id = V4L2_CID_BRIGHTNESS,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Brightness",
88 .minimum = PAC207_BRIGHTNESS_MIN,
89 .maximum = PAC207_BRIGHTNESS_MAX,
90 .step = 1,
91 .default_value = PAC207_BRIGHTNESS_DEFAULT,
92 .flags = 0,
93 },
94 .set = sd_setbrightness,
95 .get = sd_getbrightness,
96 },
97#define SD_EXPOSURE 1
98 {
99 {
100 .id = V4L2_CID_EXPOSURE,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Exposure",
103 .minimum = PAC207_EXPOSURE_MIN,
104 .maximum = PAC207_EXPOSURE_MAX,
105 .step = 1,
106 .default_value = PAC207_EXPOSURE_DEFAULT,
107 .flags = 0,
108 },
109 .set = sd_setexposure,
110 .get = sd_getexposure,
111 },
112#define SD_AUTOGAIN 2
113 {
114 {
115 .id = V4L2_CID_AUTOGAIN,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "Auto Gain",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121#define AUTOGAIN_DEF 1
122 .default_value = AUTOGAIN_DEF,
123 .flags = 0,
124 },
125 .set = sd_setautogain,
126 .get = sd_getautogain,
127 },
128#define SD_GAIN 3
129 {
130 {
131 .id = V4L2_CID_GAIN,
132 .type = V4L2_CTRL_TYPE_INTEGER,
133 .name = "Gain",
134 .minimum = PAC207_GAIN_MIN,
135 .maximum = PAC207_GAIN_MAX,
136 .step = 1,
137 .default_value = PAC207_GAIN_DEFAULT,
138 .flags = 0,
139 },
140 .set = sd_setgain,
141 .get = sd_getgain,
142 },
143};
144
145static const struct v4l2_pix_format sif_mode[] = {
146 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
147 .bytesperline = 176,
148 .sizeimage = (176 + 2) * 144,
149 /* uncompressed, add 2 bytes / line for line header */
150 .colorspace = V4L2_COLORSPACE_SRGB,
151 .priv = 1},
152 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
153 .bytesperline = 352,
154 /* compressed, but only when needed (not compressed
155 when the framerate is low) */
156 .sizeimage = (352 + 2) * 288,
157 .colorspace = V4L2_COLORSPACE_SRGB,
158 .priv = 0},
159};
160
161static const __u8 pac207_sensor_init[][8] = {
162 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
163 {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
164 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
165 {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00},
166};
167
168static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
169 const u8 *buffer, u16 length)
170{
171 struct usb_device *udev = gspca_dev->dev;
172 int err;
173
174 memcpy(gspca_dev->usb_buf, buffer, length);
175
176 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
177 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
178 0x00, index,
179 gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
180 if (err < 0)
181 err("Failed to write registers to index 0x%04X, error %d)",
182 index, err);
183
184 return err;
185}
186
187
188static int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
189{
190 struct usb_device *udev = gspca_dev->dev;
191 int err;
192
193 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
194 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
195 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
196 if (err)
197 err("Failed to write a register (index 0x%04X,"
198 " value 0x%02X, error %d)", index, value, err);
199
200 return err;
201}
202
203static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
204{
205 struct usb_device *udev = gspca_dev->dev;
206 int res;
207
208 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
209 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
210 0x00, index,
211 gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
212 if (res < 0) {
213 err("Failed to read a register (index 0x%04X, error %d)",
214 index, res);
215 return res;
216 }
217
218 return gspca_dev->usb_buf[0];
219}
220
221/* this function is called at probe time */
222static int sd_config(struct gspca_dev *gspca_dev,
223 const struct usb_device_id *id)
224{
225 struct sd *sd = (struct sd *) gspca_dev;
226 struct cam *cam;
227 u8 idreg[2];
228
229 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
230 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
231 idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4);
232 idreg[1] = idreg[1] & 0x0f;
233 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
234 idreg[0], idreg[1]);
235
236 if (idreg[0] != 0x27) {
237 PDEBUG(D_PROBE, "Error invalid sensor ID!");
238 return -ENODEV;
239 }
240
241 PDEBUG(D_PROBE,
242 "Pixart PAC207BCA Image Processor and Control Chip detected"
243 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
244
245 cam = &gspca_dev->cam;
246 cam->cam_mode = sif_mode;
247 cam->nmodes = ARRAY_SIZE(sif_mode);
248 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
249 sd->exposure = PAC207_EXPOSURE_DEFAULT;
250 sd->gain = PAC207_GAIN_DEFAULT;
251 sd->autogain = AUTOGAIN_DEF;
252
253 return 0;
254}
255
256/* this function is called at probe and resume time */
257static int sd_init(struct gspca_dev *gspca_dev)
258{
259 pac207_write_reg(gspca_dev, 0x41, 0x00);
260 /* Bit_0=Image Format,
261 * Bit_1=LED,
262 * Bit_2=Compression test mode enable */
263 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
264
265 return 0;
266}
267
268/* -- start the camera -- */
269static int sd_start(struct gspca_dev *gspca_dev)
270{
271 struct sd *sd = (struct sd *) gspca_dev;
272 __u8 mode;
273
274 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
275 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
276 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
277 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
278 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
279
280 /* Compression Balance */
281 if (gspca_dev->width == 176)
282 pac207_write_reg(gspca_dev, 0x4a, 0xff);
283 else
284 pac207_write_reg(gspca_dev, 0x4a, 0x30);
285 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
286 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
287
288 /* PGA global gain (Bit 4-0) */
289 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
290 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
291
292 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
293 if (gspca_dev->width == 176) { /* 176x144 */
294 mode |= 0x01;
295 PDEBUG(D_STREAM, "pac207_start mode 176x144");
296 } else { /* 352x288 */
297 PDEBUG(D_STREAM, "pac207_start mode 352x288");
298 }
299 pac207_write_reg(gspca_dev, 0x41, mode);
300
301 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
302 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
303 msleep(10);
304 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
305
306 sd->sof_read = 0;
307 sd->autogain_ignore_frames = 0;
308 atomic_set(&sd->avg_lum, -1);
309 return 0;
310}
311
312static void sd_stopN(struct gspca_dev *gspca_dev)
313{
314 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
315 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
316 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
317}
318
319/* Include pac common sof detection functions */
320#include "pac_common.h"
321
322static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
323{
324 struct sd *sd = (struct sd *) gspca_dev;
325 int avg_lum = atomic_read(&sd->avg_lum);
326
327 if (avg_lum == -1)
328 return;
329
330 if (sd->autogain_ignore_frames > 0)
331 sd->autogain_ignore_frames--;
332 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
333 100, PAC207_AUTOGAIN_DEADZONE,
334 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
335 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
336}
337
338static void sd_pkt_scan(struct gspca_dev *gspca_dev,
339 u8 *data,
340 int len)
341{
342 struct sd *sd = (struct sd *) gspca_dev;
343 unsigned char *sof;
344
345 sof = pac_find_sof(&sd->sof_read, data, len);
346 if (sof) {
347 int n;
348
349 /* finish decoding current frame */
350 n = sof - data;
351 if (n > sizeof pac_sof_marker)
352 n -= sizeof pac_sof_marker;
353 else
354 n = 0;
355 gspca_frame_add(gspca_dev, LAST_PACKET,
356 data, n);
357 sd->header_read = 0;
358 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
359 len -= sof - data;
360 data = sof;
361 }
362 if (sd->header_read < 11) {
363 int needed;
364
365 /* get average lumination from frame header (byte 5) */
366 if (sd->header_read < 5) {
367 needed = 5 - sd->header_read;
368 if (len >= needed)
369 atomic_set(&sd->avg_lum, data[needed - 1]);
370 }
371 /* skip the rest of the header */
372 needed = 11 - sd->header_read;
373 if (len <= needed) {
374 sd->header_read += len;
375 return;
376 }
377 data += needed;
378 len -= needed;
379 sd->header_read = 11;
380 }
381
382 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
383}
384
385static void setbrightness(struct gspca_dev *gspca_dev)
386{
387 struct sd *sd = (struct sd *) gspca_dev;
388
389 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
390 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
391 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
392}
393
394static void setexposure(struct gspca_dev *gspca_dev)
395{
396 struct sd *sd = (struct sd *) gspca_dev;
397
398 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
399 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
400 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
401}
402
403static void setgain(struct gspca_dev *gspca_dev)
404{
405 struct sd *sd = (struct sd *) gspca_dev;
406
407 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
408 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
409 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
410}
411
412static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
413{
414 struct sd *sd = (struct sd *) gspca_dev;
415
416 sd->brightness = val;
417 if (gspca_dev->streaming)
418 setbrightness(gspca_dev);
419 return 0;
420}
421
422static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
423{
424 struct sd *sd = (struct sd *) gspca_dev;
425
426 *val = sd->brightness;
427 return 0;
428}
429
430static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
431{
432 struct sd *sd = (struct sd *) gspca_dev;
433
434 sd->exposure = val;
435 if (gspca_dev->streaming)
436 setexposure(gspca_dev);
437 return 0;
438}
439
440static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
441{
442 struct sd *sd = (struct sd *) gspca_dev;
443
444 *val = sd->exposure;
445 return 0;
446}
447
448static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
449{
450 struct sd *sd = (struct sd *) gspca_dev;
451
452 sd->gain = val;
453 if (gspca_dev->streaming)
454 setgain(gspca_dev);
455 return 0;
456}
457
458static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
459{
460 struct sd *sd = (struct sd *) gspca_dev;
461
462 *val = sd->gain;
463 return 0;
464}
465
466static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
467{
468 struct sd *sd = (struct sd *) gspca_dev;
469
470 sd->autogain = val;
471 /* when switching to autogain set defaults to make sure
472 we are on a valid point of the autogain gain /
473 exposure knee graph, and give this change time to
474 take effect before doing autogain. */
475 if (sd->autogain) {
476 sd->exposure = PAC207_EXPOSURE_DEFAULT;
477 sd->gain = PAC207_GAIN_DEFAULT;
478 if (gspca_dev->streaming) {
479 sd->autogain_ignore_frames =
480 PAC_AUTOGAIN_IGNORE_FRAMES;
481 setexposure(gspca_dev);
482 setgain(gspca_dev);
483 }
484 }
485
486 return 0;
487}
488
489static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
490{
491 struct sd *sd = (struct sd *) gspca_dev;
492
493 *val = sd->autogain;
494 return 0;
495}
496
497#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
498static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
499 u8 *data, /* interrupt packet data */
500 int len) /* interrput packet length */
501{
502 int ret = -EINVAL;
503
504 if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) {
505 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
506 input_sync(gspca_dev->input_dev);
507 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
508 input_sync(gspca_dev->input_dev);
509 ret = 0;
510 }
511
512 return ret;
513}
514#endif
515
516/* sub-driver description */
517static const struct sd_desc sd_desc = {
518 .name = MODULE_NAME,
519 .ctrls = sd_ctrls,
520 .nctrls = ARRAY_SIZE(sd_ctrls),
521 .config = sd_config,
522 .init = sd_init,
523 .start = sd_start,
524 .stopN = sd_stopN,
525 .dq_callback = pac207_do_auto_gain,
526 .pkt_scan = sd_pkt_scan,
527#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
528 .int_pkt_scan = sd_int_pkt_scan,
529#endif
530};
531
532/* -- module initialisation -- */
533static const struct usb_device_id device_table[] = {
534 {USB_DEVICE(0x041e, 0x4028)},
535 {USB_DEVICE(0x093a, 0x2460)},
536 {USB_DEVICE(0x093a, 0x2461)},
537 {USB_DEVICE(0x093a, 0x2463)},
538 {USB_DEVICE(0x093a, 0x2464)},
539 {USB_DEVICE(0x093a, 0x2468)},
540 {USB_DEVICE(0x093a, 0x2470)},
541 {USB_DEVICE(0x093a, 0x2471)},
542 {USB_DEVICE(0x093a, 0x2472)},
543 {USB_DEVICE(0x093a, 0x2474)},
544 {USB_DEVICE(0x093a, 0x2476)},
545 {USB_DEVICE(0x145f, 0x013a)},
546 {USB_DEVICE(0x2001, 0xf115)},
547 {}
548};
549MODULE_DEVICE_TABLE(usb, device_table);
550
551/* -- device connect -- */
552static int sd_probe(struct usb_interface *intf,
553 const struct usb_device_id *id)
554{
555 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
556 THIS_MODULE);
557}
558
559static struct usb_driver sd_driver = {
560 .name = MODULE_NAME,
561 .id_table = device_table,
562 .probe = sd_probe,
563 .disconnect = gspca_disconnect,
564#ifdef CONFIG_PM
565 .suspend = gspca_suspend,
566 .resume = gspca_resume,
567#endif
568};
569
570/* -- module insert / remove -- */
571static int __init sd_mod_init(void)
572{
573 return usb_register(&sd_driver);
574}
575static void __exit sd_mod_exit(void)
576{
577 usb_deregister(&sd_driver);
578}
579
580module_init(sd_mod_init);
581module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
new file mode 100644
index 00000000000..5615d7bd830
--- /dev/null
+++ b/drivers/media/video/gspca/pac7302.c
@@ -0,0 +1,1233 @@
1/*
2 * Pixart PAC7302 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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/* Some documentation about various registers as determined by trial and error.
27
28 Register page 1:
29
30 Address Description
31 0x78 Global control, bit 6 controls the LED (inverted)
32
33 Register page 3:
34
35 Address Description
36 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
37 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
38 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
39 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
40 63 -> ~27 fps, the 2 msb's must always be 1 !!
41 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
42 1 -> ~30 fps, 2 -> ~20 fps
43 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
44 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
45 0x10 Master gain 0-31
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47
48 The registers are accessed in the following functions:
49
50 Page | Register | Function
51 -----+------------+---------------------------------------------------
52 0 | 0x0f..0x20 | setcolors()
53 0 | 0xa2..0xab | setbrightcont()
54 0 | 0xc5 | setredbalance()
55 0 | 0xc6 | setwhitebalance()
56 0 | 0xc7 | setbluebalance()
57 0 | 0xdc | setbrightcont(), setcolors()
58 3 | 0x02 | setexposure()
59 3 | 0x10 | setgain()
60 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
61 3 | 0x21 | sethvflip()
62*/
63
64#define MODULE_NAME "pac7302"
65
66#include <linux/input.h>
67#include <media/v4l2-chip-ident.h>
68#include "gspca.h"
69
70MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
71MODULE_DESCRIPTION("Pixart PAC7302");
72MODULE_LICENSE("GPL");
73
74/* specific webcam descriptor for pac7302 */
75struct sd {
76 struct gspca_dev gspca_dev; /* !! must be the first item */
77
78 unsigned char brightness;
79 unsigned char contrast;
80 unsigned char colors;
81 unsigned char white_balance;
82 unsigned char red_balance;
83 unsigned char blue_balance;
84 unsigned char gain;
85 unsigned char autogain;
86 unsigned short exposure;
87 __u8 hflip;
88 __u8 vflip;
89 u8 flags;
90#define FL_HFLIP 0x01 /* mirrored by default */
91#define FL_VFLIP 0x02 /* vertical flipped by default */
92
93 u8 sof_read;
94 u8 autogain_ignore_frames;
95
96 atomic_t avg_lum;
97};
98
99/* V4L2 controls supported by the driver */
100static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
101static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
102static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
103static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
104static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
105static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
106static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
108static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
110static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
111static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
112static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
113static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
114static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
115static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
116static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
117static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
118static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
119static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
120static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
121static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
122
123static const struct ctrl sd_ctrls[] = {
124 {
125 {
126 .id = V4L2_CID_BRIGHTNESS,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Brightness",
129 .minimum = 0,
130#define BRIGHTNESS_MAX 0x20
131 .maximum = BRIGHTNESS_MAX,
132 .step = 1,
133#define BRIGHTNESS_DEF 0x10
134 .default_value = BRIGHTNESS_DEF,
135 },
136 .set = sd_setbrightness,
137 .get = sd_getbrightness,
138 },
139 {
140 {
141 .id = V4L2_CID_CONTRAST,
142 .type = V4L2_CTRL_TYPE_INTEGER,
143 .name = "Contrast",
144 .minimum = 0,
145#define CONTRAST_MAX 255
146 .maximum = CONTRAST_MAX,
147 .step = 1,
148#define CONTRAST_DEF 127
149 .default_value = CONTRAST_DEF,
150 },
151 .set = sd_setcontrast,
152 .get = sd_getcontrast,
153 },
154 {
155 {
156 .id = V4L2_CID_SATURATION,
157 .type = V4L2_CTRL_TYPE_INTEGER,
158 .name = "Saturation",
159 .minimum = 0,
160#define COLOR_MAX 255
161 .maximum = COLOR_MAX,
162 .step = 1,
163#define COLOR_DEF 127
164 .default_value = COLOR_DEF,
165 },
166 .set = sd_setcolors,
167 .get = sd_getcolors,
168 },
169 {
170 {
171 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
172 .type = V4L2_CTRL_TYPE_INTEGER,
173 .name = "White Balance",
174 .minimum = 0,
175 .maximum = 255,
176 .step = 1,
177#define WHITEBALANCE_DEF 4
178 .default_value = WHITEBALANCE_DEF,
179 },
180 .set = sd_setwhitebalance,
181 .get = sd_getwhitebalance,
182 },
183 {
184 {
185 .id = V4L2_CID_RED_BALANCE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Red",
188 .minimum = 0,
189 .maximum = 3,
190 .step = 1,
191#define REDBALANCE_DEF 1
192 .default_value = REDBALANCE_DEF,
193 },
194 .set = sd_setredbalance,
195 .get = sd_getredbalance,
196 },
197 {
198 {
199 .id = V4L2_CID_BLUE_BALANCE,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Blue",
202 .minimum = 0,
203 .maximum = 3,
204 .step = 1,
205#define BLUEBALANCE_DEF 1
206 .default_value = BLUEBALANCE_DEF,
207 },
208 .set = sd_setbluebalance,
209 .get = sd_getbluebalance,
210 },
211 {
212 {
213 .id = V4L2_CID_GAIN,
214 .type = V4L2_CTRL_TYPE_INTEGER,
215 .name = "Gain",
216 .minimum = 0,
217#define GAIN_MAX 255
218 .maximum = GAIN_MAX,
219 .step = 1,
220#define GAIN_DEF 127
221#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
222 .default_value = GAIN_DEF,
223 },
224 .set = sd_setgain,
225 .get = sd_getgain,
226 },
227 {
228 {
229 .id = V4L2_CID_EXPOSURE,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Exposure",
232 .minimum = 0,
233 .maximum = 1023,
234 .step = 1,
235#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
236#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
237 .default_value = EXPOSURE_DEF,
238 },
239 .set = sd_setexposure,
240 .get = sd_getexposure,
241 },
242 {
243 {
244 .id = V4L2_CID_AUTOGAIN,
245 .type = V4L2_CTRL_TYPE_BOOLEAN,
246 .name = "Auto Gain",
247 .minimum = 0,
248 .maximum = 1,
249 .step = 1,
250#define AUTOGAIN_DEF 1
251 .default_value = AUTOGAIN_DEF,
252 },
253 .set = sd_setautogain,
254 .get = sd_getautogain,
255 },
256 {
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#define HFLIP_DEF 0
265 .default_value = HFLIP_DEF,
266 },
267 .set = sd_sethflip,
268 .get = sd_gethflip,
269 },
270 {
271 {
272 .id = V4L2_CID_VFLIP,
273 .type = V4L2_CTRL_TYPE_BOOLEAN,
274 .name = "Vflip",
275 .minimum = 0,
276 .maximum = 1,
277 .step = 1,
278#define VFLIP_DEF 0
279 .default_value = VFLIP_DEF,
280 },
281 .set = sd_setvflip,
282 .get = sd_getvflip,
283 },
284};
285
286static const struct v4l2_pix_format vga_mode[] = {
287 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
288 .bytesperline = 640,
289 .sizeimage = 640 * 480 * 3 / 8 + 590,
290 .colorspace = V4L2_COLORSPACE_JPEG,
291 .priv = 0},
292};
293
294#define LOAD_PAGE3 255
295#define END_OF_SEQUENCE 0
296
297/* pac 7302 */
298static const __u8 init_7302[] = {
299/* index,value */
300 0xff, 0x01, /* page 1 */
301 0x78, 0x00, /* deactivate */
302 0xff, 0x01,
303 0x78, 0x40, /* led off */
304};
305static const __u8 start_7302[] = {
306/* index, len, [value]* */
307 0xff, 1, 0x00, /* page 0 */
308 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
309 0x00, 0x00, 0x00, 0x00,
310 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
311 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
312 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
313 0x26, 2, 0xaa, 0xaa,
314 0x2e, 1, 0x31,
315 0x38, 1, 0x01,
316 0x3a, 3, 0x14, 0xff, 0x5a,
317 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
318 0x00, 0x54, 0x11,
319 0x55, 1, 0x00,
320 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
321 0x6b, 1, 0x00,
322 0x6e, 3, 0x08, 0x06, 0x00,
323 0x72, 3, 0x00, 0xff, 0x00,
324 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
325 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
326 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
327 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
328 0xd2, 0xeb,
329 0xaf, 1, 0x02,
330 0xb5, 2, 0x08, 0x08,
331 0xb8, 2, 0x08, 0x88,
332 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
333 0xcc, 1, 0x00,
334 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
335 0xc1, 0xd7, 0xec,
336 0xdc, 1, 0x01,
337 0xff, 1, 0x01, /* page 1 */
338 0x12, 3, 0x02, 0x00, 0x01,
339 0x3e, 2, 0x00, 0x00,
340 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
341 0x7c, 1, 0x00,
342 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
343 0x02, 0x00,
344 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
345 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
346 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
347 0xd8, 1, 0x01,
348 0xdb, 2, 0x00, 0x01,
349 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
350 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
351 0xeb, 1, 0x00,
352 0xff, 1, 0x02, /* page 2 */
353 0x22, 1, 0x00,
354 0xff, 1, 0x03, /* page 3 */
355 0, LOAD_PAGE3, /* load the page 3 */
356 0x11, 1, 0x01,
357 0xff, 1, 0x02, /* page 2 */
358 0x13, 1, 0x00,
359 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
360 0x27, 2, 0x14, 0x0c,
361 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
362 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
363 0x6e, 1, 0x08,
364 0xff, 1, 0x01, /* page 1 */
365 0x78, 1, 0x00,
366 0, END_OF_SEQUENCE /* end of sequence */
367};
368
369#define SKIP 0xaa
370/* page 3 - the value SKIP says skip the index - see reg_w_page() */
371static const __u8 page3_7302[] = {
372 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
373 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
374 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
376 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
377 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
378 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
379 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
381 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
382 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
386 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
387 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
388 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
391 0x00
392};
393
394static void reg_w_buf(struct gspca_dev *gspca_dev,
395 __u8 index,
396 const u8 *buffer, int len)
397{
398 int ret;
399
400 if (gspca_dev->usb_err < 0)
401 return;
402 memcpy(gspca_dev->usb_buf, buffer, len);
403 ret = usb_control_msg(gspca_dev->dev,
404 usb_sndctrlpipe(gspca_dev->dev, 0),
405 0, /* request */
406 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
407 0, /* value */
408 index, gspca_dev->usb_buf, len,
409 500);
410 if (ret < 0) {
411 err("reg_w_buf failed index 0x%02x, error %d",
412 index, ret);
413 gspca_dev->usb_err = ret;
414 }
415}
416
417
418static void reg_w(struct gspca_dev *gspca_dev,
419 __u8 index,
420 __u8 value)
421{
422 int ret;
423
424 if (gspca_dev->usb_err < 0)
425 return;
426 gspca_dev->usb_buf[0] = value;
427 ret = usb_control_msg(gspca_dev->dev,
428 usb_sndctrlpipe(gspca_dev->dev, 0),
429 0, /* request */
430 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
431 0, index, gspca_dev->usb_buf, 1,
432 500);
433 if (ret < 0) {
434 err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
435 index, value, ret);
436 gspca_dev->usb_err = ret;
437 }
438}
439
440static void reg_w_seq(struct gspca_dev *gspca_dev,
441 const __u8 *seq, int len)
442{
443 while (--len >= 0) {
444 reg_w(gspca_dev, seq[0], seq[1]);
445 seq += 2;
446 }
447}
448
449/* load the beginning of a page */
450static void reg_w_page(struct gspca_dev *gspca_dev,
451 const __u8 *page, int len)
452{
453 int index;
454 int ret = 0;
455
456 if (gspca_dev->usb_err < 0)
457 return;
458 for (index = 0; index < len; index++) {
459 if (page[index] == SKIP) /* skip this index */
460 continue;
461 gspca_dev->usb_buf[0] = page[index];
462 ret = usb_control_msg(gspca_dev->dev,
463 usb_sndctrlpipe(gspca_dev->dev, 0),
464 0, /* request */
465 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
466 0, index, gspca_dev->usb_buf, 1,
467 500);
468 if (ret < 0) {
469 err("reg_w_page() failed index 0x%02x, "
470 "value 0x%02x, error %d",
471 index, page[index], ret);
472 gspca_dev->usb_err = ret;
473 break;
474 }
475 }
476}
477
478/* output a variable sequence */
479static void reg_w_var(struct gspca_dev *gspca_dev,
480 const __u8 *seq,
481 const __u8 *page3, unsigned int page3_len)
482{
483 int index, len;
484
485 for (;;) {
486 index = *seq++;
487 len = *seq++;
488 switch (len) {
489 case END_OF_SEQUENCE:
490 return;
491 case LOAD_PAGE3:
492 reg_w_page(gspca_dev, page3, page3_len);
493 break;
494 default:
495 if (len > USB_BUF_SZ) {
496 PDEBUG(D_ERR|D_STREAM,
497 "Incorrect variable sequence");
498 return;
499 }
500 while (len > 0) {
501 if (len < 8) {
502 reg_w_buf(gspca_dev,
503 index, seq, len);
504 seq += len;
505 break;
506 }
507 reg_w_buf(gspca_dev, index, seq, 8);
508 seq += 8;
509 index += 8;
510 len -= 8;
511 }
512 }
513 }
514 /* not reached */
515}
516
517/* this function is called at probe time for pac7302 */
518static int sd_config(struct gspca_dev *gspca_dev,
519 const struct usb_device_id *id)
520{
521 struct sd *sd = (struct sd *) gspca_dev;
522 struct cam *cam;
523
524 cam = &gspca_dev->cam;
525
526 PDEBUG(D_CONF, "Find Sensor PAC7302");
527 cam->cam_mode = vga_mode; /* only 640x480 */
528 cam->nmodes = ARRAY_SIZE(vga_mode);
529
530 sd->brightness = BRIGHTNESS_DEF;
531 sd->contrast = CONTRAST_DEF;
532 sd->colors = COLOR_DEF;
533 sd->white_balance = WHITEBALANCE_DEF;
534 sd->red_balance = REDBALANCE_DEF;
535 sd->blue_balance = BLUEBALANCE_DEF;
536 sd->gain = GAIN_DEF;
537 sd->exposure = EXPOSURE_DEF;
538 sd->autogain = AUTOGAIN_DEF;
539 sd->hflip = HFLIP_DEF;
540 sd->vflip = VFLIP_DEF;
541 sd->flags = id->driver_info;
542 return 0;
543}
544
545/* This function is used by pac7302 only */
546static void setbrightcont(struct gspca_dev *gspca_dev)
547{
548 struct sd *sd = (struct sd *) gspca_dev;
549 int i, v;
550 static const __u8 max[10] =
551 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
552 0xd4, 0xec};
553 static const __u8 delta[10] =
554 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
555 0x11, 0x0b};
556
557 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
558 for (i = 0; i < 10; i++) {
559 v = max[i];
560 v += (sd->brightness - BRIGHTNESS_MAX)
561 * 150 / BRIGHTNESS_MAX; /* 200 ? */
562 v -= delta[i] * sd->contrast / CONTRAST_MAX;
563 if (v < 0)
564 v = 0;
565 else if (v > 0xff)
566 v = 0xff;
567 reg_w(gspca_dev, 0xa2 + i, v);
568 }
569 reg_w(gspca_dev, 0xdc, 0x01);
570}
571
572/* This function is used by pac7302 only */
573static void setcolors(struct gspca_dev *gspca_dev)
574{
575 struct sd *sd = (struct sd *) gspca_dev;
576 int i, v;
577 static const int a[9] =
578 {217, -212, 0, -101, 170, -67, -38, -315, 355};
579 static const int b[9] =
580 {19, 106, 0, 19, 106, 1, 19, 106, 1};
581
582 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
583 reg_w(gspca_dev, 0x11, 0x01);
584 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
585 for (i = 0; i < 9; i++) {
586 v = a[i] * sd->colors / COLOR_MAX + b[i];
587 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
588 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
589 }
590 reg_w(gspca_dev, 0xdc, 0x01);
591 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
592}
593
594static void setwhitebalance(struct gspca_dev *gspca_dev)
595{
596 struct sd *sd = (struct sd *) gspca_dev;
597
598 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
599 reg_w(gspca_dev, 0xc6, sd->white_balance);
600
601 reg_w(gspca_dev, 0xdc, 0x01);
602 PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
603}
604
605static void setredbalance(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608
609 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
610 reg_w(gspca_dev, 0xc5, sd->red_balance);
611
612 reg_w(gspca_dev, 0xdc, 0x01);
613 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
614}
615
616static void setbluebalance(struct gspca_dev *gspca_dev)
617{
618 struct sd *sd = (struct sd *) gspca_dev;
619
620 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
621 reg_w(gspca_dev, 0xc7, sd->blue_balance);
622
623 reg_w(gspca_dev, 0xdc, 0x01);
624 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
625}
626
627static void setgain(struct gspca_dev *gspca_dev)
628{
629 struct sd *sd = (struct sd *) gspca_dev;
630
631 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
632 reg_w(gspca_dev, 0x10, sd->gain >> 3);
633
634 /* load registers to sensor (Bit 0, auto clear) */
635 reg_w(gspca_dev, 0x11, 0x01);
636}
637
638static void setexposure(struct gspca_dev *gspca_dev)
639{
640 struct sd *sd = (struct sd *) gspca_dev;
641 __u8 clockdiv;
642 __u16 exposure;
643
644 /* register 2 of frame 3 contains the clock divider configuring the
645 no fps according to the formula: 90 / reg. sd->exposure is the
646 desired exposure time in 0.5 ms. */
647 clockdiv = (90 * sd->exposure + 1999) / 2000;
648
649 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
650 on the scene being recorded, the camera switches to another
651 quantization table for certain JPEG blocks, and we don't know how
652 to decompress these blocks. So we cap the framerate at 15 fps */
653 if (clockdiv < 6)
654 clockdiv = 6;
655 else if (clockdiv > 63)
656 clockdiv = 63;
657
658 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
659 Always round up, otherwise we cannot get the desired frametime
660 using the partial frame time exposure control */
661 if (clockdiv < 6 || clockdiv > 12)
662 clockdiv = ((clockdiv + 2) / 3) * 3;
663
664 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
665 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
666 exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv);
667 /* 0 = use full frametime, 448 = no exposure, reverse it */
668 exposure = 448 - exposure;
669
670 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
671 reg_w(gspca_dev, 0x02, clockdiv);
672 reg_w(gspca_dev, 0x0e, exposure & 0xff);
673 reg_w(gspca_dev, 0x0f, exposure >> 8);
674
675 /* load registers to sensor (Bit 0, auto clear) */
676 reg_w(gspca_dev, 0x11, 0x01);
677}
678
679static void sethvflip(struct gspca_dev *gspca_dev)
680{
681 struct sd *sd = (struct sd *) gspca_dev;
682 u8 data, hflip, vflip;
683
684 hflip = sd->hflip;
685 if (sd->flags & FL_HFLIP)
686 hflip = !hflip;
687 vflip = sd->vflip;
688 if (sd->flags & FL_VFLIP)
689 vflip = !vflip;
690
691 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
692 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
693 reg_w(gspca_dev, 0x21, data);
694
695 /* load registers to sensor (Bit 0, auto clear) */
696 reg_w(gspca_dev, 0x11, 0x01);
697}
698
699/* this function is called at probe and resume time for pac7302 */
700static int sd_init(struct gspca_dev *gspca_dev)
701{
702 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
703 return gspca_dev->usb_err;
704}
705
706static int sd_start(struct gspca_dev *gspca_dev)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
709
710 sd->sof_read = 0;
711
712 reg_w_var(gspca_dev, start_7302,
713 page3_7302, sizeof(page3_7302));
714 setbrightcont(gspca_dev);
715 setcolors(gspca_dev);
716 setwhitebalance(gspca_dev);
717 setredbalance(gspca_dev);
718 setbluebalance(gspca_dev);
719 setgain(gspca_dev);
720 setexposure(gspca_dev);
721 sethvflip(gspca_dev);
722
723 /* only resolution 640x480 is supported for pac7302 */
724
725 sd->sof_read = 0;
726 sd->autogain_ignore_frames = 0;
727 atomic_set(&sd->avg_lum, -1);
728
729 /* start stream */
730 reg_w(gspca_dev, 0xff, 0x01);
731 reg_w(gspca_dev, 0x78, 0x01);
732
733 return gspca_dev->usb_err;
734}
735
736static void sd_stopN(struct gspca_dev *gspca_dev)
737{
738
739 /* stop stream */
740 reg_w(gspca_dev, 0xff, 0x01);
741 reg_w(gspca_dev, 0x78, 0x00);
742}
743
744/* called on streamoff with alt 0 and on disconnect for pac7302 */
745static void sd_stop0(struct gspca_dev *gspca_dev)
746{
747 if (!gspca_dev->present)
748 return;
749 reg_w(gspca_dev, 0xff, 0x01);
750 reg_w(gspca_dev, 0x78, 0x40);
751}
752
753/* Include pac common sof detection functions */
754#include "pac_common.h"
755
756static void do_autogain(struct gspca_dev *gspca_dev)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759 int avg_lum = atomic_read(&sd->avg_lum);
760 int desired_lum;
761 const int deadzone = 30;
762
763 if (avg_lum == -1)
764 return;
765
766 desired_lum = 270 + sd->brightness;
767
768 if (sd->autogain_ignore_frames > 0)
769 sd->autogain_ignore_frames--;
770 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
771 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
772 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
773}
774
775/* JPEG header, part 1 */
776static const unsigned char pac_jpeg_header1[] = {
777 0xff, 0xd8, /* SOI: Start of Image */
778
779 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
780 0x00, 0x11, /* length = 17 bytes (including this length field) */
781 0x08 /* Precision: 8 */
782 /* 2 bytes is placed here: number of image lines */
783 /* 2 bytes is placed here: samples per line */
784};
785
786/* JPEG header, continued */
787static const unsigned char pac_jpeg_header2[] = {
788 0x03, /* Number of image components: 3 */
789 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
790 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
791 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
792
793 0xff, 0xda, /* SOS: Start Of Scan */
794 0x00, 0x0c, /* length = 12 bytes (including this length field) */
795 0x03, /* number of components: 3 */
796 0x01, 0x00, /* selector 1, table 0x00 */
797 0x02, 0x11, /* selector 2, table 0x11 */
798 0x03, 0x11, /* selector 3, table 0x11 */
799 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
800 0x00 /* Successive approximation: 0 */
801};
802
803static void pac_start_frame(struct gspca_dev *gspca_dev,
804 __u16 lines, __u16 samples_per_line)
805{
806 unsigned char tmpbuf[4];
807
808 gspca_frame_add(gspca_dev, FIRST_PACKET,
809 pac_jpeg_header1, sizeof(pac_jpeg_header1));
810
811 tmpbuf[0] = lines >> 8;
812 tmpbuf[1] = lines & 0xff;
813 tmpbuf[2] = samples_per_line >> 8;
814 tmpbuf[3] = samples_per_line & 0xff;
815
816 gspca_frame_add(gspca_dev, INTER_PACKET,
817 tmpbuf, sizeof(tmpbuf));
818 gspca_frame_add(gspca_dev, INTER_PACKET,
819 pac_jpeg_header2, sizeof(pac_jpeg_header2));
820}
821
822/* this function is run at interrupt level */
823static void sd_pkt_scan(struct gspca_dev *gspca_dev,
824 u8 *data, /* isoc packet */
825 int len) /* iso packet length */
826{
827 struct sd *sd = (struct sd *) gspca_dev;
828 u8 *image;
829 unsigned char *sof;
830
831 sof = pac_find_sof(&sd->sof_read, data, len);
832 if (sof) {
833 int n, lum_offset, footer_length;
834
835 /* 6 bytes after the FF D9 EOF marker a number of lumination
836 bytes are send corresponding to different parts of the
837 image, the 14th and 15th byte after the EOF seem to
838 correspond to the center of the image */
839 lum_offset = 61 + sizeof pac_sof_marker;
840 footer_length = 74;
841
842 /* Finish decoding current frame */
843 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
844 if (n < 0) {
845 gspca_dev->image_len += n;
846 n = 0;
847 } else {
848 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
849 }
850
851 image = gspca_dev->image;
852 if (image != NULL
853 && image[gspca_dev->image_len - 2] == 0xff
854 && image[gspca_dev->image_len - 1] == 0xd9)
855 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
856
857 n = sof - data;
858 len -= n;
859 data = sof;
860
861 /* Get average lumination */
862 if (gspca_dev->last_packet_type == LAST_PACKET &&
863 n >= lum_offset)
864 atomic_set(&sd->avg_lum, data[-lum_offset] +
865 data[-lum_offset + 1]);
866 else
867 atomic_set(&sd->avg_lum, -1);
868
869 /* Start the new frame with the jpeg header */
870 /* The PAC7302 has the image rotated 90 degrees */
871 pac_start_frame(gspca_dev,
872 gspca_dev->width, gspca_dev->height);
873 }
874 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
875}
876
877static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
878{
879 struct sd *sd = (struct sd *) gspca_dev;
880
881 sd->brightness = val;
882 if (gspca_dev->streaming)
883 setbrightcont(gspca_dev);
884 return gspca_dev->usb_err;
885}
886
887static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
888{
889 struct sd *sd = (struct sd *) gspca_dev;
890
891 *val = sd->brightness;
892 return 0;
893}
894
895static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 sd->contrast = val;
900 if (gspca_dev->streaming)
901 setbrightcont(gspca_dev);
902 return gspca_dev->usb_err;
903}
904
905static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 *val = sd->contrast;
910 return 0;
911}
912
913static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
914{
915 struct sd *sd = (struct sd *) gspca_dev;
916
917 sd->colors = val;
918 if (gspca_dev->streaming)
919 setcolors(gspca_dev);
920 return gspca_dev->usb_err;
921}
922
923static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926
927 *val = sd->colors;
928 return 0;
929}
930
931static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
932{
933 struct sd *sd = (struct sd *) gspca_dev;
934
935 sd->white_balance = val;
936 if (gspca_dev->streaming)
937 setwhitebalance(gspca_dev);
938 return gspca_dev->usb_err;
939}
940
941static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
944
945 *val = sd->white_balance;
946 return 0;
947}
948
949static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
950{
951 struct sd *sd = (struct sd *) gspca_dev;
952
953 sd->red_balance = val;
954 if (gspca_dev->streaming)
955 setredbalance(gspca_dev);
956 return gspca_dev->usb_err;
957}
958
959static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 *val = sd->red_balance;
964 return 0;
965}
966
967static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970
971 sd->blue_balance = val;
972 if (gspca_dev->streaming)
973 setbluebalance(gspca_dev);
974 return gspca_dev->usb_err;
975}
976
977static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 *val = sd->blue_balance;
982 return 0;
983}
984
985static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 sd->gain = val;
990 if (gspca_dev->streaming)
991 setgain(gspca_dev);
992 return gspca_dev->usb_err;
993}
994
995static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
998
999 *val = sd->gain;
1000 return 0;
1001}
1002
1003static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1004{
1005 struct sd *sd = (struct sd *) gspca_dev;
1006
1007 sd->exposure = val;
1008 if (gspca_dev->streaming)
1009 setexposure(gspca_dev);
1010 return gspca_dev->usb_err;
1011}
1012
1013static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1014{
1015 struct sd *sd = (struct sd *) gspca_dev;
1016
1017 *val = sd->exposure;
1018 return 0;
1019}
1020
1021static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1022{
1023 struct sd *sd = (struct sd *) gspca_dev;
1024
1025 sd->autogain = val;
1026 /* when switching to autogain set defaults to make sure
1027 we are on a valid point of the autogain gain /
1028 exposure knee graph, and give this change time to
1029 take effect before doing autogain. */
1030 if (sd->autogain) {
1031 sd->exposure = EXPOSURE_DEF;
1032 sd->gain = GAIN_DEF;
1033 if (gspca_dev->streaming) {
1034 sd->autogain_ignore_frames =
1035 PAC_AUTOGAIN_IGNORE_FRAMES;
1036 setexposure(gspca_dev);
1037 setgain(gspca_dev);
1038 }
1039 }
1040
1041 return gspca_dev->usb_err;
1042}
1043
1044static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1045{
1046 struct sd *sd = (struct sd *) gspca_dev;
1047
1048 *val = sd->autogain;
1049 return 0;
1050}
1051
1052static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1053{
1054 struct sd *sd = (struct sd *) gspca_dev;
1055
1056 sd->hflip = val;
1057 if (gspca_dev->streaming)
1058 sethvflip(gspca_dev);
1059 return gspca_dev->usb_err;
1060}
1061
1062static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1063{
1064 struct sd *sd = (struct sd *) gspca_dev;
1065
1066 *val = sd->hflip;
1067 return 0;
1068}
1069
1070static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1071{
1072 struct sd *sd = (struct sd *) gspca_dev;
1073
1074 sd->vflip = val;
1075 if (gspca_dev->streaming)
1076 sethvflip(gspca_dev);
1077 return gspca_dev->usb_err;
1078}
1079
1080static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
1083
1084 *val = sd->vflip;
1085 return 0;
1086}
1087
1088#ifdef CONFIG_VIDEO_ADV_DEBUG
1089static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1090 struct v4l2_dbg_register *reg)
1091{
1092 __u8 index;
1093 __u8 value;
1094
1095 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
1096 long on the USB bus)
1097 */
1098 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
1099 reg->match.addr == 0 &&
1100 (reg->reg < 0x000000ff) &&
1101 (reg->val <= 0x000000ff)
1102 ) {
1103 /* Currently writing to page 0 is only supported. */
1104 /* reg_w() only supports 8bit index */
1105 index = reg->reg & 0x000000ff;
1106 value = reg->val & 0x000000ff;
1107
1108 /* Note that there shall be no access to other page
1109 by any other function between the page swith and
1110 the actual register write */
1111 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1112 reg_w(gspca_dev, index, value);
1113
1114 reg_w(gspca_dev, 0xdc, 0x01);
1115 }
1116 return gspca_dev->usb_err;
1117}
1118
1119static int sd_chip_ident(struct gspca_dev *gspca_dev,
1120 struct v4l2_dbg_chip_ident *chip)
1121{
1122 int ret = -EINVAL;
1123
1124 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1125 chip->match.addr == 0) {
1126 chip->revision = 0;
1127 chip->ident = V4L2_IDENT_UNKNOWN;
1128 ret = 0;
1129 }
1130 return ret;
1131}
1132#endif
1133
1134#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1135static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1136 u8 *data, /* interrupt packet data */
1137 int len) /* interrput packet length */
1138{
1139 int ret = -EINVAL;
1140 u8 data0, data1;
1141
1142 if (len == 2) {
1143 data0 = data[0];
1144 data1 = data[1];
1145 if ((data0 == 0x00 && data1 == 0x11) ||
1146 (data0 == 0x22 && data1 == 0x33) ||
1147 (data0 == 0x44 && data1 == 0x55) ||
1148 (data0 == 0x66 && data1 == 0x77) ||
1149 (data0 == 0x88 && data1 == 0x99) ||
1150 (data0 == 0xaa && data1 == 0xbb) ||
1151 (data0 == 0xcc && data1 == 0xdd) ||
1152 (data0 == 0xee && data1 == 0xff)) {
1153 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1154 input_sync(gspca_dev->input_dev);
1155 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1156 input_sync(gspca_dev->input_dev);
1157 ret = 0;
1158 }
1159 }
1160
1161 return ret;
1162}
1163#endif
1164
1165/* sub-driver description for pac7302 */
1166static const struct sd_desc sd_desc = {
1167 .name = MODULE_NAME,
1168 .ctrls = sd_ctrls,
1169 .nctrls = ARRAY_SIZE(sd_ctrls),
1170 .config = sd_config,
1171 .init = sd_init,
1172 .start = sd_start,
1173 .stopN = sd_stopN,
1174 .stop0 = sd_stop0,
1175 .pkt_scan = sd_pkt_scan,
1176 .dq_callback = do_autogain,
1177#ifdef CONFIG_VIDEO_ADV_DEBUG
1178 .set_register = sd_dbg_s_register,
1179 .get_chip_ident = sd_chip_ident,
1180#endif
1181#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1182 .int_pkt_scan = sd_int_pkt_scan,
1183#endif
1184};
1185
1186/* -- module initialisation -- */
1187static const struct usb_device_id device_table[] = {
1188 {USB_DEVICE(0x06f8, 0x3009)},
1189 {USB_DEVICE(0x093a, 0x2620)},
1190 {USB_DEVICE(0x093a, 0x2621)},
1191 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1192 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
1193 {USB_DEVICE(0x093a, 0x2625)},
1194 {USB_DEVICE(0x093a, 0x2626)},
1195 {USB_DEVICE(0x093a, 0x2628)},
1196 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
1197 {USB_DEVICE(0x093a, 0x262a)},
1198 {USB_DEVICE(0x093a, 0x262c)},
1199 {}
1200};
1201MODULE_DEVICE_TABLE(usb, device_table);
1202
1203/* -- device connect -- */
1204static int sd_probe(struct usb_interface *intf,
1205 const struct usb_device_id *id)
1206{
1207 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1208 THIS_MODULE);
1209}
1210
1211static struct usb_driver sd_driver = {
1212 .name = MODULE_NAME,
1213 .id_table = device_table,
1214 .probe = sd_probe,
1215 .disconnect = gspca_disconnect,
1216#ifdef CONFIG_PM
1217 .suspend = gspca_suspend,
1218 .resume = gspca_resume,
1219#endif
1220};
1221
1222/* -- module insert / remove -- */
1223static int __init sd_mod_init(void)
1224{
1225 return usb_register(&sd_driver);
1226}
1227static void __exit sd_mod_exit(void)
1228{
1229 usb_deregister(&sd_driver);
1230}
1231
1232module_init(sd_mod_init);
1233module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
new file mode 100644
index 00000000000..f8801b50e64
--- /dev/null
+++ b/drivers/media/video/gspca/pac7311.c
@@ -0,0 +1,881 @@
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 When the register addresses differ between the 7202 and the 7311 the 2
24 different addresses are written as 7302addr/7311addr, when one of the 2
25 addresses is a - sign that register description is not valid for the
26 matching IC.
27
28 Register page 1:
29
30 Address Description
31 -/0x08 Unknown compressor related, must always be 8 except when not
32 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
33 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
34 bits 345 seem to toggle per color gains on/off (inverted)
35 0x78 Global control, bit 6 controls the LED (inverted)
36 -/0x80 JPEG compression ratio ? Best not touched
37
38 Register page 3/4:
39
40 Address Description
41 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
42 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
43 -/0x0f Master gain 1-245, low value = high gain
44 0x10/- Master gain 0-31
45 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
48 completely disable the analog amplification block. Set to 0x68
49 for max gain, 0x14 for minimal gain.
50*/
51
52#define MODULE_NAME "pac7311"
53
54#include <linux/input.h>
55#include "gspca.h"
56
57MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
58MODULE_DESCRIPTION("Pixart PAC7311");
59MODULE_LICENSE("GPL");
60
61/* specific webcam descriptor for pac7311 */
62struct sd {
63 struct gspca_dev gspca_dev; /* !! must be the first item */
64
65 unsigned char contrast;
66 unsigned char gain;
67 unsigned char exposure;
68 unsigned char autogain;
69 __u8 hflip;
70 __u8 vflip;
71
72 u8 sof_read;
73 u8 autogain_ignore_frames;
74
75 atomic_t avg_lum;
76};
77
78/* V4L2 controls supported by the driver */
79static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
91
92static const struct ctrl sd_ctrls[] = {
93/* This control is for both the 7302 and the 7311 */
94 {
95 {
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
100#define CONTRAST_MAX 255
101 .maximum = CONTRAST_MAX,
102 .step = 1,
103#define CONTRAST_DEF 127
104 .default_value = CONTRAST_DEF,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109/* All controls below are for both the 7302 and the 7311 */
110 {
111 {
112 .id = V4L2_CID_GAIN,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Gain",
115 .minimum = 0,
116#define GAIN_MAX 255
117 .maximum = GAIN_MAX,
118 .step = 1,
119#define GAIN_DEF 127
120#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
121 .default_value = GAIN_DEF,
122 },
123 .set = sd_setgain,
124 .get = sd_getgain,
125 },
126 {
127 {
128 .id = V4L2_CID_EXPOSURE,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Exposure",
131 .minimum = 0,
132#define EXPOSURE_MAX 255
133 .maximum = EXPOSURE_MAX,
134 .step = 1,
135#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
136#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
137 .default_value = EXPOSURE_DEF,
138 },
139 .set = sd_setexposure,
140 .get = sd_getexposure,
141 },
142 {
143 {
144 .id = V4L2_CID_AUTOGAIN,
145 .type = V4L2_CTRL_TYPE_BOOLEAN,
146 .name = "Auto Gain",
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
150#define AUTOGAIN_DEF 1
151 .default_value = AUTOGAIN_DEF,
152 },
153 .set = sd_setautogain,
154 .get = sd_getautogain,
155 },
156 {
157 {
158 .id = V4L2_CID_HFLIP,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "Mirror",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164#define HFLIP_DEF 0
165 .default_value = HFLIP_DEF,
166 },
167 .set = sd_sethflip,
168 .get = sd_gethflip,
169 },
170 {
171 {
172 .id = V4L2_CID_VFLIP,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "Vflip",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178#define VFLIP_DEF 0
179 .default_value = VFLIP_DEF,
180 },
181 .set = sd_setvflip,
182 .get = sd_getvflip,
183 },
184};
185
186static const struct v4l2_pix_format vga_mode[] = {
187 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
188 .bytesperline = 160,
189 .sizeimage = 160 * 120 * 3 / 8 + 590,
190 .colorspace = V4L2_COLORSPACE_JPEG,
191 .priv = 2},
192 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
193 .bytesperline = 320,
194 .sizeimage = 320 * 240 * 3 / 8 + 590,
195 .colorspace = V4L2_COLORSPACE_JPEG,
196 .priv = 1},
197 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
198 .bytesperline = 640,
199 .sizeimage = 640 * 480 * 3 / 8 + 590,
200 .colorspace = V4L2_COLORSPACE_JPEG,
201 .priv = 0},
202};
203
204#define LOAD_PAGE4 254
205#define END_OF_SEQUENCE 0
206
207/* pac 7311 */
208static const __u8 init_7311[] = {
209 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
210 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
211 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
212 0xff, 0x04,
213 0x27, 0x80,
214 0x28, 0xca,
215 0x29, 0x53,
216 0x2a, 0x0e,
217 0xff, 0x01,
218 0x3e, 0x20,
219};
220
221static const __u8 start_7311[] = {
222/* index, len, [value]* */
223 0xff, 1, 0x01, /* page 1 */
224 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
225 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
226 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
227 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00,
230 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
231 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
232 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
233 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
234 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
235 0xd0, 0xff,
236 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
237 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
238 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
239 0x18, 0x20,
240 0x96, 3, 0x01, 0x08, 0x04,
241 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
242 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
243 0x3f, 0x00, 0x0a, 0x01, 0x00,
244 0xff, 1, 0x04, /* page 4 */
245 0, LOAD_PAGE4, /* load the page 4 */
246 0x11, 1, 0x01,
247 0, END_OF_SEQUENCE /* end of sequence */
248};
249
250#define SKIP 0xaa
251/* page 4 - the value SKIP says skip the index - see reg_w_page() */
252static const __u8 page4_7311[] = {
253 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
254 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
255 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
257 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
258 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
259 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
260};
261
262static void reg_w_buf(struct gspca_dev *gspca_dev,
263 __u8 index,
264 const u8 *buffer, int len)
265{
266 int ret;
267
268 if (gspca_dev->usb_err < 0)
269 return;
270 memcpy(gspca_dev->usb_buf, buffer, len);
271 ret = usb_control_msg(gspca_dev->dev,
272 usb_sndctrlpipe(gspca_dev->dev, 0),
273 0, /* request */
274 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
275 0, /* value */
276 index, gspca_dev->usb_buf, len,
277 500);
278 if (ret < 0) {
279 err("reg_w_buf() failed index 0x%02x, error %d",
280 index, ret);
281 gspca_dev->usb_err = ret;
282 }
283}
284
285
286static void reg_w(struct gspca_dev *gspca_dev,
287 __u8 index,
288 __u8 value)
289{
290 int ret;
291
292 if (gspca_dev->usb_err < 0)
293 return;
294 gspca_dev->usb_buf[0] = value;
295 ret = usb_control_msg(gspca_dev->dev,
296 usb_sndctrlpipe(gspca_dev->dev, 0),
297 0, /* request */
298 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
299 0, index, gspca_dev->usb_buf, 1,
300 500);
301 if (ret < 0) {
302 err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
303 index, value, ret);
304 gspca_dev->usb_err = ret;
305 }
306}
307
308static void reg_w_seq(struct gspca_dev *gspca_dev,
309 const __u8 *seq, int len)
310{
311 while (--len >= 0) {
312 reg_w(gspca_dev, seq[0], seq[1]);
313 seq += 2;
314 }
315}
316
317/* load the beginning of a page */
318static void reg_w_page(struct gspca_dev *gspca_dev,
319 const __u8 *page, int len)
320{
321 int index;
322 int ret = 0;
323
324 if (gspca_dev->usb_err < 0)
325 return;
326 for (index = 0; index < len; index++) {
327 if (page[index] == SKIP) /* skip this index */
328 continue;
329 gspca_dev->usb_buf[0] = page[index];
330 ret = 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, index, gspca_dev->usb_buf, 1,
335 500);
336 if (ret < 0) {
337 err("reg_w_page() failed index 0x%02x, "
338 "value 0x%02x, error %d",
339 index, page[index], ret);
340 gspca_dev->usb_err = ret;
341 break;
342 }
343 }
344}
345
346/* output a variable sequence */
347static void reg_w_var(struct gspca_dev *gspca_dev,
348 const __u8 *seq,
349 const __u8 *page4, unsigned int page4_len)
350{
351 int index, len;
352
353 for (;;) {
354 index = *seq++;
355 len = *seq++;
356 switch (len) {
357 case END_OF_SEQUENCE:
358 return;
359 case LOAD_PAGE4:
360 reg_w_page(gspca_dev, page4, page4_len);
361 break;
362 default:
363 if (len > USB_BUF_SZ) {
364 PDEBUG(D_ERR|D_STREAM,
365 "Incorrect variable sequence");
366 return;
367 }
368 while (len > 0) {
369 if (len < 8) {
370 reg_w_buf(gspca_dev,
371 index, seq, len);
372 seq += len;
373 break;
374 }
375 reg_w_buf(gspca_dev, index, seq, 8);
376 seq += 8;
377 index += 8;
378 len -= 8;
379 }
380 }
381 }
382 /* not reached */
383}
384
385/* this function is called at probe time for pac7311 */
386static int sd_config(struct gspca_dev *gspca_dev,
387 const struct usb_device_id *id)
388{
389 struct sd *sd = (struct sd *) gspca_dev;
390 struct cam *cam;
391
392 cam = &gspca_dev->cam;
393
394 PDEBUG(D_CONF, "Find Sensor PAC7311");
395 cam->cam_mode = vga_mode;
396 cam->nmodes = ARRAY_SIZE(vga_mode);
397
398 sd->contrast = CONTRAST_DEF;
399 sd->gain = GAIN_DEF;
400 sd->exposure = EXPOSURE_DEF;
401 sd->autogain = AUTOGAIN_DEF;
402 sd->hflip = HFLIP_DEF;
403 sd->vflip = VFLIP_DEF;
404 return 0;
405}
406
407/* This function is used by pac7311 only */
408static void setcontrast(struct gspca_dev *gspca_dev)
409{
410 struct sd *sd = (struct sd *) gspca_dev;
411
412 reg_w(gspca_dev, 0xff, 0x04);
413 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
414 /* load registers to sensor (Bit 0, auto clear) */
415 reg_w(gspca_dev, 0x11, 0x01);
416}
417
418static void setgain(struct gspca_dev *gspca_dev)
419{
420 struct sd *sd = (struct sd *) gspca_dev;
421 int gain = GAIN_MAX - sd->gain;
422
423 if (gain < 1)
424 gain = 1;
425 else if (gain > 245)
426 gain = 245;
427 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
428 reg_w(gspca_dev, 0x0e, 0x00);
429 reg_w(gspca_dev, 0x0f, gain);
430
431 /* load registers to sensor (Bit 0, auto clear) */
432 reg_w(gspca_dev, 0x11, 0x01);
433}
434
435static void setexposure(struct gspca_dev *gspca_dev)
436{
437 struct sd *sd = (struct sd *) gspca_dev;
438 __u8 reg;
439
440 /* register 2 of frame 3/4 contains the clock divider configuring the
441 no fps according to the formula: 60 / reg. sd->exposure is the
442 desired exposure time in ms. */
443 reg = 120 * sd->exposure / 1000;
444 if (reg < 2)
445 reg = 2;
446 else if (reg > 63)
447 reg = 63;
448
449 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
450 reg_w(gspca_dev, 0x02, reg);
451
452 /* Page 1 register 8 must always be 0x08 except when not in
453 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
454 reg_w(gspca_dev, 0xff, 0x01);
455 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
456 reg <= 3) {
457 reg_w(gspca_dev, 0x08, 0x09);
458 } else {
459 reg_w(gspca_dev, 0x08, 0x08);
460 }
461
462 /* load registers to sensor (Bit 0, auto clear) */
463 reg_w(gspca_dev, 0x11, 0x01);
464}
465
466static void sethvflip(struct gspca_dev *gspca_dev)
467{
468 struct sd *sd = (struct sd *) gspca_dev;
469 __u8 data;
470
471 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
472 data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
473 reg_w(gspca_dev, 0x21, data);
474
475 /* load registers to sensor (Bit 0, auto clear) */
476 reg_w(gspca_dev, 0x11, 0x01);
477}
478
479/* this function is called at probe and resume time for pac7311 */
480static int sd_init(struct gspca_dev *gspca_dev)
481{
482 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
483 return gspca_dev->usb_err;
484}
485
486static int sd_start(struct gspca_dev *gspca_dev)
487{
488 struct sd *sd = (struct sd *) gspca_dev;
489
490 sd->sof_read = 0;
491
492 reg_w_var(gspca_dev, start_7311,
493 page4_7311, sizeof(page4_7311));
494 setcontrast(gspca_dev);
495 setgain(gspca_dev);
496 setexposure(gspca_dev);
497 sethvflip(gspca_dev);
498
499 /* set correct resolution */
500 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
501 case 2: /* 160x120 pac7311 */
502 reg_w(gspca_dev, 0xff, 0x01);
503 reg_w(gspca_dev, 0x17, 0x20);
504 reg_w(gspca_dev, 0x87, 0x10);
505 break;
506 case 1: /* 320x240 pac7311 */
507 reg_w(gspca_dev, 0xff, 0x01);
508 reg_w(gspca_dev, 0x17, 0x30);
509 reg_w(gspca_dev, 0x87, 0x11);
510 break;
511 case 0: /* 640x480 */
512 reg_w(gspca_dev, 0xff, 0x01);
513 reg_w(gspca_dev, 0x17, 0x00);
514 reg_w(gspca_dev, 0x87, 0x12);
515 break;
516 }
517
518 sd->sof_read = 0;
519 sd->autogain_ignore_frames = 0;
520 atomic_set(&sd->avg_lum, -1);
521
522 /* start stream */
523 reg_w(gspca_dev, 0xff, 0x01);
524 reg_w(gspca_dev, 0x78, 0x05);
525
526 return gspca_dev->usb_err;
527}
528
529static void sd_stopN(struct gspca_dev *gspca_dev)
530{
531 reg_w(gspca_dev, 0xff, 0x04);
532 reg_w(gspca_dev, 0x27, 0x80);
533 reg_w(gspca_dev, 0x28, 0xca);
534 reg_w(gspca_dev, 0x29, 0x53);
535 reg_w(gspca_dev, 0x2a, 0x0e);
536 reg_w(gspca_dev, 0xff, 0x01);
537 reg_w(gspca_dev, 0x3e, 0x20);
538 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
539 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
540 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
541}
542
543/* called on streamoff with alt 0 and on disconnect for 7311 */
544static void sd_stop0(struct gspca_dev *gspca_dev)
545{
546}
547
548/* Include pac common sof detection functions */
549#include "pac_common.h"
550
551static void do_autogain(struct gspca_dev *gspca_dev)
552{
553 struct sd *sd = (struct sd *) gspca_dev;
554 int avg_lum = atomic_read(&sd->avg_lum);
555 int desired_lum, deadzone;
556
557 if (avg_lum == -1)
558 return;
559
560 desired_lum = 200;
561 deadzone = 20;
562
563 if (sd->autogain_ignore_frames > 0)
564 sd->autogain_ignore_frames--;
565 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
566 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
567 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
568}
569
570/* JPEG header, part 1 */
571static const unsigned char pac_jpeg_header1[] = {
572 0xff, 0xd8, /* SOI: Start of Image */
573
574 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
575 0x00, 0x11, /* length = 17 bytes (including this length field) */
576 0x08 /* Precision: 8 */
577 /* 2 bytes is placed here: number of image lines */
578 /* 2 bytes is placed here: samples per line */
579};
580
581/* JPEG header, continued */
582static const unsigned char pac_jpeg_header2[] = {
583 0x03, /* Number of image components: 3 */
584 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
585 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
586 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
587
588 0xff, 0xda, /* SOS: Start Of Scan */
589 0x00, 0x0c, /* length = 12 bytes (including this length field) */
590 0x03, /* number of components: 3 */
591 0x01, 0x00, /* selector 1, table 0x00 */
592 0x02, 0x11, /* selector 2, table 0x11 */
593 0x03, 0x11, /* selector 3, table 0x11 */
594 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
595 0x00 /* Successive approximation: 0 */
596};
597
598static void pac_start_frame(struct gspca_dev *gspca_dev,
599 __u16 lines, __u16 samples_per_line)
600{
601 unsigned char tmpbuf[4];
602
603 gspca_frame_add(gspca_dev, FIRST_PACKET,
604 pac_jpeg_header1, sizeof(pac_jpeg_header1));
605
606 tmpbuf[0] = lines >> 8;
607 tmpbuf[1] = lines & 0xff;
608 tmpbuf[2] = samples_per_line >> 8;
609 tmpbuf[3] = samples_per_line & 0xff;
610
611 gspca_frame_add(gspca_dev, INTER_PACKET,
612 tmpbuf, sizeof(tmpbuf));
613 gspca_frame_add(gspca_dev, INTER_PACKET,
614 pac_jpeg_header2, sizeof(pac_jpeg_header2));
615}
616
617/* this function is run at interrupt level */
618static void sd_pkt_scan(struct gspca_dev *gspca_dev,
619 u8 *data, /* isoc packet */
620 int len) /* iso packet length */
621{
622 struct sd *sd = (struct sd *) gspca_dev;
623 u8 *image;
624 unsigned char *sof;
625
626 sof = pac_find_sof(&sd->sof_read, data, len);
627 if (sof) {
628 int n, lum_offset, footer_length;
629
630 /* 6 bytes after the FF D9 EOF marker a number of lumination
631 bytes are send corresponding to different parts of the
632 image, the 14th and 15th byte after the EOF seem to
633 correspond to the center of the image */
634 lum_offset = 24 + sizeof pac_sof_marker;
635 footer_length = 26;
636
637 /* Finish decoding current frame */
638 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
639 if (n < 0) {
640 gspca_dev->image_len += n;
641 n = 0;
642 } else {
643 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
644 }
645 image = gspca_dev->image;
646 if (image != NULL
647 && image[gspca_dev->image_len - 2] == 0xff
648 && image[gspca_dev->image_len - 1] == 0xd9)
649 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
650
651 n = sof - data;
652 len -= n;
653 data = sof;
654
655 /* Get average lumination */
656 if (gspca_dev->last_packet_type == LAST_PACKET &&
657 n >= lum_offset)
658 atomic_set(&sd->avg_lum, data[-lum_offset] +
659 data[-lum_offset + 1]);
660 else
661 atomic_set(&sd->avg_lum, -1);
662
663 /* Start the new frame with the jpeg header */
664 pac_start_frame(gspca_dev,
665 gspca_dev->height, gspca_dev->width);
666 }
667 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
668}
669
670static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673
674 sd->contrast = val;
675 if (gspca_dev->streaming)
676 setcontrast(gspca_dev);
677 return gspca_dev->usb_err;
678}
679
680static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683
684 *val = sd->contrast;
685 return 0;
686}
687
688static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691
692 sd->gain = val;
693 if (gspca_dev->streaming)
694 setgain(gspca_dev);
695 return gspca_dev->usb_err;
696}
697
698static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
699{
700 struct sd *sd = (struct sd *) gspca_dev;
701
702 *val = sd->gain;
703 return 0;
704}
705
706static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
709
710 sd->exposure = val;
711 if (gspca_dev->streaming)
712 setexposure(gspca_dev);
713 return gspca_dev->usb_err;
714}
715
716static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719
720 *val = sd->exposure;
721 return 0;
722}
723
724static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
725{
726 struct sd *sd = (struct sd *) gspca_dev;
727
728 sd->autogain = val;
729 /* when switching to autogain set defaults to make sure
730 we are on a valid point of the autogain gain /
731 exposure knee graph, and give this change time to
732 take effect before doing autogain. */
733 if (sd->autogain) {
734 sd->exposure = EXPOSURE_DEF;
735 sd->gain = GAIN_DEF;
736 if (gspca_dev->streaming) {
737 sd->autogain_ignore_frames =
738 PAC_AUTOGAIN_IGNORE_FRAMES;
739 setexposure(gspca_dev);
740 setgain(gspca_dev);
741 }
742 }
743
744 return gspca_dev->usb_err;
745}
746
747static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750
751 *val = sd->autogain;
752 return 0;
753}
754
755static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
756{
757 struct sd *sd = (struct sd *) gspca_dev;
758
759 sd->hflip = val;
760 if (gspca_dev->streaming)
761 sethvflip(gspca_dev);
762 return gspca_dev->usb_err;
763}
764
765static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768
769 *val = sd->hflip;
770 return 0;
771}
772
773static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
774{
775 struct sd *sd = (struct sd *) gspca_dev;
776
777 sd->vflip = val;
778 if (gspca_dev->streaming)
779 sethvflip(gspca_dev);
780 return gspca_dev->usb_err;
781}
782
783static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 *val = sd->vflip;
788 return 0;
789}
790
791#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
792static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
793 u8 *data, /* interrupt packet data */
794 int len) /* interrupt packet length */
795{
796 int ret = -EINVAL;
797 u8 data0, data1;
798
799 if (len == 2) {
800 data0 = data[0];
801 data1 = data[1];
802 if ((data0 == 0x00 && data1 == 0x11) ||
803 (data0 == 0x22 && data1 == 0x33) ||
804 (data0 == 0x44 && data1 == 0x55) ||
805 (data0 == 0x66 && data1 == 0x77) ||
806 (data0 == 0x88 && data1 == 0x99) ||
807 (data0 == 0xaa && data1 == 0xbb) ||
808 (data0 == 0xcc && data1 == 0xdd) ||
809 (data0 == 0xee && data1 == 0xff)) {
810 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
811 input_sync(gspca_dev->input_dev);
812 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
813 input_sync(gspca_dev->input_dev);
814 ret = 0;
815 }
816 }
817
818 return ret;
819}
820#endif
821
822/* sub-driver description for pac7311 */
823static const struct sd_desc sd_desc = {
824 .name = MODULE_NAME,
825 .ctrls = sd_ctrls,
826 .nctrls = ARRAY_SIZE(sd_ctrls),
827 .config = sd_config,
828 .init = sd_init,
829 .start = sd_start,
830 .stopN = sd_stopN,
831 .stop0 = sd_stop0,
832 .pkt_scan = sd_pkt_scan,
833 .dq_callback = do_autogain,
834#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
835 .int_pkt_scan = sd_int_pkt_scan,
836#endif
837};
838
839/* -- module initialisation -- */
840static const struct usb_device_id device_table[] = {
841 {USB_DEVICE(0x093a, 0x2600)},
842 {USB_DEVICE(0x093a, 0x2601)},
843 {USB_DEVICE(0x093a, 0x2603)},
844 {USB_DEVICE(0x093a, 0x2608)},
845 {USB_DEVICE(0x093a, 0x260e)},
846 {USB_DEVICE(0x093a, 0x260f)},
847 {}
848};
849MODULE_DEVICE_TABLE(usb, device_table);
850
851/* -- device connect -- */
852static int sd_probe(struct usb_interface *intf,
853 const struct usb_device_id *id)
854{
855 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
856 THIS_MODULE);
857}
858
859static struct usb_driver sd_driver = {
860 .name = MODULE_NAME,
861 .id_table = device_table,
862 .probe = sd_probe,
863 .disconnect = gspca_disconnect,
864#ifdef CONFIG_PM
865 .suspend = gspca_suspend,
866 .resume = gspca_resume,
867#endif
868};
869
870/* -- module insert / remove -- */
871static int __init sd_mod_init(void)
872{
873 return usb_register(&sd_driver);
874}
875static void __exit sd_mod_exit(void)
876{
877 usb_deregister(&sd_driver);
878}
879
880module_init(sd_mod_init);
881module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h
new file mode 100644
index 00000000000..8462a7c1a33
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/se401.c b/drivers/media/video/gspca/se401.c
new file mode 100644
index 00000000000..4c283c24c75
--- /dev/null
+++ b/drivers/media/video/gspca/se401.c
@@ -0,0 +1,774 @@
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 MODULE_NAME "se401"
27
28#define BULK_SIZE 4096
29#define PACKET_SIZE 1024
30#define READ_REQ_SIZE 64
31#define MAX_MODES ((READ_REQ_SIZE - 6) / 4)
32/* The se401 compression algorithm uses a fixed quant factor, which
33 can be configured by setting the high nibble of the SE401_OPERATINGMODE
34 feature. This needs to exactly match what is in libv4l! */
35#define SE401_QUANT_FACT 8
36
37#include <linux/input.h>
38#include <linux/slab.h>
39#include "gspca.h"
40#include "se401.h"
41
42MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
43MODULE_DESCRIPTION("Endpoints se401");
44MODULE_LICENSE("GPL");
45
46/* controls */
47enum e_ctrl {
48 BRIGHTNESS,
49 GAIN,
50 EXPOSURE,
51 FREQ,
52 NCTRL /* number of controls */
53};
54
55/* exposure change state machine states */
56enum {
57 EXPO_CHANGED,
58 EXPO_DROP_FRAME,
59 EXPO_NO_CHANGE,
60};
61
62/* specific webcam descriptor */
63struct sd {
64 struct gspca_dev gspca_dev; /* !! must be the first item */
65 struct gspca_ctrl ctrls[NCTRL];
66 struct v4l2_pix_format fmts[MAX_MODES];
67 int pixels_read;
68 int packet_read;
69 u8 packet[PACKET_SIZE];
70 u8 restart_stream;
71 u8 button_state;
72 u8 resetlevel;
73 u8 resetlevel_frame_count;
74 int resetlevel_adjust_dir;
75 int expo_change_state;
76};
77
78static void setbrightness(struct gspca_dev *gspca_dev);
79static void setgain(struct gspca_dev *gspca_dev);
80static void setexposure(struct gspca_dev *gspca_dev);
81
82static const struct ctrl sd_ctrls[NCTRL] = {
83[BRIGHTNESS] = {
84 {
85 .id = V4L2_CID_BRIGHTNESS,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Brightness",
88 .minimum = 0,
89 .maximum = 255,
90 .step = 1,
91 .default_value = 15,
92 },
93 .set_control = setbrightness
94 },
95[GAIN] = {
96 {
97 .id = V4L2_CID_GAIN,
98 .type = V4L2_CTRL_TYPE_INTEGER,
99 .name = "Gain",
100 .minimum = 0,
101 .maximum = 50, /* Really 63 but > 50 is not pretty */
102 .step = 1,
103 .default_value = 25,
104 },
105 .set_control = setgain
106 },
107[EXPOSURE] = {
108 {
109 .id = V4L2_CID_EXPOSURE,
110 .type = V4L2_CTRL_TYPE_INTEGER,
111 .name = "Exposure",
112 .minimum = 0,
113 .maximum = 32767,
114 .step = 1,
115 .default_value = 15000,
116 },
117 .set_control = setexposure
118 },
119[FREQ] = {
120 {
121 .id = V4L2_CID_POWER_LINE_FREQUENCY,
122 .type = V4L2_CTRL_TYPE_MENU,
123 .name = "Light frequency filter",
124 .minimum = 0,
125 .maximum = 2,
126 .step = 1,
127 .default_value = 0,
128 },
129 .set_control = setexposure
130 },
131};
132
133static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
134 int silent)
135{
136 int err;
137
138 if (gspca_dev->usb_err < 0)
139 return;
140
141 err = usb_control_msg(gspca_dev->dev,
142 usb_sndctrlpipe(gspca_dev->dev, 0), req,
143 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
144 value, 0, NULL, 0, 1000);
145 if (err < 0) {
146 if (!silent)
147 err("write req failed req %#04x val %#04x error %d",
148 req, value, err);
149 gspca_dev->usb_err = err;
150 }
151}
152
153static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
154{
155 int err;
156
157 if (gspca_dev->usb_err < 0)
158 return;
159
160 if (USB_BUF_SZ < READ_REQ_SIZE) {
161 err("USB_BUF_SZ too small!!");
162 gspca_dev->usb_err = -ENOBUFS;
163 return;
164 }
165
166 err = usb_control_msg(gspca_dev->dev,
167 usb_rcvctrlpipe(gspca_dev->dev, 0), req,
168 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
169 0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
170 if (err < 0) {
171 if (!silent)
172 err("read req failed req %#04x error %d", req, err);
173 gspca_dev->usb_err = err;
174 }
175}
176
177static void se401_set_feature(struct gspca_dev *gspca_dev,
178 u16 selector, u16 param)
179{
180 int err;
181
182 if (gspca_dev->usb_err < 0)
183 return;
184
185 err = usb_control_msg(gspca_dev->dev,
186 usb_sndctrlpipe(gspca_dev->dev, 0),
187 SE401_REQ_SET_EXT_FEATURE,
188 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
189 param, selector, NULL, 0, 1000);
190 if (err < 0) {
191 err("set feature failed sel %#04x param %#04x error %d",
192 selector, param, err);
193 gspca_dev->usb_err = err;
194 }
195}
196
197static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
198{
199 int err;
200
201 if (gspca_dev->usb_err < 0)
202 return gspca_dev->usb_err;
203
204 if (USB_BUF_SZ < 2) {
205 err("USB_BUF_SZ too small!!");
206 gspca_dev->usb_err = -ENOBUFS;
207 return gspca_dev->usb_err;
208 }
209
210 err = usb_control_msg(gspca_dev->dev,
211 usb_rcvctrlpipe(gspca_dev->dev, 0),
212 SE401_REQ_GET_EXT_FEATURE,
213 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
214 0, selector, gspca_dev->usb_buf, 2, 1000);
215 if (err < 0) {
216 err("get feature failed sel %#04x error %d", selector, err);
217 gspca_dev->usb_err = err;
218 return err;
219 }
220 return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
221}
222
223static void setbrightness(struct gspca_dev *gspca_dev)
224{
225 struct sd *sd = (struct sd *) gspca_dev;
226
227 if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
228 return;
229
230 /* HDG: this does not seem to do anything on my cam */
231 se401_write_req(gspca_dev, SE401_REQ_SET_BRT,
232 sd->ctrls[BRIGHTNESS].val, 0);
233}
234
235static void setgain(struct gspca_dev *gspca_dev)
236{
237 struct sd *sd = (struct sd *) gspca_dev;
238 u16 gain = 63 - sd->ctrls[GAIN].val;
239
240 /* red color gain */
241 se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
242 /* green color gain */
243 se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain);
244 /* blue color gain */
245 se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
246}
247
248static void setexposure(struct gspca_dev *gspca_dev)
249{
250 struct sd *sd = (struct sd *) gspca_dev;
251 int integration = sd->ctrls[EXPOSURE].val << 6;
252 u8 expose_h, expose_m, expose_l;
253
254 /* Do this before the set_feature calls, for proper timing wrt
255 the interrupt driven pkt_scan. Note we may still race but that
256 is not a big issue, the expo change state machine is merely for
257 avoiding underexposed frames getting send out, if one sneaks
258 through so be it */
259 sd->expo_change_state = EXPO_CHANGED;
260
261 if (sd->ctrls[FREQ].val == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
262 integration = integration - integration % 106667;
263 if (sd->ctrls[FREQ].val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
264 integration = integration - integration % 88889;
265
266 expose_h = (integration >> 16);
267 expose_m = (integration >> 8);
268 expose_l = integration;
269
270 /* integration time low */
271 se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l);
272 /* integration time mid */
273 se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m);
274 /* integration time high */
275 se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h);
276}
277
278static int sd_config(struct gspca_dev *gspca_dev,
279 const struct usb_device_id *id)
280{
281 struct sd *sd = (struct sd *)gspca_dev;
282 struct cam *cam = &gspca_dev->cam;
283 u8 *cd = gspca_dev->usb_buf;
284 int i, j, n;
285 int widths[MAX_MODES], heights[MAX_MODES];
286
287 /* Read the camera descriptor */
288 se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1);
289 if (gspca_dev->usb_err) {
290 /* Sometimes after being idle for a while the se401 won't
291 respond and needs a good kicking */
292 usb_reset_device(gspca_dev->dev);
293 gspca_dev->usb_err = 0;
294 se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0);
295 }
296
297 /* Some cameras start with their LED on */
298 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
299 if (gspca_dev->usb_err)
300 return gspca_dev->usb_err;
301
302 if (cd[1] != 0x41) {
303 err("Wrong descriptor type");
304 return -ENODEV;
305 }
306
307 if (!(cd[2] & SE401_FORMAT_BAYER)) {
308 err("Bayer format not supported!");
309 return -ENODEV;
310 }
311
312 if (cd[3])
313 info("ExtraFeatures: %d", cd[3]);
314
315 n = cd[4] | (cd[5] << 8);
316 if (n > MAX_MODES) {
317 err("Too many frame sizes");
318 return -ENODEV;
319 }
320
321 for (i = 0; i < n ; i++) {
322 widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8);
323 heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8);
324 }
325
326 for (i = 0; i < n ; i++) {
327 sd->fmts[i].width = widths[i];
328 sd->fmts[i].height = heights[i];
329 sd->fmts[i].field = V4L2_FIELD_NONE;
330 sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB;
331 sd->fmts[i].priv = 1;
332
333 /* janggu compression only works for 1/4th or 1/16th res */
334 for (j = 0; j < n; j++) {
335 if (widths[j] / 2 == widths[i] &&
336 heights[j] / 2 == heights[i]) {
337 sd->fmts[i].priv = 2;
338 break;
339 }
340 }
341 /* 1/16th if available too is better then 1/4th, because
342 we then use a larger area of the sensor */
343 for (j = 0; j < n; j++) {
344 if (widths[j] / 4 == widths[i] &&
345 heights[j] / 4 == heights[i]) {
346 sd->fmts[i].priv = 4;
347 break;
348 }
349 }
350
351 if (sd->fmts[i].priv == 1) {
352 /* Not a 1/4th or 1/16th res, use bayer */
353 sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
354 sd->fmts[i].bytesperline = widths[i];
355 sd->fmts[i].sizeimage = widths[i] * heights[i];
356 info("Frame size: %dx%d bayer", widths[i], heights[i]);
357 } else {
358 /* Found a match use janggu compression */
359 sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
360 sd->fmts[i].bytesperline = 0;
361 sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
362 info("Frame size: %dx%d 1/%dth janggu",
363 widths[i], heights[i],
364 sd->fmts[i].priv * sd->fmts[i].priv);
365 }
366 }
367
368 cam->cam_mode = sd->fmts;
369 cam->nmodes = n;
370 cam->bulk = 1;
371 cam->bulk_size = BULK_SIZE;
372 cam->bulk_nurbs = 4;
373 cam->ctrls = sd->ctrls;
374 gspca_dev->nbalt = 1; /* Ignore the bogus isoc alt settings */
375 sd->resetlevel = 0x2d; /* Set initial resetlevel */
376
377 /* See if the camera supports brightness */
378 se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
379 if (gspca_dev->usb_err) {
380 gspca_dev->ctrl_dis = (1 << BRIGHTNESS);
381 gspca_dev->usb_err = 0;
382 }
383
384 return 0;
385}
386
387/* this function is called at probe and resume time */
388static int sd_init(struct gspca_dev *gspca_dev)
389{
390 return 0;
391}
392
393/* -- start the camera -- */
394static int sd_start(struct gspca_dev *gspca_dev)
395{
396 struct sd *sd = (struct sd *)gspca_dev;
397 int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
398 int mode = 0;
399
400 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1);
401 if (gspca_dev->usb_err) {
402 /* Sometimes after being idle for a while the se401 won't
403 respond and needs a good kicking */
404 usb_reset_device(gspca_dev->dev);
405 gspca_dev->usb_err = 0;
406 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0);
407 }
408 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0);
409
410 se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05);
411
412 /* set size + mode */
413 se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
414 gspca_dev->width * mult, 0);
415 se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
416 gspca_dev->height * mult, 0);
417 /*
418 * HDG: disabled this as it does not seem to do anything
419 * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE,
420 * SE401_FORMAT_BAYER, 0);
421 */
422
423 switch (mult) {
424 case 1: /* Raw bayer */
425 mode = 0x03; break;
426 case 2: /* 1/4th janggu */
427 mode = SE401_QUANT_FACT << 4; break;
428 case 4: /* 1/16th janggu */
429 mode = (SE401_QUANT_FACT << 4) | 0x02; break;
430 }
431 se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
432
433 setbrightness(gspca_dev);
434 setgain(gspca_dev);
435 setexposure(gspca_dev);
436 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
437
438 sd->packet_read = 0;
439 sd->pixels_read = 0;
440 sd->restart_stream = 0;
441 sd->resetlevel_frame_count = 0;
442 sd->resetlevel_adjust_dir = 0;
443 sd->expo_change_state = EXPO_NO_CHANGE;
444
445 se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0);
446
447 return gspca_dev->usb_err;
448}
449
450static void sd_stopN(struct gspca_dev *gspca_dev)
451{
452 se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0);
453 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
454 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0);
455}
456
457static void sd_dq_callback(struct gspca_dev *gspca_dev)
458{
459 struct sd *sd = (struct sd *)gspca_dev;
460 unsigned int ahrc, alrc;
461 int oldreset, adjust_dir;
462
463 /* Restart the stream if requested do so by pkt_scan */
464 if (sd->restart_stream) {
465 sd_stopN(gspca_dev);
466 sd_start(gspca_dev);
467 sd->restart_stream = 0;
468 }
469
470 /* Automatically adjust sensor reset level
471 Hyundai have some really nice docs about this and other sensor
472 related stuff on their homepage: www.hei.co.kr */
473 sd->resetlevel_frame_count++;
474 if (sd->resetlevel_frame_count < 20)
475 return;
476
477 /* For some reason this normally read-only register doesn't get reset
478 to zero after reading them just once... */
479 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH);
480 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
481 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH);
482 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
483 ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) +
484 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
485 alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) +
486 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
487
488 /* Not an exact science, but it seems to work pretty well... */
489 oldreset = sd->resetlevel;
490 if (alrc > 10) {
491 while (alrc >= 10 && sd->resetlevel < 63) {
492 sd->resetlevel++;
493 alrc /= 2;
494 }
495 } else if (ahrc > 20) {
496 while (ahrc >= 20 && sd->resetlevel > 0) {
497 sd->resetlevel--;
498 ahrc /= 2;
499 }
500 }
501 /* Detect ping-pong-ing and halve adjustment to avoid overshoot */
502 if (sd->resetlevel > oldreset)
503 adjust_dir = 1;
504 else
505 adjust_dir = -1;
506 if (sd->resetlevel_adjust_dir &&
507 sd->resetlevel_adjust_dir != adjust_dir)
508 sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2;
509
510 if (sd->resetlevel != oldreset) {
511 sd->resetlevel_adjust_dir = adjust_dir;
512 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
513 }
514
515 sd->resetlevel_frame_count = 0;
516}
517
518static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
519{
520 struct sd *sd = (struct sd *)gspca_dev;
521
522 switch (sd->expo_change_state) {
523 case EXPO_CHANGED:
524 /* The exposure was changed while this frame
525 was being send, so this frame is ok */
526 sd->expo_change_state = EXPO_DROP_FRAME;
527 break;
528 case EXPO_DROP_FRAME:
529 /* The exposure was changed while this frame
530 was being captured, drop it! */
531 gspca_dev->last_packet_type = DISCARD_PACKET;
532 sd->expo_change_state = EXPO_NO_CHANGE;
533 break;
534 case EXPO_NO_CHANGE:
535 break;
536 }
537 gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
538}
539
540static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
541{
542 struct sd *sd = (struct sd *)gspca_dev;
543 int imagesize = gspca_dev->width * gspca_dev->height;
544 int i, plen, bits, pixels, info, count;
545
546 if (sd->restart_stream)
547 return;
548
549 /* Sometimes a 1024 bytes garbage bulk packet is send between frames */
550 if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) {
551 gspca_dev->last_packet_type = DISCARD_PACKET;
552 return;
553 }
554
555 i = 0;
556 while (i < len) {
557 /* Read header if not already be present from prev bulk pkt */
558 if (sd->packet_read < 4) {
559 count = 4 - sd->packet_read;
560 if (count > len - i)
561 count = len - i;
562 memcpy(&sd->packet[sd->packet_read], &data[i], count);
563 sd->packet_read += count;
564 i += count;
565 if (sd->packet_read < 4)
566 break;
567 }
568 bits = sd->packet[3] + (sd->packet[2] << 8);
569 pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8);
570 info = (sd->packet[0] & 0xc0) >> 6;
571 plen = ((bits + 47) >> 4) << 1;
572 /* Sanity checks */
573 if (plen > 1024) {
574 err("invalid packet len %d restarting stream", plen);
575 goto error;
576 }
577 if (info == 3) {
578 err("unknown frame info value restarting stream");
579 goto error;
580 }
581
582 /* Read (remainder of) packet contents */
583 count = plen - sd->packet_read;
584 if (count > len - i)
585 count = len - i;
586 memcpy(&sd->packet[sd->packet_read], &data[i], count);
587 sd->packet_read += count;
588 i += count;
589 if (sd->packet_read < plen)
590 break;
591
592 sd->pixels_read += pixels;
593 sd->packet_read = 0;
594
595 switch (info) {
596 case 0: /* Frame data */
597 gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet,
598 plen);
599 break;
600 case 1: /* EOF */
601 if (sd->pixels_read != imagesize) {
602 err("frame size %d expected %d",
603 sd->pixels_read, imagesize);
604 goto error;
605 }
606 sd_complete_frame(gspca_dev, sd->packet, plen);
607 return; /* Discard the rest of the bulk packet !! */
608 case 2: /* SOF */
609 gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet,
610 plen);
611 sd->pixels_read = pixels;
612 break;
613 }
614 }
615 return;
616
617error:
618 sd->restart_stream = 1;
619 /* Give userspace a 0 bytes frame, so our dq callback gets
620 called and it can restart the stream */
621 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
622 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
623}
624
625static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len)
626{
627 struct cam *cam = &gspca_dev->cam;
628 int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
629
630 if (gspca_dev->image_len == 0) {
631 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
632 return;
633 }
634
635 if (gspca_dev->image_len + len >= imagesize) {
636 sd_complete_frame(gspca_dev, data, len);
637 return;
638 }
639
640 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
641}
642
643static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
644{
645 int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
646
647 if (len == 0)
648 return;
649
650 if (mult == 1) /* mult == 1 means raw bayer */
651 sd_pkt_scan_bayer(gspca_dev, data, len);
652 else
653 sd_pkt_scan_janggu(gspca_dev, data, len);
654}
655
656static int sd_querymenu(struct gspca_dev *gspca_dev,
657 struct v4l2_querymenu *menu)
658{
659 switch (menu->id) {
660 case V4L2_CID_POWER_LINE_FREQUENCY:
661 switch (menu->index) {
662 case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
663 strcpy((char *) menu->name, "NoFliker");
664 return 0;
665 case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
666 strcpy((char *) menu->name, "50 Hz");
667 return 0;
668 case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
669 strcpy((char *) menu->name, "60 Hz");
670 return 0;
671 }
672 break;
673 }
674 return -EINVAL;
675}
676
677#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
678static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
679{
680 struct sd *sd = (struct sd *)gspca_dev;
681 u8 state;
682
683 if (len != 2)
684 return -EINVAL;
685
686 switch (data[0]) {
687 case 0:
688 case 1:
689 state = data[0];
690 break;
691 default:
692 return -EINVAL;
693 }
694 if (sd->button_state != state) {
695 input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
696 input_sync(gspca_dev->input_dev);
697 sd->button_state = state;
698 }
699
700 return 0;
701}
702#endif
703
704/* sub-driver description */
705static const struct sd_desc sd_desc = {
706 .name = MODULE_NAME,
707 .ctrls = sd_ctrls,
708 .nctrls = ARRAY_SIZE(sd_ctrls),
709 .config = sd_config,
710 .init = sd_init,
711 .start = sd_start,
712 .stopN = sd_stopN,
713 .dq_callback = sd_dq_callback,
714 .pkt_scan = sd_pkt_scan,
715 .querymenu = sd_querymenu,
716#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
717 .int_pkt_scan = sd_int_pkt_scan,
718#endif
719};
720
721/* -- module initialisation -- */
722static const struct usb_device_id device_table[] = {
723 {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */
724 {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */
725 {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */
726 {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */
727 {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */
728 {}
729};
730MODULE_DEVICE_TABLE(usb, device_table);
731
732/* -- device connect -- */
733static int sd_probe(struct usb_interface *intf,
734 const struct usb_device_id *id)
735{
736 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
737 THIS_MODULE);
738}
739
740static int sd_pre_reset(struct usb_interface *intf)
741{
742 return 0;
743}
744
745static int sd_post_reset(struct usb_interface *intf)
746{
747 return 0;
748}
749
750static struct usb_driver sd_driver = {
751 .name = MODULE_NAME,
752 .id_table = device_table,
753 .probe = sd_probe,
754 .disconnect = gspca_disconnect,
755#ifdef CONFIG_PM
756 .suspend = gspca_suspend,
757 .resume = gspca_resume,
758#endif
759 .pre_reset = sd_pre_reset,
760 .post_reset = sd_post_reset,
761};
762
763/* -- module insert / remove -- */
764static int __init sd_mod_init(void)
765{
766 return usb_register(&sd_driver);
767}
768static void __exit sd_mod_exit(void)
769{
770 usb_deregister(&sd_driver);
771}
772
773module_init(sd_mod_init);
774module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/se401.h b/drivers/media/video/gspca/se401.h
new file mode 100644
index 00000000000..96d8ebf3cf5
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c
new file mode 100644
index 00000000000..4271f86dfe0
--- /dev/null
+++ b/drivers/media/video/gspca/sn9c2028.c
@@ -0,0 +1,750 @@
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 MODULE_NAME "sn9c2028"
22
23#include "gspca.h"
24
25MODULE_AUTHOR("Theodore Kilgore");
26MODULE_DESCRIPTION("Sonix SN9C2028 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 u8 sof_read;
33 u16 model;
34};
35
36struct init_command {
37 unsigned char instruction[6];
38 unsigned char to_read; /* length to read. 0 means no reply requested */
39};
40
41/* V4L2 controls supported by the driver */
42static const struct ctrl sd_ctrls[] = {
43};
44
45/* How to change the resolution of any of the VGA cams is unknown */
46static const struct v4l2_pix_format vga_mode[] = {
47 {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
48 .bytesperline = 640,
49 .sizeimage = 640 * 480 * 3 / 4,
50 .colorspace = V4L2_COLORSPACE_SRGB,
51 .priv = 0},
52};
53
54/* No way to change the resolution of the CIF cams is known */
55static const struct v4l2_pix_format cif_mode[] = {
56 {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
57 .bytesperline = 352,
58 .sizeimage = 352 * 288 * 3 / 4,
59 .colorspace = V4L2_COLORSPACE_SRGB,
60 .priv = 0},
61};
62
63/* the bytes to write are in gspca_dev->usb_buf */
64static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
65{
66 int rc;
67
68 PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
69 command[1], command[2], command[3], command[4], command[5]);
70
71 memcpy(gspca_dev->usb_buf, command, 6);
72 rc = usb_control_msg(gspca_dev->dev,
73 usb_sndctrlpipe(gspca_dev->dev, 0),
74 USB_REQ_GET_CONFIGURATION,
75 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
76 2, 0, gspca_dev->usb_buf, 6, 500);
77 if (rc < 0) {
78 err("command write [%02x] error %d",
79 gspca_dev->usb_buf[0], rc);
80 return rc;
81 }
82
83 return 0;
84}
85
86static int sn9c2028_read1(struct gspca_dev *gspca_dev)
87{
88 int rc;
89
90 rc = usb_control_msg(gspca_dev->dev,
91 usb_rcvctrlpipe(gspca_dev->dev, 0),
92 USB_REQ_GET_STATUS,
93 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
94 1, 0, gspca_dev->usb_buf, 1, 500);
95 if (rc != 1) {
96 err("read1 error %d", rc);
97 return (rc < 0) ? rc : -EIO;
98 }
99 PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
100 return gspca_dev->usb_buf[0];
101}
102
103static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
104{
105 int rc;
106 rc = usb_control_msg(gspca_dev->dev,
107 usb_rcvctrlpipe(gspca_dev->dev, 0),
108 USB_REQ_GET_STATUS,
109 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
110 4, 0, gspca_dev->usb_buf, 4, 500);
111 if (rc != 4) {
112 err("read4 error %d", rc);
113 return (rc < 0) ? rc : -EIO;
114 }
115 memcpy(reading, gspca_dev->usb_buf, 4);
116 PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
117 reading[1], reading[2], reading[3]);
118 return rc;
119}
120
121static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
122{
123 int i, status;
124 __u8 reading[4];
125
126 status = sn9c2028_command(gspca_dev, command);
127 if (status < 0)
128 return status;
129
130 status = -1;
131 for (i = 0; i < 256 && status < 2; i++)
132 status = sn9c2028_read1(gspca_dev);
133 if (status != 2) {
134 err("long command status read error %d", status);
135 return (status < 0) ? status : -EIO;
136 }
137
138 memset(reading, 0, 4);
139 status = sn9c2028_read4(gspca_dev, reading);
140 if (status < 0)
141 return status;
142
143 /* in general, the first byte of the response is the first byte of
144 * the command, or'ed with 8 */
145 status = sn9c2028_read1(gspca_dev);
146 if (status < 0)
147 return status;
148
149 return 0;
150}
151
152static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
153{
154 int err_code;
155
156 err_code = sn9c2028_command(gspca_dev, command);
157 if (err_code < 0)
158 return err_code;
159
160 err_code = sn9c2028_read1(gspca_dev);
161 if (err_code < 0)
162 return err_code;
163
164 return 0;
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 sd *sd = (struct sd *) gspca_dev;
172 struct cam *cam = &gspca_dev->cam;
173
174 PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
175 id->idVendor, id->idProduct);
176
177 sd->model = id->idProduct;
178
179 switch (sd->model) {
180 case 0x7005:
181 PDEBUG(D_PROBE, "Genius Smart 300 camera");
182 break;
183 case 0x8000:
184 PDEBUG(D_PROBE, "DC31VC");
185 break;
186 case 0x8001:
187 PDEBUG(D_PROBE, "Spy camera");
188 break;
189 case 0x8003:
190 PDEBUG(D_PROBE, "CIF camera");
191 break;
192 case 0x8008:
193 PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
194 break;
195 case 0x800a:
196 PDEBUG(D_PROBE, "Vivitar 3350b type camera");
197 cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
198 break;
199 }
200
201 switch (sd->model) {
202 case 0x8000:
203 case 0x8001:
204 case 0x8003:
205 cam->cam_mode = cif_mode;
206 cam->nmodes = ARRAY_SIZE(cif_mode);
207 break;
208 default:
209 cam->cam_mode = vga_mode;
210 cam->nmodes = ARRAY_SIZE(vga_mode);
211 }
212 return 0;
213}
214
215/* this function is called at probe and resume time */
216static int sd_init(struct gspca_dev *gspca_dev)
217{
218 int status = -1;
219
220 sn9c2028_read1(gspca_dev);
221 sn9c2028_read1(gspca_dev);
222 status = sn9c2028_read1(gspca_dev);
223
224 return (status < 0) ? status : 0;
225}
226
227static int run_start_commands(struct gspca_dev *gspca_dev,
228 struct init_command *cam_commands, int n)
229{
230 int i, err_code = -1;
231
232 for (i = 0; i < n; i++) {
233 switch (cam_commands[i].to_read) {
234 case 4:
235 err_code = sn9c2028_long_command(gspca_dev,
236 cam_commands[i].instruction);
237 break;
238 case 1:
239 err_code = sn9c2028_short_command(gspca_dev,
240 cam_commands[i].instruction);
241 break;
242 case 0:
243 err_code = sn9c2028_command(gspca_dev,
244 cam_commands[i].instruction);
245 break;
246 }
247 if (err_code < 0)
248 return err_code;
249 }
250 return 0;
251}
252
253static int start_spy_cam(struct gspca_dev *gspca_dev)
254{
255 struct init_command spy_start_commands[] = {
256 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
257 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
258 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
259 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
260 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
261 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
262 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */
263 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
264 /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
265 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
266 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
267 /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
268 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
269 /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
270 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
271 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
272 /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
273 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
274 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
275 /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
276 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
277 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
278 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
279 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
280 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
281 {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
282 {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
283 /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
284 {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
285 /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
286 {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
287 {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
288 {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
289 /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
290 {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
291 {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
292 {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
293 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
294 {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
295 {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
296 {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
297 /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
298 /* brightness or gain. 0 is default. 4 is good
299 * indoors at night with incandescent lighting */
300 {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
301 {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
302 {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
303 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
304 {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
305 {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
306 /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
307 {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
308 /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
309 {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
310 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
311 /* Camera should start to capture now. */
312 };
313
314 return run_start_commands(gspca_dev, spy_start_commands,
315 ARRAY_SIZE(spy_start_commands));
316}
317
318static int start_cif_cam(struct gspca_dev *gspca_dev)
319{
320 struct init_command cif_start_commands[] = {
321 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
322 /* The entire sequence below seems redundant */
323 /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
324 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
325 {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
326 {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
327 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
328 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
329 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
330 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
331 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
332 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
333 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
334 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
335 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
336 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
337 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
338 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
339 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
340 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
341 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
342 {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
343 {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
344 {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
345 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
346 {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
347 {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
348 {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
349 {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
350 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
351 {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
352 {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
353 {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
354 {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
355 {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
356 {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
357 {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
358 {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
359 {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
360 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
361 {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
362 {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
363 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
364 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
365 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
366 /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
367 * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
368 * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
369 /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
370 * causes subsampling
371 * but not a change in the resolution setting! */
372 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
373 {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
374 {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
375 {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
376 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
377 {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
378 {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
379 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
380 {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
381 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
382 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
383 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
384 {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
385 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
386 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
387 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
388 /* Camera should start to capture now. */
389 };
390
391 return run_start_commands(gspca_dev, cif_start_commands,
392 ARRAY_SIZE(cif_start_commands));
393}
394
395static int start_ms350_cam(struct gspca_dev *gspca_dev)
396{
397 struct init_command ms350_start_commands[] = {
398 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
399 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
400 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
401 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
402 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
403 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
404 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
405 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
406 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
407 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
408 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
409 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
410 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
411 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
412 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
413 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
414 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
415 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
416 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
417 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
418 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
419 {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
420 {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
421 {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
422 {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
423 {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
424 {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
425 {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
426 {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
427 {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
428 {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
429 {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
430 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
431 {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
432 {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
433 {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
434 {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
435 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
436 {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
437 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
438 {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
439 {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
440 {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
441 {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
442 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */
443 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
444 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
445 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
446 {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
447 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
448 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
449 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
450 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
451 {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
452 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
453 {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
454 {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
455 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
456 /* Camera should start to capture now. */
457 };
458
459 return run_start_commands(gspca_dev, ms350_start_commands,
460 ARRAY_SIZE(ms350_start_commands));
461}
462
463static int start_genius_cam(struct gspca_dev *gspca_dev)
464{
465 struct init_command genius_start_commands[] = {
466 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
467 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
468 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
469 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
470 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
471 /* "preliminary" width and height settings */
472 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
473 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
474 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
475 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
476 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
477 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
478 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
479 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
480 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
481 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
482 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
483 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
484 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
485 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
486 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
487 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
488 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
489 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
490 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
491 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
492 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
493 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
494 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
495 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
496 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
497 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
498 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
499 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
500 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
501 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
502 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
503 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
504 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
505 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
506 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
507 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
508 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
509 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
510 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
511 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
512 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
513 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
514 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
515 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
516 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
517 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
518 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
519 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
520 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
521 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
522 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
523 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
524 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
525 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
526 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
527 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
528 /* Camera should start to capture now. */
529 };
530
531 return run_start_commands(gspca_dev, genius_start_commands,
532 ARRAY_SIZE(genius_start_commands));
533}
534
535static int start_vivitar_cam(struct gspca_dev *gspca_dev)
536{
537 struct init_command vivitar_start_commands[] = {
538 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
539 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
540 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
541 {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
542 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
543 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
544 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
545 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
546 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
547 {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
548 /*
549 * Above is changed from OEM 0x0b. Fixes Bayer tiling.
550 * Presumably gives a vertical shift of one row.
551 */
552 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
553 /* Above seems to do horizontal shift. */
554 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
555 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
556 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
557 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
558 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
559 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
560 /* Above three commands seem to relate to brightness. */
561 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
562 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
563 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
564 {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
565 {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
566 {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
567 {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
568 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
569 {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
570 {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
571 {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
572 {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
573 {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
574 {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
575 {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
576 {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
577 {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
578 {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
579 {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
580 {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
581 {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
582 {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
583 {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
584 {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
585 {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
586 {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
587 {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
588 {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
589 {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
590 {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
591 {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
592 {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
593 {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
594 {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
595 {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
596 {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
597 {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
598 /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
599 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
600 {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
601 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
602 {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
603 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
604 {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
605 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
606 {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
607 /* Above is brightness; OEM driver setting is 0x10 */
608 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
609 {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
610 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
611 };
612
613 return run_start_commands(gspca_dev, vivitar_start_commands,
614 ARRAY_SIZE(vivitar_start_commands));
615}
616
617static int sd_start(struct gspca_dev *gspca_dev)
618{
619 struct sd *sd = (struct sd *) gspca_dev;
620 int err_code;
621
622 sd->sof_read = 0;
623
624 switch (sd->model) {
625 case 0x7005:
626 err_code = start_genius_cam(gspca_dev);
627 break;
628 case 0x8001:
629 err_code = start_spy_cam(gspca_dev);
630 break;
631 case 0x8003:
632 err_code = start_cif_cam(gspca_dev);
633 break;
634 case 0x8008:
635 err_code = start_ms350_cam(gspca_dev);
636 break;
637 case 0x800a:
638 err_code = start_vivitar_cam(gspca_dev);
639 break;
640 default:
641 err("Starting unknown camera, please report this");
642 return -ENXIO;
643 }
644
645 return err_code;
646}
647
648static void sd_stopN(struct gspca_dev *gspca_dev)
649{
650 int result;
651 __u8 data[6];
652
653 result = sn9c2028_read1(gspca_dev);
654 if (result < 0)
655 PDEBUG(D_ERR, "Camera Stop read failed");
656
657 memset(data, 0, 6);
658 data[0] = 0x14;
659 result = sn9c2028_command(gspca_dev, data);
660 if (result < 0)
661 PDEBUG(D_ERR, "Camera Stop command failed");
662}
663
664/* Include sn9c2028 sof detection functions */
665#include "sn9c2028.h"
666
667static void sd_pkt_scan(struct gspca_dev *gspca_dev,
668 __u8 *data, /* isoc packet */
669 int len) /* iso packet length */
670{
671 unsigned char *sof;
672
673 sof = sn9c2028_find_sof(gspca_dev, data, len);
674 if (sof) {
675 int n;
676
677 /* finish decoding current frame */
678 n = sof - data;
679 if (n > sizeof sn9c2028_sof_marker)
680 n -= sizeof sn9c2028_sof_marker;
681 else
682 n = 0;
683 gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
684 /* Start next frame. */
685 gspca_frame_add(gspca_dev, FIRST_PACKET,
686 sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
687 len -= sof - data;
688 data = sof;
689 }
690 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
691}
692
693/* sub-driver description */
694static const struct sd_desc sd_desc = {
695 .name = MODULE_NAME,
696 .ctrls = sd_ctrls,
697 .nctrls = ARRAY_SIZE(sd_ctrls),
698 .config = sd_config,
699 .init = sd_init,
700 .start = sd_start,
701 .stopN = sd_stopN,
702 .pkt_scan = sd_pkt_scan,
703};
704
705/* -- module initialisation -- */
706static const struct usb_device_id device_table[] = {
707 {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
708 /* The Genius Smart is untested. I can't find an owner ! */
709 /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
710 {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
711 {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
712 /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
713 {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
714 {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
715 {}
716};
717MODULE_DEVICE_TABLE(usb, device_table);
718
719/* -- device connect -- */
720static int sd_probe(struct usb_interface *intf,
721 const struct usb_device_id *id)
722{
723 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
724 THIS_MODULE);
725}
726
727static struct usb_driver sd_driver = {
728 .name = MODULE_NAME,
729 .id_table = device_table,
730 .probe = sd_probe,
731 .disconnect = gspca_disconnect,
732#ifdef CONFIG_PM
733 .suspend = gspca_suspend,
734 .resume = gspca_resume,
735#endif
736};
737
738/* -- module insert / remove -- */
739static int __init sd_mod_init(void)
740{
741 return usb_register(&sd_driver);
742}
743
744static void __exit sd_mod_exit(void)
745{
746 usb_deregister(&sd_driver);
747}
748
749module_init(sd_mod_init);
750module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h
new file mode 100644
index 00000000000..8fd1d3e0566
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
new file mode 100644
index 00000000000..c431900cd29
--- /dev/null
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -0,0 +1,2566 @@
1/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.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 * 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#include <linux/input.h>
22
23#include "gspca.h"
24#include "jpeg.h"
25
26#include <media/v4l2-chip-ident.h>
27#include <linux/dmi.h>
28
29MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
30 "microdia project <microdia@googlegroups.com>");
31MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34#define MODULE_NAME "sn9c20x"
35
36/*
37 * Pixel format private data
38 */
39#define SCALE_MASK 0x0f
40#define SCALE_160x120 0
41#define SCALE_320x240 1
42#define SCALE_640x480 2
43#define SCALE_1280x1024 3
44#define MODE_RAW 0x10
45#define MODE_JPEG 0x20
46#define MODE_SXGA 0x80
47
48#define SENSOR_OV9650 0
49#define SENSOR_OV9655 1
50#define SENSOR_SOI968 2
51#define SENSOR_OV7660 3
52#define SENSOR_OV7670 4
53#define SENSOR_MT9V011 5
54#define SENSOR_MT9V111 6
55#define SENSOR_MT9V112 7
56#define SENSOR_MT9M001 8
57#define SENSOR_MT9M111 9
58#define SENSOR_MT9M112 10
59#define SENSOR_HV7131R 11
60#define SENSOR_MT9VPRB 20
61
62/* camera flags */
63#define HAS_NO_BUTTON 0x1
64#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
65#define FLIP_DETECT 0x4
66
67/* specific webcam descriptor */
68struct sd {
69 struct gspca_dev gspca_dev;
70
71#define MIN_AVG_LUM 80
72#define MAX_AVG_LUM 130
73 atomic_t avg_lum;
74 u8 old_step;
75 u8 older_step;
76 u8 exposure_step;
77
78 u8 brightness;
79 u8 contrast;
80 u8 saturation;
81 s16 hue;
82 u8 gamma;
83 u8 red;
84 u8 blue;
85
86 u8 hflip;
87 u8 vflip;
88 u8 gain;
89 u16 exposure;
90 u8 auto_exposure;
91
92 u8 i2c_addr;
93 u8 sensor;
94 u8 hstart;
95 u8 vstart;
96
97 u8 jpeg_hdr[JPEG_HDR_SZ];
98 u8 quality;
99
100 u8 flags;
101};
102
103struct i2c_reg_u8 {
104 u8 reg;
105 u8 val;
106};
107
108struct i2c_reg_u16 {
109 u8 reg;
110 u16 val;
111};
112
113static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
114static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
115static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
116static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
117static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
118static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
119static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
120static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
121static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
122static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
123static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
124static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
125static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
126static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
127static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
128static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
129static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
130static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
131static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
132static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
133static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
134static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
135static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
136static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
137
138static const struct dmi_system_id flip_dmi_table[] = {
139 {
140 .ident = "MSI MS-1034",
141 .matches = {
142 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
143 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
144 DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
145 }
146 },
147 {
148 .ident = "MSI MS-1632",
149 .matches = {
150 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
151 DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
152 }
153 },
154 {
155 .ident = "MSI MS-1633X",
156 .matches = {
157 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
158 DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
159 }
160 },
161 {
162 .ident = "MSI MS-1635X",
163 .matches = {
164 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
165 DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
166 }
167 },
168 {
169 .ident = "ASUSTeK W7J",
170 .matches = {
171 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
172 DMI_MATCH(DMI_BOARD_NAME, "W7J ")
173 }
174 },
175 {}
176};
177
178static const struct ctrl sd_ctrls[] = {
179 {
180#define BRIGHTNESS_IDX 0
181 {
182 .id = V4L2_CID_BRIGHTNESS,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "Brightness",
185 .minimum = 0,
186 .maximum = 0xff,
187 .step = 1,
188#define BRIGHTNESS_DEFAULT 0x7f
189 .default_value = BRIGHTNESS_DEFAULT,
190 },
191 .set = sd_setbrightness,
192 .get = sd_getbrightness,
193 },
194 {
195#define CONTRAST_IDX 1
196 {
197 .id = V4L2_CID_CONTRAST,
198 .type = V4L2_CTRL_TYPE_INTEGER,
199 .name = "Contrast",
200 .minimum = 0,
201 .maximum = 0xff,
202 .step = 1,
203#define CONTRAST_DEFAULT 0x7f
204 .default_value = CONTRAST_DEFAULT,
205 },
206 .set = sd_setcontrast,
207 .get = sd_getcontrast,
208 },
209 {
210#define SATURATION_IDX 2
211 {
212 .id = V4L2_CID_SATURATION,
213 .type = V4L2_CTRL_TYPE_INTEGER,
214 .name = "Saturation",
215 .minimum = 0,
216 .maximum = 0xff,
217 .step = 1,
218#define SATURATION_DEFAULT 0x7f
219 .default_value = SATURATION_DEFAULT,
220 },
221 .set = sd_setsaturation,
222 .get = sd_getsaturation,
223 },
224 {
225#define HUE_IDX 3
226 {
227 .id = V4L2_CID_HUE,
228 .type = V4L2_CTRL_TYPE_INTEGER,
229 .name = "Hue",
230 .minimum = -180,
231 .maximum = 180,
232 .step = 1,
233#define HUE_DEFAULT 0
234 .default_value = HUE_DEFAULT,
235 },
236 .set = sd_sethue,
237 .get = sd_gethue,
238 },
239 {
240#define GAMMA_IDX 4
241 {
242 .id = V4L2_CID_GAMMA,
243 .type = V4L2_CTRL_TYPE_INTEGER,
244 .name = "Gamma",
245 .minimum = 0,
246 .maximum = 0xff,
247 .step = 1,
248#define GAMMA_DEFAULT 0x10
249 .default_value = GAMMA_DEFAULT,
250 },
251 .set = sd_setgamma,
252 .get = sd_getgamma,
253 },
254 {
255#define BLUE_IDX 5
256 {
257 .id = V4L2_CID_BLUE_BALANCE,
258 .type = V4L2_CTRL_TYPE_INTEGER,
259 .name = "Blue Balance",
260 .minimum = 0,
261 .maximum = 0x7f,
262 .step = 1,
263#define BLUE_DEFAULT 0x28
264 .default_value = BLUE_DEFAULT,
265 },
266 .set = sd_setbluebalance,
267 .get = sd_getbluebalance,
268 },
269 {
270#define RED_IDX 6
271 {
272 .id = V4L2_CID_RED_BALANCE,
273 .type = V4L2_CTRL_TYPE_INTEGER,
274 .name = "Red Balance",
275 .minimum = 0,
276 .maximum = 0x7f,
277 .step = 1,
278#define RED_DEFAULT 0x28
279 .default_value = RED_DEFAULT,
280 },
281 .set = sd_setredbalance,
282 .get = sd_getredbalance,
283 },
284 {
285#define HFLIP_IDX 7
286 {
287 .id = V4L2_CID_HFLIP,
288 .type = V4L2_CTRL_TYPE_BOOLEAN,
289 .name = "Horizontal Flip",
290 .minimum = 0,
291 .maximum = 1,
292 .step = 1,
293#define HFLIP_DEFAULT 0
294 .default_value = HFLIP_DEFAULT,
295 },
296 .set = sd_sethflip,
297 .get = sd_gethflip,
298 },
299 {
300#define VFLIP_IDX 8
301 {
302 .id = V4L2_CID_VFLIP,
303 .type = V4L2_CTRL_TYPE_BOOLEAN,
304 .name = "Vertical Flip",
305 .minimum = 0,
306 .maximum = 1,
307 .step = 1,
308#define VFLIP_DEFAULT 0
309 .default_value = VFLIP_DEFAULT,
310 },
311 .set = sd_setvflip,
312 .get = sd_getvflip,
313 },
314 {
315#define EXPOSURE_IDX 9
316 {
317 .id = V4L2_CID_EXPOSURE,
318 .type = V4L2_CTRL_TYPE_INTEGER,
319 .name = "Exposure",
320 .minimum = 0,
321 .maximum = 0x1780,
322 .step = 1,
323#define EXPOSURE_DEFAULT 0x33
324 .default_value = EXPOSURE_DEFAULT,
325 },
326 .set = sd_setexposure,
327 .get = sd_getexposure,
328 },
329 {
330#define GAIN_IDX 10
331 {
332 .id = V4L2_CID_GAIN,
333 .type = V4L2_CTRL_TYPE_INTEGER,
334 .name = "Gain",
335 .minimum = 0,
336 .maximum = 28,
337 .step = 1,
338#define GAIN_DEFAULT 0x00
339 .default_value = GAIN_DEFAULT,
340 },
341 .set = sd_setgain,
342 .get = sd_getgain,
343 },
344 {
345#define AUTOGAIN_IDX 11
346 {
347 .id = V4L2_CID_AUTOGAIN,
348 .type = V4L2_CTRL_TYPE_BOOLEAN,
349 .name = "Auto Exposure",
350 .minimum = 0,
351 .maximum = 1,
352 .step = 1,
353#define AUTO_EXPOSURE_DEFAULT 1
354 .default_value = AUTO_EXPOSURE_DEFAULT,
355 },
356 .set = sd_setautoexposure,
357 .get = sd_getautoexposure,
358 },
359};
360
361static const struct v4l2_pix_format vga_mode[] = {
362 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
363 .bytesperline = 160,
364 .sizeimage = 160 * 120 * 4 / 8 + 590,
365 .colorspace = V4L2_COLORSPACE_JPEG,
366 .priv = SCALE_160x120 | MODE_JPEG},
367 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
368 .bytesperline = 160,
369 .sizeimage = 160 * 120,
370 .colorspace = V4L2_COLORSPACE_SRGB,
371 .priv = SCALE_160x120 | MODE_RAW},
372 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
373 .bytesperline = 160,
374 .sizeimage = 240 * 120,
375 .colorspace = V4L2_COLORSPACE_SRGB,
376 .priv = SCALE_160x120},
377 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
378 .bytesperline = 320,
379 .sizeimage = 320 * 240 * 4 / 8 + 590,
380 .colorspace = V4L2_COLORSPACE_JPEG,
381 .priv = SCALE_320x240 | MODE_JPEG},
382 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
383 .bytesperline = 320,
384 .sizeimage = 320 * 240 ,
385 .colorspace = V4L2_COLORSPACE_SRGB,
386 .priv = SCALE_320x240 | MODE_RAW},
387 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
388 .bytesperline = 320,
389 .sizeimage = 480 * 240 ,
390 .colorspace = V4L2_COLORSPACE_SRGB,
391 .priv = SCALE_320x240},
392 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
393 .bytesperline = 640,
394 .sizeimage = 640 * 480 * 4 / 8 + 590,
395 .colorspace = V4L2_COLORSPACE_JPEG,
396 .priv = SCALE_640x480 | MODE_JPEG},
397 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
398 .bytesperline = 640,
399 .sizeimage = 640 * 480,
400 .colorspace = V4L2_COLORSPACE_SRGB,
401 .priv = SCALE_640x480 | MODE_RAW},
402 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
403 .bytesperline = 640,
404 .sizeimage = 960 * 480,
405 .colorspace = V4L2_COLORSPACE_SRGB,
406 .priv = SCALE_640x480},
407};
408
409static const struct v4l2_pix_format sxga_mode[] = {
410 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
411 .bytesperline = 160,
412 .sizeimage = 160 * 120 * 4 / 8 + 590,
413 .colorspace = V4L2_COLORSPACE_JPEG,
414 .priv = SCALE_160x120 | MODE_JPEG},
415 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
416 .bytesperline = 160,
417 .sizeimage = 160 * 120,
418 .colorspace = V4L2_COLORSPACE_SRGB,
419 .priv = SCALE_160x120 | MODE_RAW},
420 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
421 .bytesperline = 160,
422 .sizeimage = 240 * 120,
423 .colorspace = V4L2_COLORSPACE_SRGB,
424 .priv = SCALE_160x120},
425 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
426 .bytesperline = 320,
427 .sizeimage = 320 * 240 * 4 / 8 + 590,
428 .colorspace = V4L2_COLORSPACE_JPEG,
429 .priv = SCALE_320x240 | MODE_JPEG},
430 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
431 .bytesperline = 320,
432 .sizeimage = 320 * 240 ,
433 .colorspace = V4L2_COLORSPACE_SRGB,
434 .priv = SCALE_320x240 | MODE_RAW},
435 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
436 .bytesperline = 320,
437 .sizeimage = 480 * 240 ,
438 .colorspace = V4L2_COLORSPACE_SRGB,
439 .priv = SCALE_320x240},
440 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
441 .bytesperline = 640,
442 .sizeimage = 640 * 480 * 4 / 8 + 590,
443 .colorspace = V4L2_COLORSPACE_JPEG,
444 .priv = SCALE_640x480 | MODE_JPEG},
445 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
446 .bytesperline = 640,
447 .sizeimage = 640 * 480,
448 .colorspace = V4L2_COLORSPACE_SRGB,
449 .priv = SCALE_640x480 | MODE_RAW},
450 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
451 .bytesperline = 640,
452 .sizeimage = 960 * 480,
453 .colorspace = V4L2_COLORSPACE_SRGB,
454 .priv = SCALE_640x480},
455 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
456 .bytesperline = 1280,
457 .sizeimage = 1280 * 1024,
458 .colorspace = V4L2_COLORSPACE_SRGB,
459 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
460};
461
462static const struct v4l2_pix_format mono_mode[] = {
463 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
464 .bytesperline = 160,
465 .sizeimage = 160 * 120,
466 .colorspace = V4L2_COLORSPACE_SRGB,
467 .priv = SCALE_160x120 | MODE_RAW},
468 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
469 .bytesperline = 320,
470 .sizeimage = 320 * 240 ,
471 .colorspace = V4L2_COLORSPACE_SRGB,
472 .priv = SCALE_320x240 | MODE_RAW},
473 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
474 .bytesperline = 640,
475 .sizeimage = 640 * 480,
476 .colorspace = V4L2_COLORSPACE_SRGB,
477 .priv = SCALE_640x480 | MODE_RAW},
478 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
479 .bytesperline = 1280,
480 .sizeimage = 1280 * 1024,
481 .colorspace = V4L2_COLORSPACE_SRGB,
482 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
483};
484
485static const s16 hsv_red_x[] = {
486 41, 44, 46, 48, 50, 52, 54, 56,
487 58, 60, 62, 64, 66, 68, 70, 72,
488 74, 76, 78, 80, 81, 83, 85, 87,
489 88, 90, 92, 93, 95, 97, 98, 100,
490 101, 102, 104, 105, 107, 108, 109, 110,
491 112, 113, 114, 115, 116, 117, 118, 119,
492 120, 121, 122, 123, 123, 124, 125, 125,
493 126, 127, 127, 128, 128, 129, 129, 129,
494 130, 130, 130, 130, 131, 131, 131, 131,
495 131, 131, 131, 131, 130, 130, 130, 130,
496 129, 129, 129, 128, 128, 127, 127, 126,
497 125, 125, 124, 123, 122, 122, 121, 120,
498 119, 118, 117, 116, 115, 114, 112, 111,
499 110, 109, 107, 106, 105, 103, 102, 101,
500 99, 98, 96, 94, 93, 91, 90, 88,
501 86, 84, 83, 81, 79, 77, 75, 74,
502 72, 70, 68, 66, 64, 62, 60, 58,
503 56, 54, 52, 49, 47, 45, 43, 41,
504 39, 36, 34, 32, 30, 28, 25, 23,
505 21, 19, 16, 14, 12, 9, 7, 5,
506 3, 0, -1, -3, -6, -8, -10, -12,
507 -15, -17, -19, -22, -24, -26, -28, -30,
508 -33, -35, -37, -39, -41, -44, -46, -48,
509 -50, -52, -54, -56, -58, -60, -62, -64,
510 -66, -68, -70, -72, -74, -76, -78, -80,
511 -81, -83, -85, -87, -88, -90, -92, -93,
512 -95, -97, -98, -100, -101, -102, -104, -105,
513 -107, -108, -109, -110, -112, -113, -114, -115,
514 -116, -117, -118, -119, -120, -121, -122, -123,
515 -123, -124, -125, -125, -126, -127, -127, -128,
516 -128, -128, -128, -128, -128, -128, -128, -128,
517 -128, -128, -128, -128, -128, -128, -128, -128,
518 -128, -128, -128, -128, -128, -128, -128, -128,
519 -128, -127, -127, -126, -125, -125, -124, -123,
520 -122, -122, -121, -120, -119, -118, -117, -116,
521 -115, -114, -112, -111, -110, -109, -107, -106,
522 -105, -103, -102, -101, -99, -98, -96, -94,
523 -93, -91, -90, -88, -86, -84, -83, -81,
524 -79, -77, -75, -74, -72, -70, -68, -66,
525 -64, -62, -60, -58, -56, -54, -52, -49,
526 -47, -45, -43, -41, -39, -36, -34, -32,
527 -30, -28, -25, -23, -21, -19, -16, -14,
528 -12, -9, -7, -5, -3, 0, 1, 3,
529 6, 8, 10, 12, 15, 17, 19, 22,
530 24, 26, 28, 30, 33, 35, 37, 39, 41
531};
532
533static const s16 hsv_red_y[] = {
534 82, 80, 78, 76, 74, 73, 71, 69,
535 67, 65, 63, 61, 58, 56, 54, 52,
536 50, 48, 46, 44, 41, 39, 37, 35,
537 32, 30, 28, 26, 23, 21, 19, 16,
538 14, 12, 10, 7, 5, 3, 0, -1,
539 -3, -6, -8, -10, -13, -15, -17, -19,
540 -22, -24, -26, -29, -31, -33, -35, -38,
541 -40, -42, -44, -46, -48, -51, -53, -55,
542 -57, -59, -61, -63, -65, -67, -69, -71,
543 -73, -75, -77, -79, -81, -82, -84, -86,
544 -88, -89, -91, -93, -94, -96, -98, -99,
545 -101, -102, -104, -105, -106, -108, -109, -110,
546 -112, -113, -114, -115, -116, -117, -119, -120,
547 -120, -121, -122, -123, -124, -125, -126, -126,
548 -127, -128, -128, -128, -128, -128, -128, -128,
549 -128, -128, -128, -128, -128, -128, -128, -128,
550 -128, -128, -128, -128, -128, -128, -128, -128,
551 -128, -128, -128, -128, -128, -128, -128, -128,
552 -127, -127, -126, -125, -125, -124, -123, -122,
553 -121, -120, -119, -118, -117, -116, -115, -114,
554 -113, -111, -110, -109, -107, -106, -105, -103,
555 -102, -100, -99, -97, -96, -94, -92, -91,
556 -89, -87, -85, -84, -82, -80, -78, -76,
557 -74, -73, -71, -69, -67, -65, -63, -61,
558 -58, -56, -54, -52, -50, -48, -46, -44,
559 -41, -39, -37, -35, -32, -30, -28, -26,
560 -23, -21, -19, -16, -14, -12, -10, -7,
561 -5, -3, 0, 1, 3, 6, 8, 10,
562 13, 15, 17, 19, 22, 24, 26, 29,
563 31, 33, 35, 38, 40, 42, 44, 46,
564 48, 51, 53, 55, 57, 59, 61, 63,
565 65, 67, 69, 71, 73, 75, 77, 79,
566 81, 82, 84, 86, 88, 89, 91, 93,
567 94, 96, 98, 99, 101, 102, 104, 105,
568 106, 108, 109, 110, 112, 113, 114, 115,
569 116, 117, 119, 120, 120, 121, 122, 123,
570 124, 125, 126, 126, 127, 128, 128, 129,
571 129, 130, 130, 131, 131, 131, 131, 132,
572 132, 132, 132, 132, 132, 132, 132, 132,
573 132, 132, 132, 131, 131, 131, 130, 130,
574 130, 129, 129, 128, 127, 127, 126, 125,
575 125, 124, 123, 122, 121, 120, 119, 118,
576 117, 116, 115, 114, 113, 111, 110, 109,
577 107, 106, 105, 103, 102, 100, 99, 97,
578 96, 94, 92, 91, 89, 87, 85, 84, 82
579};
580
581static const s16 hsv_green_x[] = {
582 -124, -124, -125, -125, -125, -125, -125, -125,
583 -125, -126, -126, -125, -125, -125, -125, -125,
584 -125, -124, -124, -124, -123, -123, -122, -122,
585 -121, -121, -120, -120, -119, -118, -117, -117,
586 -116, -115, -114, -113, -112, -111, -110, -109,
587 -108, -107, -105, -104, -103, -102, -100, -99,
588 -98, -96, -95, -93, -92, -91, -89, -87,
589 -86, -84, -83, -81, -79, -77, -76, -74,
590 -72, -70, -69, -67, -65, -63, -61, -59,
591 -57, -55, -53, -51, -49, -47, -45, -43,
592 -41, -39, -37, -35, -33, -30, -28, -26,
593 -24, -22, -20, -18, -15, -13, -11, -9,
594 -7, -4, -2, 0, 1, 3, 6, 8,
595 10, 12, 14, 17, 19, 21, 23, 25,
596 27, 29, 32, 34, 36, 38, 40, 42,
597 44, 46, 48, 50, 52, 54, 56, 58,
598 60, 62, 64, 66, 68, 70, 71, 73,
599 75, 77, 78, 80, 82, 83, 85, 87,
600 88, 90, 91, 93, 94, 96, 97, 98,
601 100, 101, 102, 104, 105, 106, 107, 108,
602 109, 111, 112, 113, 113, 114, 115, 116,
603 117, 118, 118, 119, 120, 120, 121, 122,
604 122, 123, 123, 124, 124, 124, 125, 125,
605 125, 125, 125, 125, 125, 126, 126, 125,
606 125, 125, 125, 125, 125, 124, 124, 124,
607 123, 123, 122, 122, 121, 121, 120, 120,
608 119, 118, 117, 117, 116, 115, 114, 113,
609 112, 111, 110, 109, 108, 107, 105, 104,
610 103, 102, 100, 99, 98, 96, 95, 93,
611 92, 91, 89, 87, 86, 84, 83, 81,
612 79, 77, 76, 74, 72, 70, 69, 67,
613 65, 63, 61, 59, 57, 55, 53, 51,
614 49, 47, 45, 43, 41, 39, 37, 35,
615 33, 30, 28, 26, 24, 22, 20, 18,
616 15, 13, 11, 9, 7, 4, 2, 0,
617 -1, -3, -6, -8, -10, -12, -14, -17,
618 -19, -21, -23, -25, -27, -29, -32, -34,
619 -36, -38, -40, -42, -44, -46, -48, -50,
620 -52, -54, -56, -58, -60, -62, -64, -66,
621 -68, -70, -71, -73, -75, -77, -78, -80,
622 -82, -83, -85, -87, -88, -90, -91, -93,
623 -94, -96, -97, -98, -100, -101, -102, -104,
624 -105, -106, -107, -108, -109, -111, -112, -113,
625 -113, -114, -115, -116, -117, -118, -118, -119,
626 -120, -120, -121, -122, -122, -123, -123, -124, -124
627};
628
629static const s16 hsv_green_y[] = {
630 -100, -99, -98, -97, -95, -94, -93, -91,
631 -90, -89, -87, -86, -84, -83, -81, -80,
632 -78, -76, -75, -73, -71, -70, -68, -66,
633 -64, -63, -61, -59, -57, -55, -53, -51,
634 -49, -48, -46, -44, -42, -40, -38, -36,
635 -34, -32, -30, -27, -25, -23, -21, -19,
636 -17, -15, -13, -11, -9, -7, -4, -2,
637 0, 1, 3, 5, 7, 9, 11, 14,
638 16, 18, 20, 22, 24, 26, 28, 30,
639 32, 34, 36, 38, 40, 42, 44, 46,
640 48, 50, 52, 54, 56, 58, 59, 61,
641 63, 65, 67, 68, 70, 72, 74, 75,
642 77, 78, 80, 82, 83, 85, 86, 88,
643 89, 90, 92, 93, 95, 96, 97, 98,
644 100, 101, 102, 103, 104, 105, 106, 107,
645 108, 109, 110, 111, 112, 112, 113, 114,
646 115, 115, 116, 116, 117, 117, 118, 118,
647 119, 119, 119, 120, 120, 120, 120, 120,
648 121, 121, 121, 121, 121, 121, 120, 120,
649 120, 120, 120, 119, 119, 119, 118, 118,
650 117, 117, 116, 116, 115, 114, 114, 113,
651 112, 111, 111, 110, 109, 108, 107, 106,
652 105, 104, 103, 102, 100, 99, 98, 97,
653 95, 94, 93, 91, 90, 89, 87, 86,
654 84, 83, 81, 80, 78, 76, 75, 73,
655 71, 70, 68, 66, 64, 63, 61, 59,
656 57, 55, 53, 51, 49, 48, 46, 44,
657 42, 40, 38, 36, 34, 32, 30, 27,
658 25, 23, 21, 19, 17, 15, 13, 11,
659 9, 7, 4, 2, 0, -1, -3, -5,
660 -7, -9, -11, -14, -16, -18, -20, -22,
661 -24, -26, -28, -30, -32, -34, -36, -38,
662 -40, -42, -44, -46, -48, -50, -52, -54,
663 -56, -58, -59, -61, -63, -65, -67, -68,
664 -70, -72, -74, -75, -77, -78, -80, -82,
665 -83, -85, -86, -88, -89, -90, -92, -93,
666 -95, -96, -97, -98, -100, -101, -102, -103,
667 -104, -105, -106, -107, -108, -109, -110, -111,
668 -112, -112, -113, -114, -115, -115, -116, -116,
669 -117, -117, -118, -118, -119, -119, -119, -120,
670 -120, -120, -120, -120, -121, -121, -121, -121,
671 -121, -121, -120, -120, -120, -120, -120, -119,
672 -119, -119, -118, -118, -117, -117, -116, -116,
673 -115, -114, -114, -113, -112, -111, -111, -110,
674 -109, -108, -107, -106, -105, -104, -103, -102, -100
675};
676
677static const s16 hsv_blue_x[] = {
678 112, 113, 114, 114, 115, 116, 117, 117,
679 118, 118, 119, 119, 120, 120, 120, 121,
680 121, 121, 122, 122, 122, 122, 122, 122,
681 122, 122, 122, 122, 122, 122, 121, 121,
682 121, 120, 120, 120, 119, 119, 118, 118,
683 117, 116, 116, 115, 114, 113, 113, 112,
684 111, 110, 109, 108, 107, 106, 105, 104,
685 103, 102, 100, 99, 98, 97, 95, 94,
686 93, 91, 90, 88, 87, 85, 84, 82,
687 80, 79, 77, 76, 74, 72, 70, 69,
688 67, 65, 63, 61, 60, 58, 56, 54,
689 52, 50, 48, 46, 44, 42, 40, 38,
690 36, 34, 32, 30, 28, 26, 24, 22,
691 19, 17, 15, 13, 11, 9, 7, 5,
692 2, 0, -1, -3, -5, -7, -9, -12,
693 -14, -16, -18, -20, -22, -24, -26, -28,
694 -31, -33, -35, -37, -39, -41, -43, -45,
695 -47, -49, -51, -53, -54, -56, -58, -60,
696 -62, -64, -66, -67, -69, -71, -73, -74,
697 -76, -78, -79, -81, -83, -84, -86, -87,
698 -89, -90, -92, -93, -94, -96, -97, -98,
699 -99, -101, -102, -103, -104, -105, -106, -107,
700 -108, -109, -110, -111, -112, -113, -114, -114,
701 -115, -116, -117, -117, -118, -118, -119, -119,
702 -120, -120, -120, -121, -121, -121, -122, -122,
703 -122, -122, -122, -122, -122, -122, -122, -122,
704 -122, -122, -121, -121, -121, -120, -120, -120,
705 -119, -119, -118, -118, -117, -116, -116, -115,
706 -114, -113, -113, -112, -111, -110, -109, -108,
707 -107, -106, -105, -104, -103, -102, -100, -99,
708 -98, -97, -95, -94, -93, -91, -90, -88,
709 -87, -85, -84, -82, -80, -79, -77, -76,
710 -74, -72, -70, -69, -67, -65, -63, -61,
711 -60, -58, -56, -54, -52, -50, -48, -46,
712 -44, -42, -40, -38, -36, -34, -32, -30,
713 -28, -26, -24, -22, -19, -17, -15, -13,
714 -11, -9, -7, -5, -2, 0, 1, 3,
715 5, 7, 9, 12, 14, 16, 18, 20,
716 22, 24, 26, 28, 31, 33, 35, 37,
717 39, 41, 43, 45, 47, 49, 51, 53,
718 54, 56, 58, 60, 62, 64, 66, 67,
719 69, 71, 73, 74, 76, 78, 79, 81,
720 83, 84, 86, 87, 89, 90, 92, 93,
721 94, 96, 97, 98, 99, 101, 102, 103,
722 104, 105, 106, 107, 108, 109, 110, 111, 112
723};
724
725static const s16 hsv_blue_y[] = {
726 -11, -13, -15, -17, -19, -21, -23, -25,
727 -27, -29, -31, -33, -35, -37, -39, -41,
728 -43, -45, -46, -48, -50, -52, -54, -55,
729 -57, -59, -61, -62, -64, -66, -67, -69,
730 -71, -72, -74, -75, -77, -78, -80, -81,
731 -83, -84, -86, -87, -88, -90, -91, -92,
732 -93, -95, -96, -97, -98, -99, -100, -101,
733 -102, -103, -104, -105, -106, -106, -107, -108,
734 -109, -109, -110, -111, -111, -112, -112, -113,
735 -113, -114, -114, -114, -115, -115, -115, -115,
736 -116, -116, -116, -116, -116, -116, -116, -116,
737 -116, -115, -115, -115, -115, -114, -114, -114,
738 -113, -113, -112, -112, -111, -111, -110, -110,
739 -109, -108, -108, -107, -106, -105, -104, -103,
740 -102, -101, -100, -99, -98, -97, -96, -95,
741 -94, -93, -91, -90, -89, -88, -86, -85,
742 -84, -82, -81, -79, -78, -76, -75, -73,
743 -71, -70, -68, -67, -65, -63, -62, -60,
744 -58, -56, -55, -53, -51, -49, -47, -45,
745 -44, -42, -40, -38, -36, -34, -32, -30,
746 -28, -26, -24, -22, -20, -18, -16, -14,
747 -12, -10, -8, -6, -4, -2, 0, 1,
748 3, 5, 7, 9, 11, 13, 15, 17,
749 19, 21, 23, 25, 27, 29, 31, 33,
750 35, 37, 39, 41, 43, 45, 46, 48,
751 50, 52, 54, 55, 57, 59, 61, 62,
752 64, 66, 67, 69, 71, 72, 74, 75,
753 77, 78, 80, 81, 83, 84, 86, 87,
754 88, 90, 91, 92, 93, 95, 96, 97,
755 98, 99, 100, 101, 102, 103, 104, 105,
756 106, 106, 107, 108, 109, 109, 110, 111,
757 111, 112, 112, 113, 113, 114, 114, 114,
758 115, 115, 115, 115, 116, 116, 116, 116,
759 116, 116, 116, 116, 116, 115, 115, 115,
760 115, 114, 114, 114, 113, 113, 112, 112,
761 111, 111, 110, 110, 109, 108, 108, 107,
762 106, 105, 104, 103, 102, 101, 100, 99,
763 98, 97, 96, 95, 94, 93, 91, 90,
764 89, 88, 86, 85, 84, 82, 81, 79,
765 78, 76, 75, 73, 71, 70, 68, 67,
766 65, 63, 62, 60, 58, 56, 55, 53,
767 51, 49, 47, 45, 44, 42, 40, 38,
768 36, 34, 32, 30, 28, 26, 24, 22,
769 20, 18, 16, 14, 12, 10, 8, 6,
770 4, 2, 0, -1, -3, -5, -7, -9, -11
771};
772
773static u16 i2c_ident[] = {
774 V4L2_IDENT_OV9650,
775 V4L2_IDENT_OV9655,
776 V4L2_IDENT_SOI968,
777 V4L2_IDENT_OV7660,
778 V4L2_IDENT_OV7670,
779 V4L2_IDENT_MT9V011,
780 V4L2_IDENT_MT9V111,
781 V4L2_IDENT_MT9V112,
782 V4L2_IDENT_MT9M001C12ST,
783 V4L2_IDENT_MT9M111,
784 V4L2_IDENT_MT9M112,
785 V4L2_IDENT_HV7131R,
786};
787
788static u16 bridge_init[][2] = {
789 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
790 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
791 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
792 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
793 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
794 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
795 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
796 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
797 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
798 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
799 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
800 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
801 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
802 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
803 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
804 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
805 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
806 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
807 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
808 {0x1007, 0x00}
809};
810
811/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
812static u8 ov_gain[] = {
813 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
814 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
815 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
816 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
817 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
818 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
819 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
820 0x70 /* 8x */
821};
822
823/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
824static u16 micron1_gain[] = {
825 /* 1x 1.25x 1.5x 1.75x */
826 0x0020, 0x0028, 0x0030, 0x0038,
827 /* 2x 2.25x 2.5x 2.75x */
828 0x00a0, 0x00a4, 0x00a8, 0x00ac,
829 /* 3x 3.25x 3.5x 3.75x */
830 0x00b0, 0x00b4, 0x00b8, 0x00bc,
831 /* 4x 4.25x 4.5x 4.75x */
832 0x00c0, 0x00c4, 0x00c8, 0x00cc,
833 /* 5x 5.25x 5.5x 5.75x */
834 0x00d0, 0x00d4, 0x00d8, 0x00dc,
835 /* 6x 6.25x 6.5x 6.75x */
836 0x00e0, 0x00e4, 0x00e8, 0x00ec,
837 /* 7x 7.25x 7.5x 7.75x */
838 0x00f0, 0x00f4, 0x00f8, 0x00fc,
839 /* 8x */
840 0x01c0
841};
842
843/* mt9m001 sensor uses a different gain formula then other micron sensors */
844/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
845static u16 micron2_gain[] = {
846 /* 1x 1.25x 1.5x 1.75x */
847 0x0008, 0x000a, 0x000c, 0x000e,
848 /* 2x 2.25x 2.5x 2.75x */
849 0x0010, 0x0012, 0x0014, 0x0016,
850 /* 3x 3.25x 3.5x 3.75x */
851 0x0018, 0x001a, 0x001c, 0x001e,
852 /* 4x 4.25x 4.5x 4.75x */
853 0x0020, 0x0051, 0x0052, 0x0053,
854 /* 5x 5.25x 5.5x 5.75x */
855 0x0054, 0x0055, 0x0056, 0x0057,
856 /* 6x 6.25x 6.5x 6.75x */
857 0x0058, 0x0059, 0x005a, 0x005b,
858 /* 7x 7.25x 7.5x 7.75x */
859 0x005c, 0x005d, 0x005e, 0x005f,
860 /* 8x */
861 0x0060
862};
863
864/* Gain = .5 + bit[7:0] / 16 */
865static u8 hv7131r_gain[] = {
866 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
867 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
868 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
869 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
870 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
871 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
872 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
873 0x78 /* 8x */
874};
875
876static struct i2c_reg_u8 soi968_init[] = {
877 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
878 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
879 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
880 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
881 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
882 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
883 {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
884 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
885 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
886 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
887 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
888};
889
890static struct i2c_reg_u8 ov7660_init[] = {
891 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
892 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
893 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
894 /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
895 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
896 {0x17, 0x10}, {0x18, 0x61},
897 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
898 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
899 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
900};
901
902static struct i2c_reg_u8 ov7670_init[] = {
903 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
904 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
905 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
906 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
907 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
908 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
909 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
910 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
911 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
912 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
913 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
914 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
915 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
916 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
917 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
918 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
919 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
920 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
921 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
922 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
923 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
924 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
925 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
926 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
927 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
928 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
929 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
930 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
931 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
932 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
933 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
934 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
935 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
936 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
937 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
938 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
939 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
940 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
941 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
942 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
943 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
944 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
945 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
946 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
947 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
948 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
949 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
950 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
951 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
952 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
953 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
954 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
955 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
956 {0x93, 0x00},
957};
958
959static struct i2c_reg_u8 ov9650_init[] = {
960 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
961 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
962 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
963 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
964 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
965 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
966 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
967 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
968 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
969 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
970 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
971 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
972 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
973 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
974 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
975 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
976 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
977 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
978 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
979 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
980 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
981 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
982 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
983 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
984 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
985 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
986 {0xaa, 0x92}, {0xab, 0x0a},
987};
988
989static struct i2c_reg_u8 ov9655_init[] = {
990 {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
991 {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
992 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
993 {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
994 {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
995 {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
996 {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
997 {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
998 {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
999 {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
1000 {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
1001 {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
1002 {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
1003 {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
1004 {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
1005 {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
1006 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
1007 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
1008 {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
1009 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
1010 {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
1011 {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
1012 {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
1013 {0x04, 0x03}, {0x00, 0x13},
1014};
1015
1016static struct i2c_reg_u16 mt9v112_init[] = {
1017 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
1018 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
1019 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
1020 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
1021 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
1022 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
1023 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
1024 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
1025 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
1026 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1027 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
1028 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1029 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
1030 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
1031 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
1032 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
1033};
1034
1035static struct i2c_reg_u16 mt9v111_init[] = {
1036 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
1037 {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
1038 {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
1039 {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
1040 {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
1041 {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
1042 {0x0e, 0x0008}, {0x20, 0x0000}
1043};
1044
1045static struct i2c_reg_u16 mt9v011_init[] = {
1046 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
1047 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
1048 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
1049 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
1050 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
1051 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
1052 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
1053 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
1054 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
1055 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
1056 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1057 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1058 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1059 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1060 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1061 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1062 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1063 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1064 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1065 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1066 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1067 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1068 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1069 {0x06, 0x0029}, {0x05, 0x0009},
1070};
1071
1072static struct i2c_reg_u16 mt9m001_init[] = {
1073 {0x0d, 0x0001},
1074 {0x0d, 0x0000},
1075 {0x04, 0x0500}, /* hres = 1280 */
1076 {0x03, 0x0400}, /* vres = 1024 */
1077 {0x20, 0x1100},
1078 {0x06, 0x0010},
1079 {0x2b, 0x0024},
1080 {0x2e, 0x0024},
1081 {0x35, 0x0024},
1082 {0x2d, 0x0020},
1083 {0x2c, 0x0020},
1084 {0x09, 0x0ad4},
1085 {0x35, 0x0057},
1086};
1087
1088static struct i2c_reg_u16 mt9m111_init[] = {
1089 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1090 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1091 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1092 {0xf0, 0x0000},
1093};
1094
1095static struct i2c_reg_u16 mt9m112_init[] = {
1096 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
1097 {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
1098 {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
1099 {0xf0, 0x0000},
1100};
1101
1102static struct i2c_reg_u8 hv7131r_init[] = {
1103 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1104 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1105 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1106 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1107 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1108 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1109 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1110 {0x23, 0x09}, {0x01, 0x08},
1111};
1112
1113static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
1114{
1115 struct usb_device *dev = gspca_dev->dev;
1116 int result;
1117 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1118 0x00,
1119 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1120 reg,
1121 0x00,
1122 gspca_dev->usb_buf,
1123 length,
1124 500);
1125 if (unlikely(result < 0 || result != length)) {
1126 err("Read register failed 0x%02X", reg);
1127 return -EIO;
1128 }
1129 return 0;
1130}
1131
1132static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
1133 const u8 *buffer, int length)
1134{
1135 struct usb_device *dev = gspca_dev->dev;
1136 int result;
1137 memcpy(gspca_dev->usb_buf, buffer, length);
1138 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1139 0x08,
1140 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1141 reg,
1142 0x00,
1143 gspca_dev->usb_buf,
1144 length,
1145 500);
1146 if (unlikely(result < 0 || result != length)) {
1147 err("Write register failed index 0x%02X", reg);
1148 return -EIO;
1149 }
1150 return 0;
1151}
1152
1153static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
1154{
1155 u8 data[1] = {value};
1156 return reg_w(gspca_dev, reg, data, 1);
1157}
1158
1159static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
1160{
1161 int i;
1162 reg_w(gspca_dev, 0x10c0, buffer, 8);
1163 for (i = 0; i < 5; i++) {
1164 reg_r(gspca_dev, 0x10c0, 1);
1165 if (gspca_dev->usb_buf[0] & 0x04) {
1166 if (gspca_dev->usb_buf[0] & 0x08)
1167 return -EIO;
1168 return 0;
1169 }
1170 msleep(1);
1171 }
1172 return -EIO;
1173}
1174
1175static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1176{
1177 struct sd *sd = (struct sd *) gspca_dev;
1178
1179 u8 row[8];
1180
1181 /*
1182 * from the point of view of the bridge, the length
1183 * includes the address
1184 */
1185 row[0] = 0x81 | (2 << 4);
1186 row[1] = sd->i2c_addr;
1187 row[2] = reg;
1188 row[3] = val;
1189 row[4] = 0x00;
1190 row[5] = 0x00;
1191 row[6] = 0x00;
1192 row[7] = 0x10;
1193
1194 return i2c_w(gspca_dev, row);
1195}
1196
1197static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
1198{
1199 struct sd *sd = (struct sd *) gspca_dev;
1200 u8 row[8];
1201
1202 /*
1203 * from the point of view of the bridge, the length
1204 * includes the address
1205 */
1206 row[0] = 0x81 | (3 << 4);
1207 row[1] = sd->i2c_addr;
1208 row[2] = reg;
1209 row[3] = (val >> 8) & 0xff;
1210 row[4] = val & 0xff;
1211 row[5] = 0x00;
1212 row[6] = 0x00;
1213 row[7] = 0x10;
1214
1215 return i2c_w(gspca_dev, row);
1216}
1217
1218static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
1219{
1220 struct sd *sd = (struct sd *) gspca_dev;
1221 u8 row[8];
1222
1223 row[0] = 0x81 | (1 << 4);
1224 row[1] = sd->i2c_addr;
1225 row[2] = reg;
1226 row[3] = 0;
1227 row[4] = 0;
1228 row[5] = 0;
1229 row[6] = 0;
1230 row[7] = 0x10;
1231 if (i2c_w(gspca_dev, row) < 0)
1232 return -EIO;
1233 row[0] = 0x81 | (1 << 4) | 0x02;
1234 row[2] = 0;
1235 if (i2c_w(gspca_dev, row) < 0)
1236 return -EIO;
1237 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1238 return -EIO;
1239 *val = gspca_dev->usb_buf[4];
1240 return 0;
1241}
1242
1243static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
1244{
1245 struct sd *sd = (struct sd *) gspca_dev;
1246 u8 row[8];
1247
1248 row[0] = 0x81 | (1 << 4);
1249 row[1] = sd->i2c_addr;
1250 row[2] = reg;
1251 row[3] = 0;
1252 row[4] = 0;
1253 row[5] = 0;
1254 row[6] = 0;
1255 row[7] = 0x10;
1256 if (i2c_w(gspca_dev, row) < 0)
1257 return -EIO;
1258 row[0] = 0x81 | (2 << 4) | 0x02;
1259 row[2] = 0;
1260 if (i2c_w(gspca_dev, row) < 0)
1261 return -EIO;
1262 if (reg_r(gspca_dev, 0x10c2, 5) < 0)
1263 return -EIO;
1264 *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1265 return 0;
1266}
1267
1268static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1269{
1270 int i;
1271 u16 id;
1272 struct sd *sd = (struct sd *) gspca_dev;
1273
1274 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1275 return -EINVAL;
1276
1277 if (id != 0x7fa2) {
1278 err("sensor id for ov9650 doesn't match (0x%04x)", id);
1279 return -ENODEV;
1280 }
1281
1282 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
1283 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1284 ov9650_init[i].val) < 0) {
1285 err("OV9650 sensor initialization failed");
1286 return -ENODEV;
1287 }
1288 }
1289 sd->hstart = 1;
1290 sd->vstart = 7;
1291 return 0;
1292}
1293
1294static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1295{
1296 int i;
1297 struct sd *sd = (struct sd *) gspca_dev;
1298
1299 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
1300 if (i2c_w1(gspca_dev, ov9655_init[i].reg,
1301 ov9655_init[i].val) < 0) {
1302 err("OV9655 sensor initialization failed");
1303 return -ENODEV;
1304 }
1305 }
1306 /* disable hflip and vflip */
1307 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1308 sd->hstart = 1;
1309 sd->vstart = 2;
1310 return 0;
1311}
1312
1313static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1314{
1315 int i;
1316 struct sd *sd = (struct sd *) gspca_dev;
1317
1318 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
1319 if (i2c_w1(gspca_dev, soi968_init[i].reg,
1320 soi968_init[i].val) < 0) {
1321 err("SOI968 sensor initialization failed");
1322 return -ENODEV;
1323 }
1324 }
1325 /* disable hflip and vflip */
1326 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX)
1327 | (1 << EXPOSURE_IDX);
1328 sd->hstart = 60;
1329 sd->vstart = 11;
1330 return 0;
1331}
1332
1333static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1334{
1335 int i;
1336 struct sd *sd = (struct sd *) gspca_dev;
1337
1338 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
1339 if (i2c_w1(gspca_dev, ov7660_init[i].reg,
1340 ov7660_init[i].val) < 0) {
1341 err("OV7660 sensor initialization failed");
1342 return -ENODEV;
1343 }
1344 }
1345 sd->hstart = 3;
1346 sd->vstart = 3;
1347 return 0;
1348}
1349
1350static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1351{
1352 int i;
1353 struct sd *sd = (struct sd *) gspca_dev;
1354
1355 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
1356 if (i2c_w1(gspca_dev, ov7670_init[i].reg,
1357 ov7670_init[i].val) < 0) {
1358 err("OV7670 sensor initialization failed");
1359 return -ENODEV;
1360 }
1361 }
1362 /* disable hflip and vflip */
1363 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1364 sd->hstart = 0;
1365 sd->vstart = 1;
1366 return 0;
1367}
1368
1369static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1370{
1371 struct sd *sd = (struct sd *) gspca_dev;
1372 int i;
1373 u16 value;
1374 int ret;
1375
1376 sd->i2c_addr = 0x5d;
1377 ret = i2c_r2(gspca_dev, 0xff, &value);
1378 if ((ret == 0) && (value == 0x8243)) {
1379 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
1380 if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
1381 mt9v011_init[i].val) < 0) {
1382 err("MT9V011 sensor initialization failed");
1383 return -ENODEV;
1384 }
1385 }
1386 sd->hstart = 2;
1387 sd->vstart = 2;
1388 sd->sensor = SENSOR_MT9V011;
1389 info("MT9V011 sensor detected");
1390 return 0;
1391 }
1392
1393 sd->i2c_addr = 0x5c;
1394 i2c_w2(gspca_dev, 0x01, 0x0004);
1395 ret = i2c_r2(gspca_dev, 0xff, &value);
1396 if ((ret == 0) && (value == 0x823a)) {
1397 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
1398 if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
1399 mt9v111_init[i].val) < 0) {
1400 err("MT9V111 sensor initialization failed");
1401 return -ENODEV;
1402 }
1403 }
1404 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX)
1405 | (1 << AUTOGAIN_IDX)
1406 | (1 << GAIN_IDX);
1407 sd->hstart = 2;
1408 sd->vstart = 2;
1409 sd->sensor = SENSOR_MT9V111;
1410 info("MT9V111 sensor detected");
1411 return 0;
1412 }
1413
1414 sd->i2c_addr = 0x5d;
1415 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1416 if (ret < 0) {
1417 sd->i2c_addr = 0x48;
1418 i2c_w2(gspca_dev, 0xf0, 0x0000);
1419 }
1420 ret = i2c_r2(gspca_dev, 0x00, &value);
1421 if ((ret == 0) && (value == 0x1229)) {
1422 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
1423 if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
1424 mt9v112_init[i].val) < 0) {
1425 err("MT9V112 sensor initialization failed");
1426 return -ENODEV;
1427 }
1428 }
1429 sd->hstart = 6;
1430 sd->vstart = 2;
1431 sd->sensor = SENSOR_MT9V112;
1432 info("MT9V112 sensor detected");
1433 return 0;
1434 }
1435
1436 return -ENODEV;
1437}
1438
1439static int mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1440{
1441 struct sd *sd = (struct sd *) gspca_dev;
1442 int i;
1443 for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) {
1444 if (i2c_w2(gspca_dev, mt9m112_init[i].reg,
1445 mt9m112_init[i].val) < 0) {
1446 err("MT9M112 sensor initialization failed");
1447 return -ENODEV;
1448 }
1449 }
1450 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1451 | (1 << GAIN_IDX);
1452 sd->hstart = 0;
1453 sd->vstart = 2;
1454 return 0;
1455}
1456
1457static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1458{
1459 struct sd *sd = (struct sd *) gspca_dev;
1460 int i;
1461 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
1462 if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
1463 mt9m111_init[i].val) < 0) {
1464 err("MT9M111 sensor initialization failed");
1465 return -ENODEV;
1466 }
1467 }
1468 gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)
1469 | (1 << GAIN_IDX);
1470 sd->hstart = 0;
1471 sd->vstart = 2;
1472 return 0;
1473}
1474
1475static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1476{
1477 struct sd *sd = (struct sd *) gspca_dev;
1478 int i;
1479 u16 id;
1480
1481 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1482 return -EINVAL;
1483
1484 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1485 switch (id) {
1486 case 0x8411:
1487 case 0x8421:
1488 info("MT9M001 color sensor detected");
1489 break;
1490 case 0x8431:
1491 info("MT9M001 mono sensor detected");
1492 break;
1493 default:
1494 err("No MT9M001 chip detected, ID = %x\n", id);
1495 return -ENODEV;
1496 }
1497
1498 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
1499 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1500 mt9m001_init[i].val) < 0) {
1501 err("MT9M001 sensor initialization failed");
1502 return -ENODEV;
1503 }
1504 }
1505 /* disable hflip and vflip */
1506 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1507 sd->hstart = 1;
1508 sd->vstart = 1;
1509 return 0;
1510}
1511
1512static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1513{
1514 int i;
1515 struct sd *sd = (struct sd *) gspca_dev;
1516
1517 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
1518 if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
1519 hv7131r_init[i].val) < 0) {
1520 err("HV7131R Sensor initialization failed");
1521 return -ENODEV;
1522 }
1523 }
1524 sd->hstart = 0;
1525 sd->vstart = 1;
1526 return 0;
1527}
1528
1529static int set_cmatrix(struct gspca_dev *gspca_dev)
1530{
1531 struct sd *sd = (struct sd *) gspca_dev;
1532 s32 hue_coord, hue_index = 180 + sd->hue;
1533 u8 cmatrix[21];
1534
1535 memset(cmatrix, 0, sizeof cmatrix);
1536 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1537 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1538 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1539 cmatrix[18] = sd->brightness - 0x80;
1540
1541 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
1542 cmatrix[6] = hue_coord;
1543 cmatrix[7] = (hue_coord >> 8) & 0x0f;
1544
1545 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
1546 cmatrix[8] = hue_coord;
1547 cmatrix[9] = (hue_coord >> 8) & 0x0f;
1548
1549 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
1550 cmatrix[10] = hue_coord;
1551 cmatrix[11] = (hue_coord >> 8) & 0x0f;
1552
1553 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
1554 cmatrix[12] = hue_coord;
1555 cmatrix[13] = (hue_coord >> 8) & 0x0f;
1556
1557 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
1558 cmatrix[14] = hue_coord;
1559 cmatrix[15] = (hue_coord >> 8) & 0x0f;
1560
1561 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
1562 cmatrix[16] = hue_coord;
1563 cmatrix[17] = (hue_coord >> 8) & 0x0f;
1564
1565 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1566}
1567
1568static int set_gamma(struct gspca_dev *gspca_dev)
1569{
1570 struct sd *sd = (struct sd *) gspca_dev;
1571 u8 gamma[17];
1572 u8 gval = sd->gamma * 0xb8 / 0x100;
1573
1574
1575 gamma[0] = 0x0a;
1576 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1577 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1578 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1579 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1580 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1581 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1582 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1583 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1584 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1585 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1586 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1587 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1588 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1589 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1590 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1591 gamma[16] = 0xf5;
1592
1593 return reg_w(gspca_dev, 0x1190, gamma, 17);
1594}
1595
1596static int set_redblue(struct gspca_dev *gspca_dev)
1597{
1598 struct sd *sd = (struct sd *) gspca_dev;
1599 reg_w1(gspca_dev, 0x118c, sd->red);
1600 reg_w1(gspca_dev, 0x118f, sd->blue);
1601 return 0;
1602}
1603
1604static int set_hvflip(struct gspca_dev *gspca_dev)
1605{
1606 u8 value, tslb, hflip, vflip;
1607 u16 value2;
1608 struct sd *sd = (struct sd *) gspca_dev;
1609
1610 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1611 hflip = !sd->hflip;
1612 vflip = !sd->vflip;
1613 } else {
1614 hflip = sd->hflip;
1615 vflip = sd->vflip;
1616 }
1617
1618 switch (sd->sensor) {
1619 case SENSOR_OV7660:
1620 value = 0x01;
1621 if (hflip)
1622 value |= 0x20;
1623 if (vflip) {
1624 value |= 0x10;
1625 sd->vstart = 2;
1626 } else
1627 sd->vstart = 3;
1628 reg_w1(gspca_dev, 0x1182, sd->vstart);
1629 i2c_w1(gspca_dev, 0x1e, value);
1630 break;
1631 case SENSOR_OV9650:
1632 i2c_r1(gspca_dev, 0x1e, &value);
1633 value &= ~0x30;
1634 tslb = 0x01;
1635 if (hflip)
1636 value |= 0x20;
1637 if (vflip) {
1638 value |= 0x10;
1639 tslb = 0x49;
1640 }
1641 i2c_w1(gspca_dev, 0x1e, value);
1642 i2c_w1(gspca_dev, 0x3a, tslb);
1643 break;
1644 case SENSOR_MT9V111:
1645 case SENSOR_MT9V011:
1646 i2c_r2(gspca_dev, 0x20, &value2);
1647 value2 &= ~0xc0a0;
1648 if (hflip)
1649 value2 |= 0x8080;
1650 if (vflip)
1651 value2 |= 0x4020;
1652 i2c_w2(gspca_dev, 0x20, value2);
1653 break;
1654 case SENSOR_MT9M112:
1655 case SENSOR_MT9M111:
1656 case SENSOR_MT9V112:
1657 i2c_r2(gspca_dev, 0x20, &value2);
1658 value2 &= ~0x0003;
1659 if (hflip)
1660 value2 |= 0x0002;
1661 if (vflip)
1662 value2 |= 0x0001;
1663 i2c_w2(gspca_dev, 0x20, value2);
1664 break;
1665 case SENSOR_HV7131R:
1666 i2c_r1(gspca_dev, 0x01, &value);
1667 value &= ~0x03;
1668 if (vflip)
1669 value |= 0x01;
1670 if (hflip)
1671 value |= 0x02;
1672 i2c_w1(gspca_dev, 0x01, value);
1673 break;
1674 }
1675 return 0;
1676}
1677
1678static int set_exposure(struct gspca_dev *gspca_dev)
1679{
1680 struct sd *sd = (struct sd *) gspca_dev;
1681 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1682 switch (sd->sensor) {
1683 case SENSOR_OV7660:
1684 case SENSOR_OV7670:
1685 case SENSOR_OV9655:
1686 case SENSOR_OV9650:
1687 exp[0] |= (3 << 4);
1688 exp[2] = 0x2d;
1689 exp[3] = sd->exposure & 0xff;
1690 exp[4] = sd->exposure >> 8;
1691 break;
1692 case SENSOR_MT9M001:
1693 case SENSOR_MT9V112:
1694 case SENSOR_MT9V011:
1695 exp[0] |= (3 << 4);
1696 exp[2] = 0x09;
1697 exp[3] = sd->exposure >> 8;
1698 exp[4] = sd->exposure & 0xff;
1699 break;
1700 case SENSOR_HV7131R:
1701 exp[0] |= (4 << 4);
1702 exp[2] = 0x25;
1703 exp[3] = (sd->exposure >> 5) & 0xff;
1704 exp[4] = (sd->exposure << 3) & 0xff;
1705 exp[5] = 0;
1706 break;
1707 default:
1708 return 0;
1709 }
1710 i2c_w(gspca_dev, exp);
1711 return 0;
1712}
1713
1714static int set_gain(struct gspca_dev *gspca_dev)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1718 switch (sd->sensor) {
1719 case SENSOR_OV7660:
1720 case SENSOR_OV7670:
1721 case SENSOR_SOI968:
1722 case SENSOR_OV9655:
1723 case SENSOR_OV9650:
1724 gain[0] |= (2 << 4);
1725 gain[3] = ov_gain[sd->gain];
1726 break;
1727 case SENSOR_MT9V011:
1728 gain[0] |= (3 << 4);
1729 gain[2] = 0x35;
1730 gain[3] = micron1_gain[sd->gain] >> 8;
1731 gain[4] = micron1_gain[sd->gain] & 0xff;
1732 break;
1733 case SENSOR_MT9V112:
1734 gain[0] |= (3 << 4);
1735 gain[2] = 0x2f;
1736 gain[3] = micron1_gain[sd->gain] >> 8;
1737 gain[4] = micron1_gain[sd->gain] & 0xff;
1738 break;
1739 case SENSOR_MT9M001:
1740 gain[0] |= (3 << 4);
1741 gain[2] = 0x2f;
1742 gain[3] = micron2_gain[sd->gain] >> 8;
1743 gain[4] = micron2_gain[sd->gain] & 0xff;
1744 break;
1745 case SENSOR_HV7131R:
1746 gain[0] |= (2 << 4);
1747 gain[2] = 0x30;
1748 gain[3] = hv7131r_gain[sd->gain];
1749 break;
1750 default:
1751 return 0;
1752 }
1753 i2c_w(gspca_dev, gain);
1754 return 0;
1755}
1756
1757static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1758{
1759 struct sd *sd = (struct sd *) gspca_dev;
1760
1761 sd->brightness = val;
1762 if (gspca_dev->streaming)
1763 return set_cmatrix(gspca_dev);
1764 return 0;
1765}
1766
1767static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1768{
1769 struct sd *sd = (struct sd *) gspca_dev;
1770 *val = sd->brightness;
1771 return 0;
1772}
1773
1774
1775static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1776{
1777 struct sd *sd = (struct sd *) gspca_dev;
1778
1779 sd->contrast = val;
1780 if (gspca_dev->streaming)
1781 return set_cmatrix(gspca_dev);
1782 return 0;
1783}
1784
1785static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1786{
1787 struct sd *sd = (struct sd *) gspca_dev;
1788 *val = sd->contrast;
1789 return 0;
1790}
1791
1792static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1793{
1794 struct sd *sd = (struct sd *) gspca_dev;
1795
1796 sd->saturation = val;
1797 if (gspca_dev->streaming)
1798 return set_cmatrix(gspca_dev);
1799 return 0;
1800}
1801
1802static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1803{
1804 struct sd *sd = (struct sd *) gspca_dev;
1805 *val = sd->saturation;
1806 return 0;
1807}
1808
1809static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1810{
1811 struct sd *sd = (struct sd *) gspca_dev;
1812
1813 sd->hue = val;
1814 if (gspca_dev->streaming)
1815 return set_cmatrix(gspca_dev);
1816 return 0;
1817}
1818
1819static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1820{
1821 struct sd *sd = (struct sd *) gspca_dev;
1822 *val = sd->hue;
1823 return 0;
1824}
1825
1826static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1827{
1828 struct sd *sd = (struct sd *) gspca_dev;
1829
1830 sd->gamma = val;
1831 if (gspca_dev->streaming)
1832 return set_gamma(gspca_dev);
1833 return 0;
1834}
1835
1836static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1837{
1838 struct sd *sd = (struct sd *) gspca_dev;
1839 *val = sd->gamma;
1840 return 0;
1841}
1842
1843static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1844{
1845 struct sd *sd = (struct sd *) gspca_dev;
1846
1847 sd->red = val;
1848 if (gspca_dev->streaming)
1849 return set_redblue(gspca_dev);
1850 return 0;
1851}
1852
1853static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1854{
1855 struct sd *sd = (struct sd *) gspca_dev;
1856 *val = sd->red;
1857 return 0;
1858}
1859
1860static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1861{
1862 struct sd *sd = (struct sd *) gspca_dev;
1863
1864 sd->blue = val;
1865 if (gspca_dev->streaming)
1866 return set_redblue(gspca_dev);
1867 return 0;
1868}
1869
1870static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1871{
1872 struct sd *sd = (struct sd *) gspca_dev;
1873 *val = sd->blue;
1874 return 0;
1875}
1876
1877static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1878{
1879 struct sd *sd = (struct sd *) gspca_dev;
1880
1881 sd->hflip = val;
1882 if (gspca_dev->streaming)
1883 return set_hvflip(gspca_dev);
1884 return 0;
1885}
1886
1887static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1888{
1889 struct sd *sd = (struct sd *) gspca_dev;
1890 *val = sd->hflip;
1891 return 0;
1892}
1893
1894static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1895{
1896 struct sd *sd = (struct sd *) gspca_dev;
1897
1898 sd->vflip = val;
1899 if (gspca_dev->streaming)
1900 return set_hvflip(gspca_dev);
1901 return 0;
1902}
1903
1904static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1905{
1906 struct sd *sd = (struct sd *) gspca_dev;
1907 *val = sd->vflip;
1908 return 0;
1909}
1910
1911static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1912{
1913 struct sd *sd = (struct sd *) gspca_dev;
1914
1915 sd->exposure = val;
1916 if (gspca_dev->streaming)
1917 return set_exposure(gspca_dev);
1918 return 0;
1919}
1920
1921static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1922{
1923 struct sd *sd = (struct sd *) gspca_dev;
1924 *val = sd->exposure;
1925 return 0;
1926}
1927
1928static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1929{
1930 struct sd *sd = (struct sd *) gspca_dev;
1931
1932 sd->gain = val;
1933 if (gspca_dev->streaming)
1934 return set_gain(gspca_dev);
1935 return 0;
1936}
1937
1938static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1939{
1940 struct sd *sd = (struct sd *) gspca_dev;
1941 *val = sd->gain;
1942 return 0;
1943}
1944
1945static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1946{
1947 struct sd *sd = (struct sd *) gspca_dev;
1948 sd->auto_exposure = val;
1949 return 0;
1950}
1951
1952static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1953{
1954 struct sd *sd = (struct sd *) gspca_dev;
1955 *val = sd->auto_exposure;
1956 return 0;
1957}
1958
1959#ifdef CONFIG_VIDEO_ADV_DEBUG
1960static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1961 struct v4l2_dbg_register *reg)
1962{
1963 struct sd *sd = (struct sd *) gspca_dev;
1964 switch (reg->match.type) {
1965 case V4L2_CHIP_MATCH_HOST:
1966 if (reg->match.addr != 0)
1967 return -EINVAL;
1968 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1969 return -EINVAL;
1970 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1971 return -EINVAL;
1972 reg->val = gspca_dev->usb_buf[0];
1973 return 0;
1974 case V4L2_CHIP_MATCH_I2C_ADDR:
1975 if (reg->match.addr != sd->i2c_addr)
1976 return -EINVAL;
1977 if (sd->sensor >= SENSOR_MT9V011 &&
1978 sd->sensor <= SENSOR_MT9M112) {
1979 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1980 return -EINVAL;
1981 } else {
1982 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1983 return -EINVAL;
1984 }
1985 return 0;
1986 }
1987 return -EINVAL;
1988}
1989
1990static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1991 struct v4l2_dbg_register *reg)
1992{
1993 struct sd *sd = (struct sd *) gspca_dev;
1994 switch (reg->match.type) {
1995 case V4L2_CHIP_MATCH_HOST:
1996 if (reg->match.addr != 0)
1997 return -EINVAL;
1998 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1999 return -EINVAL;
2000 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
2001 return -EINVAL;
2002 return 0;
2003 case V4L2_CHIP_MATCH_I2C_ADDR:
2004 if (reg->match.addr != sd->i2c_addr)
2005 return -EINVAL;
2006 if (sd->sensor >= SENSOR_MT9V011 &&
2007 sd->sensor <= SENSOR_MT9M112) {
2008 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
2009 return -EINVAL;
2010 } else {
2011 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
2012 return -EINVAL;
2013 }
2014 return 0;
2015 }
2016 return -EINVAL;
2017}
2018#endif
2019
2020static int sd_chip_ident(struct gspca_dev *gspca_dev,
2021 struct v4l2_dbg_chip_ident *chip)
2022{
2023 struct sd *sd = (struct sd *) gspca_dev;
2024
2025 switch (chip->match.type) {
2026 case V4L2_CHIP_MATCH_HOST:
2027 if (chip->match.addr != 0)
2028 return -EINVAL;
2029 chip->revision = 0;
2030 chip->ident = V4L2_IDENT_SN9C20X;
2031 return 0;
2032 case V4L2_CHIP_MATCH_I2C_ADDR:
2033 if (chip->match.addr != sd->i2c_addr)
2034 return -EINVAL;
2035 chip->revision = 0;
2036 chip->ident = i2c_ident[sd->sensor];
2037 return 0;
2038 }
2039 return -EINVAL;
2040}
2041
2042static int sd_config(struct gspca_dev *gspca_dev,
2043 const struct usb_device_id *id)
2044{
2045 struct sd *sd = (struct sd *) gspca_dev;
2046 struct cam *cam;
2047
2048 cam = &gspca_dev->cam;
2049
2050 sd->sensor = (id->driver_info >> 8) & 0xff;
2051 sd->i2c_addr = id->driver_info & 0xff;
2052 sd->flags = (id->driver_info >> 16) & 0xff;
2053
2054 switch (sd->sensor) {
2055 case SENSOR_MT9M112:
2056 case SENSOR_MT9M111:
2057 case SENSOR_OV9650:
2058 case SENSOR_SOI968:
2059 cam->cam_mode = sxga_mode;
2060 cam->nmodes = ARRAY_SIZE(sxga_mode);
2061 break;
2062 case SENSOR_MT9M001:
2063 cam->cam_mode = mono_mode;
2064 cam->nmodes = ARRAY_SIZE(mono_mode);
2065 break;
2066 default:
2067 cam->cam_mode = vga_mode;
2068 cam->nmodes = ARRAY_SIZE(vga_mode);
2069 break;
2070 }
2071
2072 sd->old_step = 0;
2073 sd->older_step = 0;
2074 sd->exposure_step = 16;
2075
2076 sd->brightness = BRIGHTNESS_DEFAULT;
2077 sd->contrast = CONTRAST_DEFAULT;
2078 sd->saturation = SATURATION_DEFAULT;
2079 sd->hue = HUE_DEFAULT;
2080 sd->gamma = GAMMA_DEFAULT;
2081 sd->red = RED_DEFAULT;
2082 sd->blue = BLUE_DEFAULT;
2083
2084 sd->hflip = HFLIP_DEFAULT;
2085 sd->vflip = VFLIP_DEFAULT;
2086 sd->exposure = EXPOSURE_DEFAULT;
2087 sd->gain = GAIN_DEFAULT;
2088 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2089
2090 sd->quality = 95;
2091
2092 return 0;
2093}
2094
2095static int sd_init(struct gspca_dev *gspca_dev)
2096{
2097 struct sd *sd = (struct sd *) gspca_dev;
2098 int i;
2099 u8 value;
2100 u8 i2c_init[9] =
2101 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2102
2103 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2104 value = bridge_init[i][1];
2105 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2106 err("Device initialization failed");
2107 return -ENODEV;
2108 }
2109 }
2110
2111 if (sd->flags & LED_REVERSE)
2112 reg_w1(gspca_dev, 0x1006, 0x00);
2113 else
2114 reg_w1(gspca_dev, 0x1006, 0x20);
2115
2116 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2117 err("Device initialization failed");
2118 return -ENODEV;
2119 }
2120
2121 switch (sd->sensor) {
2122 case SENSOR_OV9650:
2123 if (ov9650_init_sensor(gspca_dev) < 0)
2124 return -ENODEV;
2125 info("OV9650 sensor detected");
2126 break;
2127 case SENSOR_OV9655:
2128 if (ov9655_init_sensor(gspca_dev) < 0)
2129 return -ENODEV;
2130 info("OV9655 sensor detected");
2131 break;
2132 case SENSOR_SOI968:
2133 if (soi968_init_sensor(gspca_dev) < 0)
2134 return -ENODEV;
2135 info("SOI968 sensor detected");
2136 break;
2137 case SENSOR_OV7660:
2138 if (ov7660_init_sensor(gspca_dev) < 0)
2139 return -ENODEV;
2140 info("OV7660 sensor detected");
2141 break;
2142 case SENSOR_OV7670:
2143 if (ov7670_init_sensor(gspca_dev) < 0)
2144 return -ENODEV;
2145 info("OV7670 sensor detected");
2146 break;
2147 case SENSOR_MT9VPRB:
2148 if (mt9v_init_sensor(gspca_dev) < 0)
2149 return -ENODEV;
2150 break;
2151 case SENSOR_MT9M111:
2152 if (mt9m111_init_sensor(gspca_dev) < 0)
2153 return -ENODEV;
2154 info("MT9M111 sensor detected");
2155 break;
2156 case SENSOR_MT9M112:
2157 if (mt9m112_init_sensor(gspca_dev) < 0)
2158 return -ENODEV;
2159 info("MT9M112 sensor detected");
2160 break;
2161 case SENSOR_MT9M001:
2162 if (mt9m001_init_sensor(gspca_dev) < 0)
2163 return -ENODEV;
2164 break;
2165 case SENSOR_HV7131R:
2166 if (hv7131r_init_sensor(gspca_dev) < 0)
2167 return -ENODEV;
2168 info("HV7131R sensor detected");
2169 break;
2170 default:
2171 info("Unsupported Sensor");
2172 return -ENODEV;
2173 }
2174
2175 return 0;
2176}
2177
2178static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2179{
2180 struct sd *sd = (struct sd *) gspca_dev;
2181 u8 value;
2182 switch (sd->sensor) {
2183 case SENSOR_SOI968:
2184 if (mode & MODE_SXGA) {
2185 i2c_w1(gspca_dev, 0x17, 0x1d);
2186 i2c_w1(gspca_dev, 0x18, 0xbd);
2187 i2c_w1(gspca_dev, 0x19, 0x01);
2188 i2c_w1(gspca_dev, 0x1a, 0x81);
2189 i2c_w1(gspca_dev, 0x12, 0x00);
2190 sd->hstart = 140;
2191 sd->vstart = 19;
2192 } else {
2193 i2c_w1(gspca_dev, 0x17, 0x13);
2194 i2c_w1(gspca_dev, 0x18, 0x63);
2195 i2c_w1(gspca_dev, 0x19, 0x01);
2196 i2c_w1(gspca_dev, 0x1a, 0x79);
2197 i2c_w1(gspca_dev, 0x12, 0x40);
2198 sd->hstart = 60;
2199 sd->vstart = 11;
2200 }
2201 break;
2202 case SENSOR_OV9650:
2203 if (mode & MODE_SXGA) {
2204 i2c_w1(gspca_dev, 0x17, 0x1b);
2205 i2c_w1(gspca_dev, 0x18, 0xbc);
2206 i2c_w1(gspca_dev, 0x19, 0x01);
2207 i2c_w1(gspca_dev, 0x1a, 0x82);
2208 i2c_r1(gspca_dev, 0x12, &value);
2209 i2c_w1(gspca_dev, 0x12, value & 0x07);
2210 } else {
2211 i2c_w1(gspca_dev, 0x17, 0x24);
2212 i2c_w1(gspca_dev, 0x18, 0xc5);
2213 i2c_w1(gspca_dev, 0x19, 0x00);
2214 i2c_w1(gspca_dev, 0x1a, 0x3c);
2215 i2c_r1(gspca_dev, 0x12, &value);
2216 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2217 }
2218 break;
2219 case SENSOR_MT9M112:
2220 case SENSOR_MT9M111:
2221 if (mode & MODE_SXGA) {
2222 i2c_w2(gspca_dev, 0xf0, 0x0002);
2223 i2c_w2(gspca_dev, 0xc8, 0x970b);
2224 i2c_w2(gspca_dev, 0xf0, 0x0000);
2225 } else {
2226 i2c_w2(gspca_dev, 0xf0, 0x0002);
2227 i2c_w2(gspca_dev, 0xc8, 0x8000);
2228 i2c_w2(gspca_dev, 0xf0, 0x0000);
2229 }
2230 break;
2231 }
2232}
2233
2234#define HW_WIN(mode, hstart, vstart) \
2235((const u8 []){hstart, 0, vstart, 0, \
2236(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2237(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2238
2239#define CLR_WIN(width, height) \
2240((const u8 [])\
2241{0, width >> 2, 0, height >> 1,\
2242((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2243
2244static int sd_start(struct gspca_dev *gspca_dev)
2245{
2246 struct sd *sd = (struct sd *) gspca_dev;
2247 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2248 int width = gspca_dev->width;
2249 int height = gspca_dev->height;
2250 u8 fmt, scale = 0;
2251
2252 jpeg_define(sd->jpeg_hdr, height, width,
2253 0x21);
2254 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2255
2256 if (mode & MODE_RAW)
2257 fmt = 0x2d;
2258 else if (mode & MODE_JPEG)
2259 fmt = 0x2c;
2260 else
2261 fmt = 0x2f; /* YUV 420 */
2262
2263 switch (mode & SCALE_MASK) {
2264 case SCALE_1280x1024:
2265 scale = 0xc0;
2266 info("Set 1280x1024");
2267 break;
2268 case SCALE_640x480:
2269 scale = 0x80;
2270 info("Set 640x480");
2271 break;
2272 case SCALE_320x240:
2273 scale = 0x90;
2274 info("Set 320x240");
2275 break;
2276 case SCALE_160x120:
2277 scale = 0xa0;
2278 info("Set 160x120");
2279 break;
2280 }
2281
2282 configure_sensor_output(gspca_dev, mode);
2283 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2284 reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
2285 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2286 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2287 reg_w1(gspca_dev, 0x1189, scale);
2288 reg_w1(gspca_dev, 0x10e0, fmt);
2289
2290 set_cmatrix(gspca_dev);
2291 set_gamma(gspca_dev);
2292 set_redblue(gspca_dev);
2293 set_gain(gspca_dev);
2294 set_exposure(gspca_dev);
2295 set_hvflip(gspca_dev);
2296
2297 reg_w1(gspca_dev, 0x1007, 0x20);
2298
2299 reg_r(gspca_dev, 0x1061, 1);
2300 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2301 return 0;
2302}
2303
2304static void sd_stopN(struct gspca_dev *gspca_dev)
2305{
2306 reg_w1(gspca_dev, 0x1007, 0x00);
2307
2308 reg_r(gspca_dev, 0x1061, 1);
2309 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2310}
2311
2312static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
2313{
2314 struct sd *sd = (struct sd *) gspca_dev;
2315 s16 new_exp;
2316
2317 /*
2318 * some hardcoded values are present
2319 * like those for maximal/minimal exposure
2320 * and exposure steps
2321 */
2322 if (avg_lum < MIN_AVG_LUM) {
2323 if (sd->exposure > 0x1770)
2324 return;
2325
2326 new_exp = sd->exposure + sd->exposure_step;
2327 if (new_exp > 0x1770)
2328 new_exp = 0x1770;
2329 if (new_exp < 0x10)
2330 new_exp = 0x10;
2331 sd->exposure = new_exp;
2332 set_exposure(gspca_dev);
2333
2334 sd->older_step = sd->old_step;
2335 sd->old_step = 1;
2336
2337 if (sd->old_step ^ sd->older_step)
2338 sd->exposure_step /= 2;
2339 else
2340 sd->exposure_step += 2;
2341 }
2342 if (avg_lum > MAX_AVG_LUM) {
2343 if (sd->exposure < 0x10)
2344 return;
2345 new_exp = sd->exposure - sd->exposure_step;
2346 if (new_exp > 0x1700)
2347 new_exp = 0x1770;
2348 if (new_exp < 0x10)
2349 new_exp = 0x10;
2350 sd->exposure = new_exp;
2351 set_exposure(gspca_dev);
2352 sd->older_step = sd->old_step;
2353 sd->old_step = 0;
2354
2355 if (sd->old_step ^ sd->older_step)
2356 sd->exposure_step /= 2;
2357 else
2358 sd->exposure_step += 2;
2359 }
2360}
2361
2362static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2363{
2364 struct sd *sd = (struct sd *) gspca_dev;
2365
2366 if (avg_lum < MIN_AVG_LUM) {
2367 if (sd->gain + 1 <= 28) {
2368 sd->gain++;
2369 set_gain(gspca_dev);
2370 }
2371 }
2372 if (avg_lum > MAX_AVG_LUM) {
2373 if (sd->gain > 0) {
2374 sd->gain--;
2375 set_gain(gspca_dev);
2376 }
2377 }
2378}
2379
2380static void sd_dqcallback(struct gspca_dev *gspca_dev)
2381{
2382 struct sd *sd = (struct sd *) gspca_dev;
2383 int avg_lum;
2384
2385 if (!sd->auto_exposure)
2386 return;
2387
2388 avg_lum = atomic_read(&sd->avg_lum);
2389 if (sd->sensor == SENSOR_SOI968)
2390 do_autogain(gspca_dev, avg_lum);
2391 else
2392 do_autoexposure(gspca_dev, avg_lum);
2393}
2394
2395#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2396static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2397 u8 *data, /* interrupt packet */
2398 int len) /* interrupt packet length */
2399{
2400 struct sd *sd = (struct sd *) gspca_dev;
2401 int ret = -EINVAL;
2402 if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
2403 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2404 input_sync(gspca_dev->input_dev);
2405 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2406 input_sync(gspca_dev->input_dev);
2407 ret = 0;
2408 }
2409 return ret;
2410}
2411#endif
2412
2413static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2414 u8 *data, /* isoc packet */
2415 int len) /* iso packet length */
2416{
2417 struct sd *sd = (struct sd *) gspca_dev;
2418 int avg_lum;
2419 static u8 frame_header[] =
2420 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2421 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2422 avg_lum = ((data[35] >> 2) & 3) |
2423 (data[20] << 2) |
2424 (data[19] << 10);
2425 avg_lum += ((data[35] >> 4) & 3) |
2426 (data[22] << 2) |
2427 (data[21] << 10);
2428 avg_lum += ((data[35] >> 6) & 3) |
2429 (data[24] << 2) |
2430 (data[23] << 10);
2431 avg_lum += (data[36] & 3) |
2432 (data[26] << 2) |
2433 (data[25] << 10);
2434 avg_lum += ((data[36] >> 2) & 3) |
2435 (data[28] << 2) |
2436 (data[27] << 10);
2437 avg_lum += ((data[36] >> 4) & 3) |
2438 (data[30] << 2) |
2439 (data[29] << 10);
2440 avg_lum += ((data[36] >> 6) & 3) |
2441 (data[32] << 2) |
2442 (data[31] << 10);
2443 avg_lum += ((data[44] >> 4) & 3) |
2444 (data[34] << 2) |
2445 (data[33] << 10);
2446 avg_lum >>= 9;
2447 atomic_set(&sd->avg_lum, avg_lum);
2448 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
2449 return;
2450 }
2451 if (gspca_dev->last_packet_type == LAST_PACKET) {
2452 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2453 & MODE_JPEG) {
2454 gspca_frame_add(gspca_dev, FIRST_PACKET,
2455 sd->jpeg_hdr, JPEG_HDR_SZ);
2456 gspca_frame_add(gspca_dev, INTER_PACKET,
2457 data, len);
2458 } else {
2459 gspca_frame_add(gspca_dev, FIRST_PACKET,
2460 data, len);
2461 }
2462 } else {
2463 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2464 }
2465}
2466
2467/* sub-driver description */
2468static const struct sd_desc sd_desc = {
2469 .name = MODULE_NAME,
2470 .ctrls = sd_ctrls,
2471 .nctrls = ARRAY_SIZE(sd_ctrls),
2472 .config = sd_config,
2473 .init = sd_init,
2474 .start = sd_start,
2475 .stopN = sd_stopN,
2476 .pkt_scan = sd_pkt_scan,
2477#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2478 .int_pkt_scan = sd_int_pkt_scan,
2479#endif
2480 .dq_callback = sd_dqcallback,
2481#ifdef CONFIG_VIDEO_ADV_DEBUG
2482 .set_register = sd_dbg_s_register,
2483 .get_register = sd_dbg_g_register,
2484#endif
2485 .get_chip_ident = sd_chip_ident,
2486};
2487
2488#define SN9C20X(sensor, i2c_addr, flags) \
2489 .driver_info = ((flags & 0xff) << 16) \
2490 | (SENSOR_ ## sensor << 8) \
2491 | (i2c_addr)
2492
2493static const struct usb_device_id device_table[] = {
2494 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2495 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2496 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
2497 {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
2498 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
2499 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
2500 (FLIP_DETECT | HAS_NO_BUTTON))},
2501 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2502 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2503 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2504 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2505 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
2506 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2507 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2508 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2509 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
2510 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
2511 {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
2512 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2513 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2514 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2515 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2516 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
2517 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
2518 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2519 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2520 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2521 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
2522 {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
2523 {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
2524 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2525 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2526 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2527 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
2528 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
2529 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2530 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2531 {}
2532};
2533MODULE_DEVICE_TABLE(usb, device_table);
2534
2535/* -- device connect -- */
2536static int sd_probe(struct usb_interface *intf,
2537 const struct usb_device_id *id)
2538{
2539 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2540 THIS_MODULE);
2541}
2542
2543static struct usb_driver sd_driver = {
2544 .name = MODULE_NAME,
2545 .id_table = device_table,
2546 .probe = sd_probe,
2547 .disconnect = gspca_disconnect,
2548#ifdef CONFIG_PM
2549 .suspend = gspca_suspend,
2550 .resume = gspca_resume,
2551 .reset_resume = gspca_resume,
2552#endif
2553};
2554
2555/* -- module insert / remove -- */
2556static int __init sd_mod_init(void)
2557{
2558 return usb_register(&sd_driver);
2559}
2560static void __exit sd_mod_exit(void)
2561{
2562 usb_deregister(&sd_driver);
2563}
2564
2565module_init(sd_mod_init);
2566module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
new file mode 100644
index 00000000000..146b459b08d
--- /dev/null
+++ b/drivers/media/video/gspca/sonixb.c
@@ -0,0 +1,1541 @@
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/* controls */
60enum e_ctrl {
61 BRIGHTNESS,
62 GAIN,
63 EXPOSURE,
64 AUTOGAIN,
65 FREQ,
66 NCTRLS /* number of controls */
67};
68
69/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev; /* !! must be the first item */
72
73 struct gspca_ctrl ctrls[NCTRLS];
74
75 atomic_t avg_lum;
76 int prev_avg_lum;
77 int exp_too_low_cnt;
78 int exp_too_high_cnt;
79 int header_read;
80 u8 header[12]; /* Header without sof marker */
81
82 unsigned char autogain_ignore_frames;
83 unsigned char frames_to_drop;
84
85 __u8 bridge; /* Type of bridge */
86#define BRIDGE_101 0
87#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
88#define BRIDGE_103 1
89
90 __u8 sensor; /* Type of image sensor chip */
91#define SENSOR_HV7131D 0
92#define SENSOR_HV7131R 1
93#define SENSOR_OV6650 2
94#define SENSOR_OV7630 3
95#define SENSOR_PAS106 4
96#define SENSOR_PAS202 5
97#define SENSOR_TAS5110C 6
98#define SENSOR_TAS5110D 7
99#define SENSOR_TAS5130CXX 8
100 __u8 reg11;
101};
102
103typedef const __u8 sensor_init_t[8];
104
105struct sensor_data {
106 const __u8 *bridge_init;
107 sensor_init_t *sensor_init;
108 int sensor_init_size;
109 int flags;
110 unsigned ctrl_dis;
111 __u8 sensor_addr;
112};
113
114/* sensor_data flags */
115#define F_GAIN 0x01 /* has gain */
116#define F_SIF 0x02 /* sif or vga */
117#define F_COARSE_EXPO 0x04 /* exposure control is coarse */
118
119/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
120#define MODE_RAW 0x10 /* raw bayer mode */
121#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
122
123/* ctrl_dis helper macros */
124#define NO_EXPO ((1 << EXPOSURE) | (1 << AUTOGAIN))
125#define NO_FREQ (1 << FREQ)
126#define NO_BRIGHTNESS (1 << BRIGHTNESS)
127
128#define COMP 0xc7 /* 0x87 //0x07 */
129#define COMP1 0xc9 /* 0x89 //0x09 */
130
131#define MCK_INIT 0x63
132#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
133
134#define SYS_CLK 0x04
135
136#define SENS(bridge, sensor, _flags, _ctrl_dis, _sensor_addr) \
137{ \
138 .bridge_init = bridge, \
139 .sensor_init = sensor, \
140 .sensor_init_size = sizeof(sensor), \
141 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
142}
143
144/* We calculate the autogain at the end of the transfer of a frame, at this
145 moment a frame with the old settings is being captured and transmitted. So
146 if we adjust the gain or exposure we must ignore atleast the next frame for
147 the new settings to come into effect before doing any other adjustments. */
148#define AUTOGAIN_IGNORE_FRAMES 1
149
150/* V4L2 controls supported by the driver */
151static void setbrightness(struct gspca_dev *gspca_dev);
152static void setgain(struct gspca_dev *gspca_dev);
153static void setexposure(struct gspca_dev *gspca_dev);
154static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
155static void setfreq(struct gspca_dev *gspca_dev);
156
157static const struct ctrl sd_ctrls[NCTRLS] = {
158[BRIGHTNESS] = {
159 {
160 .id = V4L2_CID_BRIGHTNESS,
161 .type = V4L2_CTRL_TYPE_INTEGER,
162 .name = "Brightness",
163 .minimum = 0,
164 .maximum = 255,
165 .step = 1,
166 .default_value = 127,
167 },
168 .set_control = setbrightness
169 },
170[GAIN] = {
171 {
172 .id = V4L2_CID_GAIN,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 .name = "Gain",
175 .minimum = 0,
176 .maximum = 255,
177 .step = 1,
178#define GAIN_KNEE 230
179 .default_value = 127,
180 },
181 .set_control = setgain
182 },
183[EXPOSURE] = {
184 {
185 .id = V4L2_CID_EXPOSURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Exposure",
188 .minimum = 0,
189 .maximum = 1023,
190 .step = 1,
191 .default_value = 66,
192 /* 33 ms / 30 fps (except on PASXXX) */
193#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
194 .flags = 0,
195 },
196 .set_control = setexposure
197 },
198/* for coarse exposure */
199#define COARSE_EXPOSURE_MIN 2
200#define COARSE_EXPOSURE_MAX 15
201#define COARSE_EXPOSURE_DEF 2 /* 30 fps */
202[AUTOGAIN] = {
203 {
204 .id = V4L2_CID_AUTOGAIN,
205 .type = V4L2_CTRL_TYPE_BOOLEAN,
206 .name = "Automatic Gain (and Exposure)",
207 .minimum = 0,
208 .maximum = 1,
209 .step = 1,
210#define AUTOGAIN_DEF 1
211 .default_value = AUTOGAIN_DEF,
212 .flags = V4L2_CTRL_FLAG_UPDATE
213 },
214 .set = sd_setautogain,
215 },
216[FREQ] = {
217 {
218 .id = V4L2_CID_POWER_LINE_FREQUENCY,
219 .type = V4L2_CTRL_TYPE_MENU,
220 .name = "Light frequency filter",
221 .minimum = 0,
222 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
223 .step = 1,
224#define FREQ_DEF 0
225 .default_value = FREQ_DEF,
226 },
227 .set_control = setfreq
228 },
229};
230
231static const struct v4l2_pix_format vga_mode[] = {
232 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
233 .bytesperline = 160,
234 .sizeimage = 160 * 120,
235 .colorspace = V4L2_COLORSPACE_SRGB,
236 .priv = 2 | MODE_RAW},
237 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
238 .bytesperline = 160,
239 .sizeimage = 160 * 120 * 5 / 4,
240 .colorspace = V4L2_COLORSPACE_SRGB,
241 .priv = 2},
242 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
243 .bytesperline = 320,
244 .sizeimage = 320 * 240 * 5 / 4,
245 .colorspace = V4L2_COLORSPACE_SRGB,
246 .priv = 1},
247 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
248 .bytesperline = 640,
249 .sizeimage = 640 * 480 * 5 / 4,
250 .colorspace = V4L2_COLORSPACE_SRGB,
251 .priv = 0},
252};
253static const struct v4l2_pix_format sif_mode[] = {
254 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
255 .bytesperline = 160,
256 .sizeimage = 160 * 120,
257 .colorspace = V4L2_COLORSPACE_SRGB,
258 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
259 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
260 .bytesperline = 160,
261 .sizeimage = 160 * 120 * 5 / 4,
262 .colorspace = V4L2_COLORSPACE_SRGB,
263 .priv = 1 | MODE_REDUCED_SIF},
264 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
265 .bytesperline = 176,
266 .sizeimage = 176 * 144,
267 .colorspace = V4L2_COLORSPACE_SRGB,
268 .priv = 1 | MODE_RAW},
269 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
270 .bytesperline = 176,
271 .sizeimage = 176 * 144 * 5 / 4,
272 .colorspace = V4L2_COLORSPACE_SRGB,
273 .priv = 1},
274 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
275 .bytesperline = 320,
276 .sizeimage = 320 * 240 * 5 / 4,
277 .colorspace = V4L2_COLORSPACE_SRGB,
278 .priv = 0 | MODE_REDUCED_SIF},
279 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
280 .bytesperline = 352,
281 .sizeimage = 352 * 288 * 5 / 4,
282 .colorspace = V4L2_COLORSPACE_SRGB,
283 .priv = 0},
284};
285
286static const __u8 initHv7131d[] = {
287 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
288 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
290 0x28, 0x1e, 0x60, 0x8e, 0x42,
291};
292static const __u8 hv7131d_sensor_init[][8] = {
293 {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
294 {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
295 {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
296 {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
297 {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
298};
299
300static const __u8 initHv7131r[] = {
301 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
302 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
304 0x28, 0x1e, 0x60, 0x8a, 0x20,
305};
306static const __u8 hv7131r_sensor_init[][8] = {
307 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
308 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
309 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
310 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
311 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
312};
313static const __u8 initOv6650[] = {
314 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
315 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
317 0x10,
318};
319static const __u8 ov6650_sensor_init[][8] = {
320 /* Bright, contrast, etc are set through SCBB interface.
321 * AVCAP on win2 do not send any data on this controls. */
322 /* Anyway, some registers appears to alter bright and constrat */
323
324 /* Reset sensor */
325 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
326 /* Set clock register 0x11 low nibble is clock divider */
327 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
328 /* Next some unknown stuff */
329 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
330/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
331 * THIS SET GREEN SCREEN
332 * (pixels could be innverted in decode kind of "brg",
333 * but blue wont be there. Avoid this data ... */
334 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
335 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
336 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
337 /* Enable rgb brightness control */
338 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
339 /* HDG: Note windows uses the line below, which sets both register 0x60
340 and 0x61 I believe these registers of the ov6650 are identical as
341 those of the ov7630, because if this is true the windows settings
342 add a bit additional red gain and a lot additional blue gain, which
343 matches my findings that the windows settings make blue much too
344 blue and red a little too red.
345 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
346 /* Some more unknown stuff */
347 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
348 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
349};
350
351static const __u8 initOv7630[] = {
352 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
353 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
354 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
355 0x28, 0x1e, /* H & V sizes r15 .. r16 */
356 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
357};
358static const __u8 ov7630_sensor_init[][8] = {
359 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
360 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
361/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
362 {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
363 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
364 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
365 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
366 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
367 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
368 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
369 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
370 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
371/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
372 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
373 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
374 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
375 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
376 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
377 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
378};
379
380static const __u8 initPas106[] = {
381 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
382 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
384 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
385};
386/* compression 0x86 mckinit1 0x2b */
387
388/* "Known" PAS106B registers:
389 0x02 clock divider
390 0x03 Variable framerate bits 4-11
391 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
392 The variable framerate control must never be set lower then 300,
393 which sets the framerate at 90 / reg02, otherwise vsync is lost.
394 0x05 Shutter Time Line Offset, this can be used as an exposure control:
395 0 = use full frame time, 255 = no exposure at all
396 Note this may never be larger then "var-framerate control" / 2 - 2.
397 When var-framerate control is < 514, no exposure is reached at the max
398 allowed value for the framerate control value, rather then at 255.
399 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
400 only a very little bit, leave at 0xcd
401 0x07 offset sign bit (bit0 1 > negative offset)
402 0x08 offset
403 0x09 Blue Gain
404 0x0a Green1 Gain
405 0x0b Green2 Gain
406 0x0c Red Gain
407 0x0e Global gain
408 0x13 Write 1 to commit settings to sensor
409*/
410
411static const __u8 pas106_sensor_init[][8] = {
412 /* Pixel Clock Divider 6 */
413 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
414 /* Frame Time MSB (also seen as 0x12) */
415 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
416 /* Frame Time LSB (also seen as 0x05) */
417 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
418 /* Shutter Time Line Offset (also seen as 0x6d) */
419 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
420 /* Shutter Time Pixel Offset (also seen as 0xb1) */
421 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
422 /* Black Level Subtract Sign (also seen 0x00) */
423 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
424 /* Black Level Subtract Level (also seen 0x01) */
425 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
426 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
427 /* Color Gain B Pixel 5 a */
428 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
429 /* Color Gain G1 Pixel 1 5 */
430 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
431 /* Color Gain G2 Pixel 1 0 5 */
432 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
433 /* Color Gain R Pixel 3 1 */
434 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
435 /* Color GainH Pixel */
436 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
437 /* Global Gain */
438 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
439 /* Contrast */
440 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
441 /* H&V synchro polarity */
442 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
443 /* ?default */
444 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
445 /* DAC scale */
446 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
447 /* ?default */
448 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
449 /* Validate Settings */
450 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
451};
452
453static const __u8 initPas202[] = {
454 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
455 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
457 0x28, 0x1e, 0x20, 0x89, 0x20,
458};
459
460/* "Known" PAS202BCB registers:
461 0x02 clock divider
462 0x04 Variable framerate bits 6-11 (*)
463 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !!
464 0x07 Blue Gain
465 0x08 Green Gain
466 0x09 Red Gain
467 0x0b offset sign bit (bit0 1 > negative offset)
468 0x0c offset
469 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
470 leave at 1 otherwise we get a jump in our exposure control
471 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
472 0x10 Master gain 0 - 31
473 0x11 write 1 to apply changes
474 (*) The variable framerate control must never be set lower then 500
475 which sets the framerate at 30 / reg02, otherwise vsync is lost.
476*/
477static const __u8 pas202_sensor_init[][8] = {
478 /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
479 to set it lower, but for some reason the bridge starts missing
480 vsync's then */
481 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
482 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
483 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
484 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
485 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
486 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
487 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
488 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
489 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
490 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
491};
492
493static const __u8 initTas5110c[] = {
494 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
495 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
497 0x16, 0x12, 0x60, 0x86, 0x2b,
498};
499/* Same as above, except a different hstart */
500static const __u8 initTas5110d[] = {
501 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
502 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
504 0x16, 0x12, 0x60, 0x86, 0x2b,
505};
506/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */
507static const __u8 tas5110c_sensor_init[][8] = {
508 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
509 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
510};
511/* Known TAS5110D registers
512 * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain
513 * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted)
514 * Note: writing reg03 seems to only work when written together with 02
515 */
516static const __u8 tas5110d_sensor_init[][8] = {
517 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */
518};
519
520static const __u8 initTas5130[] = {
521 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
522 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
524 0x28, 0x1e, 0x60, COMP, MCK_INIT,
525};
526static const __u8 tas5130_sensor_init[][8] = {
527/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
528 * shutter 0x47 short exposure? */
529 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
530 /* shutter 0x01 long exposure */
531 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
532};
533
534static const struct sensor_data sensor_data[] = {
535SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
536SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
537SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60),
538SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21),
539SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0),
540SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0),
541SENS(initTas5110c, tas5110c_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
542 NO_BRIGHTNESS|NO_FREQ, 0),
543SENS(initTas5110d, tas5110d_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO,
544 NO_BRIGHTNESS|NO_FREQ, 0),
545SENS(initTas5130, tas5130_sensor_init, F_GAIN,
546 NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
547};
548
549/* get one byte in gspca_dev->usb_buf */
550static void reg_r(struct gspca_dev *gspca_dev,
551 __u16 value)
552{
553 usb_control_msg(gspca_dev->dev,
554 usb_rcvctrlpipe(gspca_dev->dev, 0),
555 0, /* request */
556 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
557 value,
558 0, /* index */
559 gspca_dev->usb_buf, 1,
560 500);
561}
562
563static void reg_w(struct gspca_dev *gspca_dev,
564 __u16 value,
565 const __u8 *buffer,
566 int len)
567{
568#ifdef GSPCA_DEBUG
569 if (len > USB_BUF_SZ) {
570 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
571 return;
572 }
573#endif
574 memcpy(gspca_dev->usb_buf, buffer, len);
575 usb_control_msg(gspca_dev->dev,
576 usb_sndctrlpipe(gspca_dev->dev, 0),
577 0x08, /* request */
578 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
579 value,
580 0, /* index */
581 gspca_dev->usb_buf, len,
582 500);
583}
584
585static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
586{
587 int retry = 60;
588
589 /* is i2c ready */
590 reg_w(gspca_dev, 0x08, buffer, 8);
591 while (retry--) {
592 msleep(10);
593 reg_r(gspca_dev, 0x08);
594 if (gspca_dev->usb_buf[0] & 0x04) {
595 if (gspca_dev->usb_buf[0] & 0x08)
596 return -1;
597 return 0;
598 }
599 }
600 return -1;
601}
602
603static void i2c_w_vector(struct gspca_dev *gspca_dev,
604 const __u8 buffer[][8], int len)
605{
606 for (;;) {
607 reg_w(gspca_dev, 0x08, *buffer, 8);
608 len -= 8;
609 if (len <= 0)
610 break;
611 buffer++;
612 }
613}
614
615static void setbrightness(struct gspca_dev *gspca_dev)
616{
617 struct sd *sd = (struct sd *) gspca_dev;
618
619 switch (sd->sensor) {
620 case SENSOR_OV6650:
621 case SENSOR_OV7630: {
622 __u8 i2cOV[] =
623 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
624
625 /* change reg 0x06 */
626 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
627 i2cOV[3] = sd->ctrls[BRIGHTNESS].val;
628 if (i2c_w(gspca_dev, i2cOV) < 0)
629 goto err;
630 break;
631 }
632 case SENSOR_PAS106:
633 case SENSOR_PAS202: {
634 __u8 i2cpbright[] =
635 {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
636 __u8 i2cpdoit[] =
637 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
638
639 /* PAS106 uses reg 7 and 8 instead of b and c */
640 if (sd->sensor == SENSOR_PAS106) {
641 i2cpbright[2] = 7;
642 i2cpdoit[2] = 0x13;
643 }
644
645 if (sd->ctrls[BRIGHTNESS].val < 127) {
646 /* change reg 0x0b, signreg */
647 i2cpbright[3] = 0x01;
648 /* set reg 0x0c, offset */
649 i2cpbright[4] = 127 - sd->ctrls[BRIGHTNESS].val;
650 } else
651 i2cpbright[4] = sd->ctrls[BRIGHTNESS].val - 127;
652
653 if (i2c_w(gspca_dev, i2cpbright) < 0)
654 goto err;
655 if (i2c_w(gspca_dev, i2cpdoit) < 0)
656 goto err;
657 break;
658 }
659 }
660 return;
661err:
662 PDEBUG(D_ERR, "i2c error brightness");
663}
664
665static void setsensorgain(struct gspca_dev *gspca_dev)
666{
667 struct sd *sd = (struct sd *) gspca_dev;
668 u8 gain = sd->ctrls[GAIN].val;
669
670 switch (sd->sensor) {
671 case SENSOR_HV7131D: {
672 __u8 i2c[] =
673 {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
674
675 i2c[3] = 0x3f - (gain / 4);
676 i2c[4] = 0x3f - (gain / 4);
677 i2c[5] = 0x3f - (gain / 4);
678
679 if (i2c_w(gspca_dev, i2c) < 0)
680 goto err;
681 break;
682 }
683 case SENSOR_TAS5110C:
684 case SENSOR_TAS5130CXX: {
685 __u8 i2c[] =
686 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
687
688 i2c[4] = 255 - gain;
689 if (i2c_w(gspca_dev, i2c) < 0)
690 goto err;
691 break;
692 }
693 case SENSOR_TAS5110D: {
694 __u8 i2c[] = {
695 0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 };
696 gain = 255 - gain;
697 /* The bits in the register are the wrong way around!! */
698 i2c[3] |= (gain & 0x80) >> 7;
699 i2c[3] |= (gain & 0x40) >> 5;
700 i2c[3] |= (gain & 0x20) >> 3;
701 i2c[3] |= (gain & 0x10) >> 1;
702 i2c[3] |= (gain & 0x08) << 1;
703 i2c[3] |= (gain & 0x04) << 3;
704 i2c[3] |= (gain & 0x02) << 5;
705 i2c[3] |= (gain & 0x01) << 7;
706 if (i2c_w(gspca_dev, i2c) < 0)
707 goto err;
708 break;
709 }
710
711 case SENSOR_OV6650:
712 gain >>= 1;
713 /* fall thru */
714 case SENSOR_OV7630: {
715 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
716
717 i2c[1] = sensor_data[sd->sensor].sensor_addr;
718 i2c[3] = gain >> 2;
719 if (i2c_w(gspca_dev, i2c) < 0)
720 goto err;
721 break;
722 }
723 case SENSOR_PAS106:
724 case SENSOR_PAS202: {
725 __u8 i2cpgain[] =
726 {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
727 __u8 i2cpcolorgain[] =
728 {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
729 __u8 i2cpdoit[] =
730 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
731
732 /* PAS106 uses different regs (and has split green gains) */
733 if (sd->sensor == SENSOR_PAS106) {
734 i2cpgain[2] = 0x0e;
735 i2cpcolorgain[0] = 0xd0;
736 i2cpcolorgain[2] = 0x09;
737 i2cpdoit[2] = 0x13;
738 }
739
740 i2cpgain[3] = gain >> 3;
741 i2cpcolorgain[3] = gain >> 4;
742 i2cpcolorgain[4] = gain >> 4;
743 i2cpcolorgain[5] = gain >> 4;
744 i2cpcolorgain[6] = gain >> 4;
745
746 if (i2c_w(gspca_dev, i2cpgain) < 0)
747 goto err;
748 if (i2c_w(gspca_dev, i2cpcolorgain) < 0)
749 goto err;
750 if (i2c_w(gspca_dev, i2cpdoit) < 0)
751 goto err;
752 break;
753 }
754 }
755 return;
756err:
757 PDEBUG(D_ERR, "i2c error gain");
758}
759
760static void setgain(struct gspca_dev *gspca_dev)
761{
762 struct sd *sd = (struct sd *) gspca_dev;
763 __u8 gain;
764 __u8 buf[3] = { 0, 0, 0 };
765
766 if (sensor_data[sd->sensor].flags & F_GAIN) {
767 /* Use the sensor gain to do the actual gain */
768 setsensorgain(gspca_dev);
769 return;
770 }
771
772 if (sd->bridge == BRIDGE_103) {
773 gain = sd->ctrls[GAIN].val >> 1;
774 buf[0] = gain; /* Red */
775 buf[1] = gain; /* Green */
776 buf[2] = gain; /* Blue */
777 reg_w(gspca_dev, 0x05, buf, 3);
778 } else {
779 gain = sd->ctrls[GAIN].val >> 4;
780 buf[0] = gain << 4 | gain; /* Red and blue */
781 buf[1] = gain; /* Green */
782 reg_w(gspca_dev, 0x10, buf, 2);
783 }
784}
785
786static void setexposure(struct gspca_dev *gspca_dev)
787{
788 struct sd *sd = (struct sd *) gspca_dev;
789
790 switch (sd->sensor) {
791 case SENSOR_HV7131D: {
792 /* Note the datasheet wrongly says line mode exposure uses reg
793 0x26 and 0x27, testing has shown 0x25 + 0x26 */
794 __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
795 /* The HV7131D's exposure goes from 0 - 65535, we scale our
796 exposure of 0-1023 to 0-6138. There are 2 reasons for this:
797 1) This puts our exposure knee of 200 at approx the point
798 where the framerate starts dropping
799 2) At 6138 the framerate has already dropped to 2 fps,
800 going any lower makes little sense */
801 u16 reg = sd->ctrls[EXPOSURE].val * 6;
802
803 i2c[3] = reg >> 8;
804 i2c[4] = reg & 0xff;
805 if (i2c_w(gspca_dev, i2c) != 0)
806 goto err;
807 break;
808 }
809 case SENSOR_TAS5110C:
810 case SENSOR_TAS5110D: {
811 /* register 19's high nibble contains the sn9c10x clock divider
812 The high nibble configures the no fps according to the
813 formula: 60 / high_nibble. With a maximum of 30 fps */
814 u8 reg = sd->ctrls[EXPOSURE].val;
815
816 reg = (reg << 4) | 0x0b;
817 reg_w(gspca_dev, 0x19, &reg, 1);
818 break;
819 }
820 case SENSOR_OV6650:
821 case SENSOR_OV7630: {
822 /* The ov6650 / ov7630 have 2 registers which both influence
823 exposure, register 11, whose low nibble sets the nr off fps
824 according to: fps = 30 / (low_nibble + 1)
825
826 The fps configures the maximum exposure setting, but it is
827 possible to use less exposure then what the fps maximum
828 allows by setting register 10. register 10 configures the
829 actual exposure as quotient of the full exposure, with 0
830 being no exposure at all (not very useful) and reg10_max
831 being max exposure possible at that framerate.
832
833 The code maps our 0 - 510 ms exposure ctrl to these 2
834 registers, trying to keep fps as high as possible.
835 */
836 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
837 int reg10, reg11, reg10_max;
838
839 /* ov6645 datasheet says reg10_max is 9a, but that uses
840 tline * 2 * reg10 as formula for calculating texpo, the
841 ov6650 probably uses the same formula as the 7730 which uses
842 tline * 4 * reg10, which explains why the reg10max we've
843 found experimentally for the ov6650 is exactly half that of
844 the ov6645. The ov7630 datasheet says the max is 0x41. */
845 if (sd->sensor == SENSOR_OV6650) {
846 reg10_max = 0x4d;
847 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
848 } else
849 reg10_max = 0x41;
850
851 reg11 = (15 * sd->ctrls[EXPOSURE].val + 999) / 1000;
852 if (reg11 < 1)
853 reg11 = 1;
854 else if (reg11 > 16)
855 reg11 = 16;
856
857 /* In 640x480, if the reg11 has less than 4, the image is
858 unstable (the bridge goes into a higher compression mode
859 which we have not reverse engineered yet). */
860 if (gspca_dev->width == 640 && reg11 < 4)
861 reg11 = 4;
862
863 /* frame exposure time in ms = 1000 * reg11 / 30 ->
864 reg10 = (sd->ctrls[EXPOSURE].val / 2) * reg10_max
865 / (1000 * reg11 / 30) */
866 reg10 = (sd->ctrls[EXPOSURE].val * 15 * reg10_max)
867 / (1000 * reg11);
868
869 /* Don't allow this to get below 10 when using autogain, the
870 steps become very large (relatively) when below 10 causing
871 the image to oscilate from much too dark, to much too bright
872 and back again. */
873 if (sd->ctrls[AUTOGAIN].val && reg10 < 10)
874 reg10 = 10;
875 else if (reg10 > reg10_max)
876 reg10 = reg10_max;
877
878 /* Write reg 10 and reg11 low nibble */
879 i2c[1] = sensor_data[sd->sensor].sensor_addr;
880 i2c[3] = reg10;
881 i2c[4] |= reg11 - 1;
882
883 /* If register 11 didn't change, don't change it */
884 if (sd->reg11 == reg11)
885 i2c[0] = 0xa0;
886
887 if (i2c_w(gspca_dev, i2c) == 0)
888 sd->reg11 = reg11;
889 else
890 goto err;
891 break;
892 }
893 case SENSOR_PAS202: {
894 __u8 i2cpframerate[] =
895 {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
896 __u8 i2cpexpo[] =
897 {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
898 const __u8 i2cpdoit[] =
899 {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
900 int framerate_ctrl;
901
902 /* The exposure knee for the autogain algorithm is 200
903 (100 ms / 10 fps on other sensors), for values below this
904 use the control for setting the partial frame expose time,
905 above that use variable framerate. This way we run at max
906 framerate (640x480@7.5 fps, 320x240@10fps) until the knee
907 is reached. Using the variable framerate control above 200
908 is better then playing around with both clockdiv + partial
909 frame exposure times (like we are doing with the ov chips),
910 as that sometimes leads to jumps in the exposure control,
911 which are bad for auto exposure. */
912 if (sd->ctrls[EXPOSURE].val < 200) {
913 i2cpexpo[3] = 255 - (sd->ctrls[EXPOSURE].val * 255)
914 / 200;
915 framerate_ctrl = 500;
916 } else {
917 /* The PAS202's exposure control goes from 0 - 4095,
918 but anything below 500 causes vsync issues, so scale
919 our 200-1023 to 500-4095 */
920 framerate_ctrl = (sd->ctrls[EXPOSURE].val - 200)
921 * 1000 / 229 + 500;
922 }
923
924 i2cpframerate[3] = framerate_ctrl >> 6;
925 i2cpframerate[4] = framerate_ctrl & 0x3f;
926 if (i2c_w(gspca_dev, i2cpframerate) < 0)
927 goto err;
928 if (i2c_w(gspca_dev, i2cpexpo) < 0)
929 goto err;
930 if (i2c_w(gspca_dev, i2cpdoit) < 0)
931 goto err;
932 break;
933 }
934 case SENSOR_PAS106: {
935 __u8 i2cpframerate[] =
936 {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
937 __u8 i2cpexpo[] =
938 {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
939 const __u8 i2cpdoit[] =
940 {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
941 int framerate_ctrl;
942
943 /* For values below 150 use partial frame exposure, above
944 that use framerate ctrl */
945 if (sd->ctrls[EXPOSURE].val < 150) {
946 i2cpexpo[3] = 150 - sd->ctrls[EXPOSURE].val;
947 framerate_ctrl = 300;
948 } else {
949 /* The PAS106's exposure control goes from 0 - 4095,
950 but anything below 300 causes vsync issues, so scale
951 our 150-1023 to 300-4095 */
952 framerate_ctrl = (sd->ctrls[EXPOSURE].val - 150)
953 * 1000 / 230 + 300;
954 }
955
956 i2cpframerate[3] = framerate_ctrl >> 4;
957 i2cpframerate[4] = framerate_ctrl & 0x0f;
958 if (i2c_w(gspca_dev, i2cpframerate) < 0)
959 goto err;
960 if (i2c_w(gspca_dev, i2cpexpo) < 0)
961 goto err;
962 if (i2c_w(gspca_dev, i2cpdoit) < 0)
963 goto err;
964 break;
965 }
966 }
967 return;
968err:
969 PDEBUG(D_ERR, "i2c error exposure");
970}
971
972static void setfreq(struct gspca_dev *gspca_dev)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
975
976 switch (sd->sensor) {
977 case SENSOR_OV6650:
978 case SENSOR_OV7630: {
979 /* Framerate adjust register for artificial light 50 hz flicker
980 compensation, for the ov6650 this is identical to ov6630
981 0x2b register, see ov6630 datasheet.
982 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
983 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
984 switch (sd->ctrls[FREQ].val) {
985 default:
986/* case 0: * no filter*/
987/* case 2: * 60 hz */
988 i2c[3] = 0;
989 break;
990 case 1: /* 50 hz */
991 i2c[3] = (sd->sensor == SENSOR_OV6650)
992 ? 0x4f : 0x8a;
993 break;
994 }
995 i2c[1] = sensor_data[sd->sensor].sensor_addr;
996 if (i2c_w(gspca_dev, i2c) < 0)
997 PDEBUG(D_ERR, "i2c error setfreq");
998 break;
999 }
1000 }
1001}
1002
1003#include "autogain_functions.h"
1004
1005static void do_autogain(struct gspca_dev *gspca_dev)
1006{
1007 int deadzone, desired_avg_lum, result;
1008 struct sd *sd = (struct sd *) gspca_dev;
1009 int avg_lum = atomic_read(&sd->avg_lum);
1010
1011 if ((gspca_dev->ctrl_dis & (1 << AUTOGAIN)) ||
1012 avg_lum == -1 || !sd->ctrls[AUTOGAIN].val)
1013 return;
1014
1015 if (sd->autogain_ignore_frames > 0) {
1016 sd->autogain_ignore_frames--;
1017 return;
1018 }
1019
1020 /* SIF / VGA sensors have a different autoexposure area and thus
1021 different avg_lum values for the same picture brightness */
1022 if (sensor_data[sd->sensor].flags & F_SIF) {
1023 deadzone = 500;
1024 /* SIF sensors tend to overexpose, so keep this small */
1025 desired_avg_lum = 5000;
1026 } else {
1027 deadzone = 1500;
1028 desired_avg_lum = 13000;
1029 }
1030
1031 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
1032 result = coarse_grained_expo_autogain(gspca_dev, avg_lum,
1033 sd->ctrls[BRIGHTNESS].val
1034 * desired_avg_lum / 127,
1035 deadzone);
1036 else
1037 result = auto_gain_n_exposure(gspca_dev, avg_lum,
1038 sd->ctrls[BRIGHTNESS].val
1039 * desired_avg_lum / 127,
1040 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
1041
1042 if (result) {
1043 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
1044 (int) sd->ctrls[GAIN].val,
1045 (int) sd->ctrls[EXPOSURE].val);
1046 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1047 }
1048}
1049
1050/* this function is called at probe time */
1051static int sd_config(struct gspca_dev *gspca_dev,
1052 const struct usb_device_id *id)
1053{
1054 struct sd *sd = (struct sd *) gspca_dev;
1055 struct cam *cam;
1056
1057 reg_r(gspca_dev, 0x00);
1058 if (gspca_dev->usb_buf[0] != 0x10)
1059 return -ENODEV;
1060
1061 /* copy the webcam info from the device id */
1062 sd->sensor = id->driver_info >> 8;
1063 sd->bridge = id->driver_info & 0xff;
1064
1065 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
1066#if AUTOGAIN_DEF
1067 if (!(gspca_dev->ctrl_dis & (1 << AUTOGAIN)))
1068 gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
1069#endif
1070
1071 cam = &gspca_dev->cam;
1072 cam->ctrls = sd->ctrls;
1073 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
1074 cam->cam_mode = vga_mode;
1075 cam->nmodes = ARRAY_SIZE(vga_mode);
1076 } else {
1077 cam->cam_mode = sif_mode;
1078 cam->nmodes = ARRAY_SIZE(sif_mode);
1079 }
1080 cam->npkt = 36; /* 36 packets per ISOC message */
1081
1082 if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
1083 sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
1084 sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
1085 sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
1086 }
1087
1088 return 0;
1089}
1090
1091/* this function is called at probe and resume time */
1092static int sd_init(struct gspca_dev *gspca_dev)
1093{
1094 const __u8 stop = 0x09; /* Disable stream turn of LED */
1095
1096 reg_w(gspca_dev, 0x01, &stop, 1);
1097
1098 return 0;
1099}
1100
1101/* -- start the camera -- */
1102static int sd_start(struct gspca_dev *gspca_dev)
1103{
1104 struct sd *sd = (struct sd *) gspca_dev;
1105 struct cam *cam = &gspca_dev->cam;
1106 int i, mode;
1107 __u8 regs[0x31];
1108
1109 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
1110 /* Copy registers 0x01 - 0x19 from the template */
1111 memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
1112 /* Set the mode */
1113 regs[0x18] |= mode << 4;
1114
1115 /* Set bridge gain to 1.0 */
1116 if (sd->bridge == BRIDGE_103) {
1117 regs[0x05] = 0x20; /* Red */
1118 regs[0x06] = 0x20; /* Green */
1119 regs[0x07] = 0x20; /* Blue */
1120 } else {
1121 regs[0x10] = 0x00; /* Red and blue */
1122 regs[0x11] = 0x00; /* Green */
1123 }
1124
1125 /* Setup pixel numbers and auto exposure window */
1126 if (sensor_data[sd->sensor].flags & F_SIF) {
1127 regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
1128 regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
1129 regs[0x1c] = 0x02; /* AE H-start 64 */
1130 regs[0x1d] = 0x02; /* AE V-start 64 */
1131 regs[0x1e] = 0x09; /* AE H-end 288 */
1132 regs[0x1f] = 0x07; /* AE V-end 224 */
1133 } else {
1134 regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
1135 regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
1136 regs[0x1c] = 0x05; /* AE H-start 160 */
1137 regs[0x1d] = 0x03; /* AE V-start 96 */
1138 regs[0x1e] = 0x0f; /* AE H-end 480 */
1139 regs[0x1f] = 0x0c; /* AE V-end 384 */
1140 }
1141
1142 /* Setup the gamma table (only used with the sn9c103 bridge) */
1143 for (i = 0; i < 16; i++)
1144 regs[0x20 + i] = i * 16;
1145 regs[0x20 + i] = 255;
1146
1147 /* Special cases where some regs depend on mode or bridge */
1148 switch (sd->sensor) {
1149 case SENSOR_TAS5130CXX:
1150 /* FIXME / TESTME
1151 probably not mode specific at all most likely the upper
1152 nibble of 0x19 is exposure (clock divider) just as with
1153 the tas5110, we need someone to test this. */
1154 regs[0x19] = mode ? 0x23 : 0x43;
1155 break;
1156 case SENSOR_OV7630:
1157 /* FIXME / TESTME for some reason with the 101/102 bridge the
1158 clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
1159 Also the hstart needs to go from 1 to 2 when using a 103,
1160 which is likely related. This does not seem right. */
1161 if (sd->bridge == BRIDGE_103) {
1162 regs[0x01] = 0x44; /* Select 24 Mhz clock */
1163 regs[0x12] = 0x02; /* Set hstart to 2 */
1164 }
1165 }
1166 /* Disable compression when the raw bayer format has been selected */
1167 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
1168 regs[0x18] &= ~0x80;
1169
1170 /* Vga mode emulation on SIF sensor? */
1171 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
1172 regs[0x12] += 16; /* hstart adjust */
1173 regs[0x13] += 24; /* vstart adjust */
1174 regs[0x15] = 320 / 16; /* hsize */
1175 regs[0x16] = 240 / 16; /* vsize */
1176 }
1177
1178 /* reg 0x01 bit 2 video transfert on */
1179 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
1180 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1181 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
1182 /* Set the registers from the template */
1183 reg_w(gspca_dev, 0x01, &regs[0x01],
1184 (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
1185
1186 /* Init the sensor */
1187 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
1188 sensor_data[sd->sensor].sensor_init_size);
1189
1190 /* Mode / bridge specific sensor setup */
1191 switch (sd->sensor) {
1192 case SENSOR_PAS202: {
1193 const __u8 i2cpclockdiv[] =
1194 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
1195 /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
1196 if (mode)
1197 i2c_w(gspca_dev, i2cpclockdiv);
1198 break;
1199 }
1200 case SENSOR_OV7630:
1201 /* FIXME / TESTME We should be able to handle this identical
1202 for the 101/102 and the 103 case */
1203 if (sd->bridge == BRIDGE_103) {
1204 const __u8 i2c[] = { 0xa0, 0x21, 0x13,
1205 0x80, 0x00, 0x00, 0x00, 0x10 };
1206 i2c_w(gspca_dev, i2c);
1207 }
1208 break;
1209 }
1210 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1211 reg_w(gspca_dev, 0x15, &regs[0x15], 2);
1212 /* compression register */
1213 reg_w(gspca_dev, 0x18, &regs[0x18], 1);
1214 /* H_start */
1215 reg_w(gspca_dev, 0x12, &regs[0x12], 1);
1216 /* V_START */
1217 reg_w(gspca_dev, 0x13, &regs[0x13], 1);
1218 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1219 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1220 reg_w(gspca_dev, 0x17, &regs[0x17], 1);
1221 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1222 reg_w(gspca_dev, 0x19, &regs[0x19], 1);
1223 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1224 reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
1225 /* Enable video transfert */
1226 reg_w(gspca_dev, 0x01, &regs[0x01], 1);
1227 /* Compression */
1228 reg_w(gspca_dev, 0x18, &regs[0x18], 2);
1229 msleep(20);
1230
1231 sd->reg11 = -1;
1232
1233 setgain(gspca_dev);
1234 setbrightness(gspca_dev);
1235 setexposure(gspca_dev);
1236 setfreq(gspca_dev);
1237
1238 sd->frames_to_drop = 0;
1239 sd->autogain_ignore_frames = 0;
1240 sd->exp_too_high_cnt = 0;
1241 sd->exp_too_low_cnt = 0;
1242 atomic_set(&sd->avg_lum, -1);
1243 return 0;
1244}
1245
1246static void sd_stopN(struct gspca_dev *gspca_dev)
1247{
1248 sd_init(gspca_dev);
1249}
1250
1251static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
1252{
1253 struct sd *sd = (struct sd *) gspca_dev;
1254 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
1255
1256 /* frames start with:
1257 * ff ff 00 c4 c4 96 synchro
1258 * 00 (unknown)
1259 * xx (frame sequence / size / compression)
1260 * (xx) (idem - extra byte for sn9c103)
1261 * ll mm brightness sum inside auto exposure
1262 * ll mm brightness sum outside auto exposure
1263 * (xx xx xx xx xx) audio values for snc103
1264 */
1265 for (i = 0; i < len; i++) {
1266 switch (sd->header_read) {
1267 case 0:
1268 if (data[i] == 0xff)
1269 sd->header_read++;
1270 break;
1271 case 1:
1272 if (data[i] == 0xff)
1273 sd->header_read++;
1274 else
1275 sd->header_read = 0;
1276 break;
1277 case 2:
1278 if (data[i] == 0x00)
1279 sd->header_read++;
1280 else if (data[i] != 0xff)
1281 sd->header_read = 0;
1282 break;
1283 case 3:
1284 if (data[i] == 0xc4)
1285 sd->header_read++;
1286 else if (data[i] == 0xff)
1287 sd->header_read = 1;
1288 else
1289 sd->header_read = 0;
1290 break;
1291 case 4:
1292 if (data[i] == 0xc4)
1293 sd->header_read++;
1294 else if (data[i] == 0xff)
1295 sd->header_read = 1;
1296 else
1297 sd->header_read = 0;
1298 break;
1299 case 5:
1300 if (data[i] == 0x96)
1301 sd->header_read++;
1302 else if (data[i] == 0xff)
1303 sd->header_read = 1;
1304 else
1305 sd->header_read = 0;
1306 break;
1307 default:
1308 sd->header[sd->header_read - 6] = data[i];
1309 sd->header_read++;
1310 if (sd->header_read == header_size) {
1311 sd->header_read = 0;
1312 return data + i + 1;
1313 }
1314 }
1315 }
1316 return NULL;
1317}
1318
1319static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1320 u8 *data, /* isoc packet */
1321 int len) /* iso packet length */
1322{
1323 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1324 struct sd *sd = (struct sd *) gspca_dev;
1325 struct cam *cam = &gspca_dev->cam;
1326 u8 *sof;
1327
1328 sof = find_sof(gspca_dev, data, len);
1329 if (sof) {
1330 if (sd->bridge == BRIDGE_103) {
1331 fr_h_sz = 18;
1332 lum_offset = 3;
1333 } else {
1334 fr_h_sz = 12;
1335 lum_offset = 2;
1336 }
1337
1338 len_after_sof = len - (sof - data);
1339 len = (sof - data) - fr_h_sz;
1340 if (len < 0)
1341 len = 0;
1342 }
1343
1344 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1345 /* In raw mode we sometimes get some garbage after the frame
1346 ignore this */
1347 int used;
1348 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1349
1350 used = gspca_dev->image_len;
1351 if (used + len > size)
1352 len = size - used;
1353 }
1354
1355 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1356
1357 if (sof) {
1358 int lum = sd->header[lum_offset] +
1359 (sd->header[lum_offset + 1] << 8);
1360
1361 /* When exposure changes midway a frame we
1362 get a lum of 0 in this case drop 2 frames
1363 as the frames directly after an exposure
1364 change have an unstable image. Sometimes lum
1365 *really* is 0 (cam used in low light with
1366 low exposure setting), so do not drop frames
1367 if the previous lum was 0 too. */
1368 if (lum == 0 && sd->prev_avg_lum != 0) {
1369 lum = -1;
1370 sd->frames_to_drop = 2;
1371 sd->prev_avg_lum = 0;
1372 } else
1373 sd->prev_avg_lum = lum;
1374 atomic_set(&sd->avg_lum, lum);
1375
1376 if (sd->frames_to_drop)
1377 sd->frames_to_drop--;
1378 else
1379 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1380
1381 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1382 }
1383}
1384
1385static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1386{
1387 struct sd *sd = (struct sd *) gspca_dev;
1388
1389 sd->ctrls[AUTOGAIN].val = val;
1390 sd->exp_too_high_cnt = 0;
1391 sd->exp_too_low_cnt = 0;
1392
1393 /* when switching to autogain set defaults to make sure
1394 we are on a valid point of the autogain gain /
1395 exposure knee graph, and give this change time to
1396 take effect before doing autogain. */
1397 if (sd->ctrls[AUTOGAIN].val
1398 && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
1399 sd->ctrls[EXPOSURE].val = sd->ctrls[EXPOSURE].def;
1400 sd->ctrls[GAIN].val = sd->ctrls[GAIN].def;
1401 if (gspca_dev->streaming) {
1402 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1403 setexposure(gspca_dev);
1404 setgain(gspca_dev);
1405 }
1406 }
1407
1408 if (sd->ctrls[AUTOGAIN].val)
1409 gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
1410 else
1411 gspca_dev->ctrl_inac = 0;
1412
1413 return 0;
1414}
1415
1416static int sd_querymenu(struct gspca_dev *gspca_dev,
1417 struct v4l2_querymenu *menu)
1418{
1419 switch (menu->id) {
1420 case V4L2_CID_POWER_LINE_FREQUENCY:
1421 switch (menu->index) {
1422 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1423 strcpy((char *) menu->name, "NoFliker");
1424 return 0;
1425 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1426 strcpy((char *) menu->name, "50 Hz");
1427 return 0;
1428 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1429 strcpy((char *) menu->name, "60 Hz");
1430 return 0;
1431 }
1432 break;
1433 }
1434 return -EINVAL;
1435}
1436
1437#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1438static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1439 u8 *data, /* interrupt packet data */
1440 int len) /* interrupt packet length */
1441{
1442 int ret = -EINVAL;
1443
1444 if (len == 1 && data[0] == 1) {
1445 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1446 input_sync(gspca_dev->input_dev);
1447 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1448 input_sync(gspca_dev->input_dev);
1449 ret = 0;
1450 }
1451
1452 return ret;
1453}
1454#endif
1455
1456/* sub-driver description */
1457static const struct sd_desc sd_desc = {
1458 .name = MODULE_NAME,
1459 .ctrls = sd_ctrls,
1460 .nctrls = ARRAY_SIZE(sd_ctrls),
1461 .config = sd_config,
1462 .init = sd_init,
1463 .start = sd_start,
1464 .stopN = sd_stopN,
1465 .pkt_scan = sd_pkt_scan,
1466 .querymenu = sd_querymenu,
1467 .dq_callback = do_autogain,
1468#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1469 .int_pkt_scan = sd_int_pkt_scan,
1470#endif
1471};
1472
1473/* -- module initialisation -- */
1474#define SB(sensor, bridge) \
1475 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1476
1477
1478static const struct usb_device_id device_table[] = {
1479 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1480 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
1481 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
1482 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1483 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
1484 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
1485 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1486#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1487 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1488 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1489#endif
1490 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1491 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
1492 {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
1493 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
1494 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
1495 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
1496 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
1497 /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
1498 /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */
1499 {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)},
1500 {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)},
1501 /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */
1502 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1503 {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)},
1504 {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)},
1505 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1506 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
1507 {}
1508};
1509MODULE_DEVICE_TABLE(usb, device_table);
1510
1511/* -- device connect -- */
1512static int sd_probe(struct usb_interface *intf,
1513 const struct usb_device_id *id)
1514{
1515 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1516 THIS_MODULE);
1517}
1518
1519static struct usb_driver sd_driver = {
1520 .name = MODULE_NAME,
1521 .id_table = device_table,
1522 .probe = sd_probe,
1523 .disconnect = gspca_disconnect,
1524#ifdef CONFIG_PM
1525 .suspend = gspca_suspend,
1526 .resume = gspca_resume,
1527#endif
1528};
1529
1530/* -- module insert / remove -- */
1531static int __init sd_mod_init(void)
1532{
1533 return usb_register(&sd_driver);
1534}
1535static void __exit sd_mod_exit(void)
1536{
1537 usb_deregister(&sd_driver);
1538}
1539
1540module_init(sd_mod_init);
1541module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
new file mode 100644
index 00000000000..c477ad11f10
--- /dev/null
+++ b/drivers/media/video/gspca/sonixj.c
@@ -0,0 +1,3119 @@
1/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
3 *
4 * Copyright (C) 2009-2010 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 MODULE_NAME "sonixj"
23
24#include <linux/input.h>
25#include "gspca.h"
26#include "jpeg.h"
27
28MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
29MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* controls */
33enum e_ctrl {
34 BRIGHTNESS,
35 CONTRAST,
36 COLORS,
37 BLUE,
38 RED,
39 GAMMA,
40 AUTOGAIN,
41 HFLIP,
42 VFLIP,
43 SHARPNESS,
44 ILLUM,
45 FREQ,
46 NCTRLS /* number of controls */
47};
48
49/* specific webcam descriptor */
50struct sd {
51 struct gspca_dev gspca_dev; /* !! must be the first item */
52
53 struct gspca_ctrl ctrls[NCTRLS];
54
55 atomic_t avg_lum;
56 u32 exposure;
57
58 struct work_struct work;
59 struct workqueue_struct *work_thread;
60
61 u32 pktsz; /* (used by pkt_scan) */
62 u16 npkt;
63 s8 nchg;
64 s8 short_mark;
65
66 u8 quality; /* image quality */
67#define QUALITY_MIN 25
68#define QUALITY_MAX 90
69#define QUALITY_DEF 70
70
71 u8 reg01;
72 u8 reg17;
73 u8 reg18;
74 u8 flags;
75
76 s8 ag_cnt;
77#define AG_CNT_START 13
78
79 u8 bridge;
80#define BRIDGE_SN9C102P 0
81#define BRIDGE_SN9C105 1
82#define BRIDGE_SN9C110 2
83#define BRIDGE_SN9C120 3
84 u8 sensor; /* Type of image sensor chip */
85 u8 i2c_addr;
86
87 u8 jpeg_hdr[JPEG_HDR_SZ];
88};
89enum sensors {
90 SENSOR_ADCM1700,
91 SENSOR_GC0307,
92 SENSOR_HV7131R,
93 SENSOR_MI0360,
94 SENSOR_MI0360B,
95 SENSOR_MO4000,
96 SENSOR_MT9V111,
97 SENSOR_OM6802,
98 SENSOR_OV7630,
99 SENSOR_OV7648,
100 SENSOR_OV7660,
101 SENSOR_PO1030,
102 SENSOR_PO2030N,
103 SENSOR_SOI768,
104 SENSOR_SP80708,
105};
106
107static void qual_upd(struct work_struct *work);
108
109/* device flags */
110#define F_PDN_INV 0x01 /* inverse pin S_PWR_DN / sn_xxx tables */
111#define F_ILLUM 0x02 /* presence of illuminator */
112
113/* sn9c1xx definitions */
114/* register 0x01 */
115#define S_PWR_DN 0x01 /* sensor power down */
116#define S_PDN_INV 0x02 /* inverse pin S_PWR_DN */
117#define V_TX_EN 0x04 /* video transfer enable */
118#define LED 0x08 /* output to pin LED */
119#define SCL_SEL_OD 0x20 /* open-drain mode */
120#define SYS_SEL_48M 0x40 /* system clock 0: 24MHz, 1: 48MHz */
121/* register 0x17 */
122#define MCK_SIZE_MASK 0x1f /* sensor master clock */
123#define SEN_CLK_EN 0x20 /* enable sensor clock */
124#define DEF_EN 0x80 /* defect pixel by 0: soft, 1: hard */
125
126/* V4L2 controls supported by the driver */
127static void setbrightness(struct gspca_dev *gspca_dev);
128static void setcontrast(struct gspca_dev *gspca_dev);
129static void setcolors(struct gspca_dev *gspca_dev);
130static void setredblue(struct gspca_dev *gspca_dev);
131static void setgamma(struct gspca_dev *gspca_dev);
132static void setautogain(struct gspca_dev *gspca_dev);
133static void sethvflip(struct gspca_dev *gspca_dev);
134static void setsharpness(struct gspca_dev *gspca_dev);
135static void setillum(struct gspca_dev *gspca_dev);
136static void setfreq(struct gspca_dev *gspca_dev);
137
138static const struct ctrl sd_ctrls[NCTRLS] = {
139[BRIGHTNESS] = {
140 {
141 .id = V4L2_CID_BRIGHTNESS,
142 .type = V4L2_CTRL_TYPE_INTEGER,
143 .name = "Brightness",
144 .minimum = 0,
145 .maximum = 0xff,
146 .step = 1,
147 .default_value = 0x80,
148 },
149 .set_control = setbrightness
150 },
151[CONTRAST] = {
152 {
153 .id = V4L2_CID_CONTRAST,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .name = "Contrast",
156 .minimum = 0,
157#define CONTRAST_MAX 127
158 .maximum = CONTRAST_MAX,
159 .step = 1,
160 .default_value = 63,
161 },
162 .set_control = setcontrast
163 },
164[COLORS] = {
165 {
166 .id = V4L2_CID_SATURATION,
167 .type = V4L2_CTRL_TYPE_INTEGER,
168 .name = "Saturation",
169 .minimum = 0,
170 .maximum = 40,
171 .step = 1,
172#define COLORS_DEF 25
173 .default_value = COLORS_DEF,
174 },
175 .set_control = setcolors
176 },
177[BLUE] = {
178 {
179 .id = V4L2_CID_BLUE_BALANCE,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "Blue Balance",
182 .minimum = 24,
183 .maximum = 40,
184 .step = 1,
185 .default_value = 32,
186 },
187 .set_control = setredblue
188 },
189[RED] = {
190 {
191 .id = V4L2_CID_RED_BALANCE,
192 .type = V4L2_CTRL_TYPE_INTEGER,
193 .name = "Red Balance",
194 .minimum = 24,
195 .maximum = 40,
196 .step = 1,
197 .default_value = 32,
198 },
199 .set_control = setredblue
200 },
201[GAMMA] = {
202 {
203 .id = V4L2_CID_GAMMA,
204 .type = V4L2_CTRL_TYPE_INTEGER,
205 .name = "Gamma",
206 .minimum = 0,
207 .maximum = 40,
208 .step = 1,
209#define GAMMA_DEF 20
210 .default_value = GAMMA_DEF,
211 },
212 .set_control = setgamma
213 },
214[AUTOGAIN] = {
215 {
216 .id = V4L2_CID_AUTOGAIN,
217 .type = V4L2_CTRL_TYPE_BOOLEAN,
218 .name = "Auto Gain",
219 .minimum = 0,
220 .maximum = 1,
221 .step = 1,
222 .default_value = 1
223 },
224 .set_control = setautogain
225 },
226[HFLIP] = {
227 {
228 .id = V4L2_CID_HFLIP,
229 .type = V4L2_CTRL_TYPE_BOOLEAN,
230 .name = "Mirror",
231 .minimum = 0,
232 .maximum = 1,
233 .step = 1,
234 .default_value = 0,
235 },
236 .set_control = sethvflip
237 },
238[VFLIP] = {
239 {
240 .id = V4L2_CID_VFLIP,
241 .type = V4L2_CTRL_TYPE_BOOLEAN,
242 .name = "Vflip",
243 .minimum = 0,
244 .maximum = 1,
245 .step = 1,
246 .default_value = 0,
247 },
248 .set_control = sethvflip
249 },
250[SHARPNESS] = {
251 {
252 .id = V4L2_CID_SHARPNESS,
253 .type = V4L2_CTRL_TYPE_INTEGER,
254 .name = "Sharpness",
255 .minimum = 0,
256 .maximum = 255,
257 .step = 1,
258 .default_value = 90,
259 },
260 .set_control = setsharpness
261 },
262[ILLUM] = {
263 {
264 .id = V4L2_CID_ILLUMINATORS_1,
265 .type = V4L2_CTRL_TYPE_BOOLEAN,
266 .name = "Illuminator / infrared",
267 .minimum = 0,
268 .maximum = 1,
269 .step = 1,
270 .default_value = 0,
271 },
272 .set_control = setillum
273 },
274/* ov7630/ov7648/ov7660 only */
275[FREQ] = {
276 {
277 .id = V4L2_CID_POWER_LINE_FREQUENCY,
278 .type = V4L2_CTRL_TYPE_MENU,
279 .name = "Light frequency filter",
280 .minimum = 0,
281 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
282 .step = 1,
283 .default_value = 1,
284 },
285 .set_control = setfreq
286 },
287};
288
289/* table of the disabled controls */
290static const __u32 ctrl_dis[] = {
291[SENSOR_ADCM1700] = (1 << AUTOGAIN) |
292 (1 << HFLIP) |
293 (1 << VFLIP) |
294 (1 << FREQ),
295
296[SENSOR_GC0307] = (1 << HFLIP) |
297 (1 << VFLIP) |
298 (1 << FREQ),
299
300[SENSOR_HV7131R] = (1 << HFLIP) |
301 (1 << FREQ),
302
303[SENSOR_MI0360] = (1 << HFLIP) |
304 (1 << VFLIP) |
305 (1 << FREQ),
306
307[SENSOR_MI0360B] = (1 << HFLIP) |
308 (1 << VFLIP) |
309 (1 << FREQ),
310
311[SENSOR_MO4000] = (1 << HFLIP) |
312 (1 << VFLIP) |
313 (1 << FREQ),
314
315[SENSOR_MT9V111] = (1 << HFLIP) |
316 (1 << VFLIP) |
317 (1 << FREQ),
318
319[SENSOR_OM6802] = (1 << HFLIP) |
320 (1 << VFLIP) |
321 (1 << FREQ),
322
323[SENSOR_OV7630] = (1 << HFLIP),
324
325[SENSOR_OV7648] = (1 << HFLIP),
326
327[SENSOR_OV7660] = (1 << AUTOGAIN) |
328 (1 << HFLIP) |
329 (1 << VFLIP),
330
331[SENSOR_PO1030] = (1 << AUTOGAIN) |
332 (1 << HFLIP) |
333 (1 << VFLIP) |
334 (1 << FREQ),
335
336[SENSOR_PO2030N] = (1 << AUTOGAIN) |
337 (1 << FREQ),
338
339[SENSOR_SOI768] = (1 << AUTOGAIN) |
340 (1 << HFLIP) |
341 (1 << VFLIP) |
342 (1 << FREQ),
343
344[SENSOR_SP80708] = (1 << AUTOGAIN) |
345 (1 << HFLIP) |
346 (1 << VFLIP) |
347 (1 << FREQ),
348};
349
350static const struct v4l2_pix_format cif_mode[] = {
351 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
352 .bytesperline = 352,
353 .sizeimage = 352 * 288 * 4 / 8 + 590,
354 .colorspace = V4L2_COLORSPACE_JPEG,
355 .priv = 0},
356};
357static const struct v4l2_pix_format vga_mode[] = {
358 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
359 .bytesperline = 160,
360 .sizeimage = 160 * 120 * 4 / 8 + 590,
361 .colorspace = V4L2_COLORSPACE_JPEG,
362 .priv = 2},
363 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
364 .bytesperline = 320,
365 .sizeimage = 320 * 240 * 3 / 8 + 590,
366 .colorspace = V4L2_COLORSPACE_JPEG,
367 .priv = 1},
368 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
369 .bytesperline = 640,
370 /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
371 .sizeimage = 640 * 480 * 3 / 4 + 590,
372 .colorspace = V4L2_COLORSPACE_JPEG,
373 .priv = 0},
374};
375
376static const u8 sn_adcm1700[0x1c] = {
377/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
378 0x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00,
379/* reg8 reg9 rega regb regc regd rege regf */
380 0x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
382 0x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42,
383/* reg18 reg19 reg1a reg1b */
384 0x06, 0x00, 0x00, 0x00
385};
386
387static const u8 sn_gc0307[0x1c] = {
388/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
389 0x00, 0x61, 0x62, 0x00, 0x1a, 0x00, 0x00, 0x00,
390/* reg8 reg9 rega regb regc regd rege regf */
391 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
393 0x03, 0x00, 0x03, 0x01, 0x08, 0x28, 0x1e, 0x02,
394/* reg18 reg19 reg1a reg1b */
395 0x06, 0x00, 0x00, 0x00
396};
397
398static const u8 sn_hv7131[0x1c] = {
399/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
400 0x00, 0x03, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20,
401/* reg8 reg9 rega regb regc regd rege regf */
402 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
404 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
405/* reg18 reg19 reg1a reg1b */
406 0x0a, 0x00, 0x00, 0x00
407};
408
409static const u8 sn_mi0360[0x1c] = {
410/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
411 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
412/* reg8 reg9 rega regb regc regd rege regf */
413 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
415 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
416/* reg18 reg19 reg1a reg1b */
417 0x06, 0x00, 0x00, 0x00
418};
419
420static const u8 sn_mi0360b[0x1c] = {
421/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
422 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
423/* reg8 reg9 rega regb regc regd rege regf */
424 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
426 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x40,
427/* reg18 reg19 reg1a reg1b */
428 0x06, 0x00, 0x00, 0x00
429};
430
431static const u8 sn_mo4000[0x1c] = {
432/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
433 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
434/* reg8 reg9 rega regb regc regd rege regf */
435 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
437 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
438/* reg18 reg19 reg1a reg1b */
439 0x08, 0x00, 0x00, 0x00
440};
441
442static const u8 sn_mt9v111[0x1c] = {
443/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
444 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
445/* reg8 reg9 rega regb regc regd rege regf */
446 0x81, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
448 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40,
449/* reg18 reg19 reg1a reg1b */
450 0x06, 0x00, 0x00, 0x00
451};
452
453static const u8 sn_om6802[0x1c] = {
454/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
455 0x00, 0x23, 0x72, 0x00, 0x1a, 0x20, 0x20, 0x19,
456/* reg8 reg9 rega regb regc regd rege regf */
457 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
459 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
460/* reg18 reg19 reg1a reg1b */
461 0x05, 0x00, 0x00, 0x00
462};
463
464static const u8 sn_ov7630[0x1c] = {
465/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
466 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
467/* reg8 reg9 rega regb regc regd rege regf */
468 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
469/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
470 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
471/* reg18 reg19 reg1a reg1b */
472 0x0b, 0x00, 0x00, 0x00
473};
474
475static const u8 sn_ov7648[0x1c] = {
476/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
477 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
478/* reg8 reg9 rega regb regc regd rege regf */
479 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
481 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
482/* reg18 reg19 reg1a reg1b */
483 0x0b, 0x00, 0x00, 0x00
484};
485
486static const u8 sn_ov7660[0x1c] = {
487/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
488 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
489/* reg8 reg9 rega regb regc regd rege regf */
490 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
492 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
493/* reg18 reg19 reg1a reg1b */
494 0x07, 0x00, 0x00, 0x00
495};
496
497static const u8 sn_po1030[0x1c] = {
498/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
499 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20,
500/* reg8 reg9 rega regb regc regd rege regf */
501 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
503 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x00,
504/* reg18 reg19 reg1a reg1b */
505 0x07, 0x00, 0x00, 0x00
506};
507
508static const u8 sn_po2030n[0x1c] = {
509/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
510 0x00, 0x63, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
511/* reg8 reg9 rega regb regc regd rege regf */
512 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
514 0x03, 0x00, 0x00, 0x01, 0x14, 0x28, 0x1e, 0x00,
515/* reg18 reg19 reg1a reg1b */
516 0x07, 0x00, 0x00, 0x00
517};
518
519static const u8 sn_soi768[0x1c] = {
520/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
521 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00,
522/* reg8 reg9 rega regb regc regd rege regf */
523 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
525 0x03, 0x00, 0x00, 0x01, 0x08, 0x28, 0x1e, 0x00,
526/* reg18 reg19 reg1a reg1b */
527 0x07, 0x00, 0x00, 0x00
528};
529
530static const u8 sn_sp80708[0x1c] = {
531/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
532 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20,
533/* reg8 reg9 rega regb regc regd rege regf */
534 0x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
536 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00,
537/* reg18 reg19 reg1a reg1b */
538 0x07, 0x00, 0x00, 0x00
539};
540
541/* sequence specific to the sensors - !! index = SENSOR_xxx */
542static const u8 *sn_tb[] = {
543[SENSOR_ADCM1700] = sn_adcm1700,
544[SENSOR_GC0307] = sn_gc0307,
545[SENSOR_HV7131R] = sn_hv7131,
546[SENSOR_MI0360] = sn_mi0360,
547[SENSOR_MI0360B] = sn_mi0360b,
548[SENSOR_MO4000] = sn_mo4000,
549[SENSOR_MT9V111] = sn_mt9v111,
550[SENSOR_OM6802] = sn_om6802,
551[SENSOR_OV7630] = sn_ov7630,
552[SENSOR_OV7648] = sn_ov7648,
553[SENSOR_OV7660] = sn_ov7660,
554[SENSOR_PO1030] = sn_po1030,
555[SENSOR_PO2030N] = sn_po2030n,
556[SENSOR_SOI768] = sn_soi768,
557[SENSOR_SP80708] = sn_sp80708,
558};
559
560/* default gamma table */
561static const u8 gamma_def[17] = {
562 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
563 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
564};
565/* gamma for sensor ADCM1700 */
566static const u8 gamma_spec_0[17] = {
567 0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
568 0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
569};
570/* gamma for sensors HV7131R and MT9V111 */
571static const u8 gamma_spec_1[17] = {
572 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
573 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
574};
575/* gamma for sensor GC0307 */
576static const u8 gamma_spec_2[17] = {
577 0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
578 0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
579};
580/* gamma for sensor SP80708 */
581static const u8 gamma_spec_3[17] = {
582 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
583 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
584};
585
586/* color matrix and offsets */
587static const u8 reg84[] = {
588 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
589 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
590 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
591 0x00, 0x00, 0x00 /* YUV offsets */
592};
593
594#define DELAY 0xdd
595
596static const u8 adcm1700_sensor_init[][8] = {
597 {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
598 {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */
599 {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
600 {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
601 {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
602 {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
603 {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
604 {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
605 {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
606 {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
607 {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
608 {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
609 {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
610 {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
611 {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
612 {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
613 {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
614 {}
615};
616static const u8 adcm1700_sensor_param1[][8] = {
617 {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */
618 {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
619
620 {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
621 {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
622 {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
623 {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
624 {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */
625
626 {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
627 {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
628 {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
629 {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
630 {}
631};
632static const u8 gc0307_sensor_init[][8] = {
633 {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
634 {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
635 {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
636 {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
637 {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
638 {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
639 {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
640 {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
641 {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
642 {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
643 {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
644 {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
645 {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
646 {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
647 {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
648 {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
649 {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
650 {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
651 {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
652 {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
653 {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
654 {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
655 {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
656 {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
657 {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
658 {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
659 {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
660 {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
661 {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
662 {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
663 {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
664 {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
665 {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
666 {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
667 {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
668 {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
669 {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
670 {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
671 {}
672};
673static const u8 gc0307_sensor_param1[][8] = {
674 {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
675 {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
676 {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
677 {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
678/*param3*/
679 {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
680 {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
681 {}
682};
683
684static const u8 hv7131r_sensor_init[][8] = {
685 {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
686 {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
687 {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
688/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
689 {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
690 {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
691/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
692
693 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
694 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
695 {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
696 {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
697 {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
698 {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
699 {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
700 {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
701
702 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
703 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
704 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
705 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
706 {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
707
708 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
709 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
710 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
711 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
712 {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
713 {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
714 /* set sensor clock */
715 {}
716};
717static const u8 mi0360_sensor_init[][8] = {
718 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
719 {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
720 {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
721 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
722 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
723 {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
724 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
725 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
726 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
727 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
728 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
729 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
730 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
731 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
732 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
733 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
734 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
735 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
736 {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
737 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
738 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
739 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
740 {0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
741 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
742 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
743 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
744 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
745 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
746 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
747 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
748 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
749 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
750 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
751
752 {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
753 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
754 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
755 {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
756 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
757
758 {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
759 {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
760 {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
761 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
762
763 {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
764 {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
765/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
766/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
767 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
768 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
769 {}
770};
771static const u8 mi0360b_sensor_init[][8] = {
772 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
773 {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
774 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
775 {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
776 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
777 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
778 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
779 {0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
780 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
781 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
782 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
783 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
784 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
785 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
786 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
787 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
788 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
789 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
790 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
791 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
792 {0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
793 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
794 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
795 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
796 {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
797 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
798 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
799 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
800 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
801 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
802 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
803 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
804 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
805 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
806 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
807
808 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
809 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
810 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
811 {0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
812 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
813 {}
814};
815static const u8 mi0360b_sensor_param1[][8] = {
816 {0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
817 {0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
818 {0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
819 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
820
821 {0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
822 {0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
823 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
824 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
825 {}
826};
827static const u8 mo4000_sensor_init[][8] = {
828 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
829 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
830 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
831 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
832 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
833 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
834 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
835 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
836 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
837 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
838 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
839 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
840 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
841 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
842 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
843 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
844 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
845 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
846 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
847 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
848 {}
849};
850static const u8 mt9v111_sensor_init[][8] = {
851 {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
852 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
853 {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
854 {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
855 {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
856 {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
857 {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
858 {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
859 {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
860 {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
861 {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
862 {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
863 {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
864 {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
865 {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
866 {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
867 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
868 {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
869 {}
870};
871static const u8 mt9v111_sensor_param1[][8] = {
872 {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
873 {0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
874 {0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
875 {0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
876 {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
877 {}
878};
879static const u8 om6802_init0[2][8] = {
880/*fixme: variable*/
881 {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
882 {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
883};
884static const u8 om6802_sensor_init[][8] = {
885 {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
886 /* factory mode */
887 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
888 /* output raw RGB */
889 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
890/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
891 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
892 /* auto-exposure speed (0) / white balance mode (auto RGB) */
893/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
894 * set color mode */
895/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
896 * max AGC value in AE */
897/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
898 * preset AGC */
899/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
900 * preset brightness */
901/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
902 * preset contrast */
903/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
904 * preset gamma */
905 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
906 /* luminance mode (0x4f -> AutoExpo on) */
907 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
908 /* preset shutter */
909/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
910 * auto frame rate */
911/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
912 {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
913 {}
914};
915static const u8 om6802_sensor_param1[][8] = {
916 {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
917 {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
918 {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
919 {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
920 {}
921};
922static const u8 ov7630_sensor_init[][8] = {
923 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
924 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
925 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
926 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
927 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
928 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
929 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
930/* win: i2c_r from 00 to 80 */
931 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
932 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
933/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
934 0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
935 {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
936 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
937 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
938 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
939 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
940 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
941 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
942 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
943 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
944 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
945 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
946 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
947 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
948 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
949 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
950 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
951 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
952 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
953 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
954 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
955 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
956 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
957 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
958 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
959 {}
960};
961static const u8 ov7630_sensor_param1[][8] = {
962 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
963 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
964/*fixme: + 0x12, 0x04*/
965/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
966 * set by setvflip */
967 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
968 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
969 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
970/* */
971/* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
972/* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
973/* */
974 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
975/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
976 {}
977};
978
979static const u8 ov7648_sensor_init[][8] = {
980 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
981 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
982 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
983 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
984 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
985 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
986 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
987 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
988 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
989 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
990 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
991 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
992 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
993 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
994 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
995 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
996 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
997 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
998 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
999 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
1000 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
1001 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
1002
1003 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
1004/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
1005/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
1006/* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
1007 {}
1008};
1009static const u8 ov7648_sensor_param1[][8] = {
1010/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
1011/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN
1012 * set by setvflip */
1013 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
1014 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
1015/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1016/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
1017/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
1018/*...*/
1019 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
1020/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1021/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1022/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
1023/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
1024/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
1025
1026 {}
1027};
1028
1029static const u8 ov7660_sensor_init[][8] = {
1030 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
1031 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1032 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
1033 /* Outformat = rawRGB */
1034 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
1035 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
1036 /* GAIN BLUE RED VREF */
1037 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
1038 /* COM 1 BAVE GEAVE AECHH */
1039 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
1040 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
1041 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
1042 /* AECH CLKRC COM7 COM8 */
1043 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
1044 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
1045 /* HSTART HSTOP VSTRT VSTOP */
1046 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
1047 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
1048 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
1049 /* BOS GBOS GROS ROS (BGGR offset) */
1050/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
1051 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
1052 /* AEW AEB VPT BBIAS */
1053 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
1054 /* GbBIAS RSVD EXHCH EXHCL */
1055 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
1056 /* RBIAS ADVFL ASDVFH YAVE */
1057 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
1058 /* HSYST HSYEN HREF */
1059 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
1060 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
1061 /* ADC ACOM OFON TSLB */
1062 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
1063 /* COM11 COM12 COM13 COM14 */
1064 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
1065 /* EDGE COM15 COM16 COM17 */
1066 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
1067 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
1068 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
1069 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
1070 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
1071 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
1072 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
1073 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
1074 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
1075 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
1076 /* LCC1 LCC2 LCC3 LCC4 */
1077 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
1078 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
1079 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
1080 /* band gap reference [0:3] DBLV */
1081 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
1082 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
1083 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
1084 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
1085 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
1086 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
1087 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
1088 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
1089 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
1090 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
1091/* not in all ms-win traces*/
1092 {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
1093 {}
1094};
1095static const u8 ov7660_sensor_param1[][8] = {
1096 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
1097 /* bits[3..0]reserved */
1098 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
1099 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
1100 /* VREF vertical frame ctrl */
1101 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
1102 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
1103 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
1104 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
1105 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
1106/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
1107/****** (some exchanges in the win trace) ******/
1108/*fixme:param2*/
1109 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
1110 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
1111 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
1112 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
1113/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
1114/****** (some exchanges in the win trace) ******/
1115/******!! startsensor KO if changed !!****/
1116/*fixme: param3*/
1117 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
1118 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
1119 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
1120 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
1121 {}
1122};
1123
1124static const u8 po1030_sensor_init[][8] = {
1125/* the sensor registers are described in m5602/m5602_po1030.h */
1126 {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
1127 {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
1128 {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
1129 {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
1130 {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
1131 {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
1132 {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
1133 {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
1134 {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
1135 {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
1136 {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
1137 {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
1138 {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
1139 {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
1140 {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
1141 {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
1142 {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
1143 {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
1144 {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
1145 {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
1146 {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
1147 {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
1148 {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
1149 {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
1150 {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
1151 {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
1152 {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
1153 {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},
1154
1155 {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
1156 {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
1157 {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
1158 {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
1159 {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
1160 {}
1161};
1162static const u8 po1030_sensor_param1[][8] = {
1163/* from ms-win traces - these values change with auto gain/expo/wb.. */
1164 {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
1165 {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
1166/* mean values */
1167 {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
1168 {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
1169 {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */
1170
1171 {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
1172 {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
1173 {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
1174/* {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
1175 {}
1176};
1177
1178static const u8 po2030n_sensor_init[][8] = {
1179 {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
1180 {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
1181 {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
1182 {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
1183 {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
1184 {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
1185 {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
1186 {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
1187 {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
1188 {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
1189 {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
1190 {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
1191 {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
1192 {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
1193 {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
1194 {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
1195 {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
1196 {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
1197 {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
1198 {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
1199 {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
1200 {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
1201 {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
1202 {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
1203 {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
1204 {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
1205 {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
1206 {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
1207 {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
1208 {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
1209 {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
1210 {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
1211 {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
1212 {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
1213 {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
1214 {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
1215 {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
1216 {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
1217 {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
1218 {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
1219 {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
1220 {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
1221 {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
1222 {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
1223 {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
1224 {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
1225 {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
1226 {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
1227 {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
1228 {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
1229 {}
1230};
1231static const u8 po2030n_sensor_param1[][8] = {
1232 {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
1233 {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
1234 {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
1235 {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
1236 {0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10},
1237/*param2*/
1238 {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
1239 {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
1240 {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
1241 {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
1242 {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
1243 {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
1244 {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10},
1245/*after start*/
1246 {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10},
1247 {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */
1248 {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10},
1249 {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */
1250 {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10},
1251 {}
1252};
1253
1254static const u8 soi768_sensor_init[][8] = {
1255 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
1256 {DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
1257 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
1258 {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
1259 {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
1260 {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
1261 {}
1262};
1263static const u8 soi768_sensor_param1[][8] = {
1264 {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
1265 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
1266 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
1267 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1268 {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
1269/* */
1270/* {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
1271/* {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
1272 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
1273/* {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
1274 {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
1275/* the next sequence should be used for auto gain */
1276 {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
1277 /* global gain ? : 07 - change with 0x15 at the end */
1278 {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
1279 {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
1280 {0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
1281 /* exposure ? : 0200 - change with 0x1e at the end */
1282 {}
1283};
1284
1285static const u8 sp80708_sensor_init[][8] = {
1286 {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
1287 {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
1288 {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
1289 {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
1290 {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
1291 {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
1292 {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
1293 {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
1294 {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
1295 {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
1296 {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
1297 {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
1298 {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
1299 {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
1300 {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
1301 {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
1302 {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
1303 {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
1304 {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
1305 {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
1306 {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
1307 {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
1308 {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
1309 {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
1310 {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
1311 {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
1312 {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
1313 {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
1314 {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
1315 {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
1316 {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
1317 {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
1318 {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
1319 {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
1320 {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
1321 {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
1322 {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
1323 {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
1324 {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
1325 {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
1326 {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
1327 {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
1328 {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
1329 {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
1330 {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
1331 {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
1332 {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
1333 {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
1334 {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
1335 {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
1336 {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
1337 {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
1338 {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
1339 {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
1340 {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
1341 {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
1342 {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
1343 {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
1344 {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
1345 {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
1346 {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
1347 {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
1348 {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
1349 {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
1350 {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
1351 {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
1352 {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
1353 {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
1354 {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
1355 {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
1356 {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
1357 {}
1358};
1359static const u8 sp80708_sensor_param1[][8] = {
1360 {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
1361 {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
1362 {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
1363 {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
1364 {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
1365 {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
1366 {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
1367 {}
1368};
1369
1370static const u8 (*sensor_init[])[8] = {
1371[SENSOR_ADCM1700] = adcm1700_sensor_init,
1372[SENSOR_GC0307] = gc0307_sensor_init,
1373[SENSOR_HV7131R] = hv7131r_sensor_init,
1374[SENSOR_MI0360] = mi0360_sensor_init,
1375[SENSOR_MI0360B] = mi0360b_sensor_init,
1376[SENSOR_MO4000] = mo4000_sensor_init,
1377[SENSOR_MT9V111] = mt9v111_sensor_init,
1378[SENSOR_OM6802] = om6802_sensor_init,
1379[SENSOR_OV7630] = ov7630_sensor_init,
1380[SENSOR_OV7648] = ov7648_sensor_init,
1381[SENSOR_OV7660] = ov7660_sensor_init,
1382[SENSOR_PO1030] = po1030_sensor_init,
1383[SENSOR_PO2030N] = po2030n_sensor_init,
1384[SENSOR_SOI768] = soi768_sensor_init,
1385[SENSOR_SP80708] = sp80708_sensor_init,
1386};
1387
1388/* read <len> bytes to gspca_dev->usb_buf */
1389static void reg_r(struct gspca_dev *gspca_dev,
1390 u16 value, int len)
1391{
1392 int ret;
1393
1394 if (gspca_dev->usb_err < 0)
1395 return;
1396#ifdef GSPCA_DEBUG
1397 if (len > USB_BUF_SZ) {
1398 err("reg_r: buffer overflow");
1399 return;
1400 }
1401#endif
1402 ret = usb_control_msg(gspca_dev->dev,
1403 usb_rcvctrlpipe(gspca_dev->dev, 0),
1404 0,
1405 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1406 value, 0,
1407 gspca_dev->usb_buf, len,
1408 500);
1409 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
1410 if (ret < 0) {
1411 err("reg_r err %d", ret);
1412 gspca_dev->usb_err = ret;
1413 }
1414}
1415
1416static void reg_w1(struct gspca_dev *gspca_dev,
1417 u16 value,
1418 u8 data)
1419{
1420 int ret;
1421
1422 if (gspca_dev->usb_err < 0)
1423 return;
1424 PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
1425 gspca_dev->usb_buf[0] = data;
1426 ret = usb_control_msg(gspca_dev->dev,
1427 usb_sndctrlpipe(gspca_dev->dev, 0),
1428 0x08,
1429 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1430 value,
1431 0,
1432 gspca_dev->usb_buf, 1,
1433 500);
1434 if (ret < 0) {
1435 err("reg_w1 err %d", ret);
1436 gspca_dev->usb_err = ret;
1437 }
1438}
1439static void reg_w(struct gspca_dev *gspca_dev,
1440 u16 value,
1441 const u8 *buffer,
1442 int len)
1443{
1444 int ret;
1445
1446 if (gspca_dev->usb_err < 0)
1447 return;
1448 PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
1449 value, buffer[0], buffer[1]);
1450#ifdef GSPCA_DEBUG
1451 if (len > USB_BUF_SZ) {
1452 err("reg_w: buffer overflow");
1453 return;
1454 }
1455#endif
1456 memcpy(gspca_dev->usb_buf, buffer, len);
1457 ret = usb_control_msg(gspca_dev->dev,
1458 usb_sndctrlpipe(gspca_dev->dev, 0),
1459 0x08,
1460 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1461 value, 0,
1462 gspca_dev->usb_buf, len,
1463 500);
1464 if (ret < 0) {
1465 err("reg_w err %d", ret);
1466 gspca_dev->usb_err = ret;
1467 }
1468}
1469
1470/* I2C write 1 byte */
1471static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1472{
1473 struct sd *sd = (struct sd *) gspca_dev;
1474 int ret;
1475
1476 if (gspca_dev->usb_err < 0)
1477 return;
1478 PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val);
1479 switch (sd->sensor) {
1480 case SENSOR_ADCM1700:
1481 case SENSOR_OM6802:
1482 case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */
1483 gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
1484 break;
1485 default: /* i2c command = a1 (400 kHz) */
1486 gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
1487 break;
1488 }
1489 gspca_dev->usb_buf[1] = sd->i2c_addr;
1490 gspca_dev->usb_buf[2] = reg;
1491 gspca_dev->usb_buf[3] = val;
1492 gspca_dev->usb_buf[4] = 0;
1493 gspca_dev->usb_buf[5] = 0;
1494 gspca_dev->usb_buf[6] = 0;
1495 gspca_dev->usb_buf[7] = 0x10;
1496 ret = usb_control_msg(gspca_dev->dev,
1497 usb_sndctrlpipe(gspca_dev->dev, 0),
1498 0x08,
1499 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1500 0x08, /* value = i2c */
1501 0,
1502 gspca_dev->usb_buf, 8,
1503 500);
1504 if (ret < 0) {
1505 err("i2c_w1 err %d", ret);
1506 gspca_dev->usb_err = ret;
1507 }
1508}
1509
1510/* I2C write 8 bytes */
1511static void i2c_w8(struct gspca_dev *gspca_dev,
1512 const u8 *buffer)
1513{
1514 int ret;
1515
1516 if (gspca_dev->usb_err < 0)
1517 return;
1518 PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..",
1519 buffer[2], buffer[3]);
1520 memcpy(gspca_dev->usb_buf, buffer, 8);
1521 ret = usb_control_msg(gspca_dev->dev,
1522 usb_sndctrlpipe(gspca_dev->dev, 0),
1523 0x08,
1524 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1525 0x08, 0, /* value, index */
1526 gspca_dev->usb_buf, 8,
1527 500);
1528 msleep(2);
1529 if (ret < 0) {
1530 err("i2c_w8 err %d", ret);
1531 gspca_dev->usb_err = ret;
1532 }
1533}
1534
1535/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
1536static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
1537{
1538 struct sd *sd = (struct sd *) gspca_dev;
1539 u8 mode[8];
1540
1541 switch (sd->sensor) {
1542 case SENSOR_ADCM1700:
1543 case SENSOR_OM6802:
1544 case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */
1545 mode[0] = 0x80 | 0x10;
1546 break;
1547 default: /* i2c command = 91 (400 kHz) */
1548 mode[0] = 0x81 | 0x10;
1549 break;
1550 }
1551 mode[1] = sd->i2c_addr;
1552 mode[2] = reg;
1553 mode[3] = 0;
1554 mode[4] = 0;
1555 mode[5] = 0;
1556 mode[6] = 0;
1557 mode[7] = 0x10;
1558 i2c_w8(gspca_dev, mode);
1559 msleep(2);
1560 mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
1561 mode[2] = 0;
1562 i2c_w8(gspca_dev, mode);
1563 msleep(2);
1564 reg_r(gspca_dev, 0x0a, 5);
1565}
1566
1567static void i2c_w_seq(struct gspca_dev *gspca_dev,
1568 const u8 (*data)[8])
1569{
1570 while ((*data)[0] != 0) {
1571 if ((*data)[0] != DELAY)
1572 i2c_w8(gspca_dev, *data);
1573 else
1574 msleep((*data)[1]);
1575 data++;
1576 }
1577}
1578
1579/* check the ID of the hv7131 sensor */
1580/* this sequence is needed because it activates the sensor */
1581static void hv7131r_probe(struct gspca_dev *gspca_dev)
1582{
1583 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
1584 msleep(10);
1585 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
1586 msleep(10);
1587 i2c_r(gspca_dev, 0, 5); /* read sensor id */
1588 if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */
1589 && gspca_dev->usb_buf[1] == 0x09
1590 && gspca_dev->usb_buf[2] == 0x01) {
1591 PDEBUG(D_PROBE, "Sensor HV7131R found");
1592 return;
1593 }
1594 warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x",
1595 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
1596 gspca_dev->usb_buf[2]);
1597}
1598
1599static void mi0360_probe(struct gspca_dev *gspca_dev)
1600{
1601 struct sd *sd = (struct sd *) gspca_dev;
1602 int i, j;
1603 u16 val = 0;
1604 static const u8 probe_tb[][4][8] = {
1605 { /* mi0360 */
1606 {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
1607 {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1608 {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1609 {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
1610 },
1611 { /* mt9v111 */
1612 {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
1613 {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
1614 {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
1615 {}
1616 },
1617 };
1618
1619 for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
1620 reg_w1(gspca_dev, 0x17, 0x62);
1621 reg_w1(gspca_dev, 0x01, 0x08);
1622 for (j = 0; j < 3; j++)
1623 i2c_w8(gspca_dev, probe_tb[i][j]);
1624 msleep(2);
1625 reg_r(gspca_dev, 0x0a, 5);
1626 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1627 if (probe_tb[i][3][0] != 0)
1628 i2c_w8(gspca_dev, probe_tb[i][3]);
1629 reg_w1(gspca_dev, 0x01, 0x29);
1630 reg_w1(gspca_dev, 0x17, 0x42);
1631 if (val != 0xffff)
1632 break;
1633 }
1634 if (gspca_dev->usb_err < 0)
1635 return;
1636 switch (val) {
1637 case 0x8221:
1638 PDEBUG(D_PROBE, "Sensor mi0360b");
1639 sd->sensor = SENSOR_MI0360B;
1640 break;
1641 case 0x823a:
1642 PDEBUG(D_PROBE, "Sensor mt9v111");
1643 sd->sensor = SENSOR_MT9V111;
1644 break;
1645 case 0x8243:
1646 PDEBUG(D_PROBE, "Sensor mi0360");
1647 break;
1648 default:
1649 PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
1650 break;
1651 }
1652}
1653
1654static void ov7630_probe(struct gspca_dev *gspca_dev)
1655{
1656 struct sd *sd = (struct sd *) gspca_dev;
1657 u16 val;
1658
1659 /* check ov76xx */
1660 reg_w1(gspca_dev, 0x17, 0x62);
1661 reg_w1(gspca_dev, 0x01, 0x08);
1662 sd->i2c_addr = 0x21;
1663 i2c_r(gspca_dev, 0x0a, 2);
1664 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1665 reg_w1(gspca_dev, 0x01, 0x29);
1666 reg_w1(gspca_dev, 0x17, 0x42);
1667 if (gspca_dev->usb_err < 0)
1668 return;
1669 if (val == 0x7628) { /* soi768 */
1670 sd->sensor = SENSOR_SOI768;
1671/*fixme: only valid for 0c45:613e?*/
1672 gspca_dev->cam.input_flags =
1673 V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
1674 PDEBUG(D_PROBE, "Sensor soi768");
1675 return;
1676 }
1677 PDEBUG(D_PROBE, "Sensor ov%04x", val);
1678}
1679
1680static void ov7648_probe(struct gspca_dev *gspca_dev)
1681{
1682 struct sd *sd = (struct sd *) gspca_dev;
1683 u16 val;
1684
1685 /* check ov76xx */
1686 reg_w1(gspca_dev, 0x17, 0x62);
1687 reg_w1(gspca_dev, 0x01, 0x08);
1688 sd->i2c_addr = 0x21;
1689 i2c_r(gspca_dev, 0x0a, 2);
1690 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1691 reg_w1(gspca_dev, 0x01, 0x29);
1692 reg_w1(gspca_dev, 0x17, 0x42);
1693 if ((val & 0xff00) == 0x7600) { /* ov76xx */
1694 PDEBUG(D_PROBE, "Sensor ov%04x", val);
1695 return;
1696 }
1697
1698 /* check po1030 */
1699 reg_w1(gspca_dev, 0x17, 0x62);
1700 reg_w1(gspca_dev, 0x01, 0x08);
1701 sd->i2c_addr = 0x6e;
1702 i2c_r(gspca_dev, 0x00, 2);
1703 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1704 reg_w1(gspca_dev, 0x01, 0x29);
1705 reg_w1(gspca_dev, 0x17, 0x42);
1706 if (gspca_dev->usb_err < 0)
1707 return;
1708 if (val == 0x1030) { /* po1030 */
1709 PDEBUG(D_PROBE, "Sensor po1030");
1710 sd->sensor = SENSOR_PO1030;
1711 return;
1712 }
1713 err("Unknown sensor %04x", val);
1714}
1715
1716/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
1717static void po2030n_probe(struct gspca_dev *gspca_dev)
1718{
1719 struct sd *sd = (struct sd *) gspca_dev;
1720 u16 val;
1721
1722 /* check gc0307 */
1723 reg_w1(gspca_dev, 0x17, 0x62);
1724 reg_w1(gspca_dev, 0x01, 0x08);
1725 reg_w1(gspca_dev, 0x02, 0x22);
1726 sd->i2c_addr = 0x21;
1727 i2c_r(gspca_dev, 0x00, 1);
1728 val = gspca_dev->usb_buf[4];
1729 reg_w1(gspca_dev, 0x01, 0x29); /* reset */
1730 reg_w1(gspca_dev, 0x17, 0x42);
1731 if (val == 0x99) { /* gc0307 (?) */
1732 PDEBUG(D_PROBE, "Sensor gc0307");
1733 sd->sensor = SENSOR_GC0307;
1734 return;
1735 }
1736
1737 /* check po2030n */
1738 reg_w1(gspca_dev, 0x17, 0x62);
1739 reg_w1(gspca_dev, 0x01, 0x0a);
1740 sd->i2c_addr = 0x6e;
1741 i2c_r(gspca_dev, 0x00, 2);
1742 val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
1743 reg_w1(gspca_dev, 0x01, 0x29);
1744 reg_w1(gspca_dev, 0x17, 0x42);
1745 if (gspca_dev->usb_err < 0)
1746 return;
1747 if (val == 0x2030) {
1748 PDEBUG(D_PROBE, "Sensor po2030n");
1749/* sd->sensor = SENSOR_PO2030N; */
1750 } else {
1751 err("Unknown sensor ID %04x", val);
1752 }
1753}
1754
1755/* this function is called at probe time */
1756static int sd_config(struct gspca_dev *gspca_dev,
1757 const struct usb_device_id *id)
1758{
1759 struct sd *sd = (struct sd *) gspca_dev;
1760 struct cam *cam;
1761
1762 sd->bridge = id->driver_info >> 16;
1763 sd->sensor = id->driver_info >> 8;
1764 sd->flags = id->driver_info;
1765
1766 cam = &gspca_dev->cam;
1767 if (sd->sensor == SENSOR_ADCM1700) {
1768 cam->cam_mode = cif_mode;
1769 cam->nmodes = ARRAY_SIZE(cif_mode);
1770 } else {
1771 cam->cam_mode = vga_mode;
1772 cam->nmodes = ARRAY_SIZE(vga_mode);
1773 }
1774 cam->npkt = 24; /* 24 packets per ISOC message */
1775 cam->ctrls = sd->ctrls;
1776
1777 sd->ag_cnt = -1;
1778 sd->quality = QUALITY_DEF;
1779
1780 /* if USB 1.1, let some bandwidth for the audio device */
1781 if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
1782 gspca_dev->nbalt--;
1783
1784 INIT_WORK(&sd->work, qual_upd);
1785
1786 return 0;
1787}
1788
1789/* this function is called at probe and resume time */
1790static int sd_init(struct gspca_dev *gspca_dev)
1791{
1792 struct sd *sd = (struct sd *) gspca_dev;
1793 const u8 *sn9c1xx;
1794 u8 regGpio[] = { 0x29, 0x70 }; /* no audio */
1795 u8 regF1;
1796
1797 /* setup a selector by bridge */
1798 reg_w1(gspca_dev, 0xf1, 0x01);
1799 reg_r(gspca_dev, 0x00, 1);
1800 reg_w1(gspca_dev, 0xf1, 0x00);
1801 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
1802 regF1 = gspca_dev->usb_buf[0];
1803 if (gspca_dev->usb_err < 0)
1804 return gspca_dev->usb_err;
1805 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
1806 if (gspca_dev->audio)
1807 regGpio[1] |= 0x04; /* with audio */
1808 switch (sd->bridge) {
1809 case BRIDGE_SN9C102P:
1810 case BRIDGE_SN9C105:
1811 if (regF1 != 0x11)
1812 return -ENODEV;
1813 break;
1814 default:
1815/* case BRIDGE_SN9C110: */
1816/* case BRIDGE_SN9C120: */
1817 if (regF1 != 0x12)
1818 return -ENODEV;
1819 }
1820
1821 switch (sd->sensor) {
1822 case SENSOR_MI0360:
1823 mi0360_probe(gspca_dev);
1824 break;
1825 case SENSOR_OV7630:
1826 ov7630_probe(gspca_dev);
1827 break;
1828 case SENSOR_OV7648:
1829 ov7648_probe(gspca_dev);
1830 break;
1831 case SENSOR_PO2030N:
1832 po2030n_probe(gspca_dev);
1833 break;
1834 }
1835
1836 switch (sd->bridge) {
1837 case BRIDGE_SN9C102P:
1838 reg_w1(gspca_dev, 0x02, regGpio[1]);
1839 break;
1840 default:
1841 reg_w(gspca_dev, 0x01, regGpio, 2);
1842 break;
1843 }
1844
1845 if (sd->sensor == SENSOR_OM6802)
1846 sd->ctrls[SHARPNESS].def = 0x10;
1847
1848 /* Note we do not disable the sensor clock here (power saving mode),
1849 as that also disables the button on the cam. */
1850 reg_w1(gspca_dev, 0xf1, 0x00);
1851
1852 /* set the i2c address */
1853 sn9c1xx = sn_tb[sd->sensor];
1854 sd->i2c_addr = sn9c1xx[9];
1855
1856 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
1857 if (!(sd->flags & F_ILLUM))
1858 gspca_dev->ctrl_dis |= (1 << ILLUM);
1859
1860 return gspca_dev->usb_err;
1861}
1862
1863static u32 setexposure(struct gspca_dev *gspca_dev,
1864 u32 expo)
1865{
1866 struct sd *sd = (struct sd *) gspca_dev;
1867
1868 switch (sd->sensor) {
1869 case SENSOR_GC0307: {
1870 int a, b;
1871
1872 /* expo = 0..255 -> a = 19..43 */
1873 a = 19 + expo * 25 / 256;
1874 i2c_w1(gspca_dev, 0x68, a);
1875 a -= 12;
1876 b = a * a * 4; /* heuristic */
1877 i2c_w1(gspca_dev, 0x03, b >> 8);
1878 i2c_w1(gspca_dev, 0x04, b);
1879 break;
1880 }
1881 case SENSOR_HV7131R: {
1882 u8 Expodoit[] =
1883 { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
1884
1885 Expodoit[3] = expo >> 16;
1886 Expodoit[4] = expo >> 8;
1887 Expodoit[5] = expo;
1888 i2c_w8(gspca_dev, Expodoit);
1889 break;
1890 }
1891 case SENSOR_MI0360:
1892 case SENSOR_MI0360B: {
1893 u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1894 { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
1895 static const u8 doit[] = /* update sensor */
1896 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1897 static const u8 sensorgo[] = /* sensor on */
1898 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1899
1900 if (expo > 0x0635)
1901 expo = 0x0635;
1902 else if (expo < 0x0001)
1903 expo = 0x0001;
1904 expoMi[3] = expo >> 8;
1905 expoMi[4] = expo;
1906 i2c_w8(gspca_dev, expoMi);
1907 i2c_w8(gspca_dev, doit);
1908 i2c_w8(gspca_dev, sensorgo);
1909 break;
1910 }
1911 case SENSOR_MO4000: {
1912 u8 expoMof[] =
1913 { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
1914 u8 expoMo10[] =
1915 { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
1916 static const u8 gainMo[] =
1917 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1918
1919 if (expo > 0x1fff)
1920 expo = 0x1fff;
1921 else if (expo < 0x0001)
1922 expo = 0x0001;
1923 expoMof[3] = (expo & 0x03fc) >> 2;
1924 i2c_w8(gspca_dev, expoMof);
1925 expoMo10[3] = ((expo & 0x1c00) >> 10)
1926 | ((expo & 0x0003) << 4);
1927 i2c_w8(gspca_dev, expoMo10);
1928 i2c_w8(gspca_dev, gainMo);
1929 PDEBUG(D_FRAM, "set exposure %d",
1930 ((expoMo10[3] & 0x07) << 10)
1931 | (expoMof[3] << 2)
1932 | ((expoMo10[3] & 0x30) >> 4));
1933 break;
1934 }
1935 case SENSOR_MT9V111: {
1936 u8 expo_c1[] =
1937 { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
1938
1939 if (expo > 0x0390)
1940 expo = 0x0390;
1941 else if (expo < 0x0060)
1942 expo = 0x0060;
1943 expo_c1[3] = expo >> 8;
1944 expo_c1[4] = expo;
1945 i2c_w8(gspca_dev, expo_c1);
1946 break;
1947 }
1948 case SENSOR_OM6802: {
1949 u8 gainOm[] =
1950 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1951 /* preset AGC - works when AutoExpo = off */
1952
1953 if (expo > 0x03ff)
1954 expo = 0x03ff;
1955 if (expo < 0x0001)
1956 expo = 0x0001;
1957 gainOm[3] = expo >> 2;
1958 i2c_w8(gspca_dev, gainOm);
1959 reg_w1(gspca_dev, 0x96, expo >> 5);
1960 PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
1961 break;
1962 }
1963 }
1964 return expo;
1965}
1966
1967static void setbrightness(struct gspca_dev *gspca_dev)
1968{
1969 struct sd *sd = (struct sd *) gspca_dev;
1970 unsigned int expo;
1971 int brightness;
1972 u8 k2;
1973
1974 brightness = sd->ctrls[BRIGHTNESS].val;
1975 k2 = (brightness - 0x80) >> 2;
1976 switch (sd->sensor) {
1977 case SENSOR_ADCM1700:
1978 if (k2 > 0x1f)
1979 k2 = 0; /* only positive Y offset */
1980 break;
1981 case SENSOR_HV7131R:
1982 expo = brightness << 12;
1983 if (expo > 0x002dc6c0)
1984 expo = 0x002dc6c0;
1985 else if (expo < 0x02a0)
1986 expo = 0x02a0;
1987 sd->exposure = setexposure(gspca_dev, expo);
1988 break;
1989 case SENSOR_MI0360:
1990 case SENSOR_MO4000:
1991 expo = brightness << 4;
1992 sd->exposure = setexposure(gspca_dev, expo);
1993 break;
1994 case SENSOR_MI0360B:
1995 expo = brightness << 2;
1996 sd->exposure = setexposure(gspca_dev, expo);
1997 break;
1998 case SENSOR_GC0307:
1999 expo = brightness;
2000 sd->exposure = setexposure(gspca_dev, expo);
2001 return; /* don't set the Y offset */
2002 case SENSOR_MT9V111:
2003 expo = brightness << 2;
2004 sd->exposure = setexposure(gspca_dev, expo);
2005 return; /* don't set the Y offset */
2006 case SENSOR_OM6802:
2007 expo = brightness << 2;
2008 sd->exposure = setexposure(gspca_dev, expo);
2009 k2 = brightness >> 3;
2010 break;
2011 }
2012
2013 reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
2014}
2015
2016static void setcontrast(struct gspca_dev *gspca_dev)
2017{
2018 struct sd *sd = (struct sd *) gspca_dev;
2019 u8 k2;
2020 u8 contrast[6];
2021
2022 k2 = sd->ctrls[CONTRAST].val * 0x30 / (CONTRAST_MAX + 1)
2023 + 0x10; /* 10..40 */
2024 contrast[0] = (k2 + 1) / 2; /* red */
2025 contrast[1] = 0;
2026 contrast[2] = k2; /* green */
2027 contrast[3] = 0;
2028 contrast[4] = (k2 + 1) / 5; /* blue */
2029 contrast[5] = 0;
2030 reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
2031}
2032
2033static void setcolors(struct gspca_dev *gspca_dev)
2034{
2035 struct sd *sd = (struct sd *) gspca_dev;
2036 int i, v, colors;
2037 const s16 *uv;
2038 u8 reg8a[12]; /* U & V gains */
2039 static const s16 uv_com[6] = { /* same as reg84 in signed decimal */
2040 -24, -38, 64, /* UR UG UB */
2041 62, -51, -9 /* VR VG VB */
2042 };
2043 static const s16 uv_mi0360b[6] = {
2044 -20, -38, 64, /* UR UG UB */
2045 60, -51, -9 /* VR VG VB */
2046 };
2047
2048 colors = sd->ctrls[COLORS].val;
2049 if (sd->sensor == SENSOR_MI0360B)
2050 uv = uv_mi0360b;
2051 else
2052 uv = uv_com;
2053 for (i = 0; i < 6; i++) {
2054 v = uv[i] * colors / COLORS_DEF;
2055 reg8a[i * 2] = v;
2056 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
2057 }
2058 reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
2059}
2060
2061static void setredblue(struct gspca_dev *gspca_dev)
2062{
2063 struct sd *sd = (struct sd *) gspca_dev;
2064
2065 reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
2066/* reg_w1(gspca_dev, 0x07, 32); */
2067 reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
2068}
2069
2070static void setgamma(struct gspca_dev *gspca_dev)
2071{
2072 struct sd *sd = (struct sd *) gspca_dev;
2073 int i, val;
2074 u8 gamma[17];
2075 const u8 *gamma_base;
2076 static const u8 delta[17] = {
2077 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
2078 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
2079 };
2080
2081 switch (sd->sensor) {
2082 case SENSOR_ADCM1700:
2083 gamma_base = gamma_spec_0;
2084 break;
2085 case SENSOR_HV7131R:
2086 case SENSOR_MI0360B:
2087 case SENSOR_MT9V111:
2088 gamma_base = gamma_spec_1;
2089 break;
2090 case SENSOR_GC0307:
2091 gamma_base = gamma_spec_2;
2092 break;
2093 case SENSOR_SP80708:
2094 gamma_base = gamma_spec_3;
2095 break;
2096 default:
2097 gamma_base = gamma_def;
2098 break;
2099 }
2100
2101 val = sd->ctrls[GAMMA].val;
2102 for (i = 0; i < sizeof gamma; i++)
2103 gamma[i] = gamma_base[i]
2104 + delta[i] * (val - GAMMA_DEF) / 32;
2105 reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
2106}
2107
2108static void setautogain(struct gspca_dev *gspca_dev)
2109{
2110 struct sd *sd = (struct sd *) gspca_dev;
2111
2112 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
2113 return;
2114 switch (sd->sensor) {
2115 case SENSOR_OV7630:
2116 case SENSOR_OV7648: {
2117 u8 comb;
2118
2119 if (sd->sensor == SENSOR_OV7630)
2120 comb = 0xc0;
2121 else
2122 comb = 0xa0;
2123 if (sd->ctrls[AUTOGAIN].val)
2124 comb |= 0x03;
2125 i2c_w1(&sd->gspca_dev, 0x13, comb);
2126 return;
2127 }
2128 }
2129 if (sd->ctrls[AUTOGAIN].val)
2130 sd->ag_cnt = AG_CNT_START;
2131 else
2132 sd->ag_cnt = -1;
2133}
2134
2135static void sethvflip(struct gspca_dev *gspca_dev)
2136{
2137 struct sd *sd = (struct sd *) gspca_dev;
2138 u8 comn;
2139
2140 switch (sd->sensor) {
2141 case SENSOR_HV7131R:
2142 comn = 0x18; /* clkdiv = 1, ablcen = 1 */
2143 if (sd->ctrls[VFLIP].val)
2144 comn |= 0x01;
2145 i2c_w1(gspca_dev, 0x01, comn); /* sctra */
2146 break;
2147 case SENSOR_OV7630:
2148 comn = 0x02;
2149 if (!sd->ctrls[VFLIP].val)
2150 comn |= 0x80;
2151 i2c_w1(gspca_dev, 0x75, comn);
2152 break;
2153 case SENSOR_OV7648:
2154 comn = 0x06;
2155 if (sd->ctrls[VFLIP].val)
2156 comn |= 0x80;
2157 i2c_w1(gspca_dev, 0x75, comn);
2158 break;
2159 case SENSOR_PO2030N:
2160 /* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
2161 * (reset value: 0x0A)
2162 * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
2163 * bit6: VM: Vertical Mirror: 0: disable, 1: enable
2164 * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
2165 * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
2166 * bit3-0: X
2167 */
2168 comn = 0x0a;
2169 if (sd->ctrls[HFLIP].val)
2170 comn |= 0x80;
2171 if (sd->ctrls[VFLIP].val)
2172 comn |= 0x40;
2173 i2c_w1(&sd->gspca_dev, 0x1e, comn);
2174 break;
2175 }
2176}
2177
2178static void setsharpness(struct gspca_dev *gspca_dev)
2179{
2180 struct sd *sd = (struct sd *) gspca_dev;
2181
2182 reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
2183}
2184
2185static void setillum(struct gspca_dev *gspca_dev)
2186{
2187 struct sd *sd = (struct sd *) gspca_dev;
2188
2189 if (gspca_dev->ctrl_dis & (1 << ILLUM))
2190 return;
2191 switch (sd->sensor) {
2192 case SENSOR_ADCM1700:
2193 reg_w1(gspca_dev, 0x02, /* gpio */
2194 sd->ctrls[ILLUM].val ? 0x64 : 0x60);
2195 break;
2196 case SENSOR_MT9V111:
2197 reg_w1(gspca_dev, 0x02,
2198 sd->ctrls[ILLUM].val ? 0x77 : 0x74);
2199/* should have been: */
2200/* 0x55 : 0x54); * 370i */
2201/* 0x66 : 0x64); * Clip */
2202 break;
2203 }
2204}
2205
2206static void setfreq(struct gspca_dev *gspca_dev)
2207{
2208 struct sd *sd = (struct sd *) gspca_dev;
2209
2210 if (gspca_dev->ctrl_dis & (1 << FREQ))
2211 return;
2212 if (sd->sensor == SENSOR_OV7660) {
2213 u8 com8;
2214
2215 com8 = 0xdf; /* auto gain/wb/expo */
2216 switch (sd->ctrls[FREQ].val) {
2217 case 0: /* Banding filter disabled */
2218 i2c_w1(gspca_dev, 0x13, com8 | 0x20);
2219 break;
2220 case 1: /* 50 hz */
2221 i2c_w1(gspca_dev, 0x13, com8);
2222 i2c_w1(gspca_dev, 0x3b, 0x0a);
2223 break;
2224 case 2: /* 60 hz */
2225 i2c_w1(gspca_dev, 0x13, com8);
2226 i2c_w1(gspca_dev, 0x3b, 0x02);
2227 break;
2228 }
2229 } else {
2230 u8 reg2a = 0, reg2b = 0, reg2d = 0;
2231
2232 /* Get reg2a / reg2d base values */
2233 switch (sd->sensor) {
2234 case SENSOR_OV7630:
2235 reg2a = 0x08;
2236 reg2d = 0x01;
2237 break;
2238 case SENSOR_OV7648:
2239 reg2a = 0x11;
2240 reg2d = 0x81;
2241 break;
2242 }
2243
2244 switch (sd->ctrls[FREQ].val) {
2245 case 0: /* Banding filter disabled */
2246 break;
2247 case 1: /* 50 hz (filter on and framerate adj) */
2248 reg2a |= 0x80;
2249 reg2b = 0xac;
2250 reg2d |= 0x04;
2251 break;
2252 case 2: /* 60 hz (filter on, no framerate adj) */
2253 reg2a |= 0x80;
2254 reg2d |= 0x04;
2255 break;
2256 }
2257 i2c_w1(gspca_dev, 0x2a, reg2a);
2258 i2c_w1(gspca_dev, 0x2b, reg2b);
2259 i2c_w1(gspca_dev, 0x2d, reg2d);
2260 }
2261}
2262
2263static void setjpegqual(struct gspca_dev *gspca_dev)
2264{
2265 struct sd *sd = (struct sd *) gspca_dev;
2266
2267 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2268#if USB_BUF_SZ < 64
2269#error "No room enough in usb_buf for quantization table"
2270#endif
2271 memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
2272 usb_control_msg(gspca_dev->dev,
2273 usb_sndctrlpipe(gspca_dev->dev, 0),
2274 0x08,
2275 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2276 0x0100, 0,
2277 gspca_dev->usb_buf, 64,
2278 500);
2279 memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
2280 usb_control_msg(gspca_dev->dev,
2281 usb_sndctrlpipe(gspca_dev->dev, 0),
2282 0x08,
2283 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
2284 0x0140, 0,
2285 gspca_dev->usb_buf, 64,
2286 500);
2287
2288 sd->reg18 ^= 0x40;
2289 reg_w1(gspca_dev, 0x18, sd->reg18);
2290}
2291
2292/* JPEG quality update */
2293/* This function is executed from a work queue. */
2294static void qual_upd(struct work_struct *work)
2295{
2296 struct sd *sd = container_of(work, struct sd, work);
2297 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2298
2299 mutex_lock(&gspca_dev->usb_lock);
2300 PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
2301 setjpegqual(gspca_dev);
2302 mutex_unlock(&gspca_dev->usb_lock);
2303}
2304
2305/* -- start the camera -- */
2306static int sd_start(struct gspca_dev *gspca_dev)
2307{
2308 struct sd *sd = (struct sd *) gspca_dev;
2309 int i;
2310 u8 reg01, reg17;
2311 u8 reg0102[2];
2312 const u8 *sn9c1xx;
2313 const u8 (*init)[8];
2314 const u8 *reg9a;
2315 int mode;
2316 static const u8 reg9a_def[] =
2317 {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
2318 static const u8 reg9a_spec[] =
2319 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
2320 static const u8 regd4[] = {0x60, 0x00, 0x00};
2321 static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
2322 static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
2323 static const u8 CA_adcm1700[] =
2324 { 0x14, 0xec, 0x0a, 0xf6 };
2325 static const u8 CA_po2030n[] =
2326 { 0x1e, 0xe2, 0x14, 0xec };
2327 static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
2328 static const u8 CE_gc0307[] =
2329 { 0x32, 0xce, 0x2d, 0xd3 };
2330 static const u8 CE_ov76xx[] =
2331 { 0x32, 0xdd, 0x32, 0xdd };
2332 static const u8 CE_po2030n[] =
2333 { 0x14, 0xe7, 0x1e, 0xdd };
2334
2335 /* create the JPEG header */
2336 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
2337 0x21); /* JPEG 422 */
2338
2339 /* initialize the bridge */
2340 sn9c1xx = sn_tb[sd->sensor];
2341
2342 /* sensor clock already enabled in sd_init */
2343 /* reg_w1(gspca_dev, 0xf1, 0x00); */
2344 reg01 = sn9c1xx[1];
2345 if (sd->flags & F_PDN_INV)
2346 reg01 ^= S_PDN_INV; /* power down inverted */
2347 reg_w1(gspca_dev, 0x01, reg01);
2348
2349 /* configure gpio */
2350 reg0102[0] = reg01;
2351 reg0102[1] = sn9c1xx[2];
2352 if (gspca_dev->audio)
2353 reg0102[1] |= 0x04; /* keep the audio connection */
2354 reg_w(gspca_dev, 0x01, reg0102, 2);
2355 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
2356 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
2357 switch (sd->sensor) {
2358 case SENSOR_GC0307:
2359 case SENSOR_OV7660:
2360 case SENSOR_PO1030:
2361 case SENSOR_PO2030N:
2362 case SENSOR_SOI768:
2363 case SENSOR_SP80708:
2364 reg9a = reg9a_spec;
2365 break;
2366 default:
2367 reg9a = reg9a_def;
2368 break;
2369 }
2370 reg_w(gspca_dev, 0x9a, reg9a, 6);
2371
2372 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
2373
2374 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
2375
2376 reg17 = sn9c1xx[0x17];
2377 switch (sd->sensor) {
2378 case SENSOR_GC0307:
2379 msleep(50); /*fixme: is it useful? */
2380 break;
2381 case SENSOR_OM6802:
2382 msleep(10);
2383 reg_w1(gspca_dev, 0x02, 0x73);
2384 reg17 |= SEN_CLK_EN;
2385 reg_w1(gspca_dev, 0x17, reg17);
2386 reg_w1(gspca_dev, 0x01, 0x22);
2387 msleep(100);
2388 reg01 = SCL_SEL_OD | S_PDN_INV;
2389 reg17 &= ~MCK_SIZE_MASK;
2390 reg17 |= 0x04; /* clock / 4 */
2391 break;
2392 }
2393 reg01 |= SYS_SEL_48M;
2394 reg_w1(gspca_dev, 0x01, reg01);
2395 reg17 |= SEN_CLK_EN;
2396 reg_w1(gspca_dev, 0x17, reg17);
2397 reg01 &= ~S_PWR_DN; /* sensor power on */
2398 reg_w1(gspca_dev, 0x01, reg01);
2399 reg01 &= ~SYS_SEL_48M;
2400 reg_w1(gspca_dev, 0x01, reg01);
2401
2402 switch (sd->sensor) {
2403 case SENSOR_HV7131R:
2404 hv7131r_probe(gspca_dev); /*fixme: is it useful? */
2405 break;
2406 case SENSOR_OM6802:
2407 msleep(10);
2408 reg_w1(gspca_dev, 0x01, reg01);
2409 i2c_w8(gspca_dev, om6802_init0[0]);
2410 i2c_w8(gspca_dev, om6802_init0[1]);
2411 msleep(15);
2412 reg_w1(gspca_dev, 0x02, 0x71);
2413 msleep(150);
2414 break;
2415 case SENSOR_SP80708:
2416 msleep(100);
2417 reg_w1(gspca_dev, 0x02, 0x62);
2418 break;
2419 }
2420
2421 /* initialize the sensor */
2422 i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
2423
2424 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
2425 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
2426 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
2427 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
2428 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
2429 if (sd->sensor == SENSOR_ADCM1700) {
2430 reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */
2431 reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */
2432 } else {
2433 reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */
2434 reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */
2435 }
2436 reg_w1(gspca_dev, 0xc6, 0x00);
2437 reg_w1(gspca_dev, 0xc7, 0x00);
2438 if (sd->sensor == SENSOR_ADCM1700) {
2439 reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */
2440 reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */
2441 } else {
2442 reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */
2443 reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */
2444 }
2445 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
2446 switch (sd->sensor) {
2447 case SENSOR_OM6802:
2448/* case SENSOR_OV7648: * fixme: sometimes */
2449 break;
2450 default:
2451 reg17 |= DEF_EN;
2452 break;
2453 }
2454 reg_w1(gspca_dev, 0x17, reg17);
2455
2456 reg_w1(gspca_dev, 0x05, 0x00); /* red */
2457 reg_w1(gspca_dev, 0x07, 0x00); /* green */
2458 reg_w1(gspca_dev, 0x06, 0x00); /* blue */
2459 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
2460
2461 setgamma(gspca_dev);
2462
2463/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
2464 for (i = 0; i < 8; i++)
2465 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
2466 switch (sd->sensor) {
2467 case SENSOR_ADCM1700:
2468 case SENSOR_OV7660:
2469 case SENSOR_SP80708:
2470 reg_w1(gspca_dev, 0x9a, 0x05);
2471 break;
2472 case SENSOR_GC0307:
2473 case SENSOR_MT9V111:
2474 case SENSOR_MI0360B:
2475 reg_w1(gspca_dev, 0x9a, 0x07);
2476 break;
2477 case SENSOR_OV7630:
2478 case SENSOR_OV7648:
2479 reg_w1(gspca_dev, 0x9a, 0x0a);
2480 break;
2481 case SENSOR_PO2030N:
2482 case SENSOR_SOI768:
2483 reg_w1(gspca_dev, 0x9a, 0x06);
2484 break;
2485 default:
2486 reg_w1(gspca_dev, 0x9a, 0x08);
2487 break;
2488 }
2489 setsharpness(gspca_dev);
2490
2491 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
2492 reg_w1(gspca_dev, 0x05, 0x20); /* red */
2493 reg_w1(gspca_dev, 0x07, 0x20); /* green */
2494 reg_w1(gspca_dev, 0x06, 0x20); /* blue */
2495
2496 init = NULL;
2497 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
2498 reg01 |= SYS_SEL_48M | V_TX_EN;
2499 reg17 &= ~MCK_SIZE_MASK;
2500 reg17 |= 0x02; /* clock / 2 */
2501 switch (sd->sensor) {
2502 case SENSOR_ADCM1700:
2503 init = adcm1700_sensor_param1;
2504 break;
2505 case SENSOR_GC0307:
2506 init = gc0307_sensor_param1;
2507 break;
2508 case SENSOR_HV7131R:
2509 case SENSOR_MI0360:
2510 if (mode)
2511 reg01 |= SYS_SEL_48M; /* 320x240: clk 48Mhz */
2512 else
2513 reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */
2514 reg17 &= ~MCK_SIZE_MASK;
2515 reg17 |= 0x01; /* clock / 1 */
2516 break;
2517 case SENSOR_MI0360B:
2518 init = mi0360b_sensor_param1;
2519 break;
2520 case SENSOR_MO4000:
2521 if (mode) { /* if 320x240 */
2522 reg01 &= ~SYS_SEL_48M; /* clk 24Mz */
2523 reg17 &= ~MCK_SIZE_MASK;
2524 reg17 |= 0x01; /* clock / 1 */
2525 }
2526 break;
2527 case SENSOR_MT9V111:
2528 init = mt9v111_sensor_param1;
2529 break;
2530 case SENSOR_OM6802:
2531 init = om6802_sensor_param1;
2532 if (!mode) { /* if 640x480 */
2533 reg17 &= ~MCK_SIZE_MASK;
2534 reg17 |= 0x04; /* clock / 4 */
2535 } else {
2536 reg01 &= ~SYS_SEL_48M; /* clk 24Mz */
2537 reg17 &= ~MCK_SIZE_MASK;
2538 reg17 |= 0x02; /* clock / 2 */
2539 }
2540 break;
2541 case SENSOR_OV7630:
2542 init = ov7630_sensor_param1;
2543 break;
2544 case SENSOR_OV7648:
2545 init = ov7648_sensor_param1;
2546 reg17 &= ~MCK_SIZE_MASK;
2547 reg17 |= 0x01; /* clock / 1 */
2548 break;
2549 case SENSOR_OV7660:
2550 init = ov7660_sensor_param1;
2551 break;
2552 case SENSOR_PO1030:
2553 init = po1030_sensor_param1;
2554 break;
2555 case SENSOR_PO2030N:
2556 init = po2030n_sensor_param1;
2557 break;
2558 case SENSOR_SOI768:
2559 init = soi768_sensor_param1;
2560 break;
2561 case SENSOR_SP80708:
2562 init = sp80708_sensor_param1;
2563 break;
2564 }
2565
2566 /* more sensor initialization - param1 */
2567 if (init != NULL) {
2568 i2c_w_seq(gspca_dev, init);
2569/* init = NULL; */
2570 }
2571
2572 reg_w(gspca_dev, 0xc0, C0, 6);
2573 switch (sd->sensor) {
2574 case SENSOR_ADCM1700:
2575 case SENSOR_GC0307:
2576 case SENSOR_SOI768:
2577 reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
2578 break;
2579 case SENSOR_PO2030N:
2580 reg_w(gspca_dev, 0xca, CA_po2030n, 4);
2581 break;
2582 default:
2583 reg_w(gspca_dev, 0xca, CA, 4);
2584 break;
2585 }
2586 switch (sd->sensor) {
2587 case SENSOR_ADCM1700:
2588 case SENSOR_OV7630:
2589 case SENSOR_OV7648:
2590 case SENSOR_OV7660:
2591 case SENSOR_SOI768:
2592 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
2593 break;
2594 case SENSOR_GC0307:
2595 reg_w(gspca_dev, 0xce, CE_gc0307, 4);
2596 break;
2597 case SENSOR_PO2030N:
2598 reg_w(gspca_dev, 0xce, CE_po2030n, 4);
2599 break;
2600 default:
2601 reg_w(gspca_dev, 0xce, CE, 4);
2602 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
2603 break;
2604 }
2605
2606 /* here change size mode 0 -> VGA; 1 -> CIF */
2607 sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
2608 reg_w1(gspca_dev, 0x18, sd->reg18);
2609 setjpegqual(gspca_dev);
2610
2611 reg_w1(gspca_dev, 0x17, reg17);
2612 reg_w1(gspca_dev, 0x01, reg01);
2613 sd->reg01 = reg01;
2614 sd->reg17 = reg17;
2615
2616 sethvflip(gspca_dev);
2617 setbrightness(gspca_dev);
2618 setcontrast(gspca_dev);
2619 setcolors(gspca_dev);
2620 setautogain(gspca_dev);
2621 setfreq(gspca_dev);
2622
2623 sd->pktsz = sd->npkt = 0;
2624 sd->nchg = sd->short_mark = 0;
2625 sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
2626
2627 return gspca_dev->usb_err;
2628}
2629
2630static void sd_stopN(struct gspca_dev *gspca_dev)
2631{
2632 struct sd *sd = (struct sd *) gspca_dev;
2633 static const u8 stophv7131[] =
2634 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
2635 static const u8 stopmi0360[] =
2636 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
2637 static const u8 stopov7648[] =
2638 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
2639 static const u8 stopsoi768[] =
2640 { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
2641 u8 reg01;
2642 u8 reg17;
2643
2644 reg01 = sd->reg01;
2645 reg17 = sd->reg17 & ~SEN_CLK_EN;
2646 switch (sd->sensor) {
2647 case SENSOR_ADCM1700:
2648 case SENSOR_GC0307:
2649 case SENSOR_PO2030N:
2650 case SENSOR_SP80708:
2651 reg01 |= LED;
2652 reg_w1(gspca_dev, 0x01, reg01);
2653 reg01 &= ~(LED | V_TX_EN);
2654 reg_w1(gspca_dev, 0x01, reg01);
2655/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */
2656 break;
2657 case SENSOR_HV7131R:
2658 reg01 &= ~V_TX_EN;
2659 reg_w1(gspca_dev, 0x01, reg01);
2660 i2c_w8(gspca_dev, stophv7131);
2661 break;
2662 case SENSOR_MI0360:
2663 case SENSOR_MI0360B:
2664 reg01 &= ~V_TX_EN;
2665 reg_w1(gspca_dev, 0x01, reg01);
2666/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */
2667 i2c_w8(gspca_dev, stopmi0360);
2668 break;
2669 case SENSOR_MT9V111:
2670 case SENSOR_OM6802:
2671 case SENSOR_PO1030:
2672 reg01 &= ~V_TX_EN;
2673 reg_w1(gspca_dev, 0x01, reg01);
2674 break;
2675 case SENSOR_OV7630:
2676 case SENSOR_OV7648:
2677 reg01 &= ~V_TX_EN;
2678 reg_w1(gspca_dev, 0x01, reg01);
2679 i2c_w8(gspca_dev, stopov7648);
2680 break;
2681 case SENSOR_OV7660:
2682 reg01 &= ~V_TX_EN;
2683 reg_w1(gspca_dev, 0x01, reg01);
2684 break;
2685 case SENSOR_SOI768:
2686 i2c_w8(gspca_dev, stopsoi768);
2687 break;
2688 }
2689
2690 reg01 |= SCL_SEL_OD;
2691 reg_w1(gspca_dev, 0x01, reg01);
2692 reg01 |= S_PWR_DN; /* sensor power down */
2693 reg_w1(gspca_dev, 0x01, reg01);
2694 reg_w1(gspca_dev, 0x17, reg17);
2695 reg01 &= ~SYS_SEL_48M; /* clock 24MHz */
2696 reg_w1(gspca_dev, 0x01, reg01);
2697 reg01 |= LED;
2698 reg_w1(gspca_dev, 0x01, reg01);
2699 /* Don't disable sensor clock as that disables the button on the cam */
2700 /* reg_w1(gspca_dev, 0xf1, 0x01); */
2701}
2702
2703/* called on streamoff with alt==0 and on disconnect */
2704/* the usb_lock is held at entry - restore on exit */
2705static void sd_stop0(struct gspca_dev *gspca_dev)
2706{
2707 struct sd *sd = (struct sd *) gspca_dev;
2708
2709 if (sd->work_thread != NULL) {
2710 mutex_unlock(&gspca_dev->usb_lock);
2711 destroy_workqueue(sd->work_thread);
2712 mutex_lock(&gspca_dev->usb_lock);
2713 sd->work_thread = NULL;
2714 }
2715}
2716
2717static void do_autogain(struct gspca_dev *gspca_dev)
2718{
2719 struct sd *sd = (struct sd *) gspca_dev;
2720 int delta;
2721 int expotimes;
2722 u8 luma_mean = 130;
2723 u8 luma_delta = 20;
2724
2725 /* Thanks S., without your advice, autobright should not work :) */
2726 if (sd->ag_cnt < 0)
2727 return;
2728 if (--sd->ag_cnt >= 0)
2729 return;
2730 sd->ag_cnt = AG_CNT_START;
2731
2732 delta = atomic_read(&sd->avg_lum);
2733 PDEBUG(D_FRAM, "mean lum %d", delta);
2734 if (delta < luma_mean - luma_delta ||
2735 delta > luma_mean + luma_delta) {
2736 switch (sd->sensor) {
2737 case SENSOR_GC0307:
2738 expotimes = sd->exposure;
2739 expotimes += (luma_mean - delta) >> 6;
2740 if (expotimes < 0)
2741 expotimes = 0;
2742 sd->exposure = setexposure(gspca_dev,
2743 (unsigned int) expotimes);
2744 break;
2745 case SENSOR_HV7131R:
2746 expotimes = sd->exposure >> 8;
2747 expotimes += (luma_mean - delta) >> 4;
2748 if (expotimes < 0)
2749 expotimes = 0;
2750 sd->exposure = setexposure(gspca_dev,
2751 (unsigned int) (expotimes << 8));
2752 break;
2753 case SENSOR_OM6802:
2754 case SENSOR_MT9V111:
2755 expotimes = sd->exposure;
2756 expotimes += (luma_mean - delta) >> 2;
2757 if (expotimes < 0)
2758 expotimes = 0;
2759 sd->exposure = setexposure(gspca_dev,
2760 (unsigned int) expotimes);
2761 setredblue(gspca_dev);
2762 break;
2763 default:
2764/* case SENSOR_MO4000: */
2765/* case SENSOR_MI0360: */
2766/* case SENSOR_MI0360B: */
2767 expotimes = sd->exposure;
2768 expotimes += (luma_mean - delta) >> 6;
2769 if (expotimes < 0)
2770 expotimes = 0;
2771 sd->exposure = setexposure(gspca_dev,
2772 (unsigned int) expotimes);
2773 setredblue(gspca_dev);
2774 break;
2775 }
2776 }
2777}
2778
2779/* set the average luminosity from an isoc marker */
2780static void set_lum(struct sd *sd,
2781 u8 *data)
2782{
2783 int avg_lum;
2784
2785 /* w0 w1 w2
2786 * w3 w4 w5
2787 * w6 w7 w8
2788 */
2789 avg_lum = (data[27] << 8) + data[28] /* w3 */
2790
2791 + (data[31] << 8) + data[32] /* w5 */
2792
2793 + (data[23] << 8) + data[24] /* w1 */
2794
2795 + (data[35] << 8) + data[36] /* w7 */
2796
2797 + (data[29] << 10) + (data[30] << 2); /* w4 * 4 */
2798 avg_lum >>= 10;
2799 atomic_set(&sd->avg_lum, avg_lum);
2800}
2801
2802/* scan the URB packets */
2803/* This function is run at interrupt level. */
2804static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2805 u8 *data, /* isoc packet */
2806 int len) /* iso packet length */
2807{
2808 struct sd *sd = (struct sd *) gspca_dev;
2809 int i, new_qual;
2810
2811 /*
2812 * A frame ends on the marker
2813 * ff ff 00 c4 c4 96 ..
2814 * which is 62 bytes long and is followed by various information
2815 * including statuses and luminosity.
2816 *
2817 * A marker may be splitted on two packets.
2818 *
2819 * The 6th byte of a marker contains the bits:
2820 * 0x08: USB full
2821 * 0xc0: frame sequence
2822 * When the bit 'USB full' is set, the frame must be discarded;
2823 * this is also the case when the 2 bytes before the marker are
2824 * not the JPEG end of frame ('ff d9').
2825 */
2826
2827/*fixme: assumption about the following code:
2828 * - there can be only one marker in a packet
2829 */
2830
2831 /* skip the remaining bytes of a short marker */
2832 i = sd->short_mark;
2833 if (i != 0) {
2834 sd->short_mark = 0;
2835 if (i < 0 /* if 'ff' at end of previous packet */
2836 && data[0] == 0xff
2837 && data[1] == 0x00)
2838 goto marker_found;
2839 if (data[0] == 0xff && data[1] == 0xff) {
2840 i = 0;
2841 goto marker_found;
2842 }
2843 len -= i;
2844 if (len <= 0)
2845 return;
2846 data += i;
2847 }
2848
2849 /* count the packets and their size */
2850 sd->npkt++;
2851 sd->pktsz += len;
2852
2853 /* search backwards if there is a marker in the packet */
2854 for (i = len - 1; --i >= 0; ) {
2855 if (data[i] != 0xff) {
2856 i--;
2857 continue;
2858 }
2859 if (data[i + 1] == 0xff) {
2860
2861 /* (there may be 'ff ff' inside a marker) */
2862 if (i + 2 >= len || data[i + 2] == 0x00)
2863 goto marker_found;
2864 }
2865 }
2866
2867 /* no marker found */
2868 /* add the JPEG header if first fragment */
2869 if (data[len - 1] == 0xff)
2870 sd->short_mark = -1;
2871 if (gspca_dev->last_packet_type == LAST_PACKET)
2872 gspca_frame_add(gspca_dev, FIRST_PACKET,
2873 sd->jpeg_hdr, JPEG_HDR_SZ);
2874 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2875 return;
2876
2877 /* marker found */
2878 /* if some error, discard the frame and decrease the quality */
2879marker_found:
2880 new_qual = 0;
2881 if (i > 2) {
2882 if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
2883 gspca_dev->last_packet_type = DISCARD_PACKET;
2884 new_qual = -3;
2885 }
2886 } else if (i + 6 < len) {
2887 if (data[i + 6] & 0x08) {
2888 gspca_dev->last_packet_type = DISCARD_PACKET;
2889 new_qual = -5;
2890 }
2891 }
2892
2893 gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
2894
2895 /* compute the filling rate and a new JPEG quality */
2896 if (new_qual == 0) {
2897 int r;
2898
2899 r = (sd->pktsz * 100) /
2900 (sd->npkt *
2901 gspca_dev->urb[0]->iso_frame_desc[0].length);
2902 if (r >= 85)
2903 new_qual = -3;
2904 else if (r < 75)
2905 new_qual = 2;
2906 }
2907 if (new_qual != 0) {
2908 sd->nchg += new_qual;
2909 if (sd->nchg < -6 || sd->nchg >= 12) {
2910 sd->nchg = 0;
2911 new_qual += sd->quality;
2912 if (new_qual < QUALITY_MIN)
2913 new_qual = QUALITY_MIN;
2914 else if (new_qual > QUALITY_MAX)
2915 new_qual = QUALITY_MAX;
2916 if (new_qual != sd->quality) {
2917 sd->quality = new_qual;
2918 queue_work(sd->work_thread, &sd->work);
2919 }
2920 }
2921 } else {
2922 sd->nchg = 0;
2923 }
2924 sd->pktsz = sd->npkt = 0;
2925
2926 /* if the marker is smaller than 62 bytes,
2927 * memorize the number of bytes to skip in the next packet */
2928 if (i + 62 > len) { /* no more usable data */
2929 sd->short_mark = i + 62 - len;
2930 return;
2931 }
2932 if (sd->ag_cnt >= 0)
2933 set_lum(sd, data + i);
2934
2935 /* if more data, start a new frame */
2936 i += 62;
2937 if (i < len) {
2938 data += i;
2939 len -= i;
2940 gspca_frame_add(gspca_dev, FIRST_PACKET,
2941 sd->jpeg_hdr, JPEG_HDR_SZ);
2942 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2943 }
2944}
2945
2946static int sd_get_jcomp(struct gspca_dev *gspca_dev,
2947 struct v4l2_jpegcompression *jcomp)
2948{
2949 struct sd *sd = (struct sd *) gspca_dev;
2950
2951 memset(jcomp, 0, sizeof *jcomp);
2952 jcomp->quality = sd->quality;
2953 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
2954 | V4L2_JPEG_MARKER_DQT;
2955 return 0;
2956}
2957
2958static int sd_querymenu(struct gspca_dev *gspca_dev,
2959 struct v4l2_querymenu *menu)
2960{
2961 switch (menu->id) {
2962 case V4L2_CID_POWER_LINE_FREQUENCY:
2963 switch (menu->index) {
2964 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
2965 strcpy((char *) menu->name, "NoFliker");
2966 return 0;
2967 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
2968 strcpy((char *) menu->name, "50 Hz");
2969 return 0;
2970 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
2971 strcpy((char *) menu->name, "60 Hz");
2972 return 0;
2973 }
2974 break;
2975 }
2976 return -EINVAL;
2977}
2978
2979#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2980static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
2981 u8 *data, /* interrupt packet data */
2982 int len) /* interrupt packet length */
2983{
2984 int ret = -EINVAL;
2985
2986 if (len == 1 && data[0] == 1) {
2987 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
2988 input_sync(gspca_dev->input_dev);
2989 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2990 input_sync(gspca_dev->input_dev);
2991 ret = 0;
2992 }
2993
2994 return ret;
2995}
2996#endif
2997
2998/* sub-driver description */
2999static const struct sd_desc sd_desc = {
3000 .name = MODULE_NAME,
3001 .ctrls = sd_ctrls,
3002 .nctrls = NCTRLS,
3003 .config = sd_config,
3004 .init = sd_init,
3005 .start = sd_start,
3006 .stopN = sd_stopN,
3007 .stop0 = sd_stop0,
3008 .pkt_scan = sd_pkt_scan,
3009 .dq_callback = do_autogain,
3010 .get_jcomp = sd_get_jcomp,
3011 .querymenu = sd_querymenu,
3012#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3013 .int_pkt_scan = sd_int_pkt_scan,
3014#endif
3015};
3016
3017/* -- module initialisation -- */
3018#define BS(bridge, sensor) \
3019 .driver_info = (BRIDGE_ ## bridge << 16) \
3020 | (SENSOR_ ## sensor << 8)
3021#define BSF(bridge, sensor, flags) \
3022 .driver_info = (BRIDGE_ ## bridge << 16) \
3023 | (SENSOR_ ## sensor << 8) \
3024 | (flags)
3025static const struct usb_device_id device_table[] = {
3026 {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
3027 {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
3028 {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
3029 {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
3030 {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
3031 {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
3032 {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
3033 {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
3034 {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
3035/* {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
3036 {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
3037/* {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
3038/* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
3039 {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
3040/* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
3041 {USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
3042 /* or MT9V111 */
3043/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
3044/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
3045/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
3046 {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
3047 {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
3048/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
3049/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
3050/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
3051 {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
3052 {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
3053 {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
3054 {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/
3055 {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, /* /GC0305*/
3056/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
3057 {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/
3058 {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/
3059 {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)}, /*sn9c128*/
3060 {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)}, /*sn9c128*/
3061/* {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
3062/* {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
3063/* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
3064 {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/
3065/*bw600.inf:*/
3066 {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c325?*/
3067 {USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
3068 {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
3069 {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
3070/* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
3071 {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
3072 /* or MT9V111 / MI0360B */
3073/* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
3074 {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
3075 {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
3076 {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
3077 {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
3078 {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
3079 {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/
3080 /* or GC0305 / GC0307 */
3081 {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/
3082 {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/
3083 {USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
3084/* {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */ /*sn9c120b*/
3085 {}
3086};
3087MODULE_DEVICE_TABLE(usb, device_table);
3088
3089/* -- device connect -- */
3090static int sd_probe(struct usb_interface *intf,
3091 const struct usb_device_id *id)
3092{
3093 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
3094 THIS_MODULE);
3095}
3096
3097static struct usb_driver sd_driver = {
3098 .name = MODULE_NAME,
3099 .id_table = device_table,
3100 .probe = sd_probe,
3101 .disconnect = gspca_disconnect,
3102#ifdef CONFIG_PM
3103 .suspend = gspca_suspend,
3104 .resume = gspca_resume,
3105#endif
3106};
3107
3108/* -- module insert / remove -- */
3109static int __init sd_mod_init(void)
3110{
3111 return usb_register(&sd_driver);
3112}
3113static void __exit sd_mod_exit(void)
3114{
3115 usb_deregister(&sd_driver);
3116}
3117
3118module_init(sd_mod_init);
3119module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c
new file mode 100644
index 00000000000..76c006b2bc8
--- /dev/null
+++ b/drivers/media/video/gspca/spca1528.c
@@ -0,0 +1,598 @@
1/*
2 * spca1528 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
21#define MODULE_NAME "spca1528"
22
23#include "gspca.h"
24#include "jpeg.h"
25
26MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
27MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
28MODULE_LICENSE("GPL");
29
30/* specific webcam descriptor */
31struct sd {
32 struct gspca_dev gspca_dev; /* !! must be the first item */
33
34 u8 brightness;
35 u8 contrast;
36 u8 hue;
37 u8 color;
38 u8 sharpness;
39
40 u8 pkt_seq;
41
42 u8 jpeg_hdr[JPEG_HDR_SZ];
43};
44
45/* V4L2 controls supported by the driver */
46static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
47static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
48static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
56
57static const struct ctrl sd_ctrls[] = {
58 {
59 {
60 .id = V4L2_CID_BRIGHTNESS,
61 .type = V4L2_CTRL_TYPE_INTEGER,
62 .name = "Brightness",
63 .minimum = 0,
64 .maximum = 255,
65 .step = 1,
66#define BRIGHTNESS_DEF 128
67 .default_value = BRIGHTNESS_DEF,
68 },
69 .set = sd_setbrightness,
70 .get = sd_getbrightness,
71 },
72 {
73 {
74 .id = V4L2_CID_CONTRAST,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Contrast",
77 .minimum = 0,
78 .maximum = 8,
79 .step = 1,
80#define CONTRAST_DEF 1
81 .default_value = CONTRAST_DEF,
82 },
83 .set = sd_setcontrast,
84 .get = sd_getcontrast,
85 },
86 {
87 {
88 .id = V4L2_CID_HUE,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Hue",
91 .minimum = 0,
92 .maximum = 255,
93 .step = 1,
94#define HUE_DEF 0
95 .default_value = HUE_DEF,
96 },
97 .set = sd_sethue,
98 .get = sd_gethue,
99 },
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Saturation",
105 .minimum = 0,
106 .maximum = 8,
107 .step = 1,
108#define COLOR_DEF 1
109 .default_value = COLOR_DEF,
110 },
111 .set = sd_setcolor,
112 .get = sd_getcolor,
113 },
114 {
115 {
116 .id = V4L2_CID_SHARPNESS,
117 .type = V4L2_CTRL_TYPE_INTEGER,
118 .name = "Sharpness",
119 .minimum = 0,
120 .maximum = 255,
121 .step = 1,
122#define SHARPNESS_DEF 0
123 .default_value = SHARPNESS_DEF,
124 },
125 .set = sd_setsharpness,
126 .get = sd_getsharpness,
127 },
128};
129
130static const struct v4l2_pix_format vga_mode[] = {
131/* (does not work correctly)
132 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 176,
134 .sizeimage = 176 * 144 * 5 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 3},
137*/
138 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139 .bytesperline = 320,
140 .sizeimage = 320 * 240 * 4 / 8 + 590,
141 .colorspace = V4L2_COLORSPACE_JPEG,
142 .priv = 2},
143 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 640,
145 .sizeimage = 640 * 480 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 1},
148};
149
150/* read <len> bytes to gspca usb_buf */
151static void reg_r(struct gspca_dev *gspca_dev,
152 u8 req,
153 u16 index,
154 int len)
155{
156#if USB_BUF_SZ < 64
157#error "USB buffer too small"
158#endif
159 struct usb_device *dev = gspca_dev->dev;
160 int ret;
161
162 if (gspca_dev->usb_err < 0)
163 return;
164 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
165 req,
166 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
167 0x0000, /* value */
168 index,
169 gspca_dev->usb_buf, len,
170 500);
171 PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
172 gspca_dev->usb_buf[0]);
173 if (ret < 0) {
174 err("reg_r err %d", ret);
175 gspca_dev->usb_err = ret;
176 }
177}
178
179static void reg_w(struct gspca_dev *gspca_dev,
180 u8 req,
181 u16 value,
182 u16 index)
183{
184 struct usb_device *dev = gspca_dev->dev;
185 int ret;
186
187 if (gspca_dev->usb_err < 0)
188 return;
189 PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
190 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
191 req,
192 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
193 value, index,
194 NULL, 0, 500);
195 if (ret < 0) {
196 err("reg_w err %d", ret);
197 gspca_dev->usb_err = ret;
198 }
199}
200
201static void reg_wb(struct gspca_dev *gspca_dev,
202 u8 req,
203 u16 value,
204 u16 index,
205 u8 byte)
206{
207 struct usb_device *dev = gspca_dev->dev;
208 int ret;
209
210 if (gspca_dev->usb_err < 0)
211 return;
212 PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
213 gspca_dev->usb_buf[0] = byte;
214 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
215 req,
216 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
217 value, index,
218 gspca_dev->usb_buf, 1, 500);
219 if (ret < 0) {
220 err("reg_w err %d", ret);
221 gspca_dev->usb_err = ret;
222 }
223}
224
225static void wait_status_0(struct gspca_dev *gspca_dev)
226{
227 int i;
228
229 i = 20;
230 do {
231 reg_r(gspca_dev, 0x21, 0x0000, 1);
232 if (gspca_dev->usb_buf[0] == 0)
233 return;
234 msleep(30);
235 } while (--i > 0);
236 PDEBUG(D_ERR, "wait_status_0 timeout");
237 gspca_dev->usb_err = -ETIME;
238}
239
240static void wait_status_1(struct gspca_dev *gspca_dev)
241{
242 int i;
243
244 i = 10;
245 do {
246 reg_r(gspca_dev, 0x21, 0x0001, 1);
247 msleep(10);
248 if (gspca_dev->usb_buf[0] == 1) {
249 reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
250 reg_r(gspca_dev, 0x21, 0x0001, 1);
251 return;
252 }
253 } while (--i > 0);
254 PDEBUG(D_ERR, "wait_status_1 timeout");
255 gspca_dev->usb_err = -ETIME;
256}
257
258static void setbrightness(struct gspca_dev *gspca_dev)
259{
260 struct sd *sd = (struct sd *) gspca_dev;
261
262 reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, sd->brightness);
263}
264
265static void setcontrast(struct gspca_dev *gspca_dev)
266{
267 struct sd *sd = (struct sd *) gspca_dev;
268
269 reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, sd->contrast);
270}
271
272static void sethue(struct gspca_dev *gspca_dev)
273{
274 struct sd *sd = (struct sd *) gspca_dev;
275
276 reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, sd->hue);
277}
278
279static void setcolor(struct gspca_dev *gspca_dev)
280{
281 struct sd *sd = (struct sd *) gspca_dev;
282
283 reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, sd->color);
284}
285
286static void setsharpness(struct gspca_dev *gspca_dev)
287{
288 struct sd *sd = (struct sd *) gspca_dev;
289
290 reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, sd->sharpness);
291}
292
293/* this function is called at probe time */
294static int sd_config(struct gspca_dev *gspca_dev,
295 const struct usb_device_id *id)
296{
297 struct sd *sd = (struct sd *) gspca_dev;
298
299 gspca_dev->cam.cam_mode = vga_mode;
300 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
301 gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
302 /*fixme: 256 in ms-win traces*/
303
304 sd->brightness = BRIGHTNESS_DEF;
305 sd->contrast = CONTRAST_DEF;
306 sd->hue = HUE_DEF;
307 sd->color = COLOR_DEF;
308 sd->sharpness = SHARPNESS_DEF;
309
310 gspca_dev->nbalt = 4; /* use alternate setting 3 */
311
312 return 0;
313}
314
315/* this function is called at probe and resume time */
316static int sd_init(struct gspca_dev *gspca_dev)
317{
318 reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
319 reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
320 reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
321 reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
322 msleep(8);
323 reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
324 reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
325 reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
326
327 reg_r(gspca_dev, 0x20, 0x0000, 1);
328 reg_r(gspca_dev, 0x20, 0x0000, 5);
329 reg_r(gspca_dev, 0x23, 0x0000, 64);
330 PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
331 &gspca_dev->usb_buf[0x30]);
332 reg_r(gspca_dev, 0x23, 0x0001, 64);
333 return gspca_dev->usb_err;
334}
335
336/* function called at start time before URB creation */
337static int sd_isoc_init(struct gspca_dev *gspca_dev)
338{
339 u8 mode;
340
341 reg_r(gspca_dev, 0x00, 0x2520, 1);
342 wait_status_0(gspca_dev);
343 reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
344 wait_status_1(gspca_dev);
345
346 wait_status_0(gspca_dev);
347 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
348 reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
349 reg_r(gspca_dev, 0x25, 0x0004, 1);
350 reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
351 reg_r(gspca_dev, 0x27, 0x0000, 1);
352 return gspca_dev->usb_err;
353}
354
355/* -- start the camera -- */
356static int sd_start(struct gspca_dev *gspca_dev)
357{
358 struct sd *sd = (struct sd *) gspca_dev;
359
360 /* initialize the JPEG header */
361 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
362 0x22); /* JPEG 411 */
363
364 /* the JPEG quality seems to be 82% */
365 jpeg_set_qual(sd->jpeg_hdr, 82);
366
367 /* set the controls */
368 setbrightness(gspca_dev);
369 setcontrast(gspca_dev);
370 sethue(gspca_dev);
371 setcolor(gspca_dev);
372 setsharpness(gspca_dev);
373
374 msleep(5);
375 reg_r(gspca_dev, 0x00, 0x2520, 1);
376 msleep(8);
377
378 /* start the capture */
379 wait_status_0(gspca_dev);
380 reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
381 wait_status_1(gspca_dev);
382 wait_status_0(gspca_dev);
383 msleep(200);
384
385 sd->pkt_seq = 0;
386 return gspca_dev->usb_err;
387}
388
389static void sd_stopN(struct gspca_dev *gspca_dev)
390{
391 /* stop the capture */
392 wait_status_0(gspca_dev);
393 reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
394 wait_status_1(gspca_dev);
395 wait_status_0(gspca_dev);
396}
397
398/* move a packet adding 0x00 after 0xff */
399static void add_packet(struct gspca_dev *gspca_dev,
400 u8 *data,
401 int len)
402{
403 int i;
404
405 i = 0;
406 do {
407 if (data[i] == 0xff) {
408 gspca_frame_add(gspca_dev, INTER_PACKET,
409 data, i + 1);
410 len -= i;
411 data += i;
412 *data = 0x00;
413 i = 0;
414 }
415 } while (++i < len);
416 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
417}
418
419static void sd_pkt_scan(struct gspca_dev *gspca_dev,
420 u8 *data, /* isoc packet */
421 int len) /* iso packet length */
422{
423 struct sd *sd = (struct sd *) gspca_dev;
424 static const u8 ffd9[] = {0xff, 0xd9};
425
426 /* image packets start with:
427 * 02 8n
428 * with <n> bit:
429 * 0x01: even (0) / odd (1) image
430 * 0x02: end of image when set
431 */
432 if (len < 3)
433 return; /* empty packet */
434 if (*data == 0x02) {
435 if (data[1] & 0x02) {
436 sd->pkt_seq = !(data[1] & 1);
437 add_packet(gspca_dev, data + 2, len - 2);
438 gspca_frame_add(gspca_dev, LAST_PACKET,
439 ffd9, 2);
440 return;
441 }
442 if ((data[1] & 1) != sd->pkt_seq)
443 goto err;
444 if (gspca_dev->last_packet_type == LAST_PACKET)
445 gspca_frame_add(gspca_dev, FIRST_PACKET,
446 sd->jpeg_hdr, JPEG_HDR_SZ);
447 add_packet(gspca_dev, data + 2, len - 2);
448 return;
449 }
450err:
451 gspca_dev->last_packet_type = DISCARD_PACKET;
452}
453
454static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
455{
456 struct sd *sd = (struct sd *) gspca_dev;
457
458 sd->brightness = val;
459 if (gspca_dev->streaming)
460 setbrightness(gspca_dev);
461 return gspca_dev->usb_err;
462}
463
464static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
465{
466 struct sd *sd = (struct sd *) gspca_dev;
467
468 *val = sd->brightness;
469 return 0;
470}
471
472static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
473{
474 struct sd *sd = (struct sd *) gspca_dev;
475
476 sd->contrast = val;
477 if (gspca_dev->streaming)
478 setcontrast(gspca_dev);
479 return gspca_dev->usb_err;
480}
481
482static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
483{
484 struct sd *sd = (struct sd *) gspca_dev;
485
486 *val = sd->contrast;
487 return 0;
488}
489
490static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
491{
492 struct sd *sd = (struct sd *) gspca_dev;
493
494 sd->hue = val;
495 if (gspca_dev->streaming)
496 sethue(gspca_dev);
497 return gspca_dev->usb_err;
498}
499
500static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
501{
502 struct sd *sd = (struct sd *) gspca_dev;
503
504 *val = sd->hue;
505 return 0;
506}
507
508static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val)
509{
510 struct sd *sd = (struct sd *) gspca_dev;
511
512 sd->color = val;
513 if (gspca_dev->streaming)
514 setcolor(gspca_dev);
515 return gspca_dev->usb_err;
516}
517
518static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val)
519{
520 struct sd *sd = (struct sd *) gspca_dev;
521
522 *val = sd->color;
523 return 0;
524}
525
526static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
527{
528 struct sd *sd = (struct sd *) gspca_dev;
529
530 sd->sharpness = val;
531 if (gspca_dev->streaming)
532 setsharpness(gspca_dev);
533 return gspca_dev->usb_err;
534}
535
536static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
537{
538 struct sd *sd = (struct sd *) gspca_dev;
539
540 *val = sd->sharpness;
541 return 0;
542}
543
544/* sub-driver description */
545static const struct sd_desc sd_desc = {
546 .name = MODULE_NAME,
547 .ctrls = sd_ctrls,
548 .nctrls = ARRAY_SIZE(sd_ctrls),
549 .config = sd_config,
550 .init = sd_init,
551 .isoc_init = sd_isoc_init,
552 .start = sd_start,
553 .stopN = sd_stopN,
554 .pkt_scan = sd_pkt_scan,
555};
556
557/* -- module initialisation -- */
558static const struct usb_device_id device_table[] = {
559 {USB_DEVICE(0x04fc, 0x1528)},
560 {}
561};
562MODULE_DEVICE_TABLE(usb, device_table);
563
564/* -- device connect -- */
565static int sd_probe(struct usb_interface *intf,
566 const struct usb_device_id *id)
567{
568 /* the video interface for isochronous transfer is 1 */
569 if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
570 return -ENODEV;
571
572 return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
573 THIS_MODULE);
574}
575
576static struct usb_driver sd_driver = {
577 .name = MODULE_NAME,
578 .id_table = device_table,
579 .probe = sd_probe,
580 .disconnect = gspca_disconnect,
581#ifdef CONFIG_PM
582 .suspend = gspca_suspend,
583 .resume = gspca_resume,
584#endif
585};
586
587/* -- module insert / remove -- */
588static int __init sd_mod_init(void)
589{
590 return usb_register(&sd_driver);
591}
592static void __exit sd_mod_exit(void)
593{
594 usb_deregister(&sd_driver);
595}
596
597module_init(sd_mod_init);
598module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
new file mode 100644
index 00000000000..3e76951e3c1
--- /dev/null
+++ b/drivers/media/video/gspca/spca500.c
@@ -0,0 +1,1104 @@
1/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA500 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 brightness;
36 unsigned char contrast;
37 unsigned char colors;
38 u8 quality;
39#define QUALITY_MIN 70
40#define QUALITY_MAX 95
41#define QUALITY_DEF 85
42
43 char subtype;
44#define AgfaCl20 0
45#define AiptekPocketDV 1
46#define BenqDC1016 2
47#define CreativePCCam300 3
48#define DLinkDSC350 4
49#define Gsmartmini 5
50#define IntelPocketPCCamera 6
51#define KodakEZ200 7
52#define LogitechClickSmart310 8
53#define LogitechClickSmart510 9
54#define LogitechTraveler 10
55#define MustekGsmart300 11
56#define Optimedia 12
57#define PalmPixDC85 13
58#define ToptroIndus 14
59
60 u8 jpeg_hdr[JPEG_HDR_SZ];
61};
62
63/* V4L2 controls supported by the driver */
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70
71static const struct ctrl sd_ctrls[] = {
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 255,
79 .step = 1,
80#define BRIGHTNESS_DEF 127
81 .default_value = BRIGHTNESS_DEF,
82 },
83 .set = sd_setbrightness,
84 .get = sd_getbrightness,
85 },
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 63,
93 .step = 1,
94#define CONTRAST_DEF 31
95 .default_value = CONTRAST_DEF,
96 },
97 .set = sd_setcontrast,
98 .get = sd_getcontrast,
99 },
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 63,
107 .step = 1,
108#define COLOR_DEF 31
109 .default_value = COLOR_DEF,
110 },
111 .set = sd_setcolors,
112 .get = sd_getcolors,
113 },
114};
115
116static const struct v4l2_pix_format vga_mode[] = {
117 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
118 .bytesperline = 320,
119 .sizeimage = 320 * 240 * 3 / 8 + 590,
120 .colorspace = V4L2_COLORSPACE_JPEG,
121 .priv = 1},
122 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
123 .bytesperline = 640,
124 .sizeimage = 640 * 480 * 3 / 8 + 590,
125 .colorspace = V4L2_COLORSPACE_JPEG,
126 .priv = 0},
127};
128
129static const struct v4l2_pix_format sif_mode[] = {
130 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 176,
132 .sizeimage = 176 * 144 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 1},
135 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 352,
137 .sizeimage = 352 * 288 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 0},
140};
141
142/* Frame packet header offsets for the spca500 */
143#define SPCA500_OFFSET_PADDINGLB 2
144#define SPCA500_OFFSET_PADDINGHB 3
145#define SPCA500_OFFSET_MODE 4
146#define SPCA500_OFFSET_IMGWIDTH 5
147#define SPCA500_OFFSET_IMGHEIGHT 6
148#define SPCA500_OFFSET_IMGMODE 7
149#define SPCA500_OFFSET_QTBLINDEX 8
150#define SPCA500_OFFSET_FRAMSEQ 9
151#define SPCA500_OFFSET_CDSPINFO 10
152#define SPCA500_OFFSET_GPIO 11
153#define SPCA500_OFFSET_AUGPIO 12
154#define SPCA500_OFFSET_DATA 16
155
156
157static const __u16 spca500_visual_defaults[][3] = {
158 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
159 * hue (H byte) = 0,
160 * saturation/hue enable,
161 * brightness/contrast enable.
162 */
163 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
164 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
165 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
166 * hue (H byte) = 0, saturation/hue enable,
167 * brightness/contrast enable.
168 * was 0x0003, now 0x0000.
169 */
170 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
171 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
172 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
173 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
174 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
175 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
176 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
177 {0x0c, 0x0004, 0x0000},
178 /* set interface */
179 {}
180};
181static const __u16 Clicksmart510_defaults[][3] = {
182 {0x00, 0x00, 0x8211},
183 {0x00, 0x01, 0x82c0},
184 {0x00, 0x10, 0x82cb},
185 {0x00, 0x0f, 0x800d},
186 {0x00, 0x82, 0x8225},
187 {0x00, 0x21, 0x8228},
188 {0x00, 0x00, 0x8203},
189 {0x00, 0x00, 0x8204},
190 {0x00, 0x08, 0x8205},
191 {0x00, 0xf8, 0x8206},
192 {0x00, 0x28, 0x8207},
193 {0x00, 0xa0, 0x8208},
194 {0x00, 0x08, 0x824a},
195 {0x00, 0x08, 0x8214},
196 {0x00, 0x80, 0x82c1},
197 {0x00, 0x00, 0x82c2},
198 {0x00, 0x00, 0x82ca},
199 {0x00, 0x80, 0x82c1},
200 {0x00, 0x04, 0x82c2},
201 {0x00, 0x00, 0x82ca},
202 {0x00, 0xfc, 0x8100},
203 {0x00, 0xfc, 0x8105},
204 {0x00, 0x30, 0x8101},
205 {0x00, 0x00, 0x8102},
206 {0x00, 0x00, 0x8103},
207 {0x00, 0x66, 0x8107},
208 {0x00, 0x00, 0x816b},
209 {0x00, 0x00, 0x8155},
210 {0x00, 0x01, 0x8156},
211 {0x00, 0x60, 0x8157},
212 {0x00, 0x40, 0x8158},
213 {0x00, 0x0a, 0x8159},
214 {0x00, 0x06, 0x815a},
215 {0x00, 0x00, 0x813f},
216 {0x00, 0x00, 0x8200},
217 {0x00, 0x19, 0x8201},
218 {0x00, 0x00, 0x82c1},
219 {0x00, 0xa0, 0x82c2},
220 {0x00, 0x00, 0x82ca},
221 {0x00, 0x00, 0x8117},
222 {0x00, 0x00, 0x8118},
223 {0x00, 0x65, 0x8119},
224 {0x00, 0x00, 0x811a},
225 {0x00, 0x00, 0x811b},
226 {0x00, 0x55, 0x811c},
227 {0x00, 0x65, 0x811d},
228 {0x00, 0x55, 0x811e},
229 {0x00, 0x16, 0x811f},
230 {0x00, 0x19, 0x8120},
231 {0x00, 0x80, 0x8103},
232 {0x00, 0x83, 0x816b},
233 {0x00, 0x25, 0x8168},
234 {0x00, 0x01, 0x820f},
235 {0x00, 0xff, 0x8115},
236 {0x00, 0x48, 0x8116},
237 {0x00, 0x50, 0x8151},
238 {0x00, 0x40, 0x8152},
239 {0x00, 0x78, 0x8153},
240 {0x00, 0x40, 0x8154},
241 {0x00, 0x00, 0x8167},
242 {0x00, 0x20, 0x8168},
243 {0x00, 0x00, 0x816a},
244 {0x00, 0x03, 0x816b},
245 {0x00, 0x20, 0x8169},
246 {0x00, 0x60, 0x8157},
247 {0x00, 0x00, 0x8190},
248 {0x00, 0x00, 0x81a1},
249 {0x00, 0x00, 0x81b2},
250 {0x00, 0x27, 0x8191},
251 {0x00, 0x27, 0x81a2},
252 {0x00, 0x27, 0x81b3},
253 {0x00, 0x4b, 0x8192},
254 {0x00, 0x4b, 0x81a3},
255 {0x00, 0x4b, 0x81b4},
256 {0x00, 0x66, 0x8193},
257 {0x00, 0x66, 0x81a4},
258 {0x00, 0x66, 0x81b5},
259 {0x00, 0x79, 0x8194},
260 {0x00, 0x79, 0x81a5},
261 {0x00, 0x79, 0x81b6},
262 {0x00, 0x8a, 0x8195},
263 {0x00, 0x8a, 0x81a6},
264 {0x00, 0x8a, 0x81b7},
265 {0x00, 0x9b, 0x8196},
266 {0x00, 0x9b, 0x81a7},
267 {0x00, 0x9b, 0x81b8},
268 {0x00, 0xa6, 0x8197},
269 {0x00, 0xa6, 0x81a8},
270 {0x00, 0xa6, 0x81b9},
271 {0x00, 0xb2, 0x8198},
272 {0x00, 0xb2, 0x81a9},
273 {0x00, 0xb2, 0x81ba},
274 {0x00, 0xbe, 0x8199},
275 {0x00, 0xbe, 0x81aa},
276 {0x00, 0xbe, 0x81bb},
277 {0x00, 0xc8, 0x819a},
278 {0x00, 0xc8, 0x81ab},
279 {0x00, 0xc8, 0x81bc},
280 {0x00, 0xd2, 0x819b},
281 {0x00, 0xd2, 0x81ac},
282 {0x00, 0xd2, 0x81bd},
283 {0x00, 0xdb, 0x819c},
284 {0x00, 0xdb, 0x81ad},
285 {0x00, 0xdb, 0x81be},
286 {0x00, 0xe4, 0x819d},
287 {0x00, 0xe4, 0x81ae},
288 {0x00, 0xe4, 0x81bf},
289 {0x00, 0xed, 0x819e},
290 {0x00, 0xed, 0x81af},
291 {0x00, 0xed, 0x81c0},
292 {0x00, 0xf7, 0x819f},
293 {0x00, 0xf7, 0x81b0},
294 {0x00, 0xf7, 0x81c1},
295 {0x00, 0xff, 0x81a0},
296 {0x00, 0xff, 0x81b1},
297 {0x00, 0xff, 0x81c2},
298 {0x00, 0x03, 0x8156},
299 {0x00, 0x00, 0x8211},
300 {0x00, 0x20, 0x8168},
301 {0x00, 0x01, 0x8202},
302 {0x00, 0x30, 0x8101},
303 {0x00, 0x00, 0x8111},
304 {0x00, 0x00, 0x8112},
305 {0x00, 0x00, 0x8113},
306 {0x00, 0x00, 0x8114},
307 {}
308};
309
310static const __u8 qtable_creative_pccam[2][64] = {
311 { /* Q-table Y-components */
312 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
313 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
314 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
315 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
316 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
317 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
318 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
319 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
320 { /* Q-table C-components */
321 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
322 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
329};
330
331static const __u8 qtable_kodak_ez200[2][64] = {
332 { /* Q-table Y-components */
333 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
334 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
335 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
336 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
337 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
338 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
339 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
340 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
341 { /* Q-table C-components */
342 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
343 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
350};
351
352static const __u8 qtable_pocketdv[2][64] = {
353 { /* Q-table Y-components start registers 0x8800 */
354 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
355 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
356 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
357 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
358 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
359 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
360 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
361 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
362 },
363 { /* Q-table C-components start registers 0x8840 */
364 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
365 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
366 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
367 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
372};
373
374/* read 'len' bytes to gspca_dev->usb_buf */
375static void reg_r(struct gspca_dev *gspca_dev,
376 __u16 index,
377 __u16 length)
378{
379 usb_control_msg(gspca_dev->dev,
380 usb_rcvctrlpipe(gspca_dev->dev, 0),
381 0,
382 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
383 0, /* value */
384 index, gspca_dev->usb_buf, length, 500);
385}
386
387static int reg_w(struct gspca_dev *gspca_dev,
388 __u16 req, __u16 index, __u16 value)
389{
390 int ret;
391
392 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
393 ret = usb_control_msg(gspca_dev->dev,
394 usb_sndctrlpipe(gspca_dev->dev, 0),
395 req,
396 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
397 value, index, NULL, 0, 500);
398 if (ret < 0)
399 err("reg write: error %d", ret);
400 return ret;
401}
402
403/* returns: negative is error, pos or zero is data */
404static int reg_r_12(struct gspca_dev *gspca_dev,
405 __u16 req, /* bRequest */
406 __u16 index, /* wIndex */
407 __u16 length) /* wLength (1 or 2 only) */
408{
409 int ret;
410
411 gspca_dev->usb_buf[1] = 0;
412 ret = usb_control_msg(gspca_dev->dev,
413 usb_rcvctrlpipe(gspca_dev->dev, 0),
414 req,
415 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
416 0, /* value */
417 index,
418 gspca_dev->usb_buf, length,
419 500); /* timeout */
420 if (ret < 0) {
421 err("reg_r_12 err %d", ret);
422 return ret;
423 }
424 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
425}
426
427/*
428 * Simple function to wait for a given 8-bit value to be returned from
429 * a reg_read call.
430 * Returns: negative is error or timeout, zero is success.
431 */
432static int reg_r_wait(struct gspca_dev *gspca_dev,
433 __u16 reg, __u16 index, __u16 value)
434{
435 int ret, cnt = 20;
436
437 while (--cnt > 0) {
438 ret = reg_r_12(gspca_dev, reg, index, 1);
439 if (ret == value)
440 return 0;
441 msleep(50);
442 }
443 return -EIO;
444}
445
446static int write_vector(struct gspca_dev *gspca_dev,
447 const __u16 data[][3])
448{
449 int ret, i = 0;
450
451 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
452 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
453 if (ret < 0)
454 return ret;
455 i++;
456 }
457 return 0;
458}
459
460static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
461 unsigned int request,
462 unsigned int ybase,
463 unsigned int cbase,
464 const __u8 qtable[2][64])
465{
466 int i, err;
467
468 /* loop over y components */
469 for (i = 0; i < 64; i++) {
470 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
471 if (err < 0)
472 return err;
473 }
474
475 /* loop over c components */
476 for (i = 0; i < 64; i++) {
477 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
478 if (err < 0)
479 return err;
480 }
481 return 0;
482}
483
484static void spca500_ping310(struct gspca_dev *gspca_dev)
485{
486 reg_r(gspca_dev, 0x0d04, 2);
487 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
488 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
489}
490
491static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
492{
493 reg_r(gspca_dev, 0x0d05, 2);
494 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
495 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
496 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
497 spca500_ping310(gspca_dev);
498
499 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
500 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
501 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
502 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
503 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
504 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
506 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
507 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
508 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
509 /* 00 for adjust shutter */
510 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
511 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
512 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
513}
514
515static void spca500_setmode(struct gspca_dev *gspca_dev,
516 __u8 xmult, __u8 ymult)
517{
518 int mode;
519
520 /* set x multiplier */
521 reg_w(gspca_dev, 0, 0x8001, xmult);
522
523 /* set y multiplier */
524 reg_w(gspca_dev, 0, 0x8002, ymult);
525
526 /* use compressed mode, VGA, with mode specific subsample */
527 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
528 reg_w(gspca_dev, 0, 0x8003, mode << 4);
529}
530
531static int spca500_full_reset(struct gspca_dev *gspca_dev)
532{
533 int err;
534
535 /* send the reset command */
536 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
537 if (err < 0)
538 return err;
539
540 /* wait for the reset to complete */
541 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
542 if (err < 0)
543 return err;
544 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
545 if (err < 0)
546 return err;
547 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
548 if (err < 0) {
549 PDEBUG(D_ERR, "reg_r_wait() failed");
550 return err;
551 }
552 /* all ok */
553 return 0;
554}
555
556/* Synchro the Bridge with sensor */
557/* Maybe that will work on all spca500 chip */
558/* because i only own a clicksmart310 try for that chip */
559/* using spca50x_set_packet_size() cause an Ooops here */
560/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
561/* up-port the same feature as in 2.4.x kernel */
562static int spca500_synch310(struct gspca_dev *gspca_dev)
563{
564 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
565 PDEBUG(D_ERR, "Set packet size: set interface error");
566 goto error;
567 }
568 spca500_ping310(gspca_dev);
569
570 reg_r(gspca_dev, 0x0d00, 1);
571
572 /* need alt setting here */
573 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
574
575 /* Windoze use pipe with altsetting 6 why 7 here */
576 if (usb_set_interface(gspca_dev->dev,
577 gspca_dev->iface,
578 gspca_dev->alt) < 0) {
579 PDEBUG(D_ERR, "Set packet size: set interface error");
580 goto error;
581 }
582 return 0;
583error:
584 return -EBUSY;
585}
586
587static void spca500_reinit(struct gspca_dev *gspca_dev)
588{
589 int err;
590 __u8 Data;
591
592 /* some unknown command from Aiptek pocket dv and family300 */
593
594 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
595 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
596 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
597
598 /* enable drop packet */
599 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
600
601 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
602 qtable_pocketdv);
603 if (err < 0)
604 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
605
606 /* set qtable index */
607 reg_w(gspca_dev, 0x00, 0x8880, 2);
608 /* family cam Quicksmart stuff */
609 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
610 /* Set agc transfer: synced between frames */
611 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
612 /* Init SDRAM - needed for SDRAM access */
613 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
614 /*Start init sequence or stream */
615 reg_w(gspca_dev, 0, 0x8003, 0x00);
616 /* switch to video camera mode */
617 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
618 msleep(2000);
619 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
620 reg_r(gspca_dev, 0x816b, 1);
621 Data = gspca_dev->usb_buf[0];
622 reg_w(gspca_dev, 0x00, 0x816b, Data);
623 }
624}
625
626/* this function is called at probe time */
627static int sd_config(struct gspca_dev *gspca_dev,
628 const struct usb_device_id *id)
629{
630 struct sd *sd = (struct sd *) gspca_dev;
631 struct cam *cam;
632
633 cam = &gspca_dev->cam;
634 sd->subtype = id->driver_info;
635 if (sd->subtype != LogitechClickSmart310) {
636 cam->cam_mode = vga_mode;
637 cam->nmodes = ARRAY_SIZE(vga_mode);
638 } else {
639 cam->cam_mode = sif_mode;
640 cam->nmodes = ARRAY_SIZE(sif_mode);
641 }
642 sd->brightness = BRIGHTNESS_DEF;
643 sd->contrast = CONTRAST_DEF;
644 sd->colors = COLOR_DEF;
645 sd->quality = QUALITY_DEF;
646 return 0;
647}
648
649/* this function is called at probe and resume time */
650static int sd_init(struct gspca_dev *gspca_dev)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
653
654 /* initialisation of spca500 based cameras is deferred */
655 PDEBUG(D_STREAM, "SPCA500 init");
656 if (sd->subtype == LogitechClickSmart310)
657 spca500_clksmart310_init(gspca_dev);
658/* else
659 spca500_initialise(gspca_dev); */
660 PDEBUG(D_STREAM, "SPCA500 init done");
661 return 0;
662}
663
664static int sd_start(struct gspca_dev *gspca_dev)
665{
666 struct sd *sd = (struct sd *) gspca_dev;
667 int err;
668 __u8 Data;
669 __u8 xmult, ymult;
670
671 /* create the JPEG header */
672 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
673 0x22); /* JPEG 411 */
674 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
675
676 if (sd->subtype == LogitechClickSmart310) {
677 xmult = 0x16;
678 ymult = 0x12;
679 } else {
680 xmult = 0x28;
681 ymult = 0x1e;
682 }
683
684 /* is there a sensor here ? */
685 reg_r(gspca_dev, 0x8a04, 1);
686 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
687 gspca_dev->usb_buf[0]);
688 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
689 gspca_dev->curr_mode, xmult, ymult);
690
691 /* setup qtable */
692 switch (sd->subtype) {
693 case LogitechClickSmart310:
694 spca500_setmode(gspca_dev, xmult, ymult);
695
696 /* enable drop packet */
697 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
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 /* Init SDRAM - needed for SDRAM access */
705 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
706
707 /* switch to video camera mode */
708 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
709 msleep(500);
710 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
711 PDEBUG(D_ERR, "reg_r_wait() failed");
712
713 reg_r(gspca_dev, 0x816b, 1);
714 Data = gspca_dev->usb_buf[0];
715 reg_w(gspca_dev, 0x00, 0x816b, Data);
716
717 spca500_synch310(gspca_dev);
718
719 write_vector(gspca_dev, spca500_visual_defaults);
720 spca500_setmode(gspca_dev, xmult, ymult);
721 /* enable drop packet */
722 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
723 if (err < 0)
724 PDEBUG(D_ERR, "failed to enable drop packet");
725 reg_w(gspca_dev, 0x00, 0x8880, 3);
726 err = spca50x_setup_qtable(gspca_dev,
727 0x00, 0x8800, 0x8840,
728 qtable_creative_pccam);
729 if (err < 0)
730 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
731
732 /* Init SDRAM - needed for SDRAM access */
733 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
734
735 /* switch to video camera mode */
736 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
737
738 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
739 PDEBUG(D_ERR, "reg_r_wait() failed");
740
741 reg_r(gspca_dev, 0x816b, 1);
742 Data = gspca_dev->usb_buf[0];
743 reg_w(gspca_dev, 0x00, 0x816b, Data);
744 break;
745 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
746 case IntelPocketPCCamera: /* FIXME: Temporary fix for
747 * Intel Pocket PC Camera
748 * - NWG (Sat 29th March 2003) */
749
750 /* do a full reset */
751 err = spca500_full_reset(gspca_dev);
752 if (err < 0)
753 PDEBUG(D_ERR, "spca500_full_reset failed");
754
755 /* enable drop packet */
756 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
757 if (err < 0)
758 PDEBUG(D_ERR, "failed to enable drop packet");
759 reg_w(gspca_dev, 0x00, 0x8880, 3);
760 err = spca50x_setup_qtable(gspca_dev,
761 0x00, 0x8800, 0x8840,
762 qtable_creative_pccam);
763 if (err < 0)
764 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
765
766 spca500_setmode(gspca_dev, xmult, ymult);
767 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
768
769 /* switch to video camera mode */
770 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
771
772 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
773 PDEBUG(D_ERR, "reg_r_wait() failed");
774
775 reg_r(gspca_dev, 0x816b, 1);
776 Data = gspca_dev->usb_buf[0];
777 reg_w(gspca_dev, 0x00, 0x816b, Data);
778
779/* write_vector(gspca_dev, spca500_visual_defaults); */
780 break;
781 case KodakEZ200: /* Kodak EZ200 */
782
783 /* do a full reset */
784 err = spca500_full_reset(gspca_dev);
785 if (err < 0)
786 PDEBUG(D_ERR, "spca500_full_reset failed");
787 /* enable drop packet */
788 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
789 reg_w(gspca_dev, 0x00, 0x8880, 0);
790 err = spca50x_setup_qtable(gspca_dev,
791 0x00, 0x8800, 0x8840,
792 qtable_kodak_ez200);
793 if (err < 0)
794 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
795 spca500_setmode(gspca_dev, xmult, ymult);
796
797 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
798
799 /* switch to video camera mode */
800 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
801
802 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
803 PDEBUG(D_ERR, "reg_r_wait() failed");
804
805 reg_r(gspca_dev, 0x816b, 1);
806 Data = gspca_dev->usb_buf[0];
807 reg_w(gspca_dev, 0x00, 0x816b, Data);
808
809/* write_vector(gspca_dev, spca500_visual_defaults); */
810 break;
811
812 case BenqDC1016:
813 case DLinkDSC350: /* FamilyCam 300 */
814 case AiptekPocketDV: /* Aiptek PocketDV */
815 case Gsmartmini: /*Mustek Gsmart Mini */
816 case MustekGsmart300: /* Mustek Gsmart 300 */
817 case PalmPixDC85:
818 case Optimedia:
819 case ToptroIndus:
820 case AgfaCl20:
821 spca500_reinit(gspca_dev);
822 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
823 /* enable drop packet */
824 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
825
826 err = spca50x_setup_qtable(gspca_dev,
827 0x00, 0x8800, 0x8840, qtable_pocketdv);
828 if (err < 0)
829 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
830 reg_w(gspca_dev, 0x00, 0x8880, 2);
831
832 /* familycam Quicksmart pocketDV stuff */
833 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
834 /* Set agc transfer: synced between frames */
835 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
836 /* Init SDRAM - needed for SDRAM access */
837 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
838
839 spca500_setmode(gspca_dev, xmult, ymult);
840 /* switch to video camera mode */
841 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
842
843 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
844
845 reg_r(gspca_dev, 0x816b, 1);
846 Data = gspca_dev->usb_buf[0];
847 reg_w(gspca_dev, 0x00, 0x816b, Data);
848 break;
849 case LogitechTraveler:
850 case LogitechClickSmart510:
851 reg_w(gspca_dev, 0x02, 0x00, 0x00);
852 /* enable drop packet */
853 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
854
855 err = spca50x_setup_qtable(gspca_dev,
856 0x00, 0x8800,
857 0x8840, qtable_creative_pccam);
858 if (err < 0)
859 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
860 reg_w(gspca_dev, 0x00, 0x8880, 3);
861 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
862 /* Init SDRAM - needed for SDRAM access */
863 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
864
865 spca500_setmode(gspca_dev, xmult, ymult);
866
867 /* switch to video camera mode */
868 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
869 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
870
871 reg_r(gspca_dev, 0x816b, 1);
872 Data = gspca_dev->usb_buf[0];
873 reg_w(gspca_dev, 0x00, 0x816b, Data);
874 write_vector(gspca_dev, Clicksmart510_defaults);
875 break;
876 }
877 return 0;
878}
879
880static void sd_stopN(struct gspca_dev *gspca_dev)
881{
882 reg_w(gspca_dev, 0, 0x8003, 0x00);
883
884 /* switch to video camera mode */
885 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
886 reg_r(gspca_dev, 0x8000, 1);
887 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
888 gspca_dev->usb_buf[0]);
889}
890
891static void sd_pkt_scan(struct gspca_dev *gspca_dev,
892 u8 *data, /* isoc packet */
893 int len) /* iso packet length */
894{
895 struct sd *sd = (struct sd *) gspca_dev;
896 int i;
897 static __u8 ffd9[] = {0xff, 0xd9};
898
899/* frames are jpeg 4.1.1 without 0xff escape */
900 if (data[0] == 0xff) {
901 if (data[1] != 0x01) { /* drop packet */
902/* gspca_dev->last_packet_type = DISCARD_PACKET; */
903 return;
904 }
905 gspca_frame_add(gspca_dev, LAST_PACKET,
906 ffd9, 2);
907
908 /* put the JPEG header in the new frame */
909 gspca_frame_add(gspca_dev, FIRST_PACKET,
910 sd->jpeg_hdr, JPEG_HDR_SZ);
911
912 data += SPCA500_OFFSET_DATA;
913 len -= SPCA500_OFFSET_DATA;
914 } else {
915 data += 1;
916 len -= 1;
917 }
918
919 /* add 0x00 after 0xff */
920 i = 0;
921 do {
922 if (data[i] == 0xff) {
923 gspca_frame_add(gspca_dev, INTER_PACKET,
924 data, i + 1);
925 len -= i;
926 data += i;
927 *data = 0x00;
928 i = 0;
929 }
930 i++;
931 } while (i < len);
932 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
933}
934
935static void setbrightness(struct gspca_dev *gspca_dev)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
938
939 reg_w(gspca_dev, 0x00, 0x8167,
940 (__u8) (sd->brightness - 128));
941}
942
943static void setcontrast(struct gspca_dev *gspca_dev)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
948}
949
950static void setcolors(struct gspca_dev *gspca_dev)
951{
952 struct sd *sd = (struct sd *) gspca_dev;
953
954 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
955}
956
957static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
960
961 sd->brightness = val;
962 if (gspca_dev->streaming)
963 setbrightness(gspca_dev);
964 return 0;
965}
966
967static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970
971 *val = sd->brightness;
972 return 0;
973}
974
975static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978
979 sd->contrast = val;
980 if (gspca_dev->streaming)
981 setcontrast(gspca_dev);
982 return 0;
983}
984
985static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 *val = sd->contrast;
990 return 0;
991}
992
993static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996
997 sd->colors = val;
998 if (gspca_dev->streaming)
999 setcolors(gspca_dev);
1000 return 0;
1001}
1002
1003static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1004{
1005 struct sd *sd = (struct sd *) gspca_dev;
1006
1007 *val = sd->colors;
1008 return 0;
1009}
1010
1011static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1012 struct v4l2_jpegcompression *jcomp)
1013{
1014 struct sd *sd = (struct sd *) gspca_dev;
1015
1016 if (jcomp->quality < QUALITY_MIN)
1017 sd->quality = QUALITY_MIN;
1018 else if (jcomp->quality > QUALITY_MAX)
1019 sd->quality = QUALITY_MAX;
1020 else
1021 sd->quality = jcomp->quality;
1022 if (gspca_dev->streaming)
1023 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1024 return 0;
1025}
1026
1027static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1028 struct v4l2_jpegcompression *jcomp)
1029{
1030 struct sd *sd = (struct sd *) gspca_dev;
1031
1032 memset(jcomp, 0, sizeof *jcomp);
1033 jcomp->quality = sd->quality;
1034 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1035 | V4L2_JPEG_MARKER_DQT;
1036 return 0;
1037}
1038
1039/* sub-driver description */
1040static const struct sd_desc sd_desc = {
1041 .name = MODULE_NAME,
1042 .ctrls = sd_ctrls,
1043 .nctrls = ARRAY_SIZE(sd_ctrls),
1044 .config = sd_config,
1045 .init = sd_init,
1046 .start = sd_start,
1047 .stopN = sd_stopN,
1048 .pkt_scan = sd_pkt_scan,
1049 .get_jcomp = sd_get_jcomp,
1050 .set_jcomp = sd_set_jcomp,
1051};
1052
1053/* -- module initialisation -- */
1054static const struct usb_device_id device_table[] = {
1055 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1056 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1057 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1058 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1059 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1060 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1061 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1062 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1063 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1064 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1065 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1066 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1067 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1068 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1069 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
1070 {}
1071};
1072MODULE_DEVICE_TABLE(usb, device_table);
1073
1074/* -- device connect -- */
1075static int sd_probe(struct usb_interface *intf,
1076 const struct usb_device_id *id)
1077{
1078 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1079 THIS_MODULE);
1080}
1081
1082static struct usb_driver sd_driver = {
1083 .name = MODULE_NAME,
1084 .id_table = device_table,
1085 .probe = sd_probe,
1086 .disconnect = gspca_disconnect,
1087#ifdef CONFIG_PM
1088 .suspend = gspca_suspend,
1089 .resume = gspca_resume,
1090#endif
1091};
1092
1093/* -- module insert / remove -- */
1094static int __init sd_mod_init(void)
1095{
1096 return usb_register(&sd_driver);
1097}
1098static void __exit sd_mod_exit(void)
1099{
1100 usb_deregister(&sd_driver);
1101}
1102
1103module_init(sd_mod_init);
1104module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
new file mode 100644
index 00000000000..f7ef282cc60
--- /dev/null
+++ b/drivers/media/video/gspca/spca501.c
@@ -0,0 +1,2200 @@
1/*
2 * SPCA501 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca501"
23
24#include "gspca.h"
25
26MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
27MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver");
28MODULE_LICENSE("GPL");
29
30/* specific webcam descriptor */
31struct sd {
32 struct gspca_dev gspca_dev; /* !! must be the first item */
33
34 unsigned short contrast;
35 __u8 brightness;
36 __u8 colors;
37 __u8 blue_balance;
38 __u8 red_balance;
39
40 char subtype;
41#define Arowana300KCMOSCamera 0
42#define IntelCreateAndShare 1
43#define KodakDVC325 2
44#define MystFromOriUnknownCamera 3
45#define SmileIntlCamera 4
46#define ThreeComHomeConnectLite 5
47#define ViewQuestM318B 6
48};
49
50/* V4L2 controls supported by the driver */
51static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
53static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
54static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
55static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
57static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
61
62static const struct ctrl sd_ctrls[] = {
63#define MY_BRIGHTNESS 0
64 {
65 {
66 .id = V4L2_CID_BRIGHTNESS,
67 .type = V4L2_CTRL_TYPE_INTEGER,
68 .name = "Brightness",
69 .minimum = 0,
70 .maximum = 127,
71 .step = 1,
72 .default_value = 0,
73 },
74 .set = sd_setbrightness,
75 .get = sd_getbrightness,
76 },
77#define MY_CONTRAST 1
78 {
79 {
80 .id = V4L2_CID_CONTRAST,
81 .type = V4L2_CTRL_TYPE_INTEGER,
82 .name = "Contrast",
83 .minimum = 0,
84 .maximum = 64725,
85 .step = 1,
86 .default_value = 64725,
87 },
88 .set = sd_setcontrast,
89 .get = sd_getcontrast,
90 },
91#define MY_COLOR 2
92 {
93 {
94 .id = V4L2_CID_SATURATION,
95 .type = V4L2_CTRL_TYPE_INTEGER,
96 .name = "Color",
97 .minimum = 0,
98 .maximum = 63,
99 .step = 1,
100 .default_value = 20,
101 },
102 .set = sd_setcolors,
103 .get = sd_getcolors,
104 },
105#define MY_BLUE_BALANCE 3
106 {
107 {
108 .id = V4L2_CID_BLUE_BALANCE,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "Blue Balance",
111 .minimum = 0,
112 .maximum = 127,
113 .step = 1,
114 .default_value = 0,
115 },
116 .set = sd_setblue_balance,
117 .get = sd_getblue_balance,
118 },
119#define MY_RED_BALANCE 4
120 {
121 {
122 .id = V4L2_CID_RED_BALANCE,
123 .type = V4L2_CTRL_TYPE_INTEGER,
124 .name = "Red Balance",
125 .minimum = 0,
126 .maximum = 127,
127 .step = 1,
128 .default_value = 0,
129 },
130 .set = sd_setred_balance,
131 .get = sd_getred_balance,
132 },
133};
134
135static const struct v4l2_pix_format vga_mode[] = {
136 {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
137 .bytesperline = 160,
138 .sizeimage = 160 * 120 * 3 / 2,
139 .colorspace = V4L2_COLORSPACE_SRGB,
140 .priv = 2},
141 {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
142 .bytesperline = 320,
143 .sizeimage = 320 * 240 * 3 / 2,
144 .colorspace = V4L2_COLORSPACE_SRGB,
145 .priv = 1},
146 {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
147 .bytesperline = 640,
148 .sizeimage = 640 * 480 * 3 / 2,
149 .colorspace = V4L2_COLORSPACE_SRGB,
150 .priv = 0},
151};
152
153#define SPCA50X_REG_USB 0x2 /* spca505 501 */
154/*
155 * Data to initialize a SPCA501. From a capture file provided by Bill Roehl
156 * With SPCA501 chip description
157 */
158#define CCDSP_SET /* set CCDSP parameters */
159#define TG_SET /* set time generator set */
160#undef DSPWIN_SET /* set DSP windows parameters */
161#undef ALTER_GAMA /* Set alternate set to YUV transform coeffs. */
162#define SPCA501_SNAPBIT 0x80
163#define SPCA501_SNAPCTRL 0x10
164/* Frame packet header offsets for the spca501 */
165#define SPCA501_OFFSET_GPIO 1
166#define SPCA501_OFFSET_TYPE 2
167#define SPCA501_OFFSET_TURN3A 3
168#define SPCA501_OFFSET_FRAMSEQ 4
169#define SPCA501_OFFSET_COMPRESS 5
170#define SPCA501_OFFSET_QUANT 6
171#define SPCA501_OFFSET_QUANT2 7
172#define SPCA501_OFFSET_DATA 8
173
174#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1)
175#define SPCA501_PROP_SNAP(d) ((d) & 0x40)
176#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10)
177#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1)
178#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4)
179
180/* SPCA501 CCDSP control */
181#define SPCA501_REG_CCDSP 0x01
182/* SPCA501 control/status registers */
183#define SPCA501_REG_CTLRL 0x02
184
185/* registers for color correction and YUV transformation */
186#define SPCA501_A11 0x08
187#define SPCA501_A12 0x09
188#define SPCA501_A13 0x0A
189#define SPCA501_A21 0x0B
190#define SPCA501_A22 0x0C
191#define SPCA501_A23 0x0D
192#define SPCA501_A31 0x0E
193#define SPCA501_A32 0x0F
194#define SPCA501_A33 0x10
195
196/* Data for video camera initialization before capturing */
197static const __u16 spca501_open_data[][3] = {
198 /* bmRequest,value,index */
199
200 {0x2, 0x50, 0x00}, /* C/S enable soft reset */
201 {0x2, 0x40, 0x00}, /* C/S disable soft reset */
202 {0x2, 0x02, 0x05}, /* C/S general purpose I/O data */
203 {0x2, 0x03, 0x05}, /* C/S general purpose I/O data */
204
205#ifdef CCDSP_SET
206 {0x1, 0x38, 0x01}, /* CCDSP options */
207 {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */
208 {0x1, 0xC0, 0x03}, /* CCDSP Optical black settings */
209
210 {0x1, 0x67, 0x07},
211 {0x1, 0x63, 0x3f}, /* CCDSP CCD gamma enable */
212 {0x1, 0x03, 0x56}, /* Add gamma correction */
213
214 {0x1, 0xFF, 0x15}, /* CCDSP High luminance for white balance */
215 {0x1, 0x01, 0x16}, /* CCDSP Low luminance for white balance */
216
217/* Color correction and RGB-to-YUV transformation coefficients changing */
218#ifdef ALTER_GAMA
219 {0x0, 0x00, 0x08}, /* A11 */
220 {0x0, 0x00, 0x09}, /* A12 */
221 {0x0, 0x90, 0x0A}, /* A13 */
222 {0x0, 0x12, 0x0B}, /* A21 */
223 {0x0, 0x00, 0x0C}, /* A22 */
224 {0x0, 0x00, 0x0D}, /* A23 */
225 {0x0, 0x00, 0x0E}, /* A31 */
226 {0x0, 0x02, 0x0F}, /* A32 */
227 {0x0, 0x00, 0x10}, /* A33 */
228#else
229 {0x1, 0x2a, 0x08}, /* A11 0x31 */
230 {0x1, 0xf8, 0x09}, /* A12 f8 */
231 {0x1, 0xf8, 0x0A}, /* A13 f8 */
232 {0x1, 0xf8, 0x0B}, /* A21 f8 */
233 {0x1, 0x14, 0x0C}, /* A22 0x14 */
234 {0x1, 0xf8, 0x0D}, /* A23 f8 */
235 {0x1, 0xf8, 0x0E}, /* A31 f8 */
236 {0x1, 0xf8, 0x0F}, /* A32 f8 */
237 {0x1, 0x20, 0x10}, /* A33 0x20 */
238#endif
239 {0x1, 0x00, 0x11}, /* R offset */
240 {0x1, 0x00, 0x12}, /* G offset */
241 {0x1, 0x00, 0x13}, /* B offset */
242 {0x1, 0x00, 0x14}, /* GB offset */
243
244#endif
245
246#ifdef TG_SET
247 /* Time generator manipulations */
248 {0x0, 0xfc, 0x0}, /* Set up high bits of shutter speed */
249 {0x0, 0x01, 0x1}, /* Set up low bits of shutter speed */
250
251 {0x0, 0xe4, 0x04}, /* DCLK*2 clock phase adjustment */
252 {0x0, 0x08, 0x05}, /* ADCK phase adjustment, inv. ext. VB */
253 {0x0, 0x03, 0x06}, /* FR phase adjustment */
254 {0x0, 0x01, 0x07}, /* FCDS phase adjustment */
255 {0x0, 0x39, 0x08}, /* FS phase adjustment */
256 {0x0, 0x88, 0x0a}, /* FH1 phase and delay adjustment */
257 {0x0, 0x03, 0x0f}, /* pixel identification */
258 {0x0, 0x00, 0x11}, /* clock source selection (default) */
259
260 /*VERY strange manipulations with
261 * select DMCLP or OBPX to be ADCLP output (0x0C)
262 * OPB always toggle or not (0x0D) but they allow
263 * us to set up brightness
264 */
265 {0x0, 0x01, 0x0c},
266 {0x0, 0xe0, 0x0d},
267 /* Done */
268#endif
269
270#ifdef DSPWIN_SET
271 {0x1, 0xa0, 0x01}, /* Setting image processing parameters */
272 {0x1, 0x1c, 0x17}, /* Changing Windows positions X1 */
273 {0x1, 0xe2, 0x19}, /* X2 */
274 {0x1, 0x1c, 0x1b}, /* X3 */
275 {0x1, 0xe2, 0x1d}, /* X4 */
276 {0x1, 0x5f, 0x1f}, /* X5 */
277 {0x1, 0x32, 0x20}, /* Y5 */
278 {0x1, 0x01, 0x10}, /* Changing A33 */
279#endif
280
281 {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */
282 {0x2, 0x94, 0x06}, /* Setting video no compression */
283 {}
284};
285
286/*
287 The SPCAxxx docs from Sunplus document these values
288 in tables, one table per register number. In the data
289 below, dmRequest is the register number, index is the Addr,
290 and value is a combination of Bit values.
291 Bit Value (hex)
292 0 01
293 1 02
294 2 04
295 3 08
296 4 10
297 5 20
298 6 40
299 7 80
300 */
301
302/* Data for chip initialization (set default values) */
303static const __u16 spca501_init_data[][3] = {
304 /* Set all the values to powerup defaults */
305 /* bmRequest,value,index */
306 {0x0, 0xAA, 0x00},
307 {0x0, 0x02, 0x01},
308 {0x0, 0x01, 0x02},
309 {0x0, 0x02, 0x03},
310 {0x0, 0xCE, 0x04},
311 {0x0, 0x00, 0x05},
312 {0x0, 0x00, 0x06},
313 {0x0, 0x00, 0x07},
314 {0x0, 0x00, 0x08},
315 {0x0, 0x00, 0x09},
316 {0x0, 0x90, 0x0A},
317 {0x0, 0x12, 0x0B},
318 {0x0, 0x00, 0x0C},
319 {0x0, 0x00, 0x0D},
320 {0x0, 0x00, 0x0E},
321 {0x0, 0x02, 0x0F},
322 {0x0, 0x00, 0x10},
323 {0x0, 0x00, 0x11},
324 {0x0, 0x00, 0x12},
325 {0x0, 0x00, 0x13},
326 {0x0, 0x00, 0x14},
327 {0x0, 0x00, 0x15},
328 {0x0, 0x00, 0x16},
329 {0x0, 0x00, 0x17},
330 {0x0, 0x00, 0x18},
331 {0x0, 0x00, 0x19},
332 {0x0, 0x00, 0x1A},
333 {0x0, 0x00, 0x1B},
334 {0x0, 0x00, 0x1C},
335 {0x0, 0x00, 0x1D},
336 {0x0, 0x00, 0x1E},
337 {0x0, 0x00, 0x1F},
338 {0x0, 0x00, 0x20},
339 {0x0, 0x00, 0x21},
340 {0x0, 0x00, 0x22},
341 {0x0, 0x00, 0x23},
342 {0x0, 0x00, 0x24},
343 {0x0, 0x00, 0x25},
344 {0x0, 0x00, 0x26},
345 {0x0, 0x00, 0x27},
346 {0x0, 0x00, 0x28},
347 {0x0, 0x00, 0x29},
348 {0x0, 0x00, 0x2A},
349 {0x0, 0x00, 0x2B},
350 {0x0, 0x00, 0x2C},
351 {0x0, 0x00, 0x2D},
352 {0x0, 0x00, 0x2E},
353 {0x0, 0x00, 0x2F},
354 {0x0, 0x00, 0x30},
355 {0x0, 0x00, 0x31},
356 {0x0, 0x00, 0x32},
357 {0x0, 0x00, 0x33},
358 {0x0, 0x00, 0x34},
359 {0x0, 0x00, 0x35},
360 {0x0, 0x00, 0x36},
361 {0x0, 0x00, 0x37},
362 {0x0, 0x00, 0x38},
363 {0x0, 0x00, 0x39},
364 {0x0, 0x00, 0x3A},
365 {0x0, 0x00, 0x3B},
366 {0x0, 0x00, 0x3C},
367 {0x0, 0x00, 0x3D},
368 {0x0, 0x00, 0x3E},
369 {0x0, 0x00, 0x3F},
370 {0x0, 0x00, 0x40},
371 {0x0, 0x00, 0x41},
372 {0x0, 0x00, 0x42},
373 {0x0, 0x00, 0x43},
374 {0x0, 0x00, 0x44},
375 {0x0, 0x00, 0x45},
376 {0x0, 0x00, 0x46},
377 {0x0, 0x00, 0x47},
378 {0x0, 0x00, 0x48},
379 {0x0, 0x00, 0x49},
380 {0x0, 0x00, 0x4A},
381 {0x0, 0x00, 0x4B},
382 {0x0, 0x00, 0x4C},
383 {0x0, 0x00, 0x4D},
384 {0x0, 0x00, 0x4E},
385 {0x0, 0x00, 0x4F},
386 {0x0, 0x00, 0x50},
387 {0x0, 0x00, 0x51},
388 {0x0, 0x00, 0x52},
389 {0x0, 0x00, 0x53},
390 {0x0, 0x00, 0x54},
391 {0x0, 0x00, 0x55},
392 {0x0, 0x00, 0x56},
393 {0x0, 0x00, 0x57},
394 {0x0, 0x00, 0x58},
395 {0x0, 0x00, 0x59},
396 {0x0, 0x00, 0x5A},
397 {0x0, 0x00, 0x5B},
398 {0x0, 0x00, 0x5C},
399 {0x0, 0x00, 0x5D},
400 {0x0, 0x00, 0x5E},
401 {0x0, 0x00, 0x5F},
402 {0x0, 0x00, 0x60},
403 {0x0, 0x00, 0x61},
404 {0x0, 0x00, 0x62},
405 {0x0, 0x00, 0x63},
406 {0x0, 0x00, 0x64},
407 {0x0, 0x00, 0x65},
408 {0x0, 0x00, 0x66},
409 {0x0, 0x00, 0x67},
410 {0x0, 0x00, 0x68},
411 {0x0, 0x00, 0x69},
412 {0x0, 0x00, 0x6A},
413 {0x0, 0x00, 0x6B},
414 {0x0, 0x00, 0x6C},
415 {0x0, 0x00, 0x6D},
416 {0x0, 0x00, 0x6E},
417 {0x0, 0x00, 0x6F},
418 {0x0, 0x00, 0x70},
419 {0x0, 0x00, 0x71},
420 {0x0, 0x00, 0x72},
421 {0x0, 0x00, 0x73},
422 {0x0, 0x00, 0x74},
423 {0x0, 0x00, 0x75},
424 {0x0, 0x00, 0x76},
425 {0x0, 0x00, 0x77},
426 {0x0, 0x00, 0x78},
427 {0x0, 0x00, 0x79},
428 {0x0, 0x00, 0x7A},
429 {0x0, 0x00, 0x7B},
430 {0x0, 0x00, 0x7C},
431 {0x0, 0x00, 0x7D},
432 {0x0, 0x00, 0x7E},
433 {0x0, 0x00, 0x7F},
434 {0x0, 0x00, 0x80},
435 {0x0, 0x00, 0x81},
436 {0x0, 0x00, 0x82},
437 {0x0, 0x00, 0x83},
438 {0x0, 0x00, 0x84},
439 {0x0, 0x00, 0x85},
440 {0x0, 0x00, 0x86},
441 {0x0, 0x00, 0x87},
442 {0x0, 0x00, 0x88},
443 {0x0, 0x00, 0x89},
444 {0x0, 0x00, 0x8A},
445 {0x0, 0x00, 0x8B},
446 {0x0, 0x00, 0x8C},
447 {0x0, 0x00, 0x8D},
448 {0x0, 0x00, 0x8E},
449 {0x0, 0x00, 0x8F},
450 {0x0, 0x00, 0x90},
451 {0x0, 0x00, 0x91},
452 {0x0, 0x00, 0x92},
453 {0x0, 0x00, 0x93},
454 {0x0, 0x00, 0x94},
455 {0x0, 0x00, 0x95},
456 {0x0, 0x00, 0x96},
457 {0x0, 0x00, 0x97},
458 {0x0, 0x00, 0x98},
459 {0x0, 0x00, 0x99},
460 {0x0, 0x00, 0x9A},
461 {0x0, 0x00, 0x9B},
462 {0x0, 0x00, 0x9C},
463 {0x0, 0x00, 0x9D},
464 {0x0, 0x00, 0x9E},
465 {0x0, 0x00, 0x9F},
466 {0x0, 0x00, 0xA0},
467 {0x0, 0x00, 0xA1},
468 {0x0, 0x00, 0xA2},
469 {0x0, 0x00, 0xA3},
470 {0x0, 0x00, 0xA4},
471 {0x0, 0x00, 0xA5},
472 {0x0, 0x00, 0xA6},
473 {0x0, 0x00, 0xA7},
474 {0x0, 0x00, 0xA8},
475 {0x0, 0x00, 0xA9},
476 {0x0, 0x00, 0xAA},
477 {0x0, 0x00, 0xAB},
478 {0x0, 0x00, 0xAC},
479 {0x0, 0x00, 0xAD},
480 {0x0, 0x00, 0xAE},
481 {0x0, 0x00, 0xAF},
482 {0x0, 0x00, 0xB0},
483 {0x0, 0x00, 0xB1},
484 {0x0, 0x00, 0xB2},
485 {0x0, 0x00, 0xB3},
486 {0x0, 0x00, 0xB4},
487 {0x0, 0x00, 0xB5},
488 {0x0, 0x00, 0xB6},
489 {0x0, 0x00, 0xB7},
490 {0x0, 0x00, 0xB8},
491 {0x0, 0x00, 0xB9},
492 {0x0, 0x00, 0xBA},
493 {0x0, 0x00, 0xBB},
494 {0x0, 0x00, 0xBC},
495 {0x0, 0x00, 0xBD},
496 {0x0, 0x00, 0xBE},
497 {0x0, 0x00, 0xBF},
498 {0x0, 0x00, 0xC0},
499 {0x0, 0x00, 0xC1},
500 {0x0, 0x00, 0xC2},
501 {0x0, 0x00, 0xC3},
502 {0x0, 0x00, 0xC4},
503 {0x0, 0x00, 0xC5},
504 {0x0, 0x00, 0xC6},
505 {0x0, 0x00, 0xC7},
506 {0x0, 0x00, 0xC8},
507 {0x0, 0x00, 0xC9},
508 {0x0, 0x00, 0xCA},
509 {0x0, 0x00, 0xCB},
510 {0x0, 0x00, 0xCC},
511 {0x1, 0xF4, 0x00},
512 {0x1, 0x38, 0x01},
513 {0x1, 0x40, 0x02},
514 {0x1, 0x0A, 0x03},
515 {0x1, 0x40, 0x04},
516 {0x1, 0x40, 0x05},
517 {0x1, 0x40, 0x06},
518 {0x1, 0x67, 0x07},
519 {0x1, 0x31, 0x08},
520 {0x1, 0x00, 0x09},
521 {0x1, 0x00, 0x0A},
522 {0x1, 0x00, 0x0B},
523 {0x1, 0x14, 0x0C},
524 {0x1, 0x00, 0x0D},
525 {0x1, 0x00, 0x0E},
526 {0x1, 0x00, 0x0F},
527 {0x1, 0x1E, 0x10},
528 {0x1, 0x00, 0x11},
529 {0x1, 0x00, 0x12},
530 {0x1, 0x00, 0x13},
531 {0x1, 0x00, 0x14},
532 {0x1, 0xFF, 0x15},
533 {0x1, 0x01, 0x16},
534 {0x1, 0x32, 0x17},
535 {0x1, 0x23, 0x18},
536 {0x1, 0xCE, 0x19},
537 {0x1, 0x23, 0x1A},
538 {0x1, 0x32, 0x1B},
539 {0x1, 0x8D, 0x1C},
540 {0x1, 0xCE, 0x1D},
541 {0x1, 0x8D, 0x1E},
542 {0x1, 0x00, 0x1F},
543 {0x1, 0x00, 0x20},
544 {0x1, 0xFF, 0x3E},
545 {0x1, 0x02, 0x3F},
546 {0x1, 0x00, 0x40},
547 {0x1, 0x00, 0x41},
548 {0x1, 0x00, 0x42},
549 {0x1, 0x00, 0x43},
550 {0x1, 0x00, 0x44},
551 {0x1, 0x00, 0x45},
552 {0x1, 0x00, 0x46},
553 {0x1, 0x00, 0x47},
554 {0x1, 0x00, 0x48},
555 {0x1, 0x00, 0x49},
556 {0x1, 0x00, 0x4A},
557 {0x1, 0x00, 0x4B},
558 {0x1, 0x00, 0x4C},
559 {0x1, 0x00, 0x4D},
560 {0x1, 0x00, 0x4E},
561 {0x1, 0x00, 0x4F},
562 {0x1, 0x00, 0x50},
563 {0x1, 0x00, 0x51},
564 {0x1, 0x00, 0x52},
565 {0x1, 0x00, 0x53},
566 {0x1, 0x00, 0x54},
567 {0x1, 0x00, 0x55},
568 {0x1, 0x00, 0x56},
569 {0x1, 0x00, 0x57},
570 {0x1, 0x00, 0x58},
571 {0x1, 0x00, 0x59},
572 {0x1, 0x00, 0x5A},
573 {0x2, 0x03, 0x00},
574 {0x2, 0x00, 0x01},
575 {0x2, 0x00, 0x05},
576 {0x2, 0x00, 0x06},
577 {0x2, 0x00, 0x07},
578 {0x2, 0x00, 0x10},
579 {0x2, 0x00, 0x11},
580 /* Strange - looks like the 501 driver doesn't do anything
581 * at insert time except read the EEPROM
582 */
583 {}
584};
585
586/* Data for video camera init before capture.
587 * Capture and decoding by Colin Peart.
588 * This is is for the 3com HomeConnect Lite which is spca501a based.
589 */
590static const __u16 spca501_3com_open_data[][3] = {
591 /* bmRequest,value,index */
592 {0x2, 0x0050, 0x0000}, /* C/S Enable TG soft reset, timing mode=010 */
593 {0x2, 0x0043, 0x0000}, /* C/S Disable TG soft reset, timing mode=010 */
594 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
595 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
596
597#ifdef CCDSP_SET
598 {0x1, 0x0020, 0x0001}, /* CCDSP Options */
599
600 {0x1, 0x0020, 0x0002}, /* CCDSP Black Level */
601 {0x1, 0x006e, 0x0007}, /* CCDSP Gamma options */
602 {0x1, 0x0090, 0x0015}, /* CCDSP Luminance Low */
603 {0x1, 0x00ff, 0x0016}, /* CCDSP Luminance High */
604 {0x1, 0x0003, 0x003F}, /* CCDSP Gamma correction toggle */
605
606#ifdef ALTER_GAMMA
607 {0x1, 0x0010, 0x0008}, /* CCDSP YUV A11 */
608 {0x1, 0x0000, 0x0009}, /* CCDSP YUV A12 */
609 {0x1, 0x0000, 0x000a}, /* CCDSP YUV A13 */
610 {0x1, 0x0000, 0x000b}, /* CCDSP YUV A21 */
611 {0x1, 0x0010, 0x000c}, /* CCDSP YUV A22 */
612 {0x1, 0x0000, 0x000d}, /* CCDSP YUV A23 */
613 {0x1, 0x0000, 0x000e}, /* CCDSP YUV A31 */
614 {0x1, 0x0000, 0x000f}, /* CCDSP YUV A32 */
615 {0x1, 0x0010, 0x0010}, /* CCDSP YUV A33 */
616 {0x1, 0x0000, 0x0011}, /* CCDSP R Offset */
617 {0x1, 0x0000, 0x0012}, /* CCDSP G Offset */
618 {0x1, 0x0001, 0x0013}, /* CCDSP B Offset */
619 {0x1, 0x0001, 0x0014}, /* CCDSP BG Offset */
620 {0x1, 0x003f, 0x00C1}, /* CCDSP Gamma Correction Enable */
621#endif
622#endif
623
624#ifdef TG_SET
625 {0x0, 0x00fc, 0x0000}, /* TG Shutter Speed High Bits */
626 {0x0, 0x0000, 0x0001}, /* TG Shutter Speed Low Bits */
627 {0x0, 0x00e4, 0x0004}, /* TG DCLK*2 Adjust */
628 {0x0, 0x0008, 0x0005}, /* TG ADCK Adjust */
629 {0x0, 0x0003, 0x0006}, /* TG FR Phase Adjust */
630 {0x0, 0x0001, 0x0007}, /* TG FCDS Phase Adjust */
631 {0x0, 0x0039, 0x0008}, /* TG FS Phase Adjust */
632 {0x0, 0x0088, 0x000a}, /* TG MH1 */
633 {0x0, 0x0003, 0x000f}, /* TG Pixel ID */
634
635 /* Like below, unexplained toglleing */
636 {0x0, 0x0080, 0x000c},
637 {0x0, 0x0000, 0x000d},
638 {0x0, 0x0080, 0x000c},
639 {0x0, 0x0004, 0x000d},
640 {0x0, 0x0000, 0x000c},
641 {0x0, 0x0000, 0x000d},
642 {0x0, 0x0040, 0x000c},
643 {0x0, 0x0017, 0x000d},
644 {0x0, 0x00c0, 0x000c},
645 {0x0, 0x0000, 0x000d},
646 {0x0, 0x0080, 0x000c},
647 {0x0, 0x0006, 0x000d},
648 {0x0, 0x0080, 0x000c},
649 {0x0, 0x0004, 0x000d},
650 {0x0, 0x0002, 0x0003},
651#endif
652
653#ifdef DSPWIN_SET
654 {0x1, 0x001c, 0x0017}, /* CCDSP W1 Start X */
655 {0x1, 0x00e2, 0x0019}, /* CCDSP W2 Start X */
656 {0x1, 0x001c, 0x001b}, /* CCDSP W3 Start X */
657 {0x1, 0x00e2, 0x001d}, /* CCDSP W4 Start X */
658 {0x1, 0x00aa, 0x001f}, /* CCDSP W5 Start X */
659 {0x1, 0x0070, 0x0020}, /* CCDSP W5 Start Y */
660#endif
661 {0x0, 0x0001, 0x0010}, /* TG Start Clock */
662
663/* {0x2, 0x006a, 0x0001}, * C/S Enable ISOSYNCH Packet Engine */
664 {0x2, 0x0068, 0x0001}, /* C/S Diable ISOSYNCH Packet Engine */
665 {0x2, 0x0000, 0x0005},
666 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
667 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
668 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
669 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
670
671 {0x2, 0x006a, 0x0001}, /* C/S Enable ISOSYNCH Packet Engine */
672 {}
673};
674
675/*
676 * Data used to initialize a SPCA501C with HV7131B sensor.
677 * From a capture file taken with USBSnoop v 1.5
678 * I have a "SPCA501C pc camera chipset" manual by sunplus, but some
679 * of the value meanings are obscure or simply "reserved".
680 * to do list:
681 * 1) Understand what every value means
682 * 2) Understand why some values seem to appear more than once
683 * 3) Write a small comment for each line of the following arrays.
684 */
685static const __u16 spca501c_arowana_open_data[][3] = {
686 /* bmRequest,value,index */
687 {0x02, 0x0007, 0x0005},
688 {0x02, 0xa048, 0x0000},
689 {0x05, 0x0022, 0x0004},
690 {0x01, 0x0006, 0x0011},
691 {0x01, 0x00ff, 0x0012},
692 {0x01, 0x0014, 0x0013},
693 {0x01, 0x0000, 0x0014},
694 {0x01, 0x0042, 0x0051},
695 {0x01, 0x0040, 0x0052},
696 {0x01, 0x0051, 0x0053},
697 {0x01, 0x0040, 0x0054},
698 {0x01, 0x0000, 0x0055},
699 {0x00, 0x0025, 0x0000},
700 {0x00, 0x0026, 0x0000},
701 {0x00, 0x0001, 0x0000},
702 {0x00, 0x0027, 0x0000},
703 {0x00, 0x008a, 0x0000},
704 {}
705};
706
707static const __u16 spca501c_arowana_init_data[][3] = {
708 /* bmRequest,value,index */
709 {0x02, 0x0007, 0x0005},
710 {0x02, 0xa048, 0x0000},
711 {0x05, 0x0022, 0x0004},
712 {0x01, 0x0006, 0x0011},
713 {0x01, 0x00ff, 0x0012},
714 {0x01, 0x0014, 0x0013},
715 {0x01, 0x0000, 0x0014},
716 {0x01, 0x0042, 0x0051},
717 {0x01, 0x0040, 0x0052},
718 {0x01, 0x0051, 0x0053},
719 {0x01, 0x0040, 0x0054},
720 {0x01, 0x0000, 0x0055},
721 {0x00, 0x0025, 0x0000},
722 {0x00, 0x0026, 0x0000},
723 {0x00, 0x0001, 0x0000},
724 {0x00, 0x0027, 0x0000},
725 {0x00, 0x008a, 0x0000},
726 {0x02, 0x0000, 0x0005},
727 {0x02, 0x0007, 0x0005},
728 {0x02, 0x2000, 0x0000},
729 {0x05, 0x0022, 0x0004},
730 {0x05, 0x0015, 0x0001},
731 {0x05, 0x00ea, 0x0000},
732 {0x05, 0x0021, 0x0001},
733 {0x05, 0x00d2, 0x0000},
734 {0x05, 0x0023, 0x0001},
735 {0x05, 0x0003, 0x0000},
736 {0x05, 0x0030, 0x0001},
737 {0x05, 0x002b, 0x0000},
738 {0x05, 0x0031, 0x0001},
739 {0x05, 0x0023, 0x0000},
740 {0x05, 0x0032, 0x0001},
741 {0x05, 0x0023, 0x0000},
742 {0x05, 0x0033, 0x0001},
743 {0x05, 0x0023, 0x0000},
744 {0x05, 0x0034, 0x0001},
745 {0x05, 0x0002, 0x0000},
746 {0x05, 0x0050, 0x0001},
747 {0x05, 0x0000, 0x0000},
748 {0x05, 0x0051, 0x0001},
749 {0x05, 0x0000, 0x0000},
750 {0x05, 0x0052, 0x0001},
751 {0x05, 0x0000, 0x0000},
752 {0x05, 0x0054, 0x0001},
753 {0x05, 0x0001, 0x0000},
754 {0x00, 0x0000, 0x0001},
755 {0x00, 0x0000, 0x0002},
756 {0x00, 0x000c, 0x0003},
757 {0x00, 0x0000, 0x0004},
758 {0x00, 0x0090, 0x0005},
759 {0x00, 0x0000, 0x0006},
760 {0x00, 0x0040, 0x0007},
761 {0x00, 0x00c0, 0x0008},
762 {0x00, 0x004a, 0x0009},
763 {0x00, 0x0000, 0x000a},
764 {0x00, 0x0000, 0x000b},
765 {0x00, 0x0001, 0x000c},
766 {0x00, 0x0001, 0x000d},
767 {0x00, 0x0000, 0x000e},
768 {0x00, 0x0002, 0x000f},
769 {0x00, 0x0001, 0x0010},
770 {0x00, 0x0000, 0x0011},
771 {0x00, 0x0000, 0x0012},
772 {0x00, 0x0002, 0x0020},
773 {0x00, 0x0080, 0x0021},
774 {0x00, 0x0001, 0x0022},
775 {0x00, 0x00e0, 0x0023},
776 {0x00, 0x0000, 0x0024},
777 {0x00, 0x00d5, 0x0025},
778 {0x00, 0x0000, 0x0026},
779 {0x00, 0x000b, 0x0027},
780 {0x00, 0x0000, 0x0046},
781 {0x00, 0x0000, 0x0047},
782 {0x00, 0x0000, 0x0048},
783 {0x00, 0x0000, 0x0049},
784 {0x00, 0x0008, 0x004a},
785 {0xff, 0x0000, 0x00d0},
786 {0xff, 0x00d8, 0x00d1},
787 {0xff, 0x0000, 0x00d4},
788 {0xff, 0x0000, 0x00d5},
789 {0x01, 0x00a6, 0x0000},
790 {0x01, 0x0028, 0x0001},
791 {0x01, 0x0000, 0x0002},
792 {0x01, 0x000a, 0x0003},
793 {0x01, 0x0040, 0x0004},
794 {0x01, 0x0066, 0x0007},
795 {0x01, 0x0011, 0x0008},
796 {0x01, 0x0032, 0x0009},
797 {0x01, 0x00fd, 0x000a},
798 {0x01, 0x0038, 0x000b},
799 {0x01, 0x00d1, 0x000c},
800 {0x01, 0x00f7, 0x000d},
801 {0x01, 0x00ed, 0x000e},
802 {0x01, 0x00d8, 0x000f},
803 {0x01, 0x0038, 0x0010},
804 {0x01, 0x00ff, 0x0015},
805 {0x01, 0x0001, 0x0016},
806 {0x01, 0x0032, 0x0017},
807 {0x01, 0x0023, 0x0018},
808 {0x01, 0x00ce, 0x0019},
809 {0x01, 0x0023, 0x001a},
810 {0x01, 0x0032, 0x001b},
811 {0x01, 0x008d, 0x001c},
812 {0x01, 0x00ce, 0x001d},
813 {0x01, 0x008d, 0x001e},
814 {0x01, 0x0000, 0x001f},
815 {0x01, 0x0000, 0x0020},
816 {0x01, 0x00ff, 0x003e},
817 {0x01, 0x0003, 0x003f},
818 {0x01, 0x0000, 0x0040},
819 {0x01, 0x0035, 0x0041},
820 {0x01, 0x0053, 0x0042},
821 {0x01, 0x0069, 0x0043},
822 {0x01, 0x007c, 0x0044},
823 {0x01, 0x008c, 0x0045},
824 {0x01, 0x009a, 0x0046},
825 {0x01, 0x00a8, 0x0047},
826 {0x01, 0x00b4, 0x0048},
827 {0x01, 0x00bf, 0x0049},
828 {0x01, 0x00ca, 0x004a},
829 {0x01, 0x00d4, 0x004b},
830 {0x01, 0x00dd, 0x004c},
831 {0x01, 0x00e7, 0x004d},
832 {0x01, 0x00ef, 0x004e},
833 {0x01, 0x00f8, 0x004f},
834 {0x01, 0x00ff, 0x0050},
835 {0x01, 0x0001, 0x0056},
836 {0x01, 0x0060, 0x0057},
837 {0x01, 0x0040, 0x0058},
838 {0x01, 0x0011, 0x0059},
839 {0x01, 0x0001, 0x005a},
840 {0x02, 0x0007, 0x0005},
841 {0x02, 0xa048, 0x0000},
842 {0x02, 0x0007, 0x0005},
843 {0x02, 0x0015, 0x0006},
844 {0x02, 0x100a, 0x0007},
845 {0x02, 0xa048, 0x0000},
846 {0x02, 0xc002, 0x0001},
847 {0x02, 0x000f, 0x0005},
848 {0x02, 0xa048, 0x0000},
849 {0x05, 0x0022, 0x0004},
850 {0x05, 0x0025, 0x0001},
851 {0x05, 0x0000, 0x0000},
852 {0x05, 0x0026, 0x0001},
853 {0x05, 0x0001, 0x0000},
854 {0x05, 0x0027, 0x0001},
855 {0x05, 0x0000, 0x0000},
856 {0x05, 0x0001, 0x0001},
857 {0x05, 0x0000, 0x0000},
858 {0x05, 0x0021, 0x0001},
859 {0x05, 0x00d2, 0x0000},
860 {0x05, 0x0020, 0x0001},
861 {0x05, 0x0000, 0x0000},
862 {0x00, 0x0090, 0x0005},
863 {0x01, 0x00a6, 0x0000},
864 {0x02, 0x0007, 0x0005},
865 {0x02, 0x2000, 0x0000},
866 {0x05, 0x0022, 0x0004},
867 {0x05, 0x0015, 0x0001},
868 {0x05, 0x00ea, 0x0000},
869 {0x05, 0x0021, 0x0001},
870 {0x05, 0x00d2, 0x0000},
871 {0x05, 0x0023, 0x0001},
872 {0x05, 0x0003, 0x0000},
873 {0x05, 0x0030, 0x0001},
874 {0x05, 0x002b, 0x0000},
875 {0x05, 0x0031, 0x0001},
876 {0x05, 0x0023, 0x0000},
877 {0x05, 0x0032, 0x0001},
878 {0x05, 0x0023, 0x0000},
879 {0x05, 0x0033, 0x0001},
880 {0x05, 0x0023, 0x0000},
881 {0x05, 0x0034, 0x0001},
882 {0x05, 0x0002, 0x0000},
883 {0x05, 0x0050, 0x0001},
884 {0x05, 0x0000, 0x0000},
885 {0x05, 0x0051, 0x0001},
886 {0x05, 0x0000, 0x0000},
887 {0x05, 0x0052, 0x0001},
888 {0x05, 0x0000, 0x0000},
889 {0x05, 0x0054, 0x0001},
890 {0x05, 0x0001, 0x0000},
891 {0x00, 0x0000, 0x0001},
892 {0x00, 0x0000, 0x0002},
893 {0x00, 0x000c, 0x0003},
894 {0x00, 0x0000, 0x0004},
895 {0x00, 0x0090, 0x0005},
896 {0x00, 0x0000, 0x0006},
897 {0x00, 0x0040, 0x0007},
898 {0x00, 0x00c0, 0x0008},
899 {0x00, 0x004a, 0x0009},
900 {0x00, 0x0000, 0x000a},
901 {0x00, 0x0000, 0x000b},
902 {0x00, 0x0001, 0x000c},
903 {0x00, 0x0001, 0x000d},
904 {0x00, 0x0000, 0x000e},
905 {0x00, 0x0002, 0x000f},
906 {0x00, 0x0001, 0x0010},
907 {0x00, 0x0000, 0x0011},
908 {0x00, 0x0000, 0x0012},
909 {0x00, 0x0002, 0x0020},
910 {0x00, 0x0080, 0x0021},
911 {0x00, 0x0001, 0x0022},
912 {0x00, 0x00e0, 0x0023},
913 {0x00, 0x0000, 0x0024},
914 {0x00, 0x00d5, 0x0025},
915 {0x00, 0x0000, 0x0026},
916 {0x00, 0x000b, 0x0027},
917 {0x00, 0x0000, 0x0046},
918 {0x00, 0x0000, 0x0047},
919 {0x00, 0x0000, 0x0048},
920 {0x00, 0x0000, 0x0049},
921 {0x00, 0x0008, 0x004a},
922 {0xff, 0x0000, 0x00d0},
923 {0xff, 0x00d8, 0x00d1},
924 {0xff, 0x0000, 0x00d4},
925 {0xff, 0x0000, 0x00d5},
926 {0x01, 0x00a6, 0x0000},
927 {0x01, 0x0028, 0x0001},
928 {0x01, 0x0000, 0x0002},
929 {0x01, 0x000a, 0x0003},
930 {0x01, 0x0040, 0x0004},
931 {0x01, 0x0066, 0x0007},
932 {0x01, 0x0011, 0x0008},
933 {0x01, 0x0032, 0x0009},
934 {0x01, 0x00fd, 0x000a},
935 {0x01, 0x0038, 0x000b},
936 {0x01, 0x00d1, 0x000c},
937 {0x01, 0x00f7, 0x000d},
938 {0x01, 0x00ed, 0x000e},
939 {0x01, 0x00d8, 0x000f},
940 {0x01, 0x0038, 0x0010},
941 {0x01, 0x00ff, 0x0015},
942 {0x01, 0x0001, 0x0016},
943 {0x01, 0x0032, 0x0017},
944 {0x01, 0x0023, 0x0018},
945 {0x01, 0x00ce, 0x0019},
946 {0x01, 0x0023, 0x001a},
947 {0x01, 0x0032, 0x001b},
948 {0x01, 0x008d, 0x001c},
949 {0x01, 0x00ce, 0x001d},
950 {0x01, 0x008d, 0x001e},
951 {0x01, 0x0000, 0x001f},
952 {0x01, 0x0000, 0x0020},
953 {0x01, 0x00ff, 0x003e},
954 {0x01, 0x0003, 0x003f},
955 {0x01, 0x0000, 0x0040},
956 {0x01, 0x0035, 0x0041},
957 {0x01, 0x0053, 0x0042},
958 {0x01, 0x0069, 0x0043},
959 {0x01, 0x007c, 0x0044},
960 {0x01, 0x008c, 0x0045},
961 {0x01, 0x009a, 0x0046},
962 {0x01, 0x00a8, 0x0047},
963 {0x01, 0x00b4, 0x0048},
964 {0x01, 0x00bf, 0x0049},
965 {0x01, 0x00ca, 0x004a},
966 {0x01, 0x00d4, 0x004b},
967 {0x01, 0x00dd, 0x004c},
968 {0x01, 0x00e7, 0x004d},
969 {0x01, 0x00ef, 0x004e},
970 {0x01, 0x00f8, 0x004f},
971 {0x01, 0x00ff, 0x0050},
972 {0x01, 0x0001, 0x0056},
973 {0x01, 0x0060, 0x0057},
974 {0x01, 0x0040, 0x0058},
975 {0x01, 0x0011, 0x0059},
976 {0x01, 0x0001, 0x005a},
977 {0x02, 0x0007, 0x0005},
978 {0x02, 0xa048, 0x0000},
979 {0x02, 0x0007, 0x0005},
980 {0x02, 0x0015, 0x0006},
981 {0x02, 0x100a, 0x0007},
982 {0x02, 0xa048, 0x0000},
983 {0x02, 0xc002, 0x0001},
984 {0x02, 0x000f, 0x0005},
985 {0x02, 0xa048, 0x0000},
986 {0x05, 0x0022, 0x0004},
987 {0x05, 0x0025, 0x0001},
988 {0x05, 0x0000, 0x0000},
989 {0x05, 0x0026, 0x0001},
990 {0x05, 0x0001, 0x0000},
991 {0x05, 0x0027, 0x0001},
992 {0x05, 0x0000, 0x0000},
993 {0x05, 0x0001, 0x0001},
994 {0x05, 0x0000, 0x0000},
995 {0x05, 0x0021, 0x0001},
996 {0x05, 0x00d2, 0x0000},
997 {0x05, 0x0020, 0x0001},
998 {0x05, 0x0000, 0x0000},
999 {0x00, 0x0090, 0x0005},
1000 {0x01, 0x00a6, 0x0000},
1001 {0x01, 0x0003, 0x003f},
1002 {0x01, 0x0001, 0x0056},
1003 {0x01, 0x0011, 0x0008},
1004 {0x01, 0x0032, 0x0009},
1005 {0x01, 0xfffd, 0x000a},
1006 {0x01, 0x0023, 0x000b},
1007 {0x01, 0xffea, 0x000c},
1008 {0x01, 0xfff4, 0x000d},
1009 {0x01, 0xfffc, 0x000e},
1010 {0x01, 0xffe3, 0x000f},
1011 {0x01, 0x001f, 0x0010},
1012 {0x01, 0x00a8, 0x0001},
1013 {0x01, 0x0067, 0x0007},
1014 {0x01, 0x0032, 0x0017},
1015 {0x01, 0x0023, 0x0018},
1016 {0x01, 0x00ce, 0x0019},
1017 {0x01, 0x0023, 0x001a},
1018 {0x01, 0x0032, 0x001b},
1019 {0x01, 0x008d, 0x001c},
1020 {0x01, 0x00ce, 0x001d},
1021 {0x01, 0x008d, 0x001e},
1022 {0x01, 0x00c8, 0x0015},
1023 {0x01, 0x0032, 0x0016},
1024 {0x01, 0x0000, 0x0011},
1025 {0x01, 0x0000, 0x0012},
1026 {0x01, 0x0000, 0x0013},
1027 {0x01, 0x000a, 0x0003},
1028 {0x02, 0xc002, 0x0001},
1029 {0x02, 0x0007, 0x0005},
1030 {0x02, 0xc000, 0x0001},
1031 {0x02, 0x0000, 0x0005},
1032 {0x02, 0x0007, 0x0005},
1033 {0x02, 0x2000, 0x0000},
1034 {0x05, 0x0022, 0x0004},
1035 {0x05, 0x0015, 0x0001},
1036 {0x05, 0x00ea, 0x0000},
1037 {0x05, 0x0021, 0x0001},
1038 {0x05, 0x00d2, 0x0000},
1039 {0x05, 0x0023, 0x0001},
1040 {0x05, 0x0003, 0x0000},
1041 {0x05, 0x0030, 0x0001},
1042 {0x05, 0x002b, 0x0000},
1043 {0x05, 0x0031, 0x0001},
1044 {0x05, 0x0023, 0x0000},
1045 {0x05, 0x0032, 0x0001},
1046 {0x05, 0x0023, 0x0000},
1047 {0x05, 0x0033, 0x0001},
1048 {0x05, 0x0023, 0x0000},
1049 {0x05, 0x0034, 0x0001},
1050 {0x05, 0x0002, 0x0000},
1051 {0x05, 0x0050, 0x0001},
1052 {0x05, 0x0000, 0x0000},
1053 {0x05, 0x0051, 0x0001},
1054 {0x05, 0x0000, 0x0000},
1055 {0x05, 0x0052, 0x0001},
1056 {0x05, 0x0000, 0x0000},
1057 {0x05, 0x0054, 0x0001},
1058 {0x05, 0x0001, 0x0000},
1059 {0x00, 0x0000, 0x0001},
1060 {0x00, 0x0000, 0x0002},
1061 {0x00, 0x000c, 0x0003},
1062 {0x00, 0x0000, 0x0004},
1063 {0x00, 0x0090, 0x0005},
1064 {0x00, 0x0000, 0x0006},
1065 {0x00, 0x0040, 0x0007},
1066 {0x00, 0x00c0, 0x0008},
1067 {0x00, 0x004a, 0x0009},
1068 {0x00, 0x0000, 0x000a},
1069 {0x00, 0x0000, 0x000b},
1070 {0x00, 0x0001, 0x000c},
1071 {0x00, 0x0001, 0x000d},
1072 {0x00, 0x0000, 0x000e},
1073 {0x00, 0x0002, 0x000f},
1074 {0x00, 0x0001, 0x0010},
1075 {0x00, 0x0000, 0x0011},
1076 {0x00, 0x0000, 0x0012},
1077 {0x00, 0x0002, 0x0020},
1078 {0x00, 0x0080, 0x0021},
1079 {0x00, 0x0001, 0x0022},
1080 {0x00, 0x00e0, 0x0023},
1081 {0x00, 0x0000, 0x0024},
1082 {0x00, 0x00d5, 0x0025},
1083 {0x00, 0x0000, 0x0026},
1084 {0x00, 0x000b, 0x0027},
1085 {0x00, 0x0000, 0x0046},
1086 {0x00, 0x0000, 0x0047},
1087 {0x00, 0x0000, 0x0048},
1088 {0x00, 0x0000, 0x0049},
1089 {0x00, 0x0008, 0x004a},
1090 {0xff, 0x0000, 0x00d0},
1091 {0xff, 0x00d8, 0x00d1},
1092 {0xff, 0x0000, 0x00d4},
1093 {0xff, 0x0000, 0x00d5},
1094 {0x01, 0x00a6, 0x0000},
1095 {0x01, 0x0028, 0x0001},
1096 {0x01, 0x0000, 0x0002},
1097 {0x01, 0x000a, 0x0003},
1098 {0x01, 0x0040, 0x0004},
1099 {0x01, 0x0066, 0x0007},
1100 {0x01, 0x0011, 0x0008},
1101 {0x01, 0x0032, 0x0009},
1102 {0x01, 0x00fd, 0x000a},
1103 {0x01, 0x0038, 0x000b},
1104 {0x01, 0x00d1, 0x000c},
1105 {0x01, 0x00f7, 0x000d},
1106 {0x01, 0x00ed, 0x000e},
1107 {0x01, 0x00d8, 0x000f},
1108 {0x01, 0x0038, 0x0010},
1109 {0x01, 0x00ff, 0x0015},
1110 {0x01, 0x0001, 0x0016},
1111 {0x01, 0x0032, 0x0017},
1112 {0x01, 0x0023, 0x0018},
1113 {0x01, 0x00ce, 0x0019},
1114 {0x01, 0x0023, 0x001a},
1115 {0x01, 0x0032, 0x001b},
1116 {0x01, 0x008d, 0x001c},
1117 {0x01, 0x00ce, 0x001d},
1118 {0x01, 0x008d, 0x001e},
1119 {0x01, 0x0000, 0x001f},
1120 {0x01, 0x0000, 0x0020},
1121 {0x01, 0x00ff, 0x003e},
1122 {0x01, 0x0003, 0x003f},
1123 {0x01, 0x0000, 0x0040},
1124 {0x01, 0x0035, 0x0041},
1125 {0x01, 0x0053, 0x0042},
1126 {0x01, 0x0069, 0x0043},
1127 {0x01, 0x007c, 0x0044},
1128 {0x01, 0x008c, 0x0045},
1129 {0x01, 0x009a, 0x0046},
1130 {0x01, 0x00a8, 0x0047},
1131 {0x01, 0x00b4, 0x0048},
1132 {0x01, 0x00bf, 0x0049},
1133 {0x01, 0x00ca, 0x004a},
1134 {0x01, 0x00d4, 0x004b},
1135 {0x01, 0x00dd, 0x004c},
1136 {0x01, 0x00e7, 0x004d},
1137 {0x01, 0x00ef, 0x004e},
1138 {0x01, 0x00f8, 0x004f},
1139 {0x01, 0x00ff, 0x0050},
1140 {0x01, 0x0001, 0x0056},
1141 {0x01, 0x0060, 0x0057},
1142 {0x01, 0x0040, 0x0058},
1143 {0x01, 0x0011, 0x0059},
1144 {0x01, 0x0001, 0x005a},
1145 {0x02, 0x0007, 0x0005},
1146 {0x02, 0xa048, 0x0000},
1147 {0x02, 0x0007, 0x0005},
1148 {0x02, 0x0015, 0x0006},
1149 {0x02, 0x100a, 0x0007},
1150 {0x02, 0xa048, 0x0000},
1151 {0x02, 0xc002, 0x0001},
1152 {0x02, 0x000f, 0x0005},
1153 {0x02, 0xa048, 0x0000},
1154 {0x05, 0x0022, 0x0004},
1155 {0x05, 0x0025, 0x0001},
1156 {0x05, 0x0000, 0x0000},
1157 {0x05, 0x0026, 0x0001},
1158 {0x05, 0x0001, 0x0000},
1159 {0x05, 0x0027, 0x0001},
1160 {0x05, 0x0000, 0x0000},
1161 {0x05, 0x0001, 0x0001},
1162 {0x05, 0x0000, 0x0000},
1163 {0x05, 0x0021, 0x0001},
1164 {0x05, 0x00d2, 0x0000},
1165 {0x05, 0x0020, 0x0001},
1166 {0x05, 0x0000, 0x0000},
1167 {0x00, 0x0090, 0x0005},
1168 {0x01, 0x00a6, 0x0000},
1169 {0x02, 0x0007, 0x0005},
1170 {0x02, 0x2000, 0x0000},
1171 {0x05, 0x0022, 0x0004},
1172 {0x05, 0x0015, 0x0001},
1173 {0x05, 0x00ea, 0x0000},
1174 {0x05, 0x0021, 0x0001},
1175 {0x05, 0x00d2, 0x0000},
1176 {0x05, 0x0023, 0x0001},
1177 {0x05, 0x0003, 0x0000},
1178 {0x05, 0x0030, 0x0001},
1179 {0x05, 0x002b, 0x0000},
1180 {0x05, 0x0031, 0x0001},
1181 {0x05, 0x0023, 0x0000},
1182 {0x05, 0x0032, 0x0001},
1183 {0x05, 0x0023, 0x0000},
1184 {0x05, 0x0033, 0x0001},
1185 {0x05, 0x0023, 0x0000},
1186 {0x05, 0x0034, 0x0001},
1187 {0x05, 0x0002, 0x0000},
1188 {0x05, 0x0050, 0x0001},
1189 {0x05, 0x0000, 0x0000},
1190 {0x05, 0x0051, 0x0001},
1191 {0x05, 0x0000, 0x0000},
1192 {0x05, 0x0052, 0x0001},
1193 {0x05, 0x0000, 0x0000},
1194 {0x05, 0x0054, 0x0001},
1195 {0x05, 0x0001, 0x0000},
1196 {0x00, 0x0000, 0x0001},
1197 {0x00, 0x0000, 0x0002},
1198 {0x00, 0x000c, 0x0003},
1199 {0x00, 0x0000, 0x0004},
1200 {0x00, 0x0090, 0x0005},
1201 {0x00, 0x0000, 0x0006},
1202 {0x00, 0x0040, 0x0007},
1203 {0x00, 0x00c0, 0x0008},
1204 {0x00, 0x004a, 0x0009},
1205 {0x00, 0x0000, 0x000a},
1206 {0x00, 0x0000, 0x000b},
1207 {0x00, 0x0001, 0x000c},
1208 {0x00, 0x0001, 0x000d},
1209 {0x00, 0x0000, 0x000e},
1210 {0x00, 0x0002, 0x000f},
1211 {0x00, 0x0001, 0x0010},
1212 {0x00, 0x0000, 0x0011},
1213 {0x00, 0x0000, 0x0012},
1214 {0x00, 0x0002, 0x0020},
1215 {0x00, 0x0080, 0x0021},
1216 {0x00, 0x0001, 0x0022},
1217 {0x00, 0x00e0, 0x0023},
1218 {0x00, 0x0000, 0x0024},
1219 {0x00, 0x00d5, 0x0025},
1220 {0x00, 0x0000, 0x0026},
1221 {0x00, 0x000b, 0x0027},
1222 {0x00, 0x0000, 0x0046},
1223 {0x00, 0x0000, 0x0047},
1224 {0x00, 0x0000, 0x0048},
1225 {0x00, 0x0000, 0x0049},
1226 {0x00, 0x0008, 0x004a},
1227 {0xff, 0x0000, 0x00d0},
1228 {0xff, 0x00d8, 0x00d1},
1229 {0xff, 0x0000, 0x00d4},
1230 {0xff, 0x0000, 0x00d5},
1231 {0x01, 0x00a6, 0x0000},
1232 {0x01, 0x0028, 0x0001},
1233 {0x01, 0x0000, 0x0002},
1234 {0x01, 0x000a, 0x0003},
1235 {0x01, 0x0040, 0x0004},
1236 {0x01, 0x0066, 0x0007},
1237 {0x01, 0x0011, 0x0008},
1238 {0x01, 0x0032, 0x0009},
1239 {0x01, 0x00fd, 0x000a},
1240 {0x01, 0x0038, 0x000b},
1241 {0x01, 0x00d1, 0x000c},
1242 {0x01, 0x00f7, 0x000d},
1243 {0x01, 0x00ed, 0x000e},
1244 {0x01, 0x00d8, 0x000f},
1245 {0x01, 0x0038, 0x0010},
1246 {0x01, 0x00ff, 0x0015},
1247 {0x01, 0x0001, 0x0016},
1248 {0x01, 0x0032, 0x0017},
1249 {0x01, 0x0023, 0x0018},
1250 {0x01, 0x00ce, 0x0019},
1251 {0x01, 0x0023, 0x001a},
1252 {0x01, 0x0032, 0x001b},
1253 {0x01, 0x008d, 0x001c},
1254 {0x01, 0x00ce, 0x001d},
1255 {0x01, 0x008d, 0x001e},
1256 {0x01, 0x0000, 0x001f},
1257 {0x01, 0x0000, 0x0020},
1258 {0x01, 0x00ff, 0x003e},
1259 {0x01, 0x0003, 0x003f},
1260 {0x01, 0x0000, 0x0040},
1261 {0x01, 0x0035, 0x0041},
1262 {0x01, 0x0053, 0x0042},
1263 {0x01, 0x0069, 0x0043},
1264 {0x01, 0x007c, 0x0044},
1265 {0x01, 0x008c, 0x0045},
1266 {0x01, 0x009a, 0x0046},
1267 {0x01, 0x00a8, 0x0047},
1268 {0x01, 0x00b4, 0x0048},
1269 {0x01, 0x00bf, 0x0049},
1270 {0x01, 0x00ca, 0x004a},
1271 {0x01, 0x00d4, 0x004b},
1272 {0x01, 0x00dd, 0x004c},
1273 {0x01, 0x00e7, 0x004d},
1274 {0x01, 0x00ef, 0x004e},
1275 {0x01, 0x00f8, 0x004f},
1276 {0x01, 0x00ff, 0x0050},
1277 {0x01, 0x0001, 0x0056},
1278 {0x01, 0x0060, 0x0057},
1279 {0x01, 0x0040, 0x0058},
1280 {0x01, 0x0011, 0x0059},
1281 {0x01, 0x0001, 0x005a},
1282 {0x02, 0x0007, 0x0005},
1283 {0x02, 0xa048, 0x0000},
1284 {0x02, 0x0007, 0x0005},
1285 {0x02, 0x0015, 0x0006},
1286 {0x02, 0x100a, 0x0007},
1287 {0x02, 0xa048, 0x0000},
1288 {0x02, 0xc002, 0x0001},
1289 {0x02, 0x000f, 0x0005},
1290 {0x02, 0xa048, 0x0000},
1291 {0x05, 0x0022, 0x0004},
1292 {0x05, 0x0025, 0x0001},
1293 {0x05, 0x0000, 0x0000},
1294 {0x05, 0x0026, 0x0001},
1295 {0x05, 0x0001, 0x0000},
1296 {0x05, 0x0027, 0x0001},
1297 {0x05, 0x0000, 0x0000},
1298 {0x05, 0x0001, 0x0001},
1299 {0x05, 0x0000, 0x0000},
1300 {0x05, 0x0021, 0x0001},
1301 {0x05, 0x00d2, 0x0000},
1302 {0x05, 0x0020, 0x0001},
1303 {0x05, 0x0000, 0x0000},
1304 {0x00, 0x0090, 0x0005},
1305 {0x01, 0x00a6, 0x0000},
1306 {0x05, 0x0026, 0x0001},
1307 {0x05, 0x0001, 0x0000},
1308 {0x05, 0x0027, 0x0001},
1309 {0x05, 0x000f, 0x0000},
1310 {0x01, 0x0003, 0x003f},
1311 {0x01, 0x0001, 0x0056},
1312 {0x01, 0x0011, 0x0008},
1313 {0x01, 0x0032, 0x0009},
1314 {0x01, 0xfffd, 0x000a},
1315 {0x01, 0x0023, 0x000b},
1316 {0x01, 0xffea, 0x000c},
1317 {0x01, 0xfff4, 0x000d},
1318 {0x01, 0xfffc, 0x000e},
1319 {0x01, 0xffe3, 0x000f},
1320 {0x01, 0x001f, 0x0010},
1321 {0x01, 0x00a8, 0x0001},
1322 {0x01, 0x0067, 0x0007},
1323 {0x01, 0x0042, 0x0051},
1324 {0x01, 0x0051, 0x0053},
1325 {0x01, 0x000a, 0x0003},
1326 {0x02, 0xc002, 0x0001},
1327 {0x02, 0x0007, 0x0005},
1328 {0x02, 0xc000, 0x0001},
1329 {0x02, 0x0000, 0x0005},
1330 {0x02, 0x0007, 0x0005},
1331 {0x02, 0x2000, 0x0000},
1332 {0x05, 0x0022, 0x0004},
1333 {0x05, 0x0015, 0x0001},
1334 {0x05, 0x00ea, 0x0000},
1335 {0x05, 0x0021, 0x0001},
1336 {0x05, 0x00d2, 0x0000},
1337 {0x05, 0x0023, 0x0001},
1338 {0x05, 0x0003, 0x0000},
1339 {0x05, 0x0030, 0x0001},
1340 {0x05, 0x002b, 0x0000},
1341 {0x05, 0x0031, 0x0001},
1342 {0x05, 0x0023, 0x0000},
1343 {0x05, 0x0032, 0x0001},
1344 {0x05, 0x0023, 0x0000},
1345 {0x05, 0x0033, 0x0001},
1346 {0x05, 0x0023, 0x0000},
1347 {0x05, 0x0034, 0x0001},
1348 {0x05, 0x0002, 0x0000},
1349 {0x05, 0x0050, 0x0001},
1350 {0x05, 0x0000, 0x0000},
1351 {0x05, 0x0051, 0x0001},
1352 {0x05, 0x0000, 0x0000},
1353 {0x05, 0x0052, 0x0001},
1354 {0x05, 0x0000, 0x0000},
1355 {0x05, 0x0054, 0x0001},
1356 {0x05, 0x0001, 0x0000},
1357 {0x00, 0x0000, 0x0001},
1358 {0x00, 0x0000, 0x0002},
1359 {0x00, 0x000c, 0x0003},
1360 {0x00, 0x0000, 0x0004},
1361 {0x00, 0x0090, 0x0005},
1362 {0x00, 0x0000, 0x0006},
1363 {0x00, 0x0040, 0x0007},
1364 {0x00, 0x00c0, 0x0008},
1365 {0x00, 0x004a, 0x0009},
1366 {0x00, 0x0000, 0x000a},
1367 {0x00, 0x0000, 0x000b},
1368 {0x00, 0x0001, 0x000c},
1369 {0x00, 0x0001, 0x000d},
1370 {0x00, 0x0000, 0x000e},
1371 {0x00, 0x0002, 0x000f},
1372 {0x00, 0x0001, 0x0010},
1373 {0x00, 0x0000, 0x0011},
1374 {0x00, 0x0000, 0x0012},
1375 {0x00, 0x0002, 0x0020},
1376 {0x00, 0x0080, 0x0021},
1377 {0x00, 0x0001, 0x0022},
1378 {0x00, 0x00e0, 0x0023},
1379 {0x00, 0x0000, 0x0024},
1380 {0x00, 0x00d5, 0x0025},
1381 {0x00, 0x0000, 0x0026},
1382 {0x00, 0x000b, 0x0027},
1383 {0x00, 0x0000, 0x0046},
1384 {0x00, 0x0000, 0x0047},
1385 {0x00, 0x0000, 0x0048},
1386 {0x00, 0x0000, 0x0049},
1387 {0x00, 0x0008, 0x004a},
1388 {0xff, 0x0000, 0x00d0},
1389 {0xff, 0x00d8, 0x00d1},
1390 {0xff, 0x0000, 0x00d4},
1391 {0xff, 0x0000, 0x00d5},
1392 {0x01, 0x00a6, 0x0000},
1393 {0x01, 0x0028, 0x0001},
1394 {0x01, 0x0000, 0x0002},
1395 {0x01, 0x000a, 0x0003},
1396 {0x01, 0x0040, 0x0004},
1397 {0x01, 0x0066, 0x0007},
1398 {0x01, 0x0011, 0x0008},
1399 {0x01, 0x0032, 0x0009},
1400 {0x01, 0x00fd, 0x000a},
1401 {0x01, 0x0038, 0x000b},
1402 {0x01, 0x00d1, 0x000c},
1403 {0x01, 0x00f7, 0x000d},
1404 {0x01, 0x00ed, 0x000e},
1405 {0x01, 0x00d8, 0x000f},
1406 {0x01, 0x0038, 0x0010},
1407 {0x01, 0x00ff, 0x0015},
1408 {0x01, 0x0001, 0x0016},
1409 {0x01, 0x0032, 0x0017},
1410 {0x01, 0x0023, 0x0018},
1411 {0x01, 0x00ce, 0x0019},
1412 {0x01, 0x0023, 0x001a},
1413 {0x01, 0x0032, 0x001b},
1414 {0x01, 0x008d, 0x001c},
1415 {0x01, 0x00ce, 0x001d},
1416 {0x01, 0x008d, 0x001e},
1417 {0x01, 0x0000, 0x001f},
1418 {0x01, 0x0000, 0x0020},
1419 {0x01, 0x00ff, 0x003e},
1420 {0x01, 0x0003, 0x003f},
1421 {0x01, 0x0000, 0x0040},
1422 {0x01, 0x0035, 0x0041},
1423 {0x01, 0x0053, 0x0042},
1424 {0x01, 0x0069, 0x0043},
1425 {0x01, 0x007c, 0x0044},
1426 {0x01, 0x008c, 0x0045},
1427 {0x01, 0x009a, 0x0046},
1428 {0x01, 0x00a8, 0x0047},
1429 {0x01, 0x00b4, 0x0048},
1430 {0x01, 0x00bf, 0x0049},
1431 {0x01, 0x00ca, 0x004a},
1432 {0x01, 0x00d4, 0x004b},
1433 {0x01, 0x00dd, 0x004c},
1434 {0x01, 0x00e7, 0x004d},
1435 {0x01, 0x00ef, 0x004e},
1436 {0x01, 0x00f8, 0x004f},
1437 {0x01, 0x00ff, 0x0050},
1438 {0x01, 0x0001, 0x0056},
1439 {0x01, 0x0060, 0x0057},
1440 {0x01, 0x0040, 0x0058},
1441 {0x01, 0x0011, 0x0059},
1442 {0x01, 0x0001, 0x005a},
1443 {0x02, 0x0007, 0x0005},
1444 {0x02, 0xa048, 0x0000},
1445 {0x02, 0x0007, 0x0005},
1446 {0x02, 0x0015, 0x0006},
1447 {0x02, 0x100a, 0x0007},
1448 {0x02, 0xa048, 0x0000},
1449 {0x02, 0xc002, 0x0001},
1450 {0x02, 0x000f, 0x0005},
1451 {0x02, 0xa048, 0x0000},
1452 {0x05, 0x0022, 0x0004},
1453 {0x05, 0x0025, 0x0001},
1454 {0x05, 0x0000, 0x0000},
1455 {0x05, 0x0026, 0x0001},
1456 {0x05, 0x0001, 0x0000},
1457 {0x05, 0x0027, 0x0001},
1458 {0x05, 0x0000, 0x0000},
1459 {0x05, 0x0001, 0x0001},
1460 {0x05, 0x0000, 0x0000},
1461 {0x05, 0x0021, 0x0001},
1462 {0x05, 0x00d2, 0x0000},
1463 {0x05, 0x0020, 0x0001},
1464 {0x05, 0x0000, 0x0000},
1465 {0x00, 0x0090, 0x0005},
1466 {0x01, 0x00a6, 0x0000},
1467 {0x02, 0x0007, 0x0005},
1468 {0x02, 0x2000, 0x0000},
1469 {0x05, 0x0022, 0x0004},
1470 {0x05, 0x0015, 0x0001},
1471 {0x05, 0x00ea, 0x0000},
1472 {0x05, 0x0021, 0x0001},
1473 {0x05, 0x00d2, 0x0000},
1474 {0x05, 0x0023, 0x0001},
1475 {0x05, 0x0003, 0x0000},
1476 {0x05, 0x0030, 0x0001},
1477 {0x05, 0x002b, 0x0000},
1478 {0x05, 0x0031, 0x0001},
1479 {0x05, 0x0023, 0x0000},
1480 {0x05, 0x0032, 0x0001},
1481 {0x05, 0x0023, 0x0000},
1482 {0x05, 0x0033, 0x0001},
1483 {0x05, 0x0023, 0x0000},
1484 {0x05, 0x0034, 0x0001},
1485 {0x05, 0x0002, 0x0000},
1486 {0x05, 0x0050, 0x0001},
1487 {0x05, 0x0000, 0x0000},
1488 {0x05, 0x0051, 0x0001},
1489 {0x05, 0x0000, 0x0000},
1490 {0x05, 0x0052, 0x0001},
1491 {0x05, 0x0000, 0x0000},
1492 {0x05, 0x0054, 0x0001},
1493 {0x05, 0x0001, 0x0000},
1494 {0x00, 0x0000, 0x0001},
1495 {0x00, 0x0000, 0x0002},
1496 {0x00, 0x000c, 0x0003},
1497 {0x00, 0x0000, 0x0004},
1498 {0x00, 0x0090, 0x0005},
1499 {0x00, 0x0000, 0x0006},
1500 {0x00, 0x0040, 0x0007},
1501 {0x00, 0x00c0, 0x0008},
1502 {0x00, 0x004a, 0x0009},
1503 {0x00, 0x0000, 0x000a},
1504 {0x00, 0x0000, 0x000b},
1505 {0x00, 0x0001, 0x000c},
1506 {0x00, 0x0001, 0x000d},
1507 {0x00, 0x0000, 0x000e},
1508 {0x00, 0x0002, 0x000f},
1509 {0x00, 0x0001, 0x0010},
1510 {0x00, 0x0000, 0x0011},
1511 {0x00, 0x0000, 0x0012},
1512 {0x00, 0x0002, 0x0020},
1513 {0x00, 0x0080, 0x0021},
1514 {0x00, 0x0001, 0x0022},
1515 {0x00, 0x00e0, 0x0023},
1516 {0x00, 0x0000, 0x0024},
1517 {0x00, 0x00d5, 0x0025},
1518 {0x00, 0x0000, 0x0026},
1519 {0x00, 0x000b, 0x0027},
1520 {0x00, 0x0000, 0x0046},
1521 {0x00, 0x0000, 0x0047},
1522 {0x00, 0x0000, 0x0048},
1523 {0x00, 0x0000, 0x0049},
1524 {0x00, 0x0008, 0x004a},
1525 {0xff, 0x0000, 0x00d0},
1526 {0xff, 0x00d8, 0x00d1},
1527 {0xff, 0x0000, 0x00d4},
1528 {0xff, 0x0000, 0x00d5},
1529 {0x01, 0x00a6, 0x0000},
1530 {0x01, 0x0028, 0x0001},
1531 {0x01, 0x0000, 0x0002},
1532 {0x01, 0x000a, 0x0003},
1533 {0x01, 0x0040, 0x0004},
1534 {0x01, 0x0066, 0x0007},
1535 {0x01, 0x0011, 0x0008},
1536 {0x01, 0x0032, 0x0009},
1537 {0x01, 0x00fd, 0x000a},
1538 {0x01, 0x0038, 0x000b},
1539 {0x01, 0x00d1, 0x000c},
1540 {0x01, 0x00f7, 0x000d},
1541 {0x01, 0x00ed, 0x000e},
1542 {0x01, 0x00d8, 0x000f},
1543 {0x01, 0x0038, 0x0010},
1544 {0x01, 0x00ff, 0x0015},
1545 {0x01, 0x0001, 0x0016},
1546 {0x01, 0x0032, 0x0017},
1547 {0x01, 0x0023, 0x0018},
1548 {0x01, 0x00ce, 0x0019},
1549 {0x01, 0x0023, 0x001a},
1550 {0x01, 0x0032, 0x001b},
1551 {0x01, 0x008d, 0x001c},
1552 {0x01, 0x00ce, 0x001d},
1553 {0x01, 0x008d, 0x001e},
1554 {0x01, 0x0000, 0x001f},
1555 {0x01, 0x0000, 0x0020},
1556 {0x01, 0x00ff, 0x003e},
1557 {0x01, 0x0003, 0x003f},
1558 {0x01, 0x0000, 0x0040},
1559 {0x01, 0x0035, 0x0041},
1560 {0x01, 0x0053, 0x0042},
1561 {0x01, 0x0069, 0x0043},
1562 {0x01, 0x007c, 0x0044},
1563 {0x01, 0x008c, 0x0045},
1564 {0x01, 0x009a, 0x0046},
1565 {0x01, 0x00a8, 0x0047},
1566 {0x01, 0x00b4, 0x0048},
1567 {0x01, 0x00bf, 0x0049},
1568 {0x01, 0x00ca, 0x004a},
1569 {0x01, 0x00d4, 0x004b},
1570 {0x01, 0x00dd, 0x004c},
1571 {0x01, 0x00e7, 0x004d},
1572 {0x01, 0x00ef, 0x004e},
1573 {0x01, 0x00f8, 0x004f},
1574 {0x01, 0x00ff, 0x0050},
1575 {0x01, 0x0001, 0x0056},
1576 {0x01, 0x0060, 0x0057},
1577 {0x01, 0x0040, 0x0058},
1578 {0x01, 0x0011, 0x0059},
1579 {0x01, 0x0001, 0x005a},
1580 {0x02, 0x0007, 0x0005},
1581 {0x02, 0xa048, 0x0000},
1582 {0x02, 0x0007, 0x0005},
1583 {0x02, 0x0015, 0x0006},
1584 {0x02, 0x100a, 0x0007},
1585 {0x02, 0xa048, 0x0000},
1586 {0x02, 0xc002, 0x0001},
1587 {0x02, 0x000f, 0x0005},
1588 {0x02, 0xa048, 0x0000},
1589 {0x05, 0x0022, 0x0004},
1590 {0x05, 0x0025, 0x0001},
1591 {0x05, 0x0000, 0x0000},
1592 {0x05, 0x0026, 0x0001},
1593 {0x05, 0x0001, 0x0000},
1594 {0x05, 0x0027, 0x0001},
1595 {0x05, 0x0000, 0x0000},
1596 {0x05, 0x0001, 0x0001},
1597 {0x05, 0x0000, 0x0000},
1598 {0x05, 0x0021, 0x0001},
1599 {0x05, 0x00d2, 0x0000},
1600 {0x05, 0x0020, 0x0001},
1601 {0x05, 0x0000, 0x0000},
1602 {0x00, 0x0090, 0x0005},
1603 {0x01, 0x00a6, 0x0000},
1604 {0x05, 0x0026, 0x0001},
1605 {0x05, 0x0001, 0x0000},
1606 {0x05, 0x0027, 0x0001},
1607 {0x05, 0x001e, 0x0000},
1608 {0x01, 0x0003, 0x003f},
1609 {0x01, 0x0001, 0x0056},
1610 {0x01, 0x0011, 0x0008},
1611 {0x01, 0x0032, 0x0009},
1612 {0x01, 0xfffd, 0x000a},
1613 {0x01, 0x0023, 0x000b},
1614 {0x01, 0xffea, 0x000c},
1615 {0x01, 0xfff4, 0x000d},
1616 {0x01, 0xfffc, 0x000e},
1617 {0x01, 0xffe3, 0x000f},
1618 {0x01, 0x001f, 0x0010},
1619 {0x01, 0x00a8, 0x0001},
1620 {0x01, 0x0067, 0x0007},
1621 {0x01, 0x0042, 0x0051},
1622 {0x01, 0x0051, 0x0053},
1623 {0x01, 0x000a, 0x0003},
1624 {0x02, 0xc002, 0x0001},
1625 {0x02, 0x0007, 0x0005},
1626 {0x01, 0x0042, 0x0051},
1627 {0x01, 0x0051, 0x0053},
1628 {0x05, 0x0026, 0x0001},
1629 {0x05, 0x0001, 0x0000},
1630 {0x05, 0x0027, 0x0001},
1631 {0x05, 0x002d, 0x0000},
1632 {0x01, 0x0003, 0x003f},
1633 {0x01, 0x0001, 0x0056},
1634 {0x02, 0xc000, 0x0001},
1635 {0x02, 0x0000, 0x0005},
1636 {}
1637};
1638
1639/* Unknown camera from Ori Usbid 0x0000:0x0000 */
1640/* Based on snoops from Ori Cohen */
1641static const __u16 spca501c_mysterious_open_data[][3] = {
1642 {0x02, 0x000f, 0x0005},
1643 {0x02, 0xa048, 0x0000},
1644 {0x05, 0x0022, 0x0004},
1645/* DSP Registers */
1646 {0x01, 0x0016, 0x0011}, /* RGB offset */
1647 {0x01, 0x0000, 0x0012},
1648 {0x01, 0x0006, 0x0013},
1649 {0x01, 0x0078, 0x0051},
1650 {0x01, 0x0040, 0x0052},
1651 {0x01, 0x0046, 0x0053},
1652 {0x01, 0x0040, 0x0054},
1653 {0x00, 0x0025, 0x0000},
1654/* {0x00, 0x0000, 0x0000 }, */
1655/* Part 2 */
1656/* TG Registers */
1657 {0x00, 0x0026, 0x0000},
1658 {0x00, 0x0001, 0x0000},
1659 {0x00, 0x0027, 0x0000},
1660 {0x00, 0x008a, 0x0000},
1661 {0x02, 0x0007, 0x0005},
1662 {0x02, 0x2000, 0x0000},
1663 {0x05, 0x0022, 0x0004},
1664 {0x05, 0x0015, 0x0001},
1665 {0x05, 0x00ea, 0x0000},
1666 {0x05, 0x0021, 0x0001},
1667 {0x05, 0x00d2, 0x0000},
1668 {0x05, 0x0023, 0x0001},
1669 {0x05, 0x0003, 0x0000},
1670 {0x05, 0x0030, 0x0001},
1671 {0x05, 0x002b, 0x0000},
1672 {0x05, 0x0031, 0x0001},
1673 {0x05, 0x0023, 0x0000},
1674 {0x05, 0x0032, 0x0001},
1675 {0x05, 0x0023, 0x0000},
1676 {0x05, 0x0033, 0x0001},
1677 {0x05, 0x0023, 0x0000},
1678 {0x05, 0x0034, 0x0001},
1679 {0x05, 0x0002, 0x0000},
1680 {0x05, 0x0050, 0x0001},
1681 {0x05, 0x0000, 0x0000},
1682 {0x05, 0x0051, 0x0001},
1683 {0x05, 0x0000, 0x0000},
1684 {0x05, 0x0052, 0x0001},
1685 {0x05, 0x0000, 0x0000},
1686 {0x05, 0x0054, 0x0001},
1687 {0x05, 0x0001, 0x0000},
1688 {}
1689};
1690
1691/* Based on snoops from Ori Cohen */
1692static const __u16 spca501c_mysterious_init_data[][3] = {
1693/* Part 3 */
1694/* TG registers */
1695/* {0x00, 0x0000, 0x0000}, */
1696 {0x00, 0x0000, 0x0001},
1697 {0x00, 0x0000, 0x0002},
1698 {0x00, 0x0006, 0x0003},
1699 {0x00, 0x0000, 0x0004},
1700 {0x00, 0x0090, 0x0005},
1701 {0x00, 0x0000, 0x0006},
1702 {0x00, 0x0040, 0x0007},
1703 {0x00, 0x00c0, 0x0008},
1704 {0x00, 0x004a, 0x0009},
1705 {0x00, 0x0000, 0x000a},
1706 {0x00, 0x0000, 0x000b},
1707 {0x00, 0x0001, 0x000c},
1708 {0x00, 0x0001, 0x000d},
1709 {0x00, 0x0000, 0x000e},
1710 {0x00, 0x0002, 0x000f},
1711 {0x00, 0x0001, 0x0010},
1712 {0x00, 0x0000, 0x0011},
1713 {0x00, 0x0001, 0x0012},
1714 {0x00, 0x0002, 0x0020},
1715 {0x00, 0x0080, 0x0021}, /* 640 */
1716 {0x00, 0x0001, 0x0022},
1717 {0x00, 0x00e0, 0x0023}, /* 480 */
1718 {0x00, 0x0000, 0x0024}, /* Offset H hight */
1719 {0x00, 0x00d3, 0x0025}, /* low */
1720 {0x00, 0x0000, 0x0026}, /* Offset V */
1721 {0x00, 0x000d, 0x0027}, /* low */
1722 {0x00, 0x0000, 0x0046},
1723 {0x00, 0x0000, 0x0047},
1724 {0x00, 0x0000, 0x0048},
1725 {0x00, 0x0000, 0x0049},
1726 {0x00, 0x0008, 0x004a},
1727/* DSP Registers */
1728 {0x01, 0x00a6, 0x0000},
1729 {0x01, 0x0028, 0x0001},
1730 {0x01, 0x0000, 0x0002},
1731 {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */
1732 {0x01, 0x0040, 0x0004},
1733 {0x01, 0x0066, 0x0007},
1734 {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */
1735 {0x01, 0x002d, 0x0009}, /* A12 */
1736 {0x01, 0x0005, 0x000a}, /* A13 */
1737 {0x01, 0x0023, 0x000b}, /* A21 */
1738 {0x01, 0x00e0, 0x000c}, /* A22 */
1739 {0x01, 0x00fd, 0x000d}, /* A23 */
1740 {0x01, 0x00f4, 0x000e}, /* A31 */
1741 {0x01, 0x00e4, 0x000f}, /* A32 */
1742 {0x01, 0x0028, 0x0010}, /* A33 */
1743 {0x01, 0x00ff, 0x0015}, /* Reserved */
1744 {0x01, 0x0001, 0x0016}, /* Reserved */
1745 {0x01, 0x0032, 0x0017}, /* Win1 Start begin */
1746 {0x01, 0x0023, 0x0018},
1747 {0x01, 0x00ce, 0x0019},
1748 {0x01, 0x0023, 0x001a},
1749 {0x01, 0x0032, 0x001b},
1750 {0x01, 0x008d, 0x001c},
1751 {0x01, 0x00ce, 0x001d},
1752 {0x01, 0x008d, 0x001e},
1753 {0x01, 0x0000, 0x001f},
1754 {0x01, 0x0000, 0x0020}, /* Win1 Start end */
1755 {0x01, 0x00ff, 0x003e}, /* Reserved begin */
1756 {0x01, 0x0002, 0x003f},
1757 {0x01, 0x0000, 0x0040},
1758 {0x01, 0x0035, 0x0041},
1759 {0x01, 0x0053, 0x0042},
1760 {0x01, 0x0069, 0x0043},
1761 {0x01, 0x007c, 0x0044},
1762 {0x01, 0x008c, 0x0045},
1763 {0x01, 0x009a, 0x0046},
1764 {0x01, 0x00a8, 0x0047},
1765 {0x01, 0x00b4, 0x0048},
1766 {0x01, 0x00bf, 0x0049},
1767 {0x01, 0x00ca, 0x004a},
1768 {0x01, 0x00d4, 0x004b},
1769 {0x01, 0x00dd, 0x004c},
1770 {0x01, 0x00e7, 0x004d},
1771 {0x01, 0x00ef, 0x004e},
1772 {0x01, 0x00f8, 0x004f},
1773 {0x01, 0x00ff, 0x0050},
1774 {0x01, 0x0003, 0x0056}, /* Reserved end */
1775 {0x01, 0x0060, 0x0057}, /* Edge Gain */
1776 {0x01, 0x0040, 0x0058},
1777 {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */
1778 {0x01, 0x0001, 0x005a},
1779 {0x02, 0x0007, 0x0005},
1780 {0x02, 0xa048, 0x0000},
1781 {0x02, 0x0007, 0x0005},
1782 {0x02, 0x0015, 0x0006},
1783 {0x02, 0x200a, 0x0007},
1784 {0x02, 0xa048, 0x0000},
1785 {0x02, 0xc000, 0x0001},
1786 {0x02, 0x000f, 0x0005},
1787 {0x02, 0xa048, 0x0000},
1788 {0x05, 0x0022, 0x0004},
1789 {0x05, 0x0025, 0x0001},
1790 {0x05, 0x0000, 0x0000},
1791/* Part 4 */
1792 {0x05, 0x0026, 0x0001},
1793 {0x05, 0x0001, 0x0000},
1794 {0x05, 0x0027, 0x0001},
1795 {0x05, 0x0000, 0x0000},
1796 {0x05, 0x0001, 0x0001},
1797 {0x05, 0x0000, 0x0000},
1798 {0x05, 0x0021, 0x0001},
1799 {0x05, 0x00d2, 0x0000},
1800 {0x05, 0x0020, 0x0001},
1801 {0x05, 0x0000, 0x0000},
1802 {0x00, 0x0090, 0x0005},
1803 {0x01, 0x00a6, 0x0000},
1804 {0x02, 0x0000, 0x0005},
1805 {0x05, 0x0026, 0x0001},
1806 {0x05, 0x0001, 0x0000},
1807 {0x05, 0x0027, 0x0001},
1808 {0x05, 0x004e, 0x0000},
1809/* Part 5 */
1810 {0x01, 0x0003, 0x003f},
1811 {0x01, 0x0001, 0x0056},
1812 {0x01, 0x000f, 0x0008},
1813 {0x01, 0x002d, 0x0009},
1814 {0x01, 0x0005, 0x000a},
1815 {0x01, 0x0023, 0x000b},
1816 {0x01, 0xffe0, 0x000c},
1817 {0x01, 0xfffd, 0x000d},
1818 {0x01, 0xfff4, 0x000e},
1819 {0x01, 0xffe4, 0x000f},
1820 {0x01, 0x0028, 0x0010},
1821 {0x01, 0x00a8, 0x0001},
1822 {0x01, 0x0066, 0x0007},
1823 {0x01, 0x0032, 0x0017},
1824 {0x01, 0x0023, 0x0018},
1825 {0x01, 0x00ce, 0x0019},
1826 {0x01, 0x0023, 0x001a},
1827 {0x01, 0x0032, 0x001b},
1828 {0x01, 0x008d, 0x001c},
1829 {0x01, 0x00ce, 0x001d},
1830 {0x01, 0x008d, 0x001e},
1831 {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */
1832 {0x01, 0x0032, 0x0016}, /* 32 */
1833 {0x01, 0x0016, 0x0011}, /* R 00 */
1834 {0x01, 0x0016, 0x0012}, /* G 00 */
1835 {0x01, 0x0016, 0x0013}, /* B 00 */
1836 {0x01, 0x000a, 0x0003},
1837 {0x02, 0xc002, 0x0001},
1838 {0x02, 0x0007, 0x0005},
1839 {}
1840};
1841
1842static int reg_write(struct usb_device *dev,
1843 __u16 req, __u16 index, __u16 value)
1844{
1845 int ret;
1846
1847 ret = usb_control_msg(dev,
1848 usb_sndctrlpipe(dev, 0),
1849 req,
1850 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1851 value, index, NULL, 0, 500);
1852 PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
1853 req, index, value);
1854 if (ret < 0)
1855 err("reg write: error %d", ret);
1856 return ret;
1857}
1858
1859
1860static int write_vector(struct gspca_dev *gspca_dev,
1861 const __u16 data[][3])
1862{
1863 struct usb_device *dev = gspca_dev->dev;
1864 int ret, i = 0;
1865
1866 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
1867 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
1868 if (ret < 0) {
1869 PDEBUG(D_ERR,
1870 "Reg write failed for 0x%02x,0x%02x,0x%02x",
1871 data[i][0], data[i][1], data[i][2]);
1872 return ret;
1873 }
1874 i++;
1875 }
1876 return 0;
1877}
1878
1879static void setbrightness(struct gspca_dev *gspca_dev)
1880{
1881 struct sd *sd = (struct sd *) gspca_dev;
1882
1883 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness);
1884}
1885
1886static void setcontrast(struct gspca_dev *gspca_dev)
1887{
1888 struct sd *sd = (struct sd *) gspca_dev;
1889
1890 reg_write(gspca_dev->dev, 0x00, 0x00,
1891 (sd->contrast >> 8) & 0xff);
1892 reg_write(gspca_dev->dev, 0x00, 0x01,
1893 sd->contrast & 0xff);
1894}
1895
1896static void setcolors(struct gspca_dev *gspca_dev)
1897{
1898 struct sd *sd = (struct sd *) gspca_dev;
1899
1900 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);
1901}
1902
1903static void setblue_balance(struct gspca_dev *gspca_dev)
1904{
1905 struct sd *sd = (struct sd *) gspca_dev;
1906
1907 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->blue_balance);
1908}
1909
1910static void setred_balance(struct gspca_dev *gspca_dev)
1911{
1912 struct sd *sd = (struct sd *) gspca_dev;
1913
1914 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->red_balance);
1915}
1916
1917/* this function is called at probe time */
1918static int sd_config(struct gspca_dev *gspca_dev,
1919 const struct usb_device_id *id)
1920{
1921 struct sd *sd = (struct sd *) gspca_dev;
1922 struct cam *cam;
1923
1924 cam = &gspca_dev->cam;
1925 cam->cam_mode = vga_mode;
1926 cam->nmodes = ARRAY_SIZE(vga_mode);
1927 sd->subtype = id->driver_info;
1928 sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value;
1929 sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
1930 sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value;
1931
1932 return 0;
1933}
1934
1935/* this function is called at probe and resume time */
1936static int sd_init(struct gspca_dev *gspca_dev)
1937{
1938 struct sd *sd = (struct sd *) gspca_dev;
1939
1940 switch (sd->subtype) {
1941 case Arowana300KCMOSCamera:
1942 case SmileIntlCamera:
1943 /* Arowana 300k CMOS Camera data */
1944 if (write_vector(gspca_dev, spca501c_arowana_init_data))
1945 goto error;
1946 break;
1947 case MystFromOriUnknownCamera:
1948 /* Unknown Ori CMOS Camera data */
1949 if (write_vector(gspca_dev, spca501c_mysterious_open_data))
1950 goto error;
1951 break;
1952 default:
1953 /* generic spca501 init data */
1954 if (write_vector(gspca_dev, spca501_init_data))
1955 goto error;
1956 break;
1957 }
1958 PDEBUG(D_STREAM, "Initializing SPCA501 finished");
1959 return 0;
1960error:
1961 return -EINVAL;
1962}
1963
1964static int sd_start(struct gspca_dev *gspca_dev)
1965{
1966 struct sd *sd = (struct sd *) gspca_dev;
1967 struct usb_device *dev = gspca_dev->dev;
1968 int mode;
1969
1970 switch (sd->subtype) {
1971 case ThreeComHomeConnectLite:
1972 /* Special handling for 3com data */
1973 write_vector(gspca_dev, spca501_3com_open_data);
1974 break;
1975 case Arowana300KCMOSCamera:
1976 case SmileIntlCamera:
1977 /* Arowana 300k CMOS Camera data */
1978 write_vector(gspca_dev, spca501c_arowana_open_data);
1979 break;
1980 case MystFromOriUnknownCamera:
1981 /* Unknown CMOS Camera data */
1982 write_vector(gspca_dev, spca501c_mysterious_init_data);
1983 break;
1984 default:
1985 /* Generic 501 open data */
1986 write_vector(gspca_dev, spca501_open_data);
1987 }
1988
1989 /* memorize the wanted pixel format */
1990 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1991
1992 /* Enable ISO packet machine CTRL reg=2,
1993 * index=1 bitmask=0x2 (bit ordinal 1) */
1994 reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
1995 switch (mode) {
1996 case 0: /* 640x480 */
1997 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
1998 break;
1999 case 1: /* 320x240 */
2000 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
2001 break;
2002 default:
2003/* case 2: * 160x120 */
2004 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
2005 break;
2006 }
2007 reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
2008
2009 /* HDG atleast the Intel CreateAndShare needs to have one of its
2010 * brightness / contrast / color set otherwise it assumes what seems
2011 * max contrast. Note that strange enough setting any of these is
2012 * enough to fix the max contrast problem, to be sure we set all 3 */
2013 setbrightness(gspca_dev);
2014 setcontrast(gspca_dev);
2015 setcolors(gspca_dev);
2016 return 0;
2017}
2018
2019static void sd_stopN(struct gspca_dev *gspca_dev)
2020{
2021 /* Disable ISO packet
2022 * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
2023 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
2024}
2025
2026/* called on streamoff with alt 0 and on disconnect */
2027static void sd_stop0(struct gspca_dev *gspca_dev)
2028{
2029 if (!gspca_dev->present)
2030 return;
2031 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
2032}
2033
2034static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2035 u8 *data, /* isoc packet */
2036 int len) /* iso packet length */
2037{
2038 switch (data[0]) {
2039 case 0: /* start of frame */
2040 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
2041 data += SPCA501_OFFSET_DATA;
2042 len -= SPCA501_OFFSET_DATA;
2043 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
2044 return;
2045 case 0xff: /* drop */
2046/* gspca_dev->last_packet_type = DISCARD_PACKET; */
2047 return;
2048 }
2049 data++;
2050 len--;
2051 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
2052}
2053
2054static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
2055{
2056 struct sd *sd = (struct sd *) gspca_dev;
2057
2058 sd->brightness = val;
2059 if (gspca_dev->streaming)
2060 setbrightness(gspca_dev);
2061 return 0;
2062}
2063
2064static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
2065{
2066 struct sd *sd = (struct sd *) gspca_dev;
2067
2068 *val = sd->brightness;
2069 return 0;
2070}
2071
2072static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
2073{
2074 struct sd *sd = (struct sd *) gspca_dev;
2075
2076 sd->contrast = val;
2077 if (gspca_dev->streaming)
2078 setcontrast(gspca_dev);
2079 return 0;
2080}
2081
2082static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
2083{
2084 struct sd *sd = (struct sd *) gspca_dev;
2085
2086 *val = sd->contrast;
2087 return 0;
2088}
2089
2090static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
2091{
2092 struct sd *sd = (struct sd *) gspca_dev;
2093
2094 sd->colors = val;
2095 if (gspca_dev->streaming)
2096 setcolors(gspca_dev);
2097 return 0;
2098}
2099
2100static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
2101{
2102 struct sd *sd = (struct sd *) gspca_dev;
2103
2104 *val = sd->colors;
2105 return 0;
2106}
2107
2108static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
2109{
2110 struct sd *sd = (struct sd *) gspca_dev;
2111
2112 sd->blue_balance = val;
2113 if (gspca_dev->streaming)
2114 setblue_balance(gspca_dev);
2115 return 0;
2116}
2117
2118static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
2119{
2120 struct sd *sd = (struct sd *) gspca_dev;
2121
2122 *val = sd->blue_balance;
2123 return 0;
2124}
2125
2126static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
2127{
2128 struct sd *sd = (struct sd *) gspca_dev;
2129
2130 sd->red_balance = val;
2131 if (gspca_dev->streaming)
2132 setred_balance(gspca_dev);
2133 return 0;
2134}
2135
2136static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
2137{
2138 struct sd *sd = (struct sd *) gspca_dev;
2139
2140 *val = sd->red_balance;
2141 return 0;
2142}
2143
2144/* sub-driver description */
2145static const struct sd_desc sd_desc = {
2146 .name = MODULE_NAME,
2147 .ctrls = sd_ctrls,
2148 .nctrls = ARRAY_SIZE(sd_ctrls),
2149 .config = sd_config,
2150 .init = sd_init,
2151 .start = sd_start,
2152 .stopN = sd_stopN,
2153 .stop0 = sd_stop0,
2154 .pkt_scan = sd_pkt_scan,
2155};
2156
2157/* -- module initialisation -- */
2158static const struct usb_device_id device_table[] = {
2159 {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325},
2160 {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera},
2161 {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite},
2162 {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare},
2163 {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B},
2164 {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera},
2165 {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera},
2166 {}
2167};
2168MODULE_DEVICE_TABLE(usb, device_table);
2169
2170/* -- device connect -- */
2171static int sd_probe(struct usb_interface *intf,
2172 const struct usb_device_id *id)
2173{
2174 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2175 THIS_MODULE);
2176}
2177
2178static struct usb_driver sd_driver = {
2179 .name = MODULE_NAME,
2180 .id_table = device_table,
2181 .probe = sd_probe,
2182 .disconnect = gspca_disconnect,
2183#ifdef CONFIG_PM
2184 .suspend = gspca_suspend,
2185 .resume = gspca_resume,
2186#endif
2187};
2188
2189/* -- module insert / remove -- */
2190static int __init sd_mod_init(void)
2191{
2192 return usb_register(&sd_driver);
2193}
2194static void __exit sd_mod_exit(void)
2195{
2196 usb_deregister(&sd_driver);
2197}
2198
2199module_init(sd_mod_init);
2200module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
new file mode 100644
index 00000000000..e5bf865147d
--- /dev/null
+++ b/drivers/media/video/gspca/spca505.c
@@ -0,0 +1,827 @@
1/*
2 * SPCA505 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca505"
23
24#include "gspca.h"
25
26MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
27MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
28MODULE_LICENSE("GPL");
29
30/* specific webcam descriptor */
31struct sd {
32 struct gspca_dev gspca_dev; /* !! must be the first item */
33
34 u8 brightness;
35
36 u8 subtype;
37#define IntelPCCameraPro 0
38#define Nxultra 1
39};
40
41/* V4L2 controls supported by the driver */
42static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
43static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
44
45static const struct ctrl sd_ctrls[] = {
46 {
47 {
48 .id = V4L2_CID_BRIGHTNESS,
49 .type = V4L2_CTRL_TYPE_INTEGER,
50 .name = "Brightness",
51 .minimum = 0,
52 .maximum = 255,
53 .step = 1,
54#define BRIGHTNESS_DEF 127
55 .default_value = BRIGHTNESS_DEF,
56 },
57 .set = sd_setbrightness,
58 .get = sd_getbrightness,
59 },
60};
61
62static const struct v4l2_pix_format vga_mode[] = {
63 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
64 .bytesperline = 160,
65 .sizeimage = 160 * 120 * 3 / 2,
66 .colorspace = V4L2_COLORSPACE_SRGB,
67 .priv = 4},
68 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
69 .bytesperline = 176,
70 .sizeimage = 176 * 144 * 3 / 2,
71 .colorspace = V4L2_COLORSPACE_SRGB,
72 .priv = 3},
73 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
74 .bytesperline = 320,
75 .sizeimage = 320 * 240 * 3 / 2,
76 .colorspace = V4L2_COLORSPACE_SRGB,
77 .priv = 2},
78 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
79 .bytesperline = 352,
80 .sizeimage = 352 * 288 * 3 / 2,
81 .colorspace = V4L2_COLORSPACE_SRGB,
82 .priv = 1},
83 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
84 .bytesperline = 640,
85 .sizeimage = 640 * 480 * 3 / 2,
86 .colorspace = V4L2_COLORSPACE_SRGB,
87 .priv = 0},
88};
89
90#define SPCA50X_OFFSET_DATA 10
91
92#define SPCA50X_REG_USB 0x02 /* spca505 501 */
93
94#define SPCA50X_USB_CTRL 0x00 /* spca505 */
95#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
96
97#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
98#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
99#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
100
101#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
102#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
103#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
104
105/* Image format and compression control */
106#define SPCA50X_REG_COMPRESS 0x04
107
108/*
109 * Data to initialize a SPCA505. Common to the CCD and external modes
110 */
111static const u8 spca505_init_data[][3] = {
112 /* bmRequest,value,index */
113 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
114 /* Sensor reset */
115 {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
116 {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
117 /* Block USB reset */
118 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
119
120 {0x05, 0x01, 0x10},
121 /* Maybe power down some stuff */
122 {0x05, 0x0f, 0x11},
123
124 /* Setup internal CCD ? */
125 {0x06, 0x10, 0x08},
126 {0x06, 0x00, 0x09},
127 {0x06, 0x00, 0x0a},
128 {0x06, 0x00, 0x0b},
129 {0x06, 0x10, 0x0c},
130 {0x06, 0x00, 0x0d},
131 {0x06, 0x00, 0x0e},
132 {0x06, 0x00, 0x0f},
133 {0x06, 0x10, 0x10},
134 {0x06, 0x02, 0x11},
135 {0x06, 0x00, 0x12},
136 {0x06, 0x04, 0x13},
137 {0x06, 0x02, 0x14},
138 {0x06, 0x8a, 0x51},
139 {0x06, 0x40, 0x52},
140 {0x06, 0xb6, 0x53},
141 {0x06, 0x3d, 0x54},
142 {}
143};
144
145/*
146 * Data to initialize the camera using the internal CCD
147 */
148static const u8 spca505_open_data_ccd[][3] = {
149 /* bmRequest,value,index */
150 /* Internal CCD data set */
151 {0x03, 0x04, 0x01},
152 /* This could be a reset */
153 {0x03, 0x00, 0x01},
154
155 /* Setup compression and image registers. 0x6 and 0x7 seem to be
156 related to H&V hold, and are resolution mode specific */
157 {0x04, 0x10, 0x01},
158 /* DIFF(0x50), was (0x10) */
159 {0x04, 0x00, 0x04},
160 {0x04, 0x00, 0x05},
161 {0x04, 0x20, 0x06},
162 {0x04, 0x20, 0x07},
163
164 {0x08, 0x0a, 0x00},
165 /* DIFF (0x4a), was (0xa) */
166
167 {0x05, 0x00, 0x10},
168 {0x05, 0x00, 0x11},
169 {0x05, 0x00, 0x00},
170 /* DIFF not written */
171 {0x05, 0x00, 0x01},
172 /* DIFF not written */
173 {0x05, 0x00, 0x02},
174 /* DIFF not written */
175 {0x05, 0x00, 0x03},
176 /* DIFF not written */
177 {0x05, 0x00, 0x04},
178 /* DIFF not written */
179 {0x05, 0x80, 0x05},
180 /* DIFF not written */
181 {0x05, 0xe0, 0x06},
182 /* DIFF not written */
183 {0x05, 0x20, 0x07},
184 /* DIFF not written */
185 {0x05, 0xa0, 0x08},
186 /* DIFF not written */
187 {0x05, 0x0, 0x12},
188 /* DIFF not written */
189 {0x05, 0x02, 0x0f},
190 /* DIFF not written */
191 {0x05, 0x10, 0x46},
192 /* DIFF not written */
193 {0x05, 0x8, 0x4a},
194 /* DIFF not written */
195
196 {0x03, 0x08, 0x03},
197 /* DIFF (0x3,0x28,0x3) */
198 {0x03, 0x08, 0x01},
199 {0x03, 0x0c, 0x03},
200 /* DIFF not written */
201 {0x03, 0x21, 0x00},
202 /* DIFF (0x39) */
203
204/* Extra block copied from init to hopefully ensure CCD is in a sane state */
205 {0x06, 0x10, 0x08},
206 {0x06, 0x00, 0x09},
207 {0x06, 0x00, 0x0a},
208 {0x06, 0x00, 0x0b},
209 {0x06, 0x10, 0x0c},
210 {0x06, 0x00, 0x0d},
211 {0x06, 0x00, 0x0e},
212 {0x06, 0x00, 0x0f},
213 {0x06, 0x10, 0x10},
214 {0x06, 0x02, 0x11},
215 {0x06, 0x00, 0x12},
216 {0x06, 0x04, 0x13},
217 {0x06, 0x02, 0x14},
218 {0x06, 0x8a, 0x51},
219 {0x06, 0x40, 0x52},
220 {0x06, 0xb6, 0x53},
221 {0x06, 0x3d, 0x54},
222 /* End of extra block */
223
224 {0x06, 0x3f, 0x1},
225 /* Block skipped */
226 {0x06, 0x10, 0x02},
227 {0x06, 0x64, 0x07},
228 {0x06, 0x10, 0x08},
229 {0x06, 0x00, 0x09},
230 {0x06, 0x00, 0x0a},
231 {0x06, 0x00, 0x0b},
232 {0x06, 0x10, 0x0c},
233 {0x06, 0x00, 0x0d},
234 {0x06, 0x00, 0x0e},
235 {0x06, 0x00, 0x0f},
236 {0x06, 0x10, 0x10},
237 {0x06, 0x02, 0x11},
238 {0x06, 0x00, 0x12},
239 {0x06, 0x04, 0x13},
240 {0x06, 0x02, 0x14},
241 {0x06, 0x8a, 0x51},
242 {0x06, 0x40, 0x52},
243 {0x06, 0xb6, 0x53},
244 {0x06, 0x3d, 0x54},
245 {0x06, 0x60, 0x57},
246 {0x06, 0x20, 0x58},
247 {0x06, 0x15, 0x59},
248 {0x06, 0x05, 0x5a},
249
250 {0x05, 0x01, 0xc0},
251 {0x05, 0x10, 0xcb},
252 {0x05, 0x80, 0xc1},
253 /* */
254 {0x05, 0x0, 0xc2},
255 /* 4 was 0 */
256 {0x05, 0x00, 0xca},
257 {0x05, 0x80, 0xc1},
258 /* */
259 {0x05, 0x04, 0xc2},
260 {0x05, 0x00, 0xca},
261 {0x05, 0x0, 0xc1},
262 /* */
263 {0x05, 0x00, 0xc2},
264 {0x05, 0x00, 0xca},
265 {0x05, 0x40, 0xc1},
266 /* */
267 {0x05, 0x17, 0xc2},
268 {0x05, 0x00, 0xca},
269 {0x05, 0x80, 0xc1},
270 /* */
271 {0x05, 0x06, 0xc2},
272 {0x05, 0x00, 0xca},
273 {0x05, 0x80, 0xc1},
274 /* */
275 {0x05, 0x04, 0xc2},
276 {0x05, 0x00, 0xca},
277
278 {0x03, 0x4c, 0x3},
279 {0x03, 0x18, 0x1},
280
281 {0x06, 0x70, 0x51},
282 {0x06, 0xbe, 0x53},
283 {0x06, 0x71, 0x57},
284 {0x06, 0x20, 0x58},
285 {0x06, 0x05, 0x59},
286 {0x06, 0x15, 0x5a},
287
288 {0x04, 0x00, 0x08},
289 /* Compress = OFF (0x1 to turn on) */
290 {0x04, 0x12, 0x09},
291 {0x04, 0x21, 0x0a},
292 {0x04, 0x10, 0x0b},
293 {0x04, 0x21, 0x0c},
294 {0x04, 0x05, 0x00},
295 /* was 5 (Image Type ? ) */
296 {0x04, 0x00, 0x01},
297
298 {0x06, 0x3f, 0x01},
299
300 {0x04, 0x00, 0x04},
301 {0x04, 0x00, 0x05},
302 {0x04, 0x40, 0x06},
303 {0x04, 0x40, 0x07},
304
305 {0x06, 0x1c, 0x17},
306 {0x06, 0xe2, 0x19},
307 {0x06, 0x1c, 0x1b},
308 {0x06, 0xe2, 0x1d},
309 {0x06, 0xaa, 0x1f},
310 {0x06, 0x70, 0x20},
311
312 {0x05, 0x01, 0x10},
313 {0x05, 0x00, 0x11},
314 {0x05, 0x01, 0x00},
315 {0x05, 0x05, 0x01},
316 {0x05, 0x00, 0xc1},
317 /* */
318 {0x05, 0x00, 0xc2},
319 {0x05, 0x00, 0xca},
320
321 {0x06, 0x70, 0x51},
322 {0x06, 0xbe, 0x53},
323 {}
324};
325
326/*
327 * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
328 * SPCA505b chip based cameras initialization data
329 */
330/* jfm */
331#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
332/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
333/*
334 * Data to initialize a SPCA505. Common to the CCD and external modes
335 */
336static const u8 spca505b_init_data[][3] = {
337/* start */
338 {0x02, 0x00, 0x00}, /* init */
339 {0x02, 0x00, 0x01},
340 {0x02, 0x00, 0x02},
341 {0x02, 0x00, 0x03},
342 {0x02, 0x00, 0x04},
343 {0x02, 0x00, 0x05},
344 {0x02, 0x00, 0x06},
345 {0x02, 0x00, 0x07},
346 {0x02, 0x00, 0x08},
347 {0x02, 0x00, 0x09},
348 {0x03, 0x00, 0x00},
349 {0x03, 0x00, 0x01},
350 {0x03, 0x00, 0x02},
351 {0x03, 0x00, 0x03},
352 {0x03, 0x00, 0x04},
353 {0x03, 0x00, 0x05},
354 {0x03, 0x00, 0x06},
355 {0x04, 0x00, 0x00},
356 {0x04, 0x00, 0x02},
357 {0x04, 0x00, 0x04},
358 {0x04, 0x00, 0x05},
359 {0x04, 0x00, 0x06},
360 {0x04, 0x00, 0x07},
361 {0x04, 0x00, 0x08},
362 {0x04, 0x00, 0x09},
363 {0x04, 0x00, 0x0a},
364 {0x04, 0x00, 0x0b},
365 {0x04, 0x00, 0x0c},
366 {0x07, 0x00, 0x00},
367 {0x07, 0x00, 0x03},
368 {0x08, 0x00, 0x00},
369 {0x08, 0x00, 0x01},
370 {0x08, 0x00, 0x02},
371 {0x06, 0x18, 0x08},
372 {0x06, 0xfc, 0x09},
373 {0x06, 0xfc, 0x0a},
374 {0x06, 0xfc, 0x0b},
375 {0x06, 0x18, 0x0c},
376 {0x06, 0xfc, 0x0d},
377 {0x06, 0xfc, 0x0e},
378 {0x06, 0xfc, 0x0f},
379 {0x06, 0x18, 0x10},
380 {0x06, 0xfe, 0x12},
381 {0x06, 0x00, 0x11},
382 {0x06, 0x00, 0x14},
383 {0x06, 0x00, 0x13},
384 {0x06, 0x28, 0x51},
385 {0x06, 0xff, 0x53},
386 {0x02, 0x00, 0x08},
387
388 {0x03, 0x00, 0x03},
389 {0x03, 0x10, 0x03},
390 {}
391};
392
393/*
394 * Data to initialize the camera using the internal CCD
395 */
396static const u8 spca505b_open_data_ccd[][3] = {
397
398/* {0x02,0x00,0x00}, */
399 {0x03, 0x04, 0x01}, /* rst */
400 {0x03, 0x00, 0x01},
401 {0x03, 0x00, 0x00},
402 {0x03, 0x21, 0x00},
403 {0x03, 0x00, 0x04},
404 {0x03, 0x00, 0x03},
405 {0x03, 0x18, 0x03},
406 {0x03, 0x08, 0x01},
407 {0x03, 0x1c, 0x03},
408 {0x03, 0x5c, 0x03},
409 {0x03, 0x5c, 0x03},
410 {0x03, 0x18, 0x01},
411
412/* same as 505 */
413 {0x04, 0x10, 0x01},
414 {0x04, 0x00, 0x04},
415 {0x04, 0x00, 0x05},
416 {0x04, 0x20, 0x06},
417 {0x04, 0x20, 0x07},
418
419 {0x08, 0x0a, 0x00},
420
421 {0x05, 0x00, 0x10},
422 {0x05, 0x00, 0x11},
423 {0x05, 0x00, 0x12},
424 {0x05, 0x6f, 0x00},
425 {0x05, initial_brightness >> 6, 0x00},
426 {0x05, (initial_brightness << 2) & 0xff, 0x01},
427 {0x05, 0x00, 0x02},
428 {0x05, 0x01, 0x03},
429 {0x05, 0x00, 0x04},
430 {0x05, 0x03, 0x05},
431 {0x05, 0xe0, 0x06},
432 {0x05, 0x20, 0x07},
433 {0x05, 0xa0, 0x08},
434 {0x05, 0x00, 0x12},
435 {0x05, 0x02, 0x0f},
436 {0x05, 0x80, 0x14}, /* max exposure off (0=on) */
437 {0x05, 0x01, 0xb0},
438 {0x05, 0x01, 0xbf},
439 {0x03, 0x02, 0x06},
440 {0x05, 0x10, 0x46},
441 {0x05, 0x08, 0x4a},
442
443 {0x06, 0x00, 0x01},
444 {0x06, 0x10, 0x02},
445 {0x06, 0x64, 0x07},
446 {0x06, 0x18, 0x08},
447 {0x06, 0xfc, 0x09},
448 {0x06, 0xfc, 0x0a},
449 {0x06, 0xfc, 0x0b},
450 {0x04, 0x00, 0x01},
451 {0x06, 0x18, 0x0c},
452 {0x06, 0xfc, 0x0d},
453 {0x06, 0xfc, 0x0e},
454 {0x06, 0xfc, 0x0f},
455 {0x06, 0x11, 0x10}, /* contrast */
456 {0x06, 0x00, 0x11},
457 {0x06, 0xfe, 0x12},
458 {0x06, 0x00, 0x13},
459 {0x06, 0x00, 0x14},
460 {0x06, 0x9d, 0x51},
461 {0x06, 0x40, 0x52},
462 {0x06, 0x7c, 0x53},
463 {0x06, 0x40, 0x54},
464 {0x06, 0x02, 0x57},
465 {0x06, 0x03, 0x58},
466 {0x06, 0x15, 0x59},
467 {0x06, 0x05, 0x5a},
468 {0x06, 0x03, 0x56},
469 {0x06, 0x02, 0x3f},
470 {0x06, 0x00, 0x40},
471 {0x06, 0x39, 0x41},
472 {0x06, 0x69, 0x42},
473 {0x06, 0x87, 0x43},
474 {0x06, 0x9e, 0x44},
475 {0x06, 0xb1, 0x45},
476 {0x06, 0xbf, 0x46},
477 {0x06, 0xcc, 0x47},
478 {0x06, 0xd5, 0x48},
479 {0x06, 0xdd, 0x49},
480 {0x06, 0xe3, 0x4a},
481 {0x06, 0xe8, 0x4b},
482 {0x06, 0xed, 0x4c},
483 {0x06, 0xf2, 0x4d},
484 {0x06, 0xf7, 0x4e},
485 {0x06, 0xfc, 0x4f},
486 {0x06, 0xff, 0x50},
487
488 {0x05, 0x01, 0xc0},
489 {0x05, 0x10, 0xcb},
490 {0x05, 0x40, 0xc1},
491 {0x05, 0x04, 0xc2},
492 {0x05, 0x00, 0xca},
493 {0x05, 0x40, 0xc1},
494 {0x05, 0x09, 0xc2},
495 {0x05, 0x00, 0xca},
496 {0x05, 0xc0, 0xc1},
497 {0x05, 0x09, 0xc2},
498 {0x05, 0x00, 0xca},
499 {0x05, 0x40, 0xc1},
500 {0x05, 0x59, 0xc2},
501 {0x05, 0x00, 0xca},
502 {0x04, 0x00, 0x01},
503 {0x05, 0x80, 0xc1},
504 {0x05, 0xec, 0xc2},
505 {0x05, 0x0, 0xca},
506
507 {0x06, 0x02, 0x57},
508 {0x06, 0x01, 0x58},
509 {0x06, 0x15, 0x59},
510 {0x06, 0x0a, 0x5a},
511 {0x06, 0x01, 0x57},
512 {0x06, 0x8a, 0x03},
513 {0x06, 0x0a, 0x6c},
514 {0x06, 0x30, 0x01},
515 {0x06, 0x20, 0x02},
516 {0x06, 0x00, 0x03},
517
518 {0x05, 0x8c, 0x25},
519
520 {0x06, 0x4d, 0x51}, /* maybe saturation (4d) */
521 {0x06, 0x84, 0x53}, /* making green (84) */
522 {0x06, 0x00, 0x57}, /* sharpness (1) */
523 {0x06, 0x18, 0x08},
524 {0x06, 0xfc, 0x09},
525 {0x06, 0xfc, 0x0a},
526 {0x06, 0xfc, 0x0b},
527 {0x06, 0x18, 0x0c}, /* maybe hue (18) */
528 {0x06, 0xfc, 0x0d},
529 {0x06, 0xfc, 0x0e},
530 {0x06, 0xfc, 0x0f},
531 {0x06, 0x18, 0x10}, /* maybe contrast (18) */
532
533 {0x05, 0x01, 0x02},
534
535 {0x04, 0x00, 0x08}, /* compression */
536 {0x04, 0x12, 0x09},
537 {0x04, 0x21, 0x0a},
538 {0x04, 0x10, 0x0b},
539 {0x04, 0x21, 0x0c},
540 {0x04, 0x1d, 0x00}, /* imagetype (1d) */
541 {0x04, 0x41, 0x01}, /* hardware snapcontrol */
542
543 {0x04, 0x00, 0x04},
544 {0x04, 0x00, 0x05},
545 {0x04, 0x10, 0x06},
546 {0x04, 0x10, 0x07},
547 {0x04, 0x40, 0x06},
548 {0x04, 0x40, 0x07},
549 {0x04, 0x00, 0x04},
550 {0x04, 0x00, 0x05},
551
552 {0x06, 0x1c, 0x17},
553 {0x06, 0xe2, 0x19},
554 {0x06, 0x1c, 0x1b},
555 {0x06, 0xe2, 0x1d},
556 {0x06, 0x5f, 0x1f},
557 {0x06, 0x32, 0x20},
558
559 {0x05, initial_brightness >> 6, 0x00},
560 {0x05, (initial_brightness << 2) & 0xff, 0x01},
561 {0x05, 0x06, 0xc1},
562 {0x05, 0x58, 0xc2},
563 {0x05, 0x00, 0xca},
564 {0x05, 0x00, 0x11},
565 {}
566};
567
568static int reg_write(struct usb_device *dev,
569 u16 req, u16 index, u16 value)
570{
571 int ret;
572
573 ret = usb_control_msg(dev,
574 usb_sndctrlpipe(dev, 0),
575 req,
576 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
577 value, index, NULL, 0, 500);
578 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
579 req, index, value, ret);
580 if (ret < 0)
581 err("reg write: error %d", ret);
582 return ret;
583}
584
585/* returns: negative is error, pos or zero is data */
586static int reg_read(struct gspca_dev *gspca_dev,
587 u16 req, /* bRequest */
588 u16 index) /* wIndex */
589{
590 int ret;
591
592 ret = usb_control_msg(gspca_dev->dev,
593 usb_rcvctrlpipe(gspca_dev->dev, 0),
594 req,
595 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
596 0, /* value */
597 index,
598 gspca_dev->usb_buf, 2,
599 500); /* timeout */
600 if (ret < 0)
601 return ret;
602 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
603}
604
605static int write_vector(struct gspca_dev *gspca_dev,
606 const u8 data[][3])
607{
608 struct usb_device *dev = gspca_dev->dev;
609 int ret, i = 0;
610
611 while (data[i][0] != 0) {
612 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
613 if (ret < 0)
614 return ret;
615 i++;
616 }
617 return 0;
618}
619
620/* this function is called at probe time */
621static int sd_config(struct gspca_dev *gspca_dev,
622 const struct usb_device_id *id)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625 struct cam *cam;
626
627 cam = &gspca_dev->cam;
628 cam->cam_mode = vga_mode;
629 sd->subtype = id->driver_info;
630 if (sd->subtype != IntelPCCameraPro)
631 cam->nmodes = ARRAY_SIZE(vga_mode);
632 else /* no 640x480 for IntelPCCameraPro */
633 cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
634 sd->brightness = BRIGHTNESS_DEF;
635
636 return 0;
637}
638
639/* this function is called at probe and resume time */
640static int sd_init(struct gspca_dev *gspca_dev)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643
644 if (write_vector(gspca_dev,
645 sd->subtype == Nxultra
646 ? spca505b_init_data
647 : spca505_init_data))
648 return -EIO;
649 return 0;
650}
651
652static void setbrightness(struct gspca_dev *gspca_dev)
653{
654 struct sd *sd = (struct sd *) gspca_dev;
655 u8 brightness = sd->brightness;
656
657 reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
658 reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
659}
660
661static int sd_start(struct gspca_dev *gspca_dev)
662{
663 struct sd *sd = (struct sd *) gspca_dev;
664 struct usb_device *dev = gspca_dev->dev;
665 int ret, mode;
666 static u8 mode_tb[][3] = {
667 /* r00 r06 r07 */
668 {0x00, 0x10, 0x10}, /* 640x480 */
669 {0x01, 0x1a, 0x1a}, /* 352x288 */
670 {0x02, 0x1c, 0x1d}, /* 320x240 */
671 {0x04, 0x34, 0x34}, /* 176x144 */
672 {0x05, 0x40, 0x40} /* 160x120 */
673 };
674
675 if (sd->subtype == Nxultra)
676 write_vector(gspca_dev, spca505b_open_data_ccd);
677 else
678 write_vector(gspca_dev, spca505_open_data_ccd);
679 ret = reg_read(gspca_dev, 0x06, 0x16);
680
681 if (ret < 0) {
682 PDEBUG(D_ERR|D_CONF,
683 "register read failed err: %d",
684 ret);
685 return ret;
686 }
687 if (ret != 0x0101) {
688 err("After vector read returns 0x%04x should be 0x0101",
689 ret);
690 }
691
692 ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
693 if (ret < 0)
694 return ret;
695 reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
696
697 /* necessary because without it we can see stream
698 * only once after loading module */
699 /* stopping usb registers Tomasz change */
700 reg_write(dev, 0x02, 0x00, 0x00);
701
702 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
703 reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
704 reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
705 reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
706
707 ret = reg_write(dev, SPCA50X_REG_USB,
708 SPCA50X_USB_CTRL,
709 SPCA50X_CUSB_ENABLE);
710
711 setbrightness(gspca_dev);
712
713 return ret;
714}
715
716static void sd_stopN(struct gspca_dev *gspca_dev)
717{
718 /* Disable ISO packet machine */
719 reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
720}
721
722/* called on streamoff with alt 0 and on disconnect */
723static void sd_stop0(struct gspca_dev *gspca_dev)
724{
725 if (!gspca_dev->present)
726 return;
727
728 /* This maybe reset or power control */
729 reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
730 reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
731 reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
732 reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
733 reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
734}
735
736static void sd_pkt_scan(struct gspca_dev *gspca_dev,
737 u8 *data, /* isoc packet */
738 int len) /* iso packet length */
739{
740 switch (data[0]) {
741 case 0: /* start of frame */
742 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
743 data += SPCA50X_OFFSET_DATA;
744 len -= SPCA50X_OFFSET_DATA;
745 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
746 break;
747 case 0xff: /* drop */
748 break;
749 default:
750 data += 1;
751 len -= 1;
752 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
753 break;
754 }
755}
756
757static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
758{
759 struct sd *sd = (struct sd *) gspca_dev;
760
761 sd->brightness = val;
762 if (gspca_dev->streaming)
763 setbrightness(gspca_dev);
764 return 0;
765}
766
767static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
768{
769 struct sd *sd = (struct sd *) gspca_dev;
770
771 *val = sd->brightness;
772 return 0;
773}
774
775/* sub-driver description */
776static const struct sd_desc sd_desc = {
777 .name = MODULE_NAME,
778 .ctrls = sd_ctrls,
779 .nctrls = ARRAY_SIZE(sd_ctrls),
780 .config = sd_config,
781 .init = sd_init,
782 .start = sd_start,
783 .stopN = sd_stopN,
784 .stop0 = sd_stop0,
785 .pkt_scan = sd_pkt_scan,
786};
787
788/* -- module initialisation -- */
789static const struct usb_device_id device_table[] = {
790 {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
791 {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
792/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
793 {}
794};
795MODULE_DEVICE_TABLE(usb, device_table);
796
797/* -- device connect -- */
798static int sd_probe(struct usb_interface *intf,
799 const struct usb_device_id *id)
800{
801 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
802 THIS_MODULE);
803}
804
805static struct usb_driver sd_driver = {
806 .name = MODULE_NAME,
807 .id_table = device_table,
808 .probe = sd_probe,
809 .disconnect = gspca_disconnect,
810#ifdef CONFIG_PM
811 .suspend = gspca_suspend,
812 .resume = gspca_resume,
813#endif
814};
815
816/* -- module insert / remove -- */
817static int __init sd_mod_init(void)
818{
819 return usb_register(&sd_driver);
820}
821static void __exit sd_mod_exit(void)
822{
823 usb_deregister(&sd_driver);
824}
825
826module_init(sd_mod_init);
827module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
new file mode 100644
index 00000000000..89fec4c500a
--- /dev/null
+++ b/drivers/media/video/gspca/spca506.c
@@ -0,0 +1,734 @@
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 unsigned char brightness;
37 unsigned char contrast;
38 unsigned char colors;
39 unsigned char hue;
40 char norme;
41 char channel;
42};
43
44/* V4L2 controls supported by the driver */
45static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
46static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
47static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
48static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
49static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
53
54static const struct ctrl sd_ctrls[] = {
55#define SD_BRIGHTNESS 0
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 0,
62 .maximum = 0xff,
63 .step = 1,
64 .default_value = 0x80,
65 },
66 .set = sd_setbrightness,
67 .get = sd_getbrightness,
68 },
69#define SD_CONTRAST 1
70 {
71 {
72 .id = V4L2_CID_CONTRAST,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Contrast",
75 .minimum = 0,
76 .maximum = 0xff,
77 .step = 1,
78 .default_value = 0x47,
79 },
80 .set = sd_setcontrast,
81 .get = sd_getcontrast,
82 },
83#define SD_COLOR 2
84 {
85 {
86 .id = V4L2_CID_SATURATION,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Saturation",
89 .minimum = 0,
90 .maximum = 0xff,
91 .step = 1,
92 .default_value = 0x40,
93 },
94 .set = sd_setcolors,
95 .get = sd_getcolors,
96 },
97#define SD_HUE 3
98 {
99 {
100 .id = V4L2_CID_HUE,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Hue",
103 .minimum = 0,
104 .maximum = 0xff,
105 .step = 1,
106 .default_value = 0,
107 },
108 .set = sd_sethue,
109 .get = sd_gethue,
110 },
111};
112
113static const struct v4l2_pix_format vga_mode[] = {
114 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
115 .bytesperline = 160,
116 .sizeimage = 160 * 120 * 3 / 2,
117 .colorspace = V4L2_COLORSPACE_SRGB,
118 .priv = 5},
119 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
120 .bytesperline = 176,
121 .sizeimage = 176 * 144 * 3 / 2,
122 .colorspace = V4L2_COLORSPACE_SRGB,
123 .priv = 4},
124 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
125 .bytesperline = 320,
126 .sizeimage = 320 * 240 * 3 / 2,
127 .colorspace = V4L2_COLORSPACE_SRGB,
128 .priv = 2},
129 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
130 .bytesperline = 352,
131 .sizeimage = 352 * 288 * 3 / 2,
132 .colorspace = V4L2_COLORSPACE_SRGB,
133 .priv = 1},
134 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
135 .bytesperline = 640,
136 .sizeimage = 640 * 480 * 3 / 2,
137 .colorspace = V4L2_COLORSPACE_SRGB,
138 .priv = 0},
139};
140
141#define SPCA50X_OFFSET_DATA 10
142
143#define SAA7113_bright 0x0a /* defaults 0x80 */
144#define SAA7113_contrast 0x0b /* defaults 0x47 */
145#define SAA7113_saturation 0x0c /* defaults 0x40 */
146#define SAA7113_hue 0x0d /* defaults 0x00 */
147#define SAA7113_I2C_BASE_WRITE 0x4a
148
149/* read 'len' bytes to gspca_dev->usb_buf */
150static void reg_r(struct gspca_dev *gspca_dev,
151 __u16 req,
152 __u16 index,
153 __u16 length)
154{
155 usb_control_msg(gspca_dev->dev,
156 usb_rcvctrlpipe(gspca_dev->dev, 0),
157 req,
158 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159 0, /* value */
160 index, gspca_dev->usb_buf, length,
161 500);
162}
163
164static void reg_w(struct usb_device *dev,
165 __u16 req,
166 __u16 value,
167 __u16 index)
168{
169 usb_control_msg(dev,
170 usb_sndctrlpipe(dev, 0),
171 req,
172 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
173 value, index,
174 NULL, 0, 500);
175}
176
177static void spca506_Initi2c(struct gspca_dev *gspca_dev)
178{
179 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
180}
181
182static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
183 __u16 reg)
184{
185 int retry = 60;
186
187 reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
188 reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
189 while (retry--) {
190 reg_r(gspca_dev, 0x07, 0x0003, 2);
191 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
192 break;
193 }
194}
195
196static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
197 __u16 norme,
198 __u16 channel)
199{
200 struct sd *sd = (struct sd *) gspca_dev;
201/* fixme: check if channel == 0..3 and 6..9 (8 values) */
202 __u8 setbit0 = 0x00;
203 __u8 setbit1 = 0x00;
204 __u8 videomask = 0x00;
205
206 PDEBUG(D_STREAM, "** Open Set Norme **");
207 spca506_Initi2c(gspca_dev);
208 /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
209 /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
210 /* and exclude SAA7113 reserved channel set default 0 otherwise */
211 if (norme & V4L2_STD_NTSC)
212 setbit0 = 0x01;
213 if (channel == 4 || channel == 5 || channel > 9)
214 channel = 0;
215 if (channel < 4)
216 setbit1 = 0x02;
217 videomask = (0x48 | setbit0 | setbit1);
218 reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
219 spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
220
221 if (norme & V4L2_STD_NTSC)
222 spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
223 /* Chrominance Control NTSC N */
224 else if (norme & V4L2_STD_SECAM)
225 spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
226 /* Chrominance Control SECAM */
227 else
228 spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
229 /* Chrominance Control PAL BGHIV */
230
231 sd->norme = norme;
232 sd->channel = channel;
233 PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
234 PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
235}
236
237static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
238 __u16 *norme, __u16 *channel)
239{
240 struct sd *sd = (struct sd *) gspca_dev;
241
242 /* Read the register is not so good value change so
243 we use your own copy in spca50x struct */
244 *norme = sd->norme;
245 *channel = sd->channel;
246 PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
247}
248
249static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
250 __u16 xmult, __u16 ymult)
251{
252 struct usb_device *dev = gspca_dev->dev;
253
254 PDEBUG(D_STREAM, "** SetSize **");
255 reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
256 /* Soft snap 0x40 Hard 0x41 */
257 reg_w(dev, 0x04, 0x41, 0x0001);
258 reg_w(dev, 0x04, 0x00, 0x0002);
259 /* reserved */
260 reg_w(dev, 0x04, 0x00, 0x0003);
261
262 /* reserved */
263 reg_w(dev, 0x04, 0x00, 0x0004);
264 /* reserved */
265 reg_w(dev, 0x04, 0x01, 0x0005);
266 /* reserced */
267 reg_w(dev, 0x04, xmult, 0x0006);
268 /* reserved */
269 reg_w(dev, 0x04, ymult, 0x0007);
270 /* compression 1 */
271 reg_w(dev, 0x04, 0x00, 0x0008);
272 /* T=64 -> 2 */
273 reg_w(dev, 0x04, 0x00, 0x0009);
274 /* threshold2D */
275 reg_w(dev, 0x04, 0x21, 0x000a);
276 /* quantization */
277 reg_w(dev, 0x04, 0x00, 0x000b);
278}
279
280/* this function is called at probe time */
281static int sd_config(struct gspca_dev *gspca_dev,
282 const struct usb_device_id *id)
283{
284 struct sd *sd = (struct sd *) gspca_dev;
285 struct cam *cam;
286
287 cam = &gspca_dev->cam;
288 cam->cam_mode = vga_mode;
289 cam->nmodes = ARRAY_SIZE(vga_mode);
290 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
291 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
292 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
293 sd->hue = sd_ctrls[SD_HUE].qctrl.default_value;
294 return 0;
295}
296
297/* this function is called at probe and resume time */
298static int sd_init(struct gspca_dev *gspca_dev)
299{
300 struct usb_device *dev = gspca_dev->dev;
301
302 reg_w(dev, 0x03, 0x00, 0x0004);
303 reg_w(dev, 0x03, 0xFF, 0x0003);
304 reg_w(dev, 0x03, 0x00, 0x0000);
305 reg_w(dev, 0x03, 0x1c, 0x0001);
306 reg_w(dev, 0x03, 0x18, 0x0001);
307 /* Init on PAL and composite input0 */
308 spca506_SetNormeInput(gspca_dev, 0, 0);
309 reg_w(dev, 0x03, 0x1c, 0x0001);
310 reg_w(dev, 0x03, 0x18, 0x0001);
311 reg_w(dev, 0x05, 0x00, 0x0000);
312 reg_w(dev, 0x05, 0xef, 0x0001);
313 reg_w(dev, 0x05, 0x00, 0x00c1);
314 reg_w(dev, 0x05, 0x00, 0x00c2);
315 reg_w(dev, 0x06, 0x18, 0x0002);
316 reg_w(dev, 0x06, 0xf5, 0x0011);
317 reg_w(dev, 0x06, 0x02, 0x0012);
318 reg_w(dev, 0x06, 0xfb, 0x0013);
319 reg_w(dev, 0x06, 0x00, 0x0014);
320 reg_w(dev, 0x06, 0xa4, 0x0051);
321 reg_w(dev, 0x06, 0x40, 0x0052);
322 reg_w(dev, 0x06, 0x71, 0x0053);
323 reg_w(dev, 0x06, 0x40, 0x0054);
324 /************************************************/
325 reg_w(dev, 0x03, 0x00, 0x0004);
326 reg_w(dev, 0x03, 0x00, 0x0003);
327 reg_w(dev, 0x03, 0x00, 0x0004);
328 reg_w(dev, 0x03, 0xFF, 0x0003);
329 reg_w(dev, 0x02, 0x00, 0x0000);
330 reg_w(dev, 0x03, 0x60, 0x0000);
331 reg_w(dev, 0x03, 0x18, 0x0001);
332 /* for a better reading mx :) */
333 /*sdca506_WriteI2c(value,register) */
334 spca506_Initi2c(gspca_dev);
335 spca506_WriteI2c(gspca_dev, 0x08, 0x01);
336 spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
337 /* input composite video */
338 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
339 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
340 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
341 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
342 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
343 spca506_WriteI2c(gspca_dev, 0x98, 0x08);
344 spca506_WriteI2c(gspca_dev, 0x03, 0x09);
345 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
346 spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
347 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
348 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
349 spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */
350 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
351 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
352 spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
353 spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
354 spca506_WriteI2c(gspca_dev, 0x01, 0x13);
355 spca506_WriteI2c(gspca_dev, 0x00, 0x14);
356 spca506_WriteI2c(gspca_dev, 0x00, 0x15);
357 spca506_WriteI2c(gspca_dev, 0x00, 0x16);
358 spca506_WriteI2c(gspca_dev, 0x00, 0x17);
359 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
360 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
361 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
362 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
363 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
364 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
365 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
366 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
367 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
368 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
369 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
370 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
371 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
372 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
373 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
374 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
375 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
376 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
377 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
378 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
379 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
380 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
381 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
382 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
383 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
384 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
385 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
386 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
387 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
388 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
389 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
390 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
391 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
392 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
393 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
394 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
395 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
396 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
397 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
398 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
399 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
400 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
401 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
402 PDEBUG(D_STREAM, "** Close Init *");
403 return 0;
404}
405
406static int sd_start(struct gspca_dev *gspca_dev)
407{
408 struct usb_device *dev = gspca_dev->dev;
409 __u16 norme;
410 __u16 channel;
411
412 /**************************************/
413 reg_w(dev, 0x03, 0x00, 0x0004);
414 reg_w(dev, 0x03, 0x00, 0x0003);
415 reg_w(dev, 0x03, 0x00, 0x0004);
416 reg_w(dev, 0x03, 0xFF, 0x0003);
417 reg_w(dev, 0x02, 0x00, 0x0000);
418 reg_w(dev, 0x03, 0x60, 0x0000);
419 reg_w(dev, 0x03, 0x18, 0x0001);
420
421 /*sdca506_WriteI2c(value,register) */
422 spca506_Initi2c(gspca_dev);
423 spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */
424/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
425 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
426 /* Analog Input Control 2 */
427 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
428 /* Analog Input Control 3 */
429 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
430 /* Analog Input Control 4 */
431 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
432 /* Horizontal Sync Start 0xe9-0x0d */
433 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
434 /* Horizontal Sync Stop 0x0d-0xf0 */
435
436 spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */
437/* Defaults value */
438 spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */
439 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
440 /* Luminance Brightness */
441 spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */
442 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
443 /* Chrominance Saturation */
444 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
445 /* Chrominance Hue Control */
446 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
447 /* Chrominance Gain Control */
448 /**************************************/
449 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
450 /* Format/Delay Control */
451 spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */
452 spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */
453 spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */
454 spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */
455 spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */
456 spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */
457 spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */
458 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
459 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
460 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
461 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
462 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
463 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
464 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
465 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
466 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
467 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
468 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
469 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
470 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
471 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
472 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
473 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
474 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
475 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
476 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
477 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
478 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
479 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
480 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
481 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
482 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
483 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
484 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
485 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
486 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
487 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
488 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
489 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
490 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
491 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
492 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
493 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
494 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
495 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
496 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
497 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
498 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
499 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
500 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
501 /**************************************/
502 reg_w(dev, 0x05, 0x00, 0x0003);
503 reg_w(dev, 0x05, 0x00, 0x0004);
504 reg_w(dev, 0x03, 0x10, 0x0001);
505 reg_w(dev, 0x03, 0x78, 0x0000);
506 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
507 case 0:
508 spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
509 break;
510 case 1:
511 spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
512 break;
513 case 2:
514 spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
515 break;
516 case 4:
517 spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
518 break;
519 default:
520/* case 5: */
521 spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
522 break;
523 }
524
525 /* compress setting and size */
526 /* set i2c luma */
527 reg_w(dev, 0x02, 0x01, 0x0000);
528 reg_w(dev, 0x03, 0x12, 0x0000);
529 reg_r(gspca_dev, 0x04, 0x0001, 2);
530 PDEBUG(D_STREAM, "webcam started");
531 spca506_GetNormeInput(gspca_dev, &norme, &channel);
532 spca506_SetNormeInput(gspca_dev, norme, channel);
533 return 0;
534}
535
536static void sd_stopN(struct gspca_dev *gspca_dev)
537{
538 struct usb_device *dev = gspca_dev->dev;
539
540 reg_w(dev, 0x02, 0x00, 0x0000);
541 reg_w(dev, 0x03, 0x00, 0x0004);
542 reg_w(dev, 0x03, 0x00, 0x0003);
543}
544
545static void sd_pkt_scan(struct gspca_dev *gspca_dev,
546 u8 *data, /* isoc packet */
547 int len) /* iso packet length */
548{
549 switch (data[0]) {
550 case 0: /* start of frame */
551 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
552 data += SPCA50X_OFFSET_DATA;
553 len -= SPCA50X_OFFSET_DATA;
554 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
555 break;
556 case 0xff: /* drop */
557/* gspca_dev->last_packet_type = DISCARD_PACKET; */
558 break;
559 default:
560 data += 1;
561 len -= 1;
562 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
563 break;
564 }
565}
566
567static void setbrightness(struct gspca_dev *gspca_dev)
568{
569 struct sd *sd = (struct sd *) gspca_dev;
570
571 spca506_Initi2c(gspca_dev);
572 spca506_WriteI2c(gspca_dev, sd->brightness, SAA7113_bright);
573 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
574}
575
576static void setcontrast(struct gspca_dev *gspca_dev)
577{
578 struct sd *sd = (struct sd *) gspca_dev;
579
580 spca506_Initi2c(gspca_dev);
581 spca506_WriteI2c(gspca_dev, sd->contrast, SAA7113_contrast);
582 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
583}
584
585static void setcolors(struct gspca_dev *gspca_dev)
586{
587 struct sd *sd = (struct sd *) gspca_dev;
588
589 spca506_Initi2c(gspca_dev);
590 spca506_WriteI2c(gspca_dev, sd->colors, SAA7113_saturation);
591 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
592}
593
594static void sethue(struct gspca_dev *gspca_dev)
595{
596 struct sd *sd = (struct sd *) gspca_dev;
597
598 spca506_Initi2c(gspca_dev);
599 spca506_WriteI2c(gspca_dev, sd->hue, SAA7113_hue);
600 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
601}
602
603static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
604{
605 struct sd *sd = (struct sd *) gspca_dev;
606
607 sd->brightness = val;
608 if (gspca_dev->streaming)
609 setbrightness(gspca_dev);
610 return 0;
611}
612
613static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
614{
615 struct sd *sd = (struct sd *) gspca_dev;
616
617 *val = sd->brightness;
618 return 0;
619}
620
621static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
622{
623 struct sd *sd = (struct sd *) gspca_dev;
624
625 sd->contrast = val;
626 if (gspca_dev->streaming)
627 setcontrast(gspca_dev);
628 return 0;
629}
630
631static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
632{
633 struct sd *sd = (struct sd *) gspca_dev;
634
635 *val = sd->contrast;
636 return 0;
637}
638
639static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
640{
641 struct sd *sd = (struct sd *) gspca_dev;
642
643 sd->colors = val;
644 if (gspca_dev->streaming)
645 setcolors(gspca_dev);
646 return 0;
647}
648
649static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
650{
651 struct sd *sd = (struct sd *) gspca_dev;
652
653 *val = sd->colors;
654 return 0;
655}
656
657static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
658{
659 struct sd *sd = (struct sd *) gspca_dev;
660
661 sd->hue = val;
662 if (gspca_dev->streaming)
663 sethue(gspca_dev);
664 return 0;
665}
666
667static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
668{
669 struct sd *sd = (struct sd *) gspca_dev;
670
671 *val = sd->hue;
672 return 0;
673}
674
675/* sub-driver description */
676static const struct sd_desc sd_desc = {
677 .name = MODULE_NAME,
678 .ctrls = sd_ctrls,
679 .nctrls = ARRAY_SIZE(sd_ctrls),
680 .config = sd_config,
681 .init = sd_init,
682 .start = sd_start,
683 .stopN = sd_stopN,
684 .pkt_scan = sd_pkt_scan,
685};
686
687/* -- module initialisation -- */
688static const struct usb_device_id device_table[] __devinitconst = {
689 {USB_DEVICE(0x06e1, 0xa190)},
690/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
691 {USB_DEVICE(0x0733, 0x0430)}, */
692 {USB_DEVICE(0x0734, 0x043b)},
693 {USB_DEVICE(0x99fa, 0x8988)},
694 {}
695};
696MODULE_DEVICE_TABLE(usb, device_table);
697
698/* -- device connect -- */
699static int __devinit sd_probe(struct usb_interface *intf,
700 const struct usb_device_id *id)
701{
702 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
703 THIS_MODULE);
704}
705
706static struct usb_driver sd_driver = {
707 .name = MODULE_NAME,
708 .id_table = device_table,
709 .probe = sd_probe,
710 .disconnect = gspca_disconnect,
711#ifdef CONFIG_PM
712 .suspend = gspca_suspend,
713 .resume = gspca_resume,
714#endif
715};
716
717/* -- module insert / remove -- */
718static int __init sd_mod_init(void)
719{
720 int ret;
721 ret = usb_register(&sd_driver);
722 if (ret < 0)
723 return ret;
724 PDEBUG(D_PROBE, "registered");
725 return 0;
726}
727static void __exit sd_mod_exit(void)
728{
729 usb_deregister(&sd_driver);
730 PDEBUG(D_PROBE, "deregistered");
731}
732
733module_init(sd_mod_init);
734module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
new file mode 100644
index 00000000000..9d0b46027b9
--- /dev/null
+++ b/drivers/media/video/gspca/spca508.c
@@ -0,0 +1,1556 @@
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 MODULE_NAME "spca508"
22
23#include "gspca.h"
24
25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26MODULE_DESCRIPTION("GSPCA/SPCA508 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 brightness;
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
44/* V4L2 controls supported by the driver */
45static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
46static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
47
48static const struct ctrl sd_ctrls[] = {
49 {
50 {
51 .id = V4L2_CID_BRIGHTNESS,
52 .type = V4L2_CTRL_TYPE_INTEGER,
53 .name = "Brightness",
54 .minimum = 0,
55 .maximum = 255,
56 .step = 1,
57#define BRIGHTNESS_DEF 128
58 .default_value = BRIGHTNESS_DEF,
59 },
60 .set = sd_setbrightness,
61 .get = sd_getbrightness,
62 },
63};
64
65static const struct v4l2_pix_format sif_mode[] = {
66 {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
67 .bytesperline = 160,
68 .sizeimage = 160 * 120 * 3 / 2,
69 .colorspace = V4L2_COLORSPACE_SRGB,
70 .priv = 3},
71 {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
72 .bytesperline = 176,
73 .sizeimage = 176 * 144 * 3 / 2,
74 .colorspace = V4L2_COLORSPACE_SRGB,
75 .priv = 2},
76 {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
77 .bytesperline = 320,
78 .sizeimage = 320 * 240 * 3 / 2,
79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .priv = 1},
81 {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
82 .bytesperline = 352,
83 .sizeimage = 352 * 288 * 3 / 2,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0},
86};
87
88/* Frame packet header offsets for the spca508 */
89#define SPCA508_OFFSET_DATA 37
90
91/*
92 * Initialization data: this is the first set-up data written to the
93 * device (before the open data).
94 */
95static const u16 spca508_init_data[][2] = {
96 {0x0000, 0x870b},
97
98 {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */
99 {0x0003, 0x8111}, /* Reset compression & memory */
100 {0x0000, 0x8110}, /* Disable all outputs */
101 /* READ {0x0000, 0x8114} -> 0000: 00 */
102 {0x0000, 0x8114}, /* SW GPIO data */
103 {0x0008, 0x8110}, /* Enable charge pump output */
104 {0x0002, 0x8116}, /* 200 kHz pump clock */
105 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
106 {0x0003, 0x8111}, /* Reset compression & memory */
107 {0x0000, 0x8111}, /* Normal mode (not reset) */
108 {0x0098, 0x8110},
109 /* Enable charge pump output, sync.serial,external 2x clock */
110 {0x000d, 0x8114}, /* SW GPIO data */
111 {0x0002, 0x8116}, /* 200 kHz pump clock */
112 {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */
113/* --------------------------------------- */
114 {0x000f, 0x8402}, /* memory bank */
115 {0x0000, 0x8403}, /* ... address */
116/* --------------------------------------- */
117/* 0x88__ is Synchronous Serial Interface. */
118/* TBD: This table could be expressed more compactly */
119/* using spca508_write_i2c_vector(). */
120/* TBD: Should see if the values in spca50x_i2c_data */
121/* would work with the VQ110 instead of the values */
122/* below. */
123 {0x00c0, 0x8804}, /* SSI slave addr */
124 {0x0008, 0x8802}, /* 375 Khz SSI clock */
125 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
126 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
127 {0x0008, 0x8802}, /* 375 Khz SSI clock */
128 {0x0012, 0x8801}, /* SSI reg addr */
129 {0x0080, 0x8800}, /* SSI data to write */
130 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
131 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
132 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
133 {0x0008, 0x8802}, /* 375 Khz SSI clock */
134 {0x0012, 0x8801}, /* SSI reg addr */
135 {0x0000, 0x8800}, /* SSI data to write */
136 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
137 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
138 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
139 {0x0008, 0x8802}, /* 375 Khz SSI clock */
140 {0x0011, 0x8801}, /* SSI reg addr */
141 {0x0040, 0x8800}, /* SSI data to write */
142 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
143 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
144 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
145 {0x0008, 0x8802},
146 {0x0013, 0x8801},
147 {0x0000, 0x8800},
148 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
149 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
150 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
151 {0x0008, 0x8802},
152 {0x0014, 0x8801},
153 {0x0000, 0x8800},
154 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
155 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
156 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
157 {0x0008, 0x8802},
158 {0x0015, 0x8801},
159 {0x0001, 0x8800},
160 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
161 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
162 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
163 {0x0008, 0x8802},
164 {0x0016, 0x8801},
165 {0x0003, 0x8800},
166 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
167 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
168 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
169 {0x0008, 0x8802},
170 {0x0017, 0x8801},
171 {0x0036, 0x8800},
172 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
173 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
174 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
175 {0x0008, 0x8802},
176 {0x0018, 0x8801},
177 {0x00ec, 0x8800},
178 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
179 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
180 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
181 {0x0008, 0x8802},
182 {0x001a, 0x8801},
183 {0x0094, 0x8800},
184 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
185 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
186 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
187 {0x0008, 0x8802},
188 {0x001b, 0x8801},
189 {0x0000, 0x8800},
190 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
191 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
192 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
193 {0x0008, 0x8802},
194 {0x0027, 0x8801},
195 {0x00a2, 0x8800},
196 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
197 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
198 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
199 {0x0008, 0x8802},
200 {0x0028, 0x8801},
201 {0x0040, 0x8800},
202 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
203 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
204 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
205 {0x0008, 0x8802},
206 {0x002a, 0x8801},
207 {0x0084, 0x8800},
208 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
209 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
210 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
211 {0x0008, 0x8802},
212 {0x002b, 0x8801},
213 {0x00a8, 0x8800},
214 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
215 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
216 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
217 {0x0008, 0x8802},
218 {0x002c, 0x8801},
219 {0x00fe, 0x8800},
220 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
221 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
222 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
223 {0x0008, 0x8802},
224 {0x002d, 0x8801},
225 {0x0003, 0x8800},
226 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
227 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
228 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
229 {0x0008, 0x8802},
230 {0x0038, 0x8801},
231 {0x0083, 0x8800},
232 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
233 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
234 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
235 {0x0008, 0x8802},
236 {0x0033, 0x8801},
237 {0x0081, 0x8800},
238 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
239 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
240 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
241 {0x0008, 0x8802},
242 {0x0034, 0x8801},
243 {0x004a, 0x8800},
244 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
245 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
246 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
247 {0x0008, 0x8802},
248 {0x0039, 0x8801},
249 {0x0000, 0x8800},
250 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
251 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
252 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
253 {0x0008, 0x8802},
254 {0x0010, 0x8801},
255 {0x00a8, 0x8800},
256 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
257 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
258 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
259 {0x0008, 0x8802},
260 {0x0006, 0x8801},
261 {0x0058, 0x8800},
262 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
263 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
264 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
265 {0x0008, 0x8802},
266 {0x0000, 0x8801},
267 {0x0004, 0x8800},
268 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
269 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
270 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
271 {0x0008, 0x8802},
272 {0x0040, 0x8801},
273 {0x0080, 0x8800},
274 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
275 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
276 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
277 {0x0008, 0x8802},
278 {0x0041, 0x8801},
279 {0x000c, 0x8800},
280 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
281 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
282 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
283 {0x0008, 0x8802},
284 {0x0042, 0x8801},
285 {0x000c, 0x8800},
286 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
287 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
288 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
289 {0x0008, 0x8802},
290 {0x0043, 0x8801},
291 {0x0028, 0x8800},
292 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
293 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
294 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
295 {0x0008, 0x8802},
296 {0x0044, 0x8801},
297 {0x0080, 0x8800},
298 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
299 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
300 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
301 {0x0008, 0x8802},
302 {0x0045, 0x8801},
303 {0x0020, 0x8800},
304 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
305 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
306 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
307 {0x0008, 0x8802},
308 {0x0046, 0x8801},
309 {0x0020, 0x8800},
310 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
311 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
312 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
313 {0x0008, 0x8802},
314 {0x0047, 0x8801},
315 {0x0080, 0x8800},
316 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
317 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
318 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
319 {0x0008, 0x8802},
320 {0x0048, 0x8801},
321 {0x004c, 0x8800},
322 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
323 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
324 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
325 {0x0008, 0x8802},
326 {0x0049, 0x8801},
327 {0x0084, 0x8800},
328 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
329 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
330 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
331 {0x0008, 0x8802},
332 {0x004a, 0x8801},
333 {0x0084, 0x8800},
334 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
335 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
336 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
337 {0x0008, 0x8802},
338 {0x004b, 0x8801},
339 {0x0084, 0x8800},
340 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
341 /* --------------------------------------- */
342 {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
343 {0x0000, 0x8701}, /* CKx1 clock delay adj */
344 {0x0000, 0x8701}, /* CKx1 clock delay adj */
345 {0x0001, 0x870c}, /* CKOx2 output */
346 /* --------------------------------------- */
347 {0x0080, 0x8600}, /* Line memory read counter (L) */
348 {0x0001, 0x8606}, /* reserved */
349 {0x0064, 0x8607}, /* Line memory read counter (H) 0x6480=25,728 */
350 {0x002a, 0x8601}, /* CDSP sharp interpolation mode,
351 * line sel for color sep, edge enhance enab */
352 {0x0000, 0x8602}, /* optical black level for user settng = 0 */
353 {0x0080, 0x8600}, /* Line memory read counter (L) */
354 {0x000a, 0x8603}, /* optical black level calc mode:
355 * auto; optical black offset = 10 */
356 {0x00df, 0x865b}, /* Horiz offset for valid pixels (L)=0xdf */
357 {0x0012, 0x865c}, /* Vert offset for valid lines (L)=0x12 */
358
359/* The following two lines seem to be the "wrong" resolution. */
360/* But perhaps these indicate the actual size of the sensor */
361/* rather than the size of the current video mode. */
362 {0x0058, 0x865d}, /* Horiz valid pixels (*4) (L) = 352 */
363 {0x0048, 0x865e}, /* Vert valid lines (*4) (L) = 288 */
364
365 {0x0015, 0x8608}, /* A11 Coef ... */
366 {0x0030, 0x8609},
367 {0x00fb, 0x860a},
368 {0x003e, 0x860b},
369 {0x00ce, 0x860c},
370 {0x00f4, 0x860d},
371 {0x00eb, 0x860e},
372 {0x00dc, 0x860f},
373 {0x0039, 0x8610},
374 {0x0001, 0x8611}, /* R offset for white balance ... */
375 {0x0000, 0x8612},
376 {0x0001, 0x8613},
377 {0x0000, 0x8614},
378 {0x005b, 0x8651}, /* R gain for white balance ... */
379 {0x0040, 0x8652},
380 {0x0060, 0x8653},
381 {0x0040, 0x8654},
382 {0x0000, 0x8655},
383 {0x0001, 0x863f}, /* Fixed gamma correction enable, USB control,
384 * lum filter disable, lum noise clip disable */
385 {0x00a1, 0x8656}, /* Window1 size 256x256, Windows2 size 64x64,
386 * gamma look-up disable,
387 * new edge enhancement enable */
388 {0x0018, 0x8657}, /* Edge gain high thresh */
389 {0x0020, 0x8658}, /* Edge gain low thresh */
390 {0x000a, 0x8659}, /* Edge bandwidth high threshold */
391 {0x0005, 0x865a}, /* Edge bandwidth low threshold */
392 /* -------------------------------- */
393 {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */
394 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
395 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
396 {0xa908, 0x8802},
397 {0x0034, 0x8801}, /* SSI reg addr */
398 {0x00ca, 0x8800},
399 /* SSI data to write */
400 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
401 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
402 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
403 {0x1f08, 0x8802},
404 {0x0006, 0x8801},
405 {0x0080, 0x8800},
406 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
407
408/* ----- Read back coefs we wrote earlier. */
409 /* READ { 0x0000, 0x8608 } -> 0000: 15 */
410 /* READ { 0x0000, 0x8609 } -> 0000: 30 */
411 /* READ { 0x0000, 0x860a } -> 0000: fb */
412 /* READ { 0x0000, 0x860b } -> 0000: 3e */
413 /* READ { 0x0000, 0x860c } -> 0000: ce */
414 /* READ { 0x0000, 0x860d } -> 0000: f4 */
415 /* READ { 0x0000, 0x860e } -> 0000: eb */
416 /* READ { 0x0000, 0x860f } -> 0000: dc */
417 /* READ { 0x0000, 0x8610 } -> 0000: 39 */
418 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
419 /* READ { 0x0001, 0x8802 } -> 0000: 08 */
420 {0xb008, 0x8802},
421 {0x0006, 0x8801},
422 {0x007d, 0x8800},
423 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
424
425
426 /* This chunk is seemingly redundant with */
427 /* earlier commands (A11 Coef...), but if I disable it, */
428 /* the image appears too dark. Maybe there was some kind of */
429 /* reset since the earlier commands, so this is necessary again. */
430 {0x0015, 0x8608},
431 {0x0030, 0x8609},
432 {0xfffb, 0x860a},
433 {0x003e, 0x860b},
434 {0xffce, 0x860c},
435 {0xfff4, 0x860d},
436 {0xffeb, 0x860e},
437 {0xffdc, 0x860f},
438 {0x0039, 0x8610},
439 {0x0018, 0x8657},
440
441 {0x0000, 0x8508}, /* Disable compression. */
442 /* Previous line was:
443 {0x0021, 0x8508}, * Enable compression. */
444 {0x0032, 0x850b}, /* compression stuff */
445 {0x0003, 0x8509}, /* compression stuff */
446 {0x0011, 0x850a}, /* compression stuff */
447 {0x0021, 0x850d}, /* compression stuff */
448 {0x0010, 0x850c}, /* compression stuff */
449 {0x0003, 0x8500}, /* *** Video mode: 160x120 */
450 {0x0001, 0x8501}, /* Hardware-dominated snap control */
451 {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128,
452 * gamma look-up disable,
453 * new edge enhancement enable */
454 {0x0018, 0x8617}, /* Window1 start X (*2) */
455 {0x0008, 0x8618}, /* Window1 start Y (*2) */
456 {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128,
457 * gamma look-up disable,
458 * new edge enhancement enable */
459 {0x0058, 0x8619}, /* Window2 start X (*2) */
460 {0x0008, 0x861a}, /* Window2 start Y (*2) */
461 {0x00ff, 0x8615}, /* High lum thresh for white balance */
462 {0x0000, 0x8616}, /* Low lum thresh for white balance */
463 {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
464 {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
465 /* READ { 0x0000, 0x8656 } -> 0000: 61 */
466 {0x0028, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
467 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
468 /* READ { 0x0001, 0x8802 } -> 0000: 28 */
469 {0x1f28, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
470 {0x0010, 0x8801}, /* SSI reg addr */
471 {0x003e, 0x8800}, /* SSI data to write */
472 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
473 {0x0028, 0x8802},
474 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
475 /* READ { 0x0001, 0x8802 } -> 0000: 28 */
476 {0x1f28, 0x8802},
477 {0x0000, 0x8801},
478 {0x001f, 0x8800},
479 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
480 {0x0001, 0x8602}, /* optical black level for user settning = 1 */
481
482 /* Original: */
483 {0x0023, 0x8700}, /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
484 {0x000f, 0x8602}, /* optical black level for user settning = 15 */
485
486 {0x0028, 0x8802},
487 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
488 /* READ { 0x0001, 0x8802 } -> 0000: 28 */
489 {0x1f28, 0x8802},
490 {0x0010, 0x8801},
491 {0x007b, 0x8800},
492 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
493 {0x002f, 0x8651}, /* R gain for white balance ... */
494 {0x0080, 0x8653},
495 /* READ { 0x0000, 0x8655 } -> 0000: 00 */
496 {0x0000, 0x8655},
497
498 {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */
499 {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */
500 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
501 {}
502};
503
504/*
505 * Initialization data for Intel EasyPC Camera CS110
506 */
507static const u16 spca508cs110_init_data[][2] = {
508 {0x0000, 0x870b}, /* Reset CTL3 */
509 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
510 {0x0000, 0x8111}, /* Normal operation on reset */
511 {0x0090, 0x8110},
512 /* External Clock 2x & Synchronous Serial Interface Output */
513 {0x0020, 0x8112}, /* Video Drop packet enable */
514 {0x0000, 0x8114}, /* Software GPIO output data */
515 {0x0001, 0x8114},
516 {0x0001, 0x8114},
517 {0x0001, 0x8114},
518 {0x0003, 0x8114},
519
520 /* Initial sequence Synchronous Serial Interface */
521 {0x000f, 0x8402}, /* Memory bank Address */
522 {0x0000, 0x8403}, /* Memory bank Address */
523 {0x00ba, 0x8804}, /* SSI Slave address */
524 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
525 {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */
526
527 {0x0001, 0x8801},
528 {0x000a, 0x8805}, /* a - NWG: Dunno what this is about */
529 {0x0000, 0x8800},
530 {0x0010, 0x8802},
531
532 {0x0002, 0x8801},
533 {0x0000, 0x8805},
534 {0x0000, 0x8800},
535 {0x0010, 0x8802},
536
537 {0x0003, 0x8801},
538 {0x0027, 0x8805},
539 {0x0001, 0x8800},
540 {0x0010, 0x8802},
541
542 {0x0004, 0x8801},
543 {0x0065, 0x8805},
544 {0x0001, 0x8800},
545 {0x0010, 0x8802},
546
547 {0x0005, 0x8801},
548 {0x0003, 0x8805},
549 {0x0000, 0x8800},
550 {0x0010, 0x8802},
551
552 {0x0006, 0x8801},
553 {0x001c, 0x8805},
554 {0x0000, 0x8800},
555 {0x0010, 0x8802},
556
557 {0x0007, 0x8801},
558 {0x002a, 0x8805},
559 {0x0000, 0x8800},
560 {0x0010, 0x8802},
561
562 {0x0002, 0x8704}, /* External input CKIx1 */
563 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
564 {0x009a, 0x8600}, /* Line memory Read Counter (L) */
565 {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
566 {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */
567 {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */
568
569 {0x0006, 0x8660}, /* Nibble data + input order */
570
571 {0x000a, 0x8602}, /* Optical black level set to 0x0a */
572 {0x0000, 0x8603}, /* Optical black level Offset */
573
574/* {0x0000, 0x8611}, * 0 R Offset for white Balance */
575/* {0x0000, 0x8612}, * 1 Gr Offset for white Balance */
576/* {0x0000, 0x8613}, * 1f B Offset for white Balance */
577/* {0x0000, 0x8614}, * f0 Gb Offset for white Balance */
578
579 {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */
580 {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */
581 {0x0035, 0x8653}, /* 26 RED gain for white balance */
582 {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */
583 {0x0041, 0x863f},
584 /* Fixed Gamma correction enabled (makes colours look better) */
585
586 {0x0000, 0x8655},
587 /* High bits for white balance*****brightness control*** */
588 {}
589};
590
591static const u16 spca508_sightcam_init_data[][2] = {
592/* This line seems to setup the frame/canvas */
593 {0x000f, 0x8402},
594
595/* These 6 lines are needed to startup the webcam */
596 {0x0090, 0x8110},
597 {0x0001, 0x8114},
598 {0x0001, 0x8114},
599 {0x0001, 0x8114},
600 {0x0003, 0x8114},
601 {0x0080, 0x8804},
602
603/* This part seems to make the pictures darker? (autobrightness?) */
604 {0x0001, 0x8801},
605 {0x0004, 0x8800},
606 {0x0003, 0x8801},
607 {0x00e0, 0x8800},
608 {0x0004, 0x8801},
609 {0x00b4, 0x8800},
610 {0x0005, 0x8801},
611 {0x0000, 0x8800},
612
613 {0x0006, 0x8801},
614 {0x00e0, 0x8800},
615 {0x0007, 0x8801},
616 {0x000c, 0x8800},
617
618/* This section is just needed, it probably
619 * does something like the previous section,
620 * but the cam won't start if it's not included.
621 */
622 {0x0014, 0x8801},
623 {0x0008, 0x8800},
624 {0x0015, 0x8801},
625 {0x0067, 0x8800},
626 {0x0016, 0x8801},
627 {0x0000, 0x8800},
628 {0x0017, 0x8801},
629 {0x0020, 0x8800},
630 {0x0018, 0x8801},
631 {0x0044, 0x8800},
632
633/* Makes the picture darker - and the
634 * cam won't start if not included
635 */
636 {0x001e, 0x8801},
637 {0x00ea, 0x8800},
638 {0x001f, 0x8801},
639 {0x0001, 0x8800},
640 {0x0003, 0x8801},
641 {0x00e0, 0x8800},
642
643/* seems to place the colors ontop of each other #1 */
644 {0x0006, 0x8704},
645 {0x0001, 0x870c},
646 {0x0016, 0x8600},
647 {0x0002, 0x8606},
648
649/* if not included the pictures becomes _very_ dark */
650 {0x0064, 0x8607},
651 {0x003a, 0x8601},
652 {0x0000, 0x8602},
653
654/* seems to place the colors ontop of each other #2 */
655 {0x0016, 0x8600},
656 {0x0018, 0x8617},
657 {0x0008, 0x8618},
658 {0x00a1, 0x8656},
659
660/* webcam won't start if not included */
661 {0x0007, 0x865b},
662 {0x0001, 0x865c},
663 {0x0058, 0x865d},
664 {0x0048, 0x865e},
665
666/* adjusts the colors */
667 {0x0049, 0x8651},
668 {0x0040, 0x8652},
669 {0x004c, 0x8653},
670 {0x0040, 0x8654},
671 {}
672};
673
674static const u16 spca508_sightcam2_init_data[][2] = {
675 {0x0020, 0x8112},
676
677 {0x000f, 0x8402},
678 {0x0000, 0x8403},
679
680 {0x0008, 0x8201},
681 {0x0008, 0x8200},
682 {0x0001, 0x8200},
683 {0x0009, 0x8201},
684 {0x0008, 0x8200},
685 {0x0001, 0x8200},
686 {0x000a, 0x8201},
687 {0x0008, 0x8200},
688 {0x0001, 0x8200},
689 {0x000b, 0x8201},
690 {0x0008, 0x8200},
691 {0x0001, 0x8200},
692 {0x000c, 0x8201},
693 {0x0008, 0x8200},
694 {0x0001, 0x8200},
695 {0x000d, 0x8201},
696 {0x0008, 0x8200},
697 {0x0001, 0x8200},
698 {0x000e, 0x8201},
699 {0x0008, 0x8200},
700 {0x0001, 0x8200},
701 {0x0007, 0x8201},
702 {0x0008, 0x8200},
703 {0x0001, 0x8200},
704 {0x000f, 0x8201},
705 {0x0008, 0x8200},
706 {0x0001, 0x8200},
707
708 {0x0018, 0x8660},
709 {0x0010, 0x8201},
710
711 {0x0008, 0x8200},
712 {0x0001, 0x8200},
713 {0x0011, 0x8201},
714 {0x0008, 0x8200},
715 {0x0001, 0x8200},
716
717 {0x0000, 0x86b0},
718 {0x0034, 0x86b1},
719 {0x0000, 0x86b2},
720 {0x0049, 0x86b3},
721 {0x0000, 0x86b4},
722 {0x0000, 0x86b4},
723
724 {0x0012, 0x8201},
725 {0x0008, 0x8200},
726 {0x0001, 0x8200},
727 {0x0013, 0x8201},
728 {0x0008, 0x8200},
729 {0x0001, 0x8200},
730
731 {0x0001, 0x86b0},
732 {0x00aa, 0x86b1},
733 {0x0000, 0x86b2},
734 {0x00e4, 0x86b3},
735 {0x0000, 0x86b4},
736 {0x0000, 0x86b4},
737
738 {0x0018, 0x8660},
739
740 {0x0090, 0x8110},
741 {0x0001, 0x8114},
742 {0x0001, 0x8114},
743 {0x0001, 0x8114},
744 {0x0003, 0x8114},
745
746 {0x0080, 0x8804},
747 {0x0003, 0x8801},
748 {0x0012, 0x8800},
749 {0x0004, 0x8801},
750 {0x0005, 0x8800},
751 {0x0005, 0x8801},
752 {0x0000, 0x8800},
753 {0x0006, 0x8801},
754 {0x0000, 0x8800},
755 {0x0007, 0x8801},
756 {0x0000, 0x8800},
757 {0x0008, 0x8801},
758 {0x0005, 0x8800},
759 {0x000a, 0x8700},
760 {0x000e, 0x8801},
761 {0x0004, 0x8800},
762 {0x0005, 0x8801},
763 {0x0047, 0x8800},
764 {0x0006, 0x8801},
765 {0x0000, 0x8800},
766 {0x0007, 0x8801},
767 {0x00c0, 0x8800},
768 {0x0008, 0x8801},
769 {0x0003, 0x8800},
770 {0x0013, 0x8801},
771 {0x0001, 0x8800},
772 {0x0009, 0x8801},
773 {0x0000, 0x8800},
774 {0x000a, 0x8801},
775 {0x0000, 0x8800},
776 {0x000b, 0x8801},
777 {0x0000, 0x8800},
778 {0x000c, 0x8801},
779 {0x0000, 0x8800},
780 {0x000e, 0x8801},
781 {0x0004, 0x8800},
782 {0x000f, 0x8801},
783 {0x0000, 0x8800},
784 {0x0010, 0x8801},
785 {0x0006, 0x8800},
786 {0x0011, 0x8801},
787 {0x0006, 0x8800},
788 {0x0012, 0x8801},
789 {0x0000, 0x8800},
790 {0x0013, 0x8801},
791 {0x0001, 0x8800},
792
793 {0x000a, 0x8700},
794 {0x0000, 0x8702},
795 {0x0000, 0x8703},
796 {0x00c2, 0x8704},
797 {0x0001, 0x870c},
798
799 {0x0044, 0x8600},
800 {0x0002, 0x8606},
801 {0x0064, 0x8607},
802 {0x003a, 0x8601},
803 {0x0008, 0x8602},
804 {0x0044, 0x8600},
805 {0x0018, 0x8617},
806 {0x0008, 0x8618},
807 {0x00a1, 0x8656},
808 {0x0004, 0x865b},
809 {0x0002, 0x865c},
810 {0x0058, 0x865d},
811 {0x0048, 0x865e},
812 {0x0012, 0x8608},
813 {0x002c, 0x8609},
814 {0x0002, 0x860a},
815 {0x002c, 0x860b},
816 {0x00db, 0x860c},
817 {0x00f9, 0x860d},
818 {0x00f1, 0x860e},
819 {0x00e3, 0x860f},
820 {0x002c, 0x8610},
821 {0x006c, 0x8651},
822 {0x0041, 0x8652},
823 {0x0059, 0x8653},
824 {0x0040, 0x8654},
825 {0x00fa, 0x8611},
826 {0x00ff, 0x8612},
827 {0x00f8, 0x8613},
828 {0x0000, 0x8614},
829 {0x0001, 0x863f},
830 {0x0000, 0x8640},
831 {0x0026, 0x8641},
832 {0x0045, 0x8642},
833 {0x0060, 0x8643},
834 {0x0075, 0x8644},
835 {0x0088, 0x8645},
836 {0x009b, 0x8646},
837 {0x00b0, 0x8647},
838 {0x00c5, 0x8648},
839 {0x00d2, 0x8649},
840 {0x00dc, 0x864a},
841 {0x00e5, 0x864b},
842 {0x00eb, 0x864c},
843 {0x00f0, 0x864d},
844 {0x00f6, 0x864e},
845 {0x00fa, 0x864f},
846 {0x00ff, 0x8650},
847 {0x0060, 0x8657},
848 {0x0010, 0x8658},
849 {0x0018, 0x8659},
850 {0x0005, 0x865a},
851 {0x0018, 0x8660},
852 {0x0003, 0x8509},
853 {0x0011, 0x850a},
854 {0x0032, 0x850b},
855 {0x0010, 0x850c},
856 {0x0021, 0x850d},
857 {0x0001, 0x8500},
858 {0x0000, 0x8508},
859 {0x0012, 0x8608},
860 {0x002c, 0x8609},
861 {0x0002, 0x860a},
862 {0x0039, 0x860b},
863 {0x00d0, 0x860c},
864 {0x00f7, 0x860d},
865 {0x00ed, 0x860e},
866 {0x00db, 0x860f},
867 {0x0039, 0x8610},
868 {0x0012, 0x8657},
869 {0x000c, 0x8619},
870 {0x0004, 0x861a},
871 {0x00a1, 0x8656},
872 {0x00c8, 0x8615},
873 {0x0032, 0x8616},
874
875 {0x0030, 0x8112},
876 {0x0020, 0x8112},
877 {0x0020, 0x8112},
878 {0x000f, 0x8402},
879 {0x0000, 0x8403},
880
881 {0x0090, 0x8110},
882 {0x0001, 0x8114},
883 {0x0001, 0x8114},
884 {0x0001, 0x8114},
885 {0x0003, 0x8114},
886 {0x0080, 0x8804},
887
888 {0x0003, 0x8801},
889 {0x0012, 0x8800},
890 {0x0004, 0x8801},
891 {0x0005, 0x8800},
892 {0x0005, 0x8801},
893 {0x0047, 0x8800},
894 {0x0006, 0x8801},
895 {0x0000, 0x8800},
896 {0x0007, 0x8801},
897 {0x00c0, 0x8800},
898 {0x0008, 0x8801},
899 {0x0003, 0x8800},
900 {0x000a, 0x8700},
901 {0x000e, 0x8801},
902 {0x0004, 0x8800},
903 {0x0005, 0x8801},
904 {0x0047, 0x8800},
905 {0x0006, 0x8801},
906 {0x0000, 0x8800},
907 {0x0007, 0x8801},
908 {0x00c0, 0x8800},
909 {0x0008, 0x8801},
910 {0x0003, 0x8800},
911 {0x0013, 0x8801},
912 {0x0001, 0x8800},
913 {0x0009, 0x8801},
914 {0x0000, 0x8800},
915 {0x000a, 0x8801},
916 {0x0000, 0x8800},
917 {0x000b, 0x8801},
918 {0x0000, 0x8800},
919 {0x000c, 0x8801},
920 {0x0000, 0x8800},
921 {0x000e, 0x8801},
922 {0x0004, 0x8800},
923 {0x000f, 0x8801},
924 {0x0000, 0x8800},
925 {0x0010, 0x8801},
926 {0x0006, 0x8800},
927 {0x0011, 0x8801},
928 {0x0006, 0x8800},
929 {0x0012, 0x8801},
930 {0x0000, 0x8800},
931 {0x0013, 0x8801},
932 {0x0001, 0x8800},
933 {0x000a, 0x8700},
934 {0x0000, 0x8702},
935 {0x0000, 0x8703},
936 {0x00c2, 0x8704},
937 {0x0001, 0x870c},
938 {0x0044, 0x8600},
939 {0x0002, 0x8606},
940 {0x0064, 0x8607},
941 {0x003a, 0x8601},
942 {0x0008, 0x8602},
943 {0x0044, 0x8600},
944 {0x0018, 0x8617},
945 {0x0008, 0x8618},
946 {0x00a1, 0x8656},
947 {0x0004, 0x865b},
948 {0x0002, 0x865c},
949 {0x0058, 0x865d},
950 {0x0048, 0x865e},
951 {0x0012, 0x8608},
952 {0x002c, 0x8609},
953 {0x0002, 0x860a},
954 {0x002c, 0x860b},
955 {0x00db, 0x860c},
956 {0x00f9, 0x860d},
957 {0x00f1, 0x860e},
958 {0x00e3, 0x860f},
959 {0x002c, 0x8610},
960 {0x006c, 0x8651},
961 {0x0041, 0x8652},
962 {0x0059, 0x8653},
963 {0x0040, 0x8654},
964 {0x00fa, 0x8611},
965 {0x00ff, 0x8612},
966 {0x00f8, 0x8613},
967 {0x0000, 0x8614},
968 {0x0001, 0x863f},
969 {0x0000, 0x8640},
970 {0x0026, 0x8641},
971 {0x0045, 0x8642},
972 {0x0060, 0x8643},
973 {0x0075, 0x8644},
974 {0x0088, 0x8645},
975 {0x009b, 0x8646},
976 {0x00b0, 0x8647},
977 {0x00c5, 0x8648},
978 {0x00d2, 0x8649},
979 {0x00dc, 0x864a},
980 {0x00e5, 0x864b},
981 {0x00eb, 0x864c},
982 {0x00f0, 0x864d},
983 {0x00f6, 0x864e},
984 {0x00fa, 0x864f},
985 {0x00ff, 0x8650},
986 {0x0060, 0x8657},
987 {0x0010, 0x8658},
988 {0x0018, 0x8659},
989 {0x0005, 0x865a},
990 {0x0018, 0x8660},
991 {0x0003, 0x8509},
992 {0x0011, 0x850a},
993 {0x0032, 0x850b},
994 {0x0010, 0x850c},
995 {0x0021, 0x850d},
996 {0x0001, 0x8500},
997 {0x0000, 0x8508},
998
999 {0x0012, 0x8608},
1000 {0x002c, 0x8609},
1001 {0x0002, 0x860a},
1002 {0x0039, 0x860b},
1003 {0x00d0, 0x860c},
1004 {0x00f7, 0x860d},
1005 {0x00ed, 0x860e},
1006 {0x00db, 0x860f},
1007 {0x0039, 0x8610},
1008 {0x0012, 0x8657},
1009 {0x0064, 0x8619},
1010
1011/* This line starts it all, it is not needed here */
1012/* since it has been build into the driver */
1013/* jfm: don't start now */
1014/* {0x0030, 0x8112}, */
1015 {}
1016};
1017
1018/*
1019 * Initialization data for Creative Webcam Vista
1020 */
1021static const u16 spca508_vista_init_data[][2] = {
1022 {0x0008, 0x8200}, /* Clear register */
1023 {0x0000, 0x870b}, /* Reset CTL3 */
1024 {0x0020, 0x8112}, /* Video Drop packet enable */
1025 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
1026 {0x0000, 0x8110}, /* Disable everything */
1027 {0x0000, 0x8114}, /* Software GPIO output data */
1028 {0x0000, 0x8114},
1029
1030 {0x0003, 0x8111},
1031 {0x0000, 0x8111},
1032 {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */
1033 {0x0020, 0x8112},
1034 {0x0000, 0x8114},
1035 {0x0001, 0x8114},
1036 {0x0001, 0x8114},
1037 {0x0001, 0x8114},
1038 {0x0003, 0x8114},
1039
1040 {0x000f, 0x8402}, /* Memory bank Address */
1041 {0x0000, 0x8403}, /* Memory bank Address */
1042 {0x00ba, 0x8804}, /* SSI Slave address */
1043 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
1044
1045 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1046 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1047 {0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */
1048 {0x0020, 0x8801}, /* Register address for SSI read/write */
1049 {0x0044, 0x8805}, /* DATA2 */
1050 {0x0004, 0x8800}, /* DATA1 -> write triggered */
1051 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1052
1053 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1054 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1055 {0x0010, 0x8802},
1056 {0x0009, 0x8801},
1057 {0x0042, 0x8805},
1058 {0x0001, 0x8800},
1059 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1060
1061 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1062 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1063 {0x0010, 0x8802},
1064 {0x003c, 0x8801},
1065 {0x0001, 0x8805},
1066 {0x0000, 0x8800},
1067 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1068
1069 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1070 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1071 {0x0010, 0x8802},
1072 {0x0001, 0x8801},
1073 {0x000a, 0x8805},
1074 {0x0000, 0x8800},
1075 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1076
1077 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1078 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1079 {0x0010, 0x8802},
1080 {0x0002, 0x8801},
1081 {0x0000, 0x8805},
1082 {0x0000, 0x8800},
1083 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1084
1085 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1086 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1087 {0x0010, 0x8802},
1088 {0x0003, 0x8801},
1089 {0x0027, 0x8805},
1090 {0x0001, 0x8800},
1091 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1092
1093 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1094 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1095 {0x0010, 0x8802},
1096 {0x0004, 0x8801},
1097 {0x0065, 0x8805},
1098 {0x0001, 0x8800},
1099 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1100
1101 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1102 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1103 {0x0010, 0x8802},
1104 {0x0005, 0x8801},
1105 {0x0003, 0x8805},
1106 {0x0000, 0x8800},
1107 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1108
1109 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1110 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1111 {0x0010, 0x8802},
1112 {0x0006, 0x8801},
1113 {0x001c, 0x8805},
1114 {0x0000, 0x8800},
1115 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1116
1117 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1118 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1119 {0x0010, 0x8802},
1120 {0x0007, 0x8801},
1121 {0x002a, 0x8805},
1122 {0x0000, 0x8800},
1123 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1124
1125 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1126 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1127 {0x0010, 0x8802},
1128 {0x000e, 0x8801},
1129 {0x0000, 0x8805},
1130 {0x0000, 0x8800},
1131 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1132
1133 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1134 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1135 {0x0010, 0x8802},
1136 {0x0028, 0x8801},
1137 {0x002e, 0x8805},
1138 {0x0000, 0x8800},
1139 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1140
1141 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1142 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1143 {0x0010, 0x8802},
1144 {0x0039, 0x8801},
1145 {0x0013, 0x8805},
1146 {0x0000, 0x8800},
1147 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1148
1149 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1150 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1151 {0x0010, 0x8802},
1152 {0x003b, 0x8801},
1153 {0x000c, 0x8805},
1154 {0x0000, 0x8800},
1155 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1156
1157 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1158 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1159 {0x0010, 0x8802},
1160 {0x0035, 0x8801},
1161 {0x0028, 0x8805},
1162 {0x0000, 0x8800},
1163 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1164
1165 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1166 /* READ { 0x0001, 0x8802 } -> 0000: 10 */
1167 {0x0010, 0x8802},
1168 {0x0009, 0x8801},
1169 {0x0042, 0x8805},
1170 {0x0001, 0x8800},
1171 /* READ { 0x0001, 0x8803 } -> 0000: 00 */
1172
1173 {0x0050, 0x8703},
1174 {0x0002, 0x8704}, /* External input CKIx1 */
1175 {0x0001, 0x870c}, /* Select CKOx2 output */
1176 {0x009a, 0x8600}, /* Line memory Read Counter (L) */
1177 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
1178 {0x0023, 0x8601},
1179 {0x0010, 0x8602},
1180 {0x000a, 0x8603},
1181 {0x009a, 0x8600},
1182 {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
1183 {0x0003, 0x865c}, /* Vertical offset for valid lines (L) */
1184 {0x0058, 0x865d}, /* Horizontal valid pixels window (L) */
1185 {0x0048, 0x865e}, /* Vertical valid lines window (L) */
1186 {0x0000, 0x865f},
1187
1188 {0x0006, 0x8660},
1189 /* Enable nibble data input, select nibble input order */
1190
1191 {0x0013, 0x8608}, /* A11 Coeficients for color correction */
1192 {0x0028, 0x8609},
1193 /* Note: these values are confirmed at the end of array */
1194 {0x0005, 0x860a}, /* ... */
1195 {0x0025, 0x860b},
1196 {0x00e1, 0x860c},
1197 {0x00fa, 0x860d},
1198 {0x00f4, 0x860e},
1199 {0x00e8, 0x860f},
1200 {0x0025, 0x8610}, /* A33 Coef. */
1201 {0x00fc, 0x8611}, /* White balance offset: R */
1202 {0x0001, 0x8612}, /* White balance offset: Gr */
1203 {0x00fe, 0x8613}, /* White balance offset: B */
1204 {0x0000, 0x8614}, /* White balance offset: Gb */
1205
1206 {0x0064, 0x8651}, /* R gain for white balance (L) */
1207 {0x0040, 0x8652}, /* Gr gain for white balance (L) */
1208 {0x0066, 0x8653}, /* B gain for white balance (L) */
1209 {0x0040, 0x8654}, /* Gb gain for white balance (L) */
1210 {0x0001, 0x863f}, /* Enable fixed gamma correction */
1211
1212 {0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128,
1213 * UV division: UV no change,
1214 * Enable New edge enhancement */
1215 {0x0018, 0x8657}, /* Edge gain high threshold */
1216 {0x0020, 0x8658}, /* Edge gain low threshold */
1217 {0x000a, 0x8659}, /* Edge bandwidth high threshold */
1218 {0x0005, 0x865a}, /* Edge bandwidth low threshold */
1219 {0x0064, 0x8607}, /* UV filter enable */
1220
1221 {0x0016, 0x8660},
1222 {0x0000, 0x86b0}, /* Bad pixels compensation address */
1223 {0x00dc, 0x86b1}, /* X coord for bad pixels compensation (L) */
1224 {0x0000, 0x86b2},
1225 {0x0009, 0x86b3}, /* Y coord for bad pixels compensation (L) */
1226 {0x0000, 0x86b4},
1227
1228 {0x0001, 0x86b0},
1229 {0x00f5, 0x86b1},
1230 {0x0000, 0x86b2},
1231 {0x00c6, 0x86b3},
1232 {0x0000, 0x86b4},
1233
1234 {0x0002, 0x86b0},
1235 {0x001c, 0x86b1},
1236 {0x0001, 0x86b2},
1237 {0x00d7, 0x86b3},
1238 {0x0000, 0x86b4},
1239
1240 {0x0003, 0x86b0},
1241 {0x001c, 0x86b1},
1242 {0x0001, 0x86b2},
1243 {0x00d8, 0x86b3},
1244 {0x0000, 0x86b4},
1245
1246 {0x0004, 0x86b0},
1247 {0x001d, 0x86b1},
1248 {0x0001, 0x86b2},
1249 {0x00d8, 0x86b3},
1250 {0x0000, 0x86b4},
1251 {0x001e, 0x8660},
1252
1253 /* READ { 0x0000, 0x8608 } -> 0000: 13 */
1254 /* READ { 0x0000, 0x8609 } -> 0000: 28 */
1255 /* READ { 0x0000, 0x8610 } -> 0000: 05 */
1256 /* READ { 0x0000, 0x8611 } -> 0000: 25 */
1257 /* READ { 0x0000, 0x8612 } -> 0000: e1 */
1258 /* READ { 0x0000, 0x8613 } -> 0000: fa */
1259 /* READ { 0x0000, 0x8614 } -> 0000: f4 */
1260 /* READ { 0x0000, 0x8615 } -> 0000: e8 */
1261 /* READ { 0x0000, 0x8616 } -> 0000: 25 */
1262 {}
1263};
1264
1265static int reg_write(struct usb_device *dev,
1266 u16 index, u16 value)
1267{
1268 int ret;
1269
1270 ret = usb_control_msg(dev,
1271 usb_sndctrlpipe(dev, 0),
1272 0, /* request */
1273 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1274 value, index, NULL, 0, 500);
1275 PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
1276 index, value);
1277 if (ret < 0)
1278 err("reg write: error %d", ret);
1279 return ret;
1280}
1281
1282/* read 1 byte */
1283/* returns: negative is error, pos or zero is data */
1284static int reg_read(struct gspca_dev *gspca_dev,
1285 u16 index) /* wIndex */
1286{
1287 int ret;
1288
1289 ret = usb_control_msg(gspca_dev->dev,
1290 usb_rcvctrlpipe(gspca_dev->dev, 0),
1291 0, /* register */
1292 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1293 0, /* value */
1294 index,
1295 gspca_dev->usb_buf, 1,
1296 500); /* timeout */
1297 PDEBUG(D_USBI, "reg read i:%04x --> %02x",
1298 index, gspca_dev->usb_buf[0]);
1299 if (ret < 0) {
1300 err("reg_read err %d", ret);
1301 return ret;
1302 }
1303 return gspca_dev->usb_buf[0];
1304}
1305
1306/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
1307static int ssi_w(struct gspca_dev *gspca_dev,
1308 u16 reg, u16 val)
1309{
1310 struct usb_device *dev = gspca_dev->dev;
1311 int ret, retry;
1312
1313 ret = reg_write(dev, 0x8802, reg >> 8);
1314 if (ret < 0)
1315 goto out;
1316 ret = reg_write(dev, 0x8801, reg & 0x00ff);
1317 if (ret < 0)
1318 goto out;
1319 if ((reg & 0xff00) == 0x1000) { /* if 2 bytes */
1320 ret = reg_write(dev, 0x8805, val & 0x00ff);
1321 if (ret < 0)
1322 goto out;
1323 val >>= 8;
1324 }
1325 ret = reg_write(dev, 0x8800, val);
1326 if (ret < 0)
1327 goto out;
1328
1329 /* poll until not busy */
1330 retry = 10;
1331 for (;;) {
1332 ret = reg_read(gspca_dev, 0x8803);
1333 if (ret < 0)
1334 break;
1335 if (gspca_dev->usb_buf[0] == 0)
1336 break;
1337 if (--retry <= 0) {
1338 PDEBUG(D_ERR, "ssi_w busy %02x",
1339 gspca_dev->usb_buf[0]);
1340 ret = -1;
1341 break;
1342 }
1343 msleep(8);
1344 }
1345
1346out:
1347 return ret;
1348}
1349
1350static int write_vector(struct gspca_dev *gspca_dev,
1351 const u16 (*data)[2])
1352{
1353 struct usb_device *dev = gspca_dev->dev;
1354 int ret = 0;
1355
1356 while ((*data)[1] != 0) {
1357 if ((*data)[1] & 0x8000) {
1358 if ((*data)[1] == 0xdd00) /* delay */
1359 msleep((*data)[0]);
1360 else
1361 ret = reg_write(dev, (*data)[1], (*data)[0]);
1362 } else {
1363 ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
1364 }
1365 if (ret < 0)
1366 break;
1367 data++;
1368 }
1369 return ret;
1370}
1371
1372/* this function is called at probe time */
1373static int sd_config(struct gspca_dev *gspca_dev,
1374 const struct usb_device_id *id)
1375{
1376 struct sd *sd = (struct sd *) gspca_dev;
1377 struct cam *cam;
1378 const u16 (*init_data)[2];
1379 static const u16 (*(init_data_tb[]))[2] = {
1380 spca508_vista_init_data, /* CreativeVista 0 */
1381 spca508_sightcam_init_data, /* HamaUSBSightcam 1 */
1382 spca508_sightcam2_init_data, /* HamaUSBSightcam2 2 */
1383 spca508cs110_init_data, /* IntelEasyPCCamera 3 */
1384 spca508cs110_init_data, /* MicroInnovationIC200 4 */
1385 spca508_init_data, /* ViewQuestVQ110 5 */
1386 };
1387
1388#ifdef GSPCA_DEBUG
1389 int data1, data2;
1390
1391 /* Read from global register the USB product and vendor IDs, just to
1392 * prove that we can communicate with the device. This works, which
1393 * confirms at we are communicating properly and that the device
1394 * is a 508. */
1395 data1 = reg_read(gspca_dev, 0x8104);
1396 data2 = reg_read(gspca_dev, 0x8105);
1397 PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1398
1399 data1 = reg_read(gspca_dev, 0x8106);
1400 data2 = reg_read(gspca_dev, 0x8107);
1401 PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1402
1403 data1 = reg_read(gspca_dev, 0x8621);
1404 PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1405#endif
1406
1407 cam = &gspca_dev->cam;
1408 cam->cam_mode = sif_mode;
1409 cam->nmodes = ARRAY_SIZE(sif_mode);
1410
1411 sd->subtype = id->driver_info;
1412 sd->brightness = BRIGHTNESS_DEF;
1413
1414 init_data = init_data_tb[sd->subtype];
1415 return write_vector(gspca_dev, init_data);
1416}
1417
1418/* this function is called at probe and resume time */
1419static int sd_init(struct gspca_dev *gspca_dev)
1420{
1421 return 0;
1422}
1423
1424static int sd_start(struct gspca_dev *gspca_dev)
1425{
1426 int mode;
1427
1428 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1429 reg_write(gspca_dev->dev, 0x8500, mode);
1430 switch (mode) {
1431 case 0:
1432 case 1:
1433 reg_write(gspca_dev->dev, 0x8700, 0x28); /* clock */
1434 break;
1435 default:
1436/* case 2: */
1437/* case 3: */
1438 reg_write(gspca_dev->dev, 0x8700, 0x23); /* clock */
1439 break;
1440 }
1441 reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
1442 return 0;
1443}
1444
1445static void sd_stopN(struct gspca_dev *gspca_dev)
1446{
1447 /* Video ISO disable, Video Drop Packet enable: */
1448 reg_write(gspca_dev->dev, 0x8112, 0x20);
1449}
1450
1451static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1452 u8 *data, /* isoc packet */
1453 int len) /* iso packet length */
1454{
1455 switch (data[0]) {
1456 case 0: /* start of frame */
1457 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1458 data += SPCA508_OFFSET_DATA;
1459 len -= SPCA508_OFFSET_DATA;
1460 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1461 break;
1462 case 0xff: /* drop */
1463 break;
1464 default:
1465 data += 1;
1466 len -= 1;
1467 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1468 break;
1469 }
1470}
1471
1472static void setbrightness(struct gspca_dev *gspca_dev)
1473{
1474 struct sd *sd = (struct sd *) gspca_dev;
1475 u8 brightness = sd->brightness;
1476
1477 /* MX seem contrast */
1478 reg_write(gspca_dev->dev, 0x8651, brightness);
1479 reg_write(gspca_dev->dev, 0x8652, brightness);
1480 reg_write(gspca_dev->dev, 0x8653, brightness);
1481 reg_write(gspca_dev->dev, 0x8654, brightness);
1482}
1483
1484static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1485{
1486 struct sd *sd = (struct sd *) gspca_dev;
1487
1488 sd->brightness = val;
1489 if (gspca_dev->streaming)
1490 setbrightness(gspca_dev);
1491 return 0;
1492}
1493
1494static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1495{
1496 struct sd *sd = (struct sd *) gspca_dev;
1497
1498 *val = sd->brightness;
1499 return 0;
1500}
1501
1502/* sub-driver description */
1503static const struct sd_desc sd_desc = {
1504 .name = MODULE_NAME,
1505 .ctrls = sd_ctrls,
1506 .nctrls = ARRAY_SIZE(sd_ctrls),
1507 .config = sd_config,
1508 .init = sd_init,
1509 .start = sd_start,
1510 .stopN = sd_stopN,
1511 .pkt_scan = sd_pkt_scan,
1512};
1513
1514/* -- module initialisation -- */
1515static const struct usb_device_id device_table[] = {
1516 {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
1517 {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
1518 {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
1519 {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
1520 {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
1521 {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
1522 {}
1523};
1524MODULE_DEVICE_TABLE(usb, device_table);
1525
1526/* -- device connect -- */
1527static int sd_probe(struct usb_interface *intf,
1528 const struct usb_device_id *id)
1529{
1530 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1531 THIS_MODULE);
1532}
1533
1534static struct usb_driver sd_driver = {
1535 .name = MODULE_NAME,
1536 .id_table = device_table,
1537 .probe = sd_probe,
1538 .disconnect = gspca_disconnect,
1539#ifdef CONFIG_PM
1540 .suspend = gspca_suspend,
1541 .resume = gspca_resume,
1542#endif
1543};
1544
1545/* -- module insert / remove -- */
1546static int __init sd_mod_init(void)
1547{
1548 return usb_register(&sd_driver);
1549}
1550static void __exit sd_mod_exit(void)
1551{
1552 usb_deregister(&sd_driver);
1553}
1554
1555module_init(sd_mod_init);
1556module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
new file mode 100644
index 00000000000..e836e778dfb
--- /dev/null
+++ b/drivers/media/video/gspca/spca561.c
@@ -0,0 +1,1118 @@
1/*
2 * Sunplus spca561 subdriver
3 *
4 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define MODULE_NAME "spca561"
24
25#include <linux/input.h>
26#include "gspca.h"
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA561 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 __u16 exposure; /* rev12a only */
37#define EXPOSURE_MIN 1
38#define EXPOSURE_DEF 700 /* == 10 fps */
39#define EXPOSURE_MAX (2047 + 325) /* see setexposure */
40
41 __u8 contrast; /* rev72a only */
42#define CONTRAST_MIN 0x00
43#define CONTRAST_DEF 0x20
44#define CONTRAST_MAX 0x3f
45
46 __u8 brightness; /* rev72a only */
47#define BRIGHTNESS_MIN 0
48#define BRIGHTNESS_DEF 0x20
49#define BRIGHTNESS_MAX 0x3f
50
51 __u8 white;
52#define HUE_MIN 1
53#define HUE_DEF 0x40
54#define HUE_MAX 0x7f
55
56 __u8 autogain;
57#define AUTOGAIN_MIN 0
58#define AUTOGAIN_DEF 1
59#define AUTOGAIN_MAX 1
60
61 __u8 gain; /* rev12a only */
62#define GAIN_MIN 0
63#define GAIN_DEF 63
64#define GAIN_MAX 255
65
66#define EXPO12A_DEF 3
67 __u8 expo12a; /* expo/gain? for rev 12a */
68
69 __u8 chip_revision;
70#define Rev012A 0
71#define Rev072A 1
72
73 signed char ag_cnt;
74#define AG_CNT_START 13
75};
76
77static const struct v4l2_pix_format sif_012a_mode[] = {
78 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
79 .bytesperline = 160,
80 .sizeimage = 160 * 120,
81 .colorspace = V4L2_COLORSPACE_SRGB,
82 .priv = 3},
83 {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
84 .bytesperline = 176,
85 .sizeimage = 176 * 144,
86 .colorspace = V4L2_COLORSPACE_SRGB,
87 .priv = 2},
88 {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
89 .bytesperline = 320,
90 .sizeimage = 320 * 240 * 4 / 8,
91 .colorspace = V4L2_COLORSPACE_SRGB,
92 .priv = 1},
93 {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
94 .bytesperline = 352,
95 .sizeimage = 352 * 288 * 4 / 8,
96 .colorspace = V4L2_COLORSPACE_SRGB,
97 .priv = 0},
98};
99
100static const struct v4l2_pix_format sif_072a_mode[] = {
101 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
102 .bytesperline = 160,
103 .sizeimage = 160 * 120,
104 .colorspace = V4L2_COLORSPACE_SRGB,
105 .priv = 3},
106 {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
107 .bytesperline = 176,
108 .sizeimage = 176 * 144,
109 .colorspace = V4L2_COLORSPACE_SRGB,
110 .priv = 2},
111 {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
112 .bytesperline = 320,
113 .sizeimage = 320 * 240,
114 .colorspace = V4L2_COLORSPACE_SRGB,
115 .priv = 1},
116 {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
117 .bytesperline = 352,
118 .sizeimage = 352 * 288,
119 .colorspace = V4L2_COLORSPACE_SRGB,
120 .priv = 0},
121};
122
123/*
124 * Initialization data
125 * I'm not very sure how to split initialization from open data
126 * chunks. For now, we'll consider everything as initialization
127 */
128/* Frame packet header offsets for the spca561 */
129#define SPCA561_OFFSET_SNAP 1
130#define SPCA561_OFFSET_TYPE 2
131#define SPCA561_OFFSET_COMPRESS 3
132#define SPCA561_OFFSET_FRAMSEQ 4
133#define SPCA561_OFFSET_GPIO 5
134#define SPCA561_OFFSET_USBBUFF 6
135#define SPCA561_OFFSET_WIN2GRAVE 7
136#define SPCA561_OFFSET_WIN2RAVE 8
137#define SPCA561_OFFSET_WIN2BAVE 9
138#define SPCA561_OFFSET_WIN2GBAVE 10
139#define SPCA561_OFFSET_WIN1GRAVE 11
140#define SPCA561_OFFSET_WIN1RAVE 12
141#define SPCA561_OFFSET_WIN1BAVE 13
142#define SPCA561_OFFSET_WIN1GBAVE 14
143#define SPCA561_OFFSET_FREQ 15
144#define SPCA561_OFFSET_VSYNC 16
145#define SPCA561_INDEX_I2C_BASE 0x8800
146#define SPCA561_SNAPBIT 0x20
147#define SPCA561_SNAPCTRL 0x40
148
149static const u16 rev72a_reset[][2] = {
150 {0x0000, 0x8114}, /* Software GPIO output data */
151 {0x0001, 0x8114}, /* Software GPIO output data */
152 {0x0000, 0x8112}, /* Some kind of reset */
153 {}
154};
155static const __u16 rev72a_init_data1[][2] = {
156 {0x0003, 0x8701}, /* PCLK clock delay adjustment */
157 {0x0001, 0x8703}, /* HSYNC from cmos inverted */
158 {0x0011, 0x8118}, /* Enable and conf sensor */
159 {0x0001, 0x8118}, /* Conf sensor */
160 {0x0092, 0x8804}, /* I know nothing about these */
161 {0x0010, 0x8802}, /* 0x88xx registers, so I won't */
162 {}
163};
164static const u16 rev72a_init_sensor1[][2] = {
165 {0x0001, 0x000d},
166 {0x0002, 0x0018},
167 {0x0004, 0x0165},
168 {0x0005, 0x0021},
169 {0x0007, 0x00aa},
170 {0x0020, 0x1504},
171 {0x0039, 0x0002},
172 {0x0035, 0x0010},
173 {0x0009, 0x1049},
174 {0x0028, 0x000b},
175 {0x003b, 0x000f},
176 {0x003c, 0x0000},
177 {}
178};
179static const __u16 rev72a_init_data2[][2] = {
180 {0x0018, 0x8601}, /* Pixel/line selection for color separation */
181 {0x0000, 0x8602}, /* Optical black level for user setting */
182 {0x0060, 0x8604}, /* Optical black horizontal offset */
183 {0x0002, 0x8605}, /* Optical black vertical offset */
184 {0x0000, 0x8603}, /* Non-automatic optical black level */
185 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
186 {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */
187 {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */
188 {0x0090, 0x865e}, /* Vertical valid lines window (x2) */
189 {0x00e0, 0x8406}, /* Memory buffer threshold */
190 {0x0000, 0x8660}, /* Compensation memory stuff */
191 {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */
192 {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
193 {0x0001, 0x8200}, /* OprMode to be executed by hardware */
194/* from ms-win */
195 {0x0000, 0x8611}, /* R offset for white balance */
196 {0x00fd, 0x8612}, /* Gr offset for white balance */
197 {0x0003, 0x8613}, /* B offset for white balance */
198 {0x0000, 0x8614}, /* Gb offset for white balance */
199/* from ms-win */
200 {0x0035, 0x8651}, /* R gain for white balance */
201 {0x0040, 0x8652}, /* Gr gain for white balance */
202 {0x005f, 0x8653}, /* B gain for white balance */
203 {0x0040, 0x8654}, /* Gb gain for white balance */
204 {0x0002, 0x8502}, /* Maximum average bit rate stuff */
205 {0x0011, 0x8802},
206
207 {0x0087, 0x8700}, /* Set master clock (96Mhz????) */
208 {0x0081, 0x8702}, /* Master clock output enable */
209
210 {0x0000, 0x8500}, /* Set image type (352x288 no compression) */
211 /* Originally was 0x0010 (352x288 compression) */
212
213 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
214 {0x0003, 0x865c}, /* Vertical offset for valid lines */
215 {}
216};
217static const u16 rev72a_init_sensor2[][2] = {
218 {0x0003, 0x0121},
219 {0x0004, 0x0165},
220 {0x0005, 0x002f}, /* blanking control column */
221 {0x0006, 0x0000}, /* blanking mode row*/
222 {0x000a, 0x0002},
223 {0x0009, 0x1061}, /* setexposure times && pixel clock
224 * 0001 0 | 000 0110 0001 */
225 {0x0035, 0x0014},
226 {}
227};
228
229/******************** QC Express etch2 stuff ********************/
230static const __u16 Pb100_1map8300[][2] = {
231 /* reg, value */
232 {0x8320, 0x3304},
233
234 {0x8303, 0x0125}, /* image area */
235 {0x8304, 0x0169},
236 {0x8328, 0x000b},
237 {0x833c, 0x0001}, /*fixme: win:07*/
238
239 {0x832f, 0x1904}, /*fixme: was 0419*/
240 {0x8307, 0x00aa},
241 {0x8301, 0x0003},
242 {0x8302, 0x000e},
243 {}
244};
245static const __u16 Pb100_2map8300[][2] = {
246 /* reg, value */
247 {0x8339, 0x0000},
248 {0x8307, 0x00aa},
249 {}
250};
251
252static const __u16 spca561_161rev12A_data1[][2] = {
253 {0x29, 0x8118}, /* Control register (various enable bits) */
254 {0x08, 0x8114}, /* GPIO: Led off */
255 {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */
256 {0x00, 0x8102}, /* white balance - new */
257 {0x92, 0x8804},
258 {0x04, 0x8802}, /* windows uses 08 */
259 {}
260};
261static const __u16 spca561_161rev12A_data2[][2] = {
262 {0x21, 0x8118},
263 {0x10, 0x8500},
264 {0x07, 0x8601},
265 {0x07, 0x8602},
266 {0x04, 0x8501},
267
268 {0x07, 0x8201}, /* windows uses 02 */
269 {0x08, 0x8200},
270 {0x01, 0x8200},
271
272 {0x90, 0x8604},
273 {0x00, 0x8605},
274 {0xb0, 0x8603},
275
276 /* sensor gains */
277 {0x07, 0x8601}, /* white balance - new */
278 {0x07, 0x8602}, /* white balance - new */
279 {0x00, 0x8610}, /* *red */
280 {0x00, 0x8611}, /* 3f *green */
281 {0x00, 0x8612}, /* green *blue */
282 {0x00, 0x8613}, /* blue *green */
283 {0x43, 0x8614}, /* green *red - white balance - was 0x35 */
284 {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */
285 {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */
286 {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */
287
288 {0x0c, 0x8620}, /* 0c */
289 {0xc8, 0x8631}, /* c8 */
290 {0xc8, 0x8634}, /* c8 */
291 {0x23, 0x8635}, /* 23 */
292 {0x1f, 0x8636}, /* 1f */
293 {0xdd, 0x8637}, /* dd */
294 {0xe1, 0x8638}, /* e1 */
295 {0x1d, 0x8639}, /* 1d */
296 {0x21, 0x863a}, /* 21 */
297 {0xe3, 0x863b}, /* e3 */
298 {0xdf, 0x863c}, /* df */
299 {0xf0, 0x8505},
300 {0x32, 0x850a},
301/* {0x99, 0x8700}, * - white balance - new (removed) */
302 /* HDG we used to do this in stop0, making the init state and the state
303 after a start / stop different, so do this here instead. */
304 {0x29, 0x8118},
305 {}
306};
307
308static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
309{
310 int ret;
311
312 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
313 0, /* request */
314 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
315 value, index, NULL, 0, 500);
316 PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
317 if (ret < 0)
318 err("reg write: error %d", ret);
319}
320
321static void write_vector(struct gspca_dev *gspca_dev,
322 const __u16 data[][2])
323{
324 struct usb_device *dev = gspca_dev->dev;
325 int i;
326
327 i = 0;
328 while (data[i][1] != 0) {
329 reg_w_val(dev, data[i][1], data[i][0]);
330 i++;
331 }
332}
333
334/* read 'len' bytes to gspca_dev->usb_buf */
335static void reg_r(struct gspca_dev *gspca_dev,
336 __u16 index, __u16 length)
337{
338 usb_control_msg(gspca_dev->dev,
339 usb_rcvctrlpipe(gspca_dev->dev, 0),
340 0, /* request */
341 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
342 0, /* value */
343 index, gspca_dev->usb_buf, length, 500);
344}
345
346/* write 'len' bytes from gspca_dev->usb_buf */
347static void reg_w_buf(struct gspca_dev *gspca_dev,
348 __u16 index, __u16 len)
349{
350 usb_control_msg(gspca_dev->dev,
351 usb_sndctrlpipe(gspca_dev->dev, 0),
352 0, /* request */
353 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
354 0, /* value */
355 index, gspca_dev->usb_buf, len, 500);
356}
357
358static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
359{
360 int retry = 60;
361
362 reg_w_val(gspca_dev->dev, 0x8801, reg);
363 reg_w_val(gspca_dev->dev, 0x8805, value);
364 reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
365 do {
366 reg_r(gspca_dev, 0x8803, 1);
367 if (!gspca_dev->usb_buf[0])
368 return;
369 msleep(10);
370 } while (--retry);
371}
372
373static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
374{
375 int retry = 60;
376 __u8 value;
377
378 reg_w_val(gspca_dev->dev, 0x8804, 0x92);
379 reg_w_val(gspca_dev->dev, 0x8801, reg);
380 reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
381 do {
382 reg_r(gspca_dev, 0x8803, 1);
383 if (!gspca_dev->usb_buf[0]) {
384 reg_r(gspca_dev, 0x8800, 1);
385 value = gspca_dev->usb_buf[0];
386 reg_r(gspca_dev, 0x8805, 1);
387 return ((int) value << 8) | gspca_dev->usb_buf[0];
388 }
389 msleep(10);
390 } while (--retry);
391 return -1;
392}
393
394static void sensor_mapwrite(struct gspca_dev *gspca_dev,
395 const __u16 (*sensormap)[2])
396{
397 while ((*sensormap)[0]) {
398 gspca_dev->usb_buf[0] = (*sensormap)[1];
399 gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
400 reg_w_buf(gspca_dev, (*sensormap)[0], 2);
401 sensormap++;
402 }
403}
404
405static void write_sensor_72a(struct gspca_dev *gspca_dev,
406 const __u16 (*sensor)[2])
407{
408 while ((*sensor)[0]) {
409 i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
410 sensor++;
411 }
412}
413
414static void init_161rev12A(struct gspca_dev *gspca_dev)
415{
416 write_vector(gspca_dev, spca561_161rev12A_data1);
417 sensor_mapwrite(gspca_dev, Pb100_1map8300);
418/*fixme: should be in sd_start*/
419 write_vector(gspca_dev, spca561_161rev12A_data2);
420 sensor_mapwrite(gspca_dev, Pb100_2map8300);
421}
422
423/* this function is called at probe time */
424static int sd_config(struct gspca_dev *gspca_dev,
425 const struct usb_device_id *id)
426{
427 struct sd *sd = (struct sd *) gspca_dev;
428 struct cam *cam;
429 __u16 vendor, product;
430 __u8 data1, data2;
431
432 /* Read frm global register the USB product and vendor IDs, just to
433 * prove that we can communicate with the device. This works, which
434 * confirms at we are communicating properly and that the device
435 * is a 561. */
436 reg_r(gspca_dev, 0x8104, 1);
437 data1 = gspca_dev->usb_buf[0];
438 reg_r(gspca_dev, 0x8105, 1);
439 data2 = gspca_dev->usb_buf[0];
440 vendor = (data2 << 8) | data1;
441 reg_r(gspca_dev, 0x8106, 1);
442 data1 = gspca_dev->usb_buf[0];
443 reg_r(gspca_dev, 0x8107, 1);
444 data2 = gspca_dev->usb_buf[0];
445 product = (data2 << 8) | data1;
446 if (vendor != id->idVendor || product != id->idProduct) {
447 PDEBUG(D_PROBE, "Bad vendor / product from device");
448 return -EINVAL;
449 }
450
451 cam = &gspca_dev->cam;
452 gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */
453
454 sd->chip_revision = id->driver_info;
455 if (sd->chip_revision == Rev012A) {
456 cam->cam_mode = sif_012a_mode;
457 cam->nmodes = ARRAY_SIZE(sif_012a_mode);
458 } else {
459 cam->cam_mode = sif_072a_mode;
460 cam->nmodes = ARRAY_SIZE(sif_072a_mode);
461 }
462 sd->brightness = BRIGHTNESS_DEF;
463 sd->contrast = CONTRAST_DEF;
464 sd->white = HUE_DEF;
465 sd->exposure = EXPOSURE_DEF;
466 sd->autogain = AUTOGAIN_DEF;
467 sd->gain = GAIN_DEF;
468 sd->expo12a = EXPO12A_DEF;
469 return 0;
470}
471
472/* this function is called at probe and resume time */
473static int sd_init_12a(struct gspca_dev *gspca_dev)
474{
475 PDEBUG(D_STREAM, "Chip revision: 012a");
476 init_161rev12A(gspca_dev);
477 return 0;
478}
479static int sd_init_72a(struct gspca_dev *gspca_dev)
480{
481 PDEBUG(D_STREAM, "Chip revision: 072a");
482 write_vector(gspca_dev, rev72a_reset);
483 msleep(200);
484 write_vector(gspca_dev, rev72a_init_data1);
485 write_sensor_72a(gspca_dev, rev72a_init_sensor1);
486 write_vector(gspca_dev, rev72a_init_data2);
487 write_sensor_72a(gspca_dev, rev72a_init_sensor2);
488 reg_w_val(gspca_dev->dev, 0x8112, 0x30);
489 return 0;
490}
491
492/* rev 72a only */
493static void setbrightness(struct gspca_dev *gspca_dev)
494{
495 struct sd *sd = (struct sd *) gspca_dev;
496 struct usb_device *dev = gspca_dev->dev;
497 __u8 value;
498
499 value = sd->brightness;
500
501 /* offsets for white balance */
502 reg_w_val(dev, 0x8611, value); /* R */
503 reg_w_val(dev, 0x8612, value); /* Gr */
504 reg_w_val(dev, 0x8613, value); /* B */
505 reg_w_val(dev, 0x8614, value); /* Gb */
506}
507
508static void setwhite(struct gspca_dev *gspca_dev)
509{
510 struct sd *sd = (struct sd *) gspca_dev;
511 __u16 white;
512 __u8 blue, red;
513 __u16 reg;
514
515 /* try to emulate MS-win as possible */
516 white = sd->white;
517 red = 0x20 + white * 3 / 8;
518 blue = 0x90 - white * 5 / 8;
519 if (sd->chip_revision == Rev012A) {
520 reg = 0x8614;
521 } else {
522 reg = 0x8651;
523 red += sd->contrast - 0x20;
524 blue += sd->contrast - 0x20;
525 }
526 reg_w_val(gspca_dev->dev, reg, red);
527 reg_w_val(gspca_dev->dev, reg + 2, blue);
528}
529
530static void setcontrast(struct gspca_dev *gspca_dev)
531{
532 struct sd *sd = (struct sd *) gspca_dev;
533 struct usb_device *dev = gspca_dev->dev;
534 __u8 value;
535
536 if (sd->chip_revision != Rev072A)
537 return;
538 value = sd->contrast + 0x20;
539
540 /* gains for white balance */
541 setwhite(gspca_dev);
542/* reg_w_val(dev, 0x8651, value); * R - done by setwhite */
543 reg_w_val(dev, 0x8652, value); /* Gr */
544/* reg_w_val(dev, 0x8653, value); * B - done by setwhite */
545 reg_w_val(dev, 0x8654, value); /* Gb */
546}
547
548/* rev 12a only */
549static void setexposure(struct gspca_dev *gspca_dev)
550{
551 struct sd *sd = (struct sd *) gspca_dev;
552 int i, expo = 0;
553
554 /* Register 0x8309 controls exposure for the spca561,
555 the basic exposure setting goes from 1-2047, where 1 is completely
556 dark and 2047 is very bright. It not only influences exposure but
557 also the framerate (to allow for longer exposure) from 1 - 300 it
558 only raises the exposure time then from 300 - 600 it halves the
559 framerate to be able to further raise the exposure time and for every
560 300 more it halves the framerate again. This allows for a maximum
561 exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
562 Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
563 configure a divider for the base framerate which us used at the
564 exposure setting of 1-300. These bits configure the base framerate
565 according to the following formula: fps = 60 / (value + 2) */
566
567 /* We choose to use the high bits setting the fixed framerate divisor
568 asap, as setting high basic exposure setting without the fixed
569 divider in combination with high gains makes the cam stop */
570 int table[] = { 0, 450, 550, 625, EXPOSURE_MAX };
571
572 for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
573 if (sd->exposure <= table[i + 1]) {
574 expo = sd->exposure - table[i];
575 if (i)
576 expo += 300;
577 expo |= i << 11;
578 break;
579 }
580 }
581
582 gspca_dev->usb_buf[0] = expo;
583 gspca_dev->usb_buf[1] = expo >> 8;
584 reg_w_buf(gspca_dev, 0x8309, 2);
585}
586
587/* rev 12a only */
588static void setgain(struct gspca_dev *gspca_dev)
589{
590 struct sd *sd = (struct sd *) gspca_dev;
591
592 /* gain reg low 6 bits 0-63 gain, bit 6 and 7, both double the
593 sensitivity when set, so 31 + one of them set == 63, and 15
594 with both of them set == 63 */
595 if (sd->gain < 64)
596 gspca_dev->usb_buf[0] = sd->gain;
597 else if (sd->gain < 128)
598 gspca_dev->usb_buf[0] = (sd->gain / 2) | 0x40;
599 else
600 gspca_dev->usb_buf[0] = (sd->gain / 4) | 0xc0;
601
602 gspca_dev->usb_buf[1] = 0;
603 reg_w_buf(gspca_dev, 0x8335, 2);
604}
605
606static void setautogain(struct gspca_dev *gspca_dev)
607{
608 struct sd *sd = (struct sd *) gspca_dev;
609
610 if (sd->autogain)
611 sd->ag_cnt = AG_CNT_START;
612 else
613 sd->ag_cnt = -1;
614}
615
616static int sd_start_12a(struct gspca_dev *gspca_dev)
617{
618 struct usb_device *dev = gspca_dev->dev;
619 int mode;
620 static const __u8 Reg8391[8] =
621 {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
622
623 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
624 if (mode <= 1) {
625 /* Use compression on 320x240 and above */
626 reg_w_val(dev, 0x8500, 0x10 | mode);
627 } else {
628 /* I couldn't get the compression to work below 320x240
629 * Fortunately at these resolutions the bandwidth
630 * is sufficient to push raw frames at ~20fps */
631 reg_w_val(dev, 0x8500, mode);
632 } /* -- qq@kuku.eu.org */
633
634 gspca_dev->usb_buf[0] = 0xaa;
635 gspca_dev->usb_buf[1] = 0x00;
636 reg_w_buf(gspca_dev, 0x8307, 2);
637 /* clock - lower 0x8X values lead to fps > 30 */
638 reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
639 /* 0x8f 0x85 0x27 clock */
640 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
641 reg_w_val(gspca_dev->dev, 0x850b, 0x03);
642 memcpy(gspca_dev->usb_buf, Reg8391, 8);
643 reg_w_buf(gspca_dev, 0x8391, 8);
644 reg_w_buf(gspca_dev, 0x8390, 8);
645 setwhite(gspca_dev);
646 setgain(gspca_dev);
647 setexposure(gspca_dev);
648
649 /* Led ON (bit 3 -> 0 */
650 reg_w_val(gspca_dev->dev, 0x8114, 0x00);
651 return 0;
652}
653static int sd_start_72a(struct gspca_dev *gspca_dev)
654{
655 struct usb_device *dev = gspca_dev->dev;
656 int Clck;
657 int mode;
658
659 write_vector(gspca_dev, rev72a_reset);
660 msleep(200);
661 write_vector(gspca_dev, rev72a_init_data1);
662 write_sensor_72a(gspca_dev, rev72a_init_sensor1);
663
664 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
665 switch (mode) {
666 default:
667 case 0:
668 Clck = 0x27; /* ms-win 0x87 */
669 break;
670 case 1:
671 Clck = 0x25;
672 break;
673 case 2:
674 Clck = 0x22;
675 break;
676 case 3:
677 Clck = 0x21;
678 break;
679 }
680 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
681 reg_w_val(dev, 0x8702, 0x81);
682 reg_w_val(dev, 0x8500, mode); /* mode */
683 write_sensor_72a(gspca_dev, rev72a_init_sensor2);
684 setcontrast(gspca_dev);
685/* setbrightness(gspca_dev); * fixme: bad values */
686 setautogain(gspca_dev);
687 reg_w_val(dev, 0x8112, 0x10 | 0x20);
688 return 0;
689}
690
691static void sd_stopN(struct gspca_dev *gspca_dev)
692{
693 struct sd *sd = (struct sd *) gspca_dev;
694
695 if (sd->chip_revision == Rev012A) {
696 reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
697 /* Led Off (bit 3 -> 1 */
698 reg_w_val(gspca_dev->dev, 0x8114, 0x08);
699 } else {
700 reg_w_val(gspca_dev->dev, 0x8112, 0x20);
701/* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
702 }
703}
704
705static void do_autogain(struct gspca_dev *gspca_dev)
706{
707 struct sd *sd = (struct sd *) gspca_dev;
708 int expotimes;
709 int pixelclk;
710 int gainG;
711 __u8 R, Gr, Gb, B;
712 int y;
713 __u8 luma_mean = 110;
714 __u8 luma_delta = 20;
715 __u8 spring = 4;
716
717 if (sd->ag_cnt < 0)
718 return;
719 if (--sd->ag_cnt >= 0)
720 return;
721 sd->ag_cnt = AG_CNT_START;
722
723 switch (sd->chip_revision) {
724 case Rev072A:
725 reg_r(gspca_dev, 0x8621, 1);
726 Gr = gspca_dev->usb_buf[0];
727 reg_r(gspca_dev, 0x8622, 1);
728 R = gspca_dev->usb_buf[0];
729 reg_r(gspca_dev, 0x8623, 1);
730 B = gspca_dev->usb_buf[0];
731 reg_r(gspca_dev, 0x8624, 1);
732 Gb = gspca_dev->usb_buf[0];
733 y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
734 /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
735 /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
736 /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
737
738 if (y < luma_mean - luma_delta ||
739 y > luma_mean + luma_delta) {
740 expotimes = i2c_read(gspca_dev, 0x09, 0x10);
741 pixelclk = 0x0800;
742 expotimes = expotimes & 0x07ff;
743 /* PDEBUG(D_PACK,
744 "Exposition Times 0x%03X Clock 0x%04X ",
745 expotimes,pixelclk); */
746 gainG = i2c_read(gspca_dev, 0x35, 0x10);
747 /* PDEBUG(D_PACK,
748 "reading Gain register %d", gainG); */
749
750 expotimes += (luma_mean - y) >> spring;
751 gainG += (luma_mean - y) / 50;
752 /* PDEBUG(D_PACK,
753 "compute expotimes %d gain %d",
754 expotimes,gainG); */
755
756 if (gainG > 0x3f)
757 gainG = 0x3f;
758 else if (gainG < 3)
759 gainG = 3;
760 i2c_write(gspca_dev, gainG, 0x35);
761
762 if (expotimes > 0x0256)
763 expotimes = 0x0256;
764 else if (expotimes < 3)
765 expotimes = 3;
766 i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
767 }
768 break;
769 }
770}
771
772static void sd_pkt_scan(struct gspca_dev *gspca_dev,
773 u8 *data, /* isoc packet */
774 int len) /* iso packet length */
775{
776 struct sd *sd = (struct sd *) gspca_dev;
777
778 len--;
779 switch (*data++) { /* sequence number */
780 case 0: /* start of frame */
781 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
782
783 /* This should never happen */
784 if (len < 2) {
785 PDEBUG(D_ERR, "Short SOF packet, ignoring");
786 gspca_dev->last_packet_type = DISCARD_PACKET;
787 return;
788 }
789
790#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
791 if (data[0] & 0x20) {
792 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
793 input_sync(gspca_dev->input_dev);
794 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
795 input_sync(gspca_dev->input_dev);
796 }
797#endif
798
799 if (data[1] & 0x10) {
800 /* compressed bayer */
801 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
802 } else {
803 /* raw bayer (with a header, which we skip) */
804 if (sd->chip_revision == Rev012A) {
805 data += 20;
806 len -= 20;
807 } else {
808 data += 16;
809 len -= 16;
810 }
811 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
812 }
813 return;
814 case 0xff: /* drop (empty mpackets) */
815 return;
816 }
817 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
818}
819
820/* rev 72a only */
821static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
822{
823 struct sd *sd = (struct sd *) gspca_dev;
824
825 sd->brightness = val;
826 if (gspca_dev->streaming)
827 setbrightness(gspca_dev);
828 return 0;
829}
830
831static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
832{
833 struct sd *sd = (struct sd *) gspca_dev;
834
835 *val = sd->brightness;
836 return 0;
837}
838
839/* rev 72a only */
840static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
841{
842 struct sd *sd = (struct sd *) gspca_dev;
843
844 sd->contrast = val;
845 if (gspca_dev->streaming)
846 setcontrast(gspca_dev);
847 return 0;
848}
849
850static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
851{
852 struct sd *sd = (struct sd *) gspca_dev;
853
854 *val = sd->contrast;
855 return 0;
856}
857
858static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
859{
860 struct sd *sd = (struct sd *) gspca_dev;
861
862 sd->autogain = val;
863 if (gspca_dev->streaming)
864 setautogain(gspca_dev);
865 return 0;
866}
867
868static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
869{
870 struct sd *sd = (struct sd *) gspca_dev;
871
872 *val = sd->autogain;
873 return 0;
874}
875
876static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
877{
878 struct sd *sd = (struct sd *) gspca_dev;
879
880 sd->white = val;
881 if (gspca_dev->streaming)
882 setwhite(gspca_dev);
883 return 0;
884}
885
886static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val)
887{
888 struct sd *sd = (struct sd *) gspca_dev;
889
890 *val = sd->white;
891 return 0;
892}
893
894/* rev12a only */
895static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 sd->exposure = val;
900 if (gspca_dev->streaming)
901 setexposure(gspca_dev);
902 return 0;
903}
904
905static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 *val = sd->exposure;
910 return 0;
911}
912
913/* rev12a only */
914static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
915{
916 struct sd *sd = (struct sd *) gspca_dev;
917
918 sd->gain = val;
919 if (gspca_dev->streaming)
920 setgain(gspca_dev);
921 return 0;
922}
923
924static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
925{
926 struct sd *sd = (struct sd *) gspca_dev;
927
928 *val = sd->gain;
929 return 0;
930}
931
932/* control tables */
933static const struct ctrl sd_ctrls_12a[] = {
934 {
935 {
936 .id = V4L2_CID_HUE,
937 .type = V4L2_CTRL_TYPE_INTEGER,
938 .name = "Hue",
939 .minimum = HUE_MIN,
940 .maximum = HUE_MAX,
941 .step = 1,
942 .default_value = HUE_DEF,
943 },
944 .set = sd_setwhite,
945 .get = sd_getwhite,
946 },
947 {
948 {
949 .id = V4L2_CID_EXPOSURE,
950 .type = V4L2_CTRL_TYPE_INTEGER,
951 .name = "Exposure",
952 .minimum = EXPOSURE_MIN,
953 .maximum = EXPOSURE_MAX,
954 .step = 1,
955 .default_value = EXPOSURE_DEF,
956 },
957 .set = sd_setexposure,
958 .get = sd_getexposure,
959 },
960 {
961 {
962 .id = V4L2_CID_GAIN,
963 .type = V4L2_CTRL_TYPE_INTEGER,
964 .name = "Gain",
965 .minimum = GAIN_MIN,
966 .maximum = GAIN_MAX,
967 .step = 1,
968 .default_value = GAIN_DEF,
969 },
970 .set = sd_setgain,
971 .get = sd_getgain,
972 },
973};
974
975static const struct ctrl sd_ctrls_72a[] = {
976 {
977 {
978 .id = V4L2_CID_HUE,
979 .type = V4L2_CTRL_TYPE_INTEGER,
980 .name = "Hue",
981 .minimum = HUE_MIN,
982 .maximum = HUE_MAX,
983 .step = 1,
984 .default_value = HUE_DEF,
985 },
986 .set = sd_setwhite,
987 .get = sd_getwhite,
988 },
989 {
990 {
991 .id = V4L2_CID_BRIGHTNESS,
992 .type = V4L2_CTRL_TYPE_INTEGER,
993 .name = "Brightness",
994 .minimum = BRIGHTNESS_MIN,
995 .maximum = BRIGHTNESS_MAX,
996 .step = 1,
997 .default_value = BRIGHTNESS_DEF,
998 },
999 .set = sd_setbrightness,
1000 .get = sd_getbrightness,
1001 },
1002 {
1003 {
1004 .id = V4L2_CID_CONTRAST,
1005 .type = V4L2_CTRL_TYPE_INTEGER,
1006 .name = "Contrast",
1007 .minimum = CONTRAST_MIN,
1008 .maximum = CONTRAST_MAX,
1009 .step = 1,
1010 .default_value = CONTRAST_DEF,
1011 },
1012 .set = sd_setcontrast,
1013 .get = sd_getcontrast,
1014 },
1015 {
1016 {
1017 .id = V4L2_CID_AUTOGAIN,
1018 .type = V4L2_CTRL_TYPE_BOOLEAN,
1019 .name = "Auto Gain",
1020 .minimum = AUTOGAIN_MIN,
1021 .maximum = AUTOGAIN_MAX,
1022 .step = 1,
1023 .default_value = AUTOGAIN_DEF,
1024 },
1025 .set = sd_setautogain,
1026 .get = sd_getautogain,
1027 },
1028};
1029
1030/* sub-driver description */
1031static const struct sd_desc sd_desc_12a = {
1032 .name = MODULE_NAME,
1033 .ctrls = sd_ctrls_12a,
1034 .nctrls = ARRAY_SIZE(sd_ctrls_12a),
1035 .config = sd_config,
1036 .init = sd_init_12a,
1037 .start = sd_start_12a,
1038 .stopN = sd_stopN,
1039 .pkt_scan = sd_pkt_scan,
1040#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1041 .other_input = 1,
1042#endif
1043};
1044static const struct sd_desc sd_desc_72a = {
1045 .name = MODULE_NAME,
1046 .ctrls = sd_ctrls_72a,
1047 .nctrls = ARRAY_SIZE(sd_ctrls_72a),
1048 .config = sd_config,
1049 .init = sd_init_72a,
1050 .start = sd_start_72a,
1051 .stopN = sd_stopN,
1052 .pkt_scan = sd_pkt_scan,
1053 .dq_callback = do_autogain,
1054#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1055 .other_input = 1,
1056#endif
1057};
1058static const struct sd_desc *sd_desc[2] = {
1059 &sd_desc_12a,
1060 &sd_desc_72a
1061};
1062
1063/* -- module initialisation -- */
1064static const struct usb_device_id device_table[] = {
1065 {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
1066 {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
1067 {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
1068 {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
1069 {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
1070 {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
1071 {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
1072 {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
1073 {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
1074 {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
1075 {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
1076 {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
1077 {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
1078 {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
1079 {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
1080 {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
1081 {}
1082};
1083
1084MODULE_DEVICE_TABLE(usb, device_table);
1085
1086/* -- device connect -- */
1087static int sd_probe(struct usb_interface *intf,
1088 const struct usb_device_id *id)
1089{
1090 return gspca_dev_probe(intf, id,
1091 sd_desc[id->driver_info],
1092 sizeof(struct sd),
1093 THIS_MODULE);
1094}
1095
1096static struct usb_driver sd_driver = {
1097 .name = MODULE_NAME,
1098 .id_table = device_table,
1099 .probe = sd_probe,
1100 .disconnect = gspca_disconnect,
1101#ifdef CONFIG_PM
1102 .suspend = gspca_suspend,
1103 .resume = gspca_resume,
1104#endif
1105};
1106
1107/* -- module insert / remove -- */
1108static int __init sd_mod_init(void)
1109{
1110 return usb_register(&sd_driver);
1111}
1112static void __exit sd_mod_exit(void)
1113{
1114 usb_deregister(&sd_driver);
1115}
1116
1117module_init(sd_mod_init);
1118module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
new file mode 100644
index 00000000000..5ba96aff225
--- /dev/null
+++ b/drivers/media/video/gspca/sq905.c
@@ -0,0 +1,448 @@
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 MODULE_NAME "sq905"
37
38#include <linux/workqueue.h>
39#include <linux/slab.h>
40#include "gspca.h"
41
42MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
43 "Theodore Kilgore <kilgota@auburn.edu>");
44MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
45MODULE_LICENSE("GPL");
46
47/* Default timeouts, in ms */
48#define SQ905_CMD_TIMEOUT 500
49#define SQ905_DATA_TIMEOUT 1000
50
51/* Maximum transfer size to use. */
52#define SQ905_MAX_TRANSFER 0x8000
53#define FRAME_HEADER_LEN 64
54
55/* The known modes, or registers. These go in the "value" slot. */
56
57/* 00 is "none" obviously */
58
59#define SQ905_BULK_READ 0x03 /* precedes any bulk read */
60#define SQ905_COMMAND 0x06 /* precedes the command codes below */
61#define SQ905_PING 0x07 /* when reading an "idling" command */
62#define SQ905_READ_DONE 0xc0 /* ack bulk read completed */
63
64/* Any non-zero value in the bottom 2 bits of the 2nd byte of
65 * the ID appears to indicate the camera can do 640*480. If the
66 * LSB of that byte is set the image is just upside down, otherwise
67 * it is rotated 180 degrees. */
68#define SQ905_HIRES_MASK 0x00000300
69#define SQ905_ORIENTATION_MASK 0x00000100
70
71/* Some command codes. These go in the "index" slot. */
72
73#define SQ905_ID 0xf0 /* asks for model string */
74#define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */
75#define SQ905_DATA 0x30 /* accesses photo data, not used here */
76#define SQ905_CLEAR 0xa0 /* clear everything */
77#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */
78#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */
79#define SQ905_CAPTURE_HIGH 0x62 /* Starts capture at 640x480 (some cams only) */
80/* note that the capture command also controls the output dimensions */
81
82/* Structure to hold all of our device specific stuff */
83struct sd {
84 struct gspca_dev gspca_dev; /* !! must be the first item */
85
86 /*
87 * Driver stuff
88 */
89 struct work_struct work_struct;
90 struct workqueue_struct *work_thread;
91};
92
93static struct v4l2_pix_format sq905_mode[] = {
94 { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
95 .bytesperline = 160,
96 .sizeimage = 160 * 120,
97 .colorspace = V4L2_COLORSPACE_SRGB,
98 .priv = 0},
99 { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
100 .bytesperline = 320,
101 .sizeimage = 320 * 240,
102 .colorspace = V4L2_COLORSPACE_SRGB,
103 .priv = 0},
104 { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
105 .bytesperline = 640,
106 .sizeimage = 640 * 480,
107 .colorspace = V4L2_COLORSPACE_SRGB,
108 .priv = 0}
109};
110
111/*
112 * Send a command to the camera.
113 */
114static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
115{
116 int ret;
117
118 gspca_dev->usb_buf[0] = '\0';
119 ret = usb_control_msg(gspca_dev->dev,
120 usb_sndctrlpipe(gspca_dev->dev, 0),
121 USB_REQ_SYNCH_FRAME, /* request */
122 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
123 SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
124 SQ905_CMD_TIMEOUT);
125 if (ret < 0) {
126 err("%s: usb_control_msg failed (%d)",
127 __func__, ret);
128 return ret;
129 }
130
131 ret = usb_control_msg(gspca_dev->dev,
132 usb_sndctrlpipe(gspca_dev->dev, 0),
133 USB_REQ_SYNCH_FRAME, /* request */
134 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
135 SQ905_PING, 0, gspca_dev->usb_buf, 1,
136 SQ905_CMD_TIMEOUT);
137 if (ret < 0) {
138 err("%s: usb_control_msg failed 2 (%d)",
139 __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 err("%s: usb_control_msg failed (%d)", __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 err("%s: usb_control_msg failed (%d)", __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 err("bulk read fail (%d) len %d/%d",
199 ret, act_len, size);
200 return -EIO;
201 }
202 return 0;
203}
204
205/* This function is called as a workqueue function and runs whenever the camera
206 * is streaming data. Because it is a workqueue function it is allowed to sleep
207 * so we can use synchronous USB calls. To avoid possible collisions with other
208 * threads attempting to use the camera's USB interface we take the gspca
209 * usb_lock when performing USB operations. In practice the only thing we need
210 * to protect against is the usb_set_interface call that gspca makes during
211 * stream_off as the camera doesn't provide any controls that the user could try
212 * to change.
213 */
214static void sq905_dostream(struct work_struct *work)
215{
216 struct sd *dev = container_of(work, struct sd, work_struct);
217 struct gspca_dev *gspca_dev = &dev->gspca_dev;
218 int bytes_left; /* bytes remaining in current frame. */
219 int data_len; /* size to use for the next read. */
220 int header_read; /* true if we have already read the frame header. */
221 int packet_type;
222 int frame_sz;
223 int ret;
224 u8 *data;
225 u8 *buffer;
226
227 buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
228 if (!buffer) {
229 err("Couldn't allocate USB buffer");
230 goto quit_stream;
231 }
232
233 frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
234 + FRAME_HEADER_LEN;
235
236 while (gspca_dev->present && gspca_dev->streaming) {
237 /* request some data and then read it until we have
238 * a complete frame. */
239 bytes_left = frame_sz;
240 header_read = 0;
241
242 /* Note we do not check for gspca_dev->streaming here, as
243 we must finish reading an entire frame, otherwise the
244 next time we stream we start reading in the middle of a
245 frame. */
246 while (bytes_left > 0 && gspca_dev->present) {
247 data_len = bytes_left > SQ905_MAX_TRANSFER ?
248 SQ905_MAX_TRANSFER : bytes_left;
249 ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
250 if (ret < 0)
251 goto quit_stream;
252 PDEBUG(D_PACK,
253 "Got %d bytes out of %d for frame",
254 data_len, bytes_left);
255 bytes_left -= data_len;
256 data = buffer;
257 if (!header_read) {
258 packet_type = FIRST_PACKET;
259 /* The first 64 bytes of each frame are
260 * a header full of FF 00 bytes */
261 data += FRAME_HEADER_LEN;
262 data_len -= FRAME_HEADER_LEN;
263 header_read = 1;
264 } else if (bytes_left == 0) {
265 packet_type = LAST_PACKET;
266 } else {
267 packet_type = INTER_PACKET;
268 }
269 gspca_frame_add(gspca_dev, packet_type,
270 data, data_len);
271 /* If entire frame fits in one packet we still
272 need to add a LAST_PACKET */
273 if (packet_type == FIRST_PACKET &&
274 bytes_left == 0)
275 gspca_frame_add(gspca_dev, LAST_PACKET,
276 NULL, 0);
277 }
278 if (gspca_dev->present) {
279 /* acknowledge the frame */
280 mutex_lock(&gspca_dev->usb_lock);
281 ret = sq905_ack_frame(gspca_dev);
282 mutex_unlock(&gspca_dev->usb_lock);
283 if (ret < 0)
284 goto quit_stream;
285 }
286 }
287quit_stream:
288 if (gspca_dev->present) {
289 mutex_lock(&gspca_dev->usb_lock);
290 sq905_command(gspca_dev, SQ905_CLEAR);
291 mutex_unlock(&gspca_dev->usb_lock);
292 }
293 kfree(buffer);
294}
295
296/* This function is called at probe time just before sd_init */
297static int sd_config(struct gspca_dev *gspca_dev,
298 const struct usb_device_id *id)
299{
300 struct cam *cam = &gspca_dev->cam;
301 struct sd *dev = (struct sd *) gspca_dev;
302
303 /* We don't use the buffer gspca allocates so make it small. */
304 cam->bulk = 1;
305 cam->bulk_size = 64;
306
307 INIT_WORK(&dev->work_struct, sq905_dostream);
308
309 return 0;
310}
311
312/* called on streamoff with alt==0 and on disconnect */
313/* the usb_lock is held at entry - restore on exit */
314static void sd_stop0(struct gspca_dev *gspca_dev)
315{
316 struct sd *dev = (struct sd *) gspca_dev;
317
318 /* wait for the work queue to terminate */
319 mutex_unlock(&gspca_dev->usb_lock);
320 /* This waits for sq905_dostream to finish */
321 destroy_workqueue(dev->work_thread);
322 dev->work_thread = NULL;
323 mutex_lock(&gspca_dev->usb_lock);
324}
325
326/* this function is called at probe and resume time */
327static int sd_init(struct gspca_dev *gspca_dev)
328{
329 u32 ident;
330 int ret;
331
332 /* connect to the camera and read
333 * the model ID and process that and put it away.
334 */
335 ret = sq905_command(gspca_dev, SQ905_CLEAR);
336 if (ret < 0)
337 return ret;
338 ret = sq905_command(gspca_dev, SQ905_ID);
339 if (ret < 0)
340 return ret;
341 ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
342 if (ret < 0)
343 return ret;
344 /* usb_buf is allocated with kmalloc so is aligned.
345 * Camera model number is the right way round if we assume this
346 * reverse engineered ID is supposed to be big endian. */
347 ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf);
348 ret = sq905_command(gspca_dev, SQ905_CLEAR);
349 if (ret < 0)
350 return ret;
351 PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident);
352 gspca_dev->cam.cam_mode = sq905_mode;
353 gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode);
354 if (!(ident & SQ905_HIRES_MASK))
355 gspca_dev->cam.nmodes--;
356
357 if (ident & SQ905_ORIENTATION_MASK)
358 gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP;
359 else
360 gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP |
361 V4L2_IN_ST_HFLIP;
362 return 0;
363}
364
365/* Set up for getting frames. */
366static int sd_start(struct gspca_dev *gspca_dev)
367{
368 struct sd *dev = (struct sd *) gspca_dev;
369 int ret;
370
371 /* "Open the shutter" and set size, to start capture */
372 switch (gspca_dev->curr_mode) {
373 default:
374/* case 2: */
375 PDEBUG(D_STREAM, "Start streaming at high resolution");
376 ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH);
377 break;
378 case 1:
379 PDEBUG(D_STREAM, "Start streaming at medium resolution");
380 ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
381 break;
382 case 0:
383 PDEBUG(D_STREAM, "Start streaming at low resolution");
384 ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW);
385 }
386
387 if (ret < 0) {
388 PDEBUG(D_ERR, "Start streaming command failed");
389 return ret;
390 }
391 /* Start the workqueue function to do the streaming */
392 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
393 queue_work(dev->work_thread, &dev->work_struct);
394
395 return 0;
396}
397
398/* Table of supported USB devices */
399static const struct usb_device_id device_table[] = {
400 {USB_DEVICE(0x2770, 0x9120)},
401 {}
402};
403
404MODULE_DEVICE_TABLE(usb, device_table);
405
406/* sub-driver description */
407static const struct sd_desc sd_desc = {
408 .name = MODULE_NAME,
409 .config = sd_config,
410 .init = sd_init,
411 .start = sd_start,
412 .stop0 = sd_stop0,
413};
414
415/* -- device connect -- */
416static int sd_probe(struct usb_interface *intf,
417 const struct usb_device_id *id)
418{
419 return gspca_dev_probe(intf, id,
420 &sd_desc,
421 sizeof(struct sd),
422 THIS_MODULE);
423}
424
425static struct usb_driver sd_driver = {
426 .name = MODULE_NAME,
427 .id_table = device_table,
428 .probe = sd_probe,
429 .disconnect = gspca_disconnect,
430#ifdef CONFIG_PM
431 .suspend = gspca_suspend,
432 .resume = gspca_resume,
433#endif
434};
435
436/* -- module insert / remove -- */
437static int __init sd_mod_init(void)
438{
439 return usb_register(&sd_driver);
440}
441
442static void __exit sd_mod_exit(void)
443{
444 usb_deregister(&sd_driver);
445}
446
447module_init(sd_mod_init);
448module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
new file mode 100644
index 00000000000..457563b7a71
--- /dev/null
+++ b/drivers/media/video/gspca/sq905c.c
@@ -0,0 +1,354 @@
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 MODULE_NAME "sq905c"
31
32#include <linux/workqueue.h>
33#include <linux/slab.h>
34#include "gspca.h"
35
36MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
37MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
38MODULE_LICENSE("GPL");
39
40/* Default timeouts, in ms */
41#define SQ905C_CMD_TIMEOUT 500
42#define SQ905C_DATA_TIMEOUT 1000
43
44/* Maximum transfer size to use. */
45#define SQ905C_MAX_TRANSFER 0x8000
46
47#define FRAME_HEADER_LEN 0x50
48
49/* Commands. These go in the "value" slot. */
50#define SQ905C_CLEAR 0xa0 /* clear everything */
51#define SQ905C_GET_ID 0x14f4 /* Read version number */
52#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */
53#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */
54#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */
55
56/* For capture, this must go in the "index" slot. */
57#define SQ905C_CAPTURE_INDEX 0x110f
58
59/* Structure to hold all of our device specific stuff */
60struct sd {
61 struct gspca_dev gspca_dev; /* !! must be the first item */
62 const struct v4l2_pix_format *cap_mode;
63 /* Driver stuff */
64 struct work_struct work_struct;
65 struct workqueue_struct *work_thread;
66};
67
68/*
69 * Most of these cameras will do 640x480 and 320x240. 160x120 works
70 * in theory but gives very poor output. Therefore, not supported.
71 * The 0x2770:0x9050 cameras have max resolution of 320x240.
72 */
73static struct v4l2_pix_format sq905c_mode[] = {
74 { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
75 .bytesperline = 320,
76 .sizeimage = 320 * 240,
77 .colorspace = V4L2_COLORSPACE_SRGB,
78 .priv = 0},
79 { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
80 .bytesperline = 640,
81 .sizeimage = 640 * 480,
82 .colorspace = V4L2_COLORSPACE_SRGB,
83 .priv = 0}
84};
85
86/* Send a command to the camera. */
87static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
88{
89 int ret;
90
91 ret = usb_control_msg(gspca_dev->dev,
92 usb_sndctrlpipe(gspca_dev->dev, 0),
93 USB_REQ_SYNCH_FRAME, /* request */
94 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
95 command, index, NULL, 0,
96 SQ905C_CMD_TIMEOUT);
97 if (ret < 0) {
98 err("%s: usb_control_msg failed (%d)",
99 __func__, ret);
100 return ret;
101 }
102
103 return 0;
104}
105
106static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
107 int size)
108{
109 int ret;
110
111 ret = usb_control_msg(gspca_dev->dev,
112 usb_rcvctrlpipe(gspca_dev->dev, 0),
113 USB_REQ_SYNCH_FRAME, /* request */
114 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
115 command, index, gspca_dev->usb_buf, size,
116 SQ905C_CMD_TIMEOUT);
117 if (ret < 0) {
118 err("%s: usb_control_msg failed (%d)",
119 __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 err("Couldn't allocate USB buffer");
150 goto quit_stream;
151 }
152
153 while (gspca_dev->present && gspca_dev->streaming) {
154 /* Request the header, which tells the size to download */
155 ret = usb_bulk_msg(gspca_dev->dev,
156 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
157 buffer, FRAME_HEADER_LEN, &act_len,
158 SQ905C_DATA_TIMEOUT);
159 PDEBUG(D_STREAM,
160 "Got %d bytes out of %d for header",
161 act_len, FRAME_HEADER_LEN);
162 if (ret < 0 || act_len < FRAME_HEADER_LEN)
163 goto quit_stream;
164 /* size is read from 4 bytes starting 0x40, little endian */
165 bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
166 |(buffer[0x43]<<24);
167 PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
168 /* We keep the header. It has other information, too. */
169 packet_type = FIRST_PACKET;
170 gspca_frame_add(gspca_dev, packet_type,
171 buffer, FRAME_HEADER_LEN);
172 while (bytes_left > 0 && gspca_dev->present) {
173 data_len = bytes_left > SQ905C_MAX_TRANSFER ?
174 SQ905C_MAX_TRANSFER : bytes_left;
175 ret = usb_bulk_msg(gspca_dev->dev,
176 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
177 buffer, data_len, &act_len,
178 SQ905C_DATA_TIMEOUT);
179 if (ret < 0 || act_len < data_len)
180 goto quit_stream;
181 PDEBUG(D_STREAM,
182 "Got %d bytes out of %d for frame",
183 data_len, bytes_left);
184 bytes_left -= data_len;
185 if (bytes_left == 0)
186 packet_type = LAST_PACKET;
187 else
188 packet_type = INTER_PACKET;
189 gspca_frame_add(gspca_dev, packet_type,
190 buffer, data_len);
191 }
192 }
193quit_stream:
194 if (gspca_dev->present) {
195 mutex_lock(&gspca_dev->usb_lock);
196 sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
197 mutex_unlock(&gspca_dev->usb_lock);
198 }
199 kfree(buffer);
200}
201
202/* This function is called at probe time just before sd_init */
203static int sd_config(struct gspca_dev *gspca_dev,
204 const struct usb_device_id *id)
205{
206 struct cam *cam = &gspca_dev->cam;
207 struct sd *dev = (struct sd *) gspca_dev;
208 int ret;
209
210 PDEBUG(D_PROBE,
211 "SQ9050 camera detected"
212 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
213
214 ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
215 if (ret < 0) {
216 PDEBUG(D_ERR, "Get version command failed");
217 return ret;
218 }
219
220 ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
221 if (ret < 0) {
222 PDEBUG(D_ERR, "Reading version command failed");
223 return ret;
224 }
225 /* Note we leave out the usb id and the manufacturing date */
226 PDEBUG(D_PROBE,
227 "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x",
228 gspca_dev->usb_buf[3],
229 gspca_dev->usb_buf[14], gspca_dev->usb_buf[15],
230 gspca_dev->usb_buf[16], gspca_dev->usb_buf[17],
231 gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]);
232
233 cam->cam_mode = sq905c_mode;
234 cam->nmodes = 2;
235 if (gspca_dev->usb_buf[15] == 0)
236 cam->nmodes = 1;
237 /* We don't use the buffer gspca allocates so make it small. */
238 cam->bulk_size = 32;
239 cam->bulk = 1;
240 INIT_WORK(&dev->work_struct, sq905c_dostream);
241 return 0;
242}
243
244/* called on streamoff with alt==0 and on disconnect */
245/* the usb_lock is held at entry - restore on exit */
246static void sd_stop0(struct gspca_dev *gspca_dev)
247{
248 struct sd *dev = (struct sd *) gspca_dev;
249
250 /* wait for the work queue to terminate */
251 mutex_unlock(&gspca_dev->usb_lock);
252 /* This waits for sq905c_dostream to finish */
253 destroy_workqueue(dev->work_thread);
254 dev->work_thread = NULL;
255 mutex_lock(&gspca_dev->usb_lock);
256}
257
258/* this function is called at probe and resume time */
259static int sd_init(struct gspca_dev *gspca_dev)
260{
261 int ret;
262
263 /* connect to the camera and reset it. */
264 ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
265 return ret;
266}
267
268/* Set up for getting frames. */
269static int sd_start(struct gspca_dev *gspca_dev)
270{
271 struct sd *dev = (struct sd *) gspca_dev;
272 int ret;
273
274 dev->cap_mode = gspca_dev->cam.cam_mode;
275 /* "Open the shutter" and set size, to start capture */
276 switch (gspca_dev->width) {
277 case 640:
278 PDEBUG(D_STREAM, "Start streaming at high resolution");
279 dev->cap_mode++;
280 ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
281 SQ905C_CAPTURE_INDEX);
282 break;
283 default: /* 320 */
284 PDEBUG(D_STREAM, "Start streaming at medium resolution");
285 ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
286 SQ905C_CAPTURE_INDEX);
287 }
288
289 if (ret < 0) {
290 PDEBUG(D_ERR, "Start streaming command failed");
291 return ret;
292 }
293 /* Start the workqueue function to do the streaming */
294 dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
295 queue_work(dev->work_thread, &dev->work_struct);
296
297 return 0;
298}
299
300/* Table of supported USB devices */
301static const struct usb_device_id device_table[] = {
302 {USB_DEVICE(0x2770, 0x905c)},
303 {USB_DEVICE(0x2770, 0x9050)},
304 {USB_DEVICE(0x2770, 0x9051)},
305 {USB_DEVICE(0x2770, 0x9052)},
306 {USB_DEVICE(0x2770, 0x913d)},
307 {}
308};
309
310MODULE_DEVICE_TABLE(usb, device_table);
311
312/* sub-driver description */
313static const struct sd_desc sd_desc = {
314 .name = MODULE_NAME,
315 .config = sd_config,
316 .init = sd_init,
317 .start = sd_start,
318 .stop0 = sd_stop0,
319};
320
321/* -- device connect -- */
322static int sd_probe(struct usb_interface *intf,
323 const struct usb_device_id *id)
324{
325 return gspca_dev_probe(intf, id,
326 &sd_desc,
327 sizeof(struct sd),
328 THIS_MODULE);
329}
330
331static struct usb_driver sd_driver = {
332 .name = MODULE_NAME,
333 .id_table = device_table,
334 .probe = sd_probe,
335 .disconnect = gspca_disconnect,
336#ifdef CONFIG_PM
337 .suspend = gspca_suspend,
338 .resume = gspca_resume,
339#endif
340};
341
342/* -- module insert / remove -- */
343static int __init sd_mod_init(void)
344{
345 return usb_register(&sd_driver);
346}
347
348static void __exit sd_mod_exit(void)
349{
350 usb_deregister(&sd_driver);
351}
352
353module_init(sd_mod_init);
354module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c
new file mode 100644
index 00000000000..8215d5dcd45
--- /dev/null
+++ b/drivers/media/video/gspca/sq930x.c
@@ -0,0 +1,1208 @@
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 MODULE_NAME "sq930x"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"
28 "Gerard Klaver <gerard at gkall dot hobby dot nl\n"
29 "Sam Revitch <samr7@cs.washington.edu>");
30MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* Structure to hold all of our device specific stuff */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 u16 expo;
38 u8 gain;
39
40 u8 do_ctrl;
41 u8 gpio[2];
42 u8 sensor;
43 u8 type;
44#define Generic 0
45#define Creative_live_motion 1
46};
47enum sensors {
48 SENSOR_ICX098BQ,
49 SENSOR_LZ24BP,
50 SENSOR_MI0360,
51 SENSOR_MT9V111, /* = MI360SOC */
52 SENSOR_OV7660,
53 SENSOR_OV9630,
54};
55
56static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getexpo(struct gspca_dev *gspca_dev, __s32 *val);
58static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
59static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
60
61static const struct ctrl sd_ctrls[] = {
62 {
63 {
64 .id = V4L2_CID_EXPOSURE,
65 .type = V4L2_CTRL_TYPE_INTEGER,
66 .name = "Exposure",
67 .minimum = 0x0001,
68 .maximum = 0x0fff,
69 .step = 1,
70#define EXPO_DEF 0x0356
71 .default_value = EXPO_DEF,
72 },
73 .set = sd_setexpo,
74 .get = sd_getexpo,
75 },
76 {
77 {
78 .id = V4L2_CID_GAIN,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Gain",
81 .minimum = 0x01,
82 .maximum = 0xff,
83 .step = 1,
84#define GAIN_DEF 0x8d
85 .default_value = GAIN_DEF,
86 },
87 .set = sd_setgain,
88 .get = sd_getgain,
89 },
90};
91
92static struct v4l2_pix_format vga_mode[] = {
93 {320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
94 .bytesperline = 320,
95 .sizeimage = 320 * 240,
96 .colorspace = V4L2_COLORSPACE_SRGB,
97 .priv = 0},
98 {640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
99 .bytesperline = 640,
100 .sizeimage = 640 * 480,
101 .colorspace = V4L2_COLORSPACE_SRGB,
102 .priv = 1},
103};
104
105/* sq930x registers */
106#define SQ930_CTRL_UCBUS_IO 0x0001
107#define SQ930_CTRL_I2C_IO 0x0002
108#define SQ930_CTRL_GPIO 0x0005
109#define SQ930_CTRL_CAP_START 0x0010
110#define SQ930_CTRL_CAP_STOP 0x0011
111#define SQ930_CTRL_SET_EXPOSURE 0x001d
112#define SQ930_CTRL_RESET 0x001e
113#define SQ930_CTRL_GET_DEV_INFO 0x001f
114
115/* gpio 1 (8..15) */
116#define SQ930_GPIO_DFL_I2C_SDA 0x0001
117#define SQ930_GPIO_DFL_I2C_SCL 0x0002
118#define SQ930_GPIO_RSTBAR 0x0004
119#define SQ930_GPIO_EXTRA1 0x0040
120#define SQ930_GPIO_EXTRA2 0x0080
121/* gpio 3 (24..31) */
122#define SQ930_GPIO_POWER 0x0200
123#define SQ930_GPIO_DFL_LED 0x1000
124
125struct ucbus_write_cmd {
126 u16 bw_addr;
127 u8 bw_data;
128};
129struct i2c_write_cmd {
130 u8 reg;
131 u16 val;
132};
133
134static const struct ucbus_write_cmd icx098bq_start_0[] = {
135 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce},
136 {0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e},
137 {0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02},
138 {0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02},
139 {0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00},
140 {0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04},
141 {0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00},
142 {0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48},
143 {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
144 {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
145 {0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff},
146 {0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
147 {0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00},
148 {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
149 {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
150 {0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c},
151 {0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30},
152 {0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30},
153 {0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc},
154 {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
155 {0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00},
156 {0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00},
157 {0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa},
158 {0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa},
159 {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
160 {0xf800, 0x03}
161};
162static const struct ucbus_write_cmd icx098bq_start_1[] = {
163 {0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
164 {0xf5f4, 0xc0},
165 {0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
166 {0xf5f4, 0xc0},
167 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
168 {0xf5f9, 0x00}
169};
170
171static const struct ucbus_write_cmd icx098bq_start_2[] = {
172 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00},
173 {0xf807, 0x7f}, {0xf800, 0x03},
174 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00},
175 {0xf807, 0x7f}, {0xf800, 0x03},
176 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0},
177 {0xf807, 0x7f}, {0xf800, 0x03},
178 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
179 {0xf807, 0x7f}, {0xf800, 0x03}
180};
181
182static const struct ucbus_write_cmd lz24bp_start_0[] = {
183 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe},
184 {0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06},
185 {0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02},
186 {0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00},
187 {0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00},
188 {0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03},
189 {0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00},
190 {0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48},
191 {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
192 {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
193 {0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0},
194 {0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
195 {0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00},
196 {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
197 {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
198 {0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30},
199 {0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c},
200 {0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c},
201 {0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d},
202 {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
203 {0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d},
204 {0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d},
205 {0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04},
206 {0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04},
207 {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
208 {0xf800, 0x03}
209};
210static const struct ucbus_write_cmd lz24bp_start_1_gen[] = {
211 {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
212 {0xf5f4, 0xb3},
213 {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
214 {0xf5f4, 0xb3},
215 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
216 {0xf5f9, 0x00}
217};
218
219static const struct ucbus_write_cmd lz24bp_start_1_clm[] = {
220 {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
221 {0xf5f4, 0xc0},
222 {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
223 {0xf5f4, 0xc0},
224 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
225 {0xf5f9, 0x00}
226};
227
228static const struct ucbus_write_cmd lz24bp_start_2[] = {
229 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00},
230 {0xf807, 0x7f}, {0xf800, 0x03},
231 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00},
232 {0xf807, 0x7f}, {0xf800, 0x03},
233 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48},
234 {0xf807, 0x7f}, {0xf800, 0x03},
235 {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
236 {0xf807, 0x7f}, {0xf800, 0x03}
237};
238
239static const struct ucbus_write_cmd mi0360_start_0[] = {
240 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc},
241 {0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00}
242};
243static const struct i2c_write_cmd mi0360_init_23[] = {
244 {0x30, 0x0040}, /* reserved - def 0x0005 */
245 {0x31, 0x0000}, /* reserved - def 0x002a */
246 {0x34, 0x0100}, /* reserved - def 0x0100 */
247 {0x3d, 0x068f}, /* reserved - def 0x068f */
248};
249static const struct i2c_write_cmd mi0360_init_24[] = {
250 {0x03, 0x01e5}, /* window height */
251 {0x04, 0x0285}, /* window width */
252};
253static const struct i2c_write_cmd mi0360_init_25[] = {
254 {0x35, 0x0020}, /* global gain */
255 {0x2b, 0x0020}, /* green1 gain */
256 {0x2c, 0x002a}, /* blue gain */
257 {0x2d, 0x0028}, /* red gain */
258 {0x2e, 0x0020}, /* green2 gain */
259};
260static const struct ucbus_write_cmd mi0360_start_1[] = {
261 {0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
262 {0xf5f4, 0xa6},
263 {0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
264 {0xf5f4, 0xa6},
265 {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
266 {0xf5f9, 0x00}
267};
268static const struct i2c_write_cmd mi0360_start_2[] = {
269 {0x62, 0x041d}, /* reserved - def 0x0418 */
270};
271static const struct i2c_write_cmd mi0360_start_3[] = {
272 {0x05, 0x007b}, /* horiz blanking */
273};
274static const struct i2c_write_cmd mi0360_start_4[] = {
275 {0x05, 0x03f5}, /* horiz blanking */
276};
277
278static const struct i2c_write_cmd mt9v111_init_0[] = {
279 {0x01, 0x0001}, /* select IFP/SOC registers */
280 {0x06, 0x300c}, /* operating mode control */
281 {0x08, 0xcc00}, /* output format control (RGB) */
282 {0x01, 0x0004}, /* select sensor core registers */
283};
284static const struct i2c_write_cmd mt9v111_init_1[] = {
285 {0x03, 0x01e5}, /* window height */
286 {0x04, 0x0285}, /* window width */
287};
288static const struct i2c_write_cmd mt9v111_init_2[] = {
289 {0x30, 0x7800},
290 {0x31, 0x0000},
291 {0x07, 0x3002}, /* output control */
292 {0x35, 0x0020}, /* global gain */
293 {0x2b, 0x0020}, /* green1 gain */
294 {0x2c, 0x0020}, /* blue gain */
295 {0x2d, 0x0020}, /* red gain */
296 {0x2e, 0x0020}, /* green2 gain */
297};
298static const struct ucbus_write_cmd mt9v111_start_1[] = {
299 {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
300 {0xf5f4, 0xaa},
301 {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
302 {0xf5f4, 0xaa},
303 {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a},
304 {0xf5f9, 0x0a}
305};
306static const struct i2c_write_cmd mt9v111_init_3[] = {
307 {0x62, 0x0405},
308};
309static const struct i2c_write_cmd mt9v111_init_4[] = {
310/* {0x05, 0x00ce}, */
311 {0x05, 0x005d}, /* horizontal blanking */
312};
313
314static const struct ucbus_write_cmd ov7660_start_0[] = {
315 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0},
316 {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03}
317};
318
319static const struct ucbus_write_cmd ov9630_start_0[] = {
320 {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00},
321 {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03}
322};
323
324/* start parameters indexed by [sensor][mode] */
325static const struct cap_s {
326 u8 cc_sizeid;
327 u8 cc_bytes[32];
328} capconfig[4][2] = {
329 [SENSOR_ICX098BQ] = {
330 {2, /* Bayer 320x240 */
331 {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
332 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
335 {4, /* Bayer 640x480 */
336 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
337 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
340 },
341 [SENSOR_LZ24BP] = {
342 {2, /* Bayer 320x240 */
343 {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
344 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
347 {4, /* Bayer 640x480 */
348 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
349 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
352 },
353 [SENSOR_MI0360] = {
354 {2, /* Bayer 320x240 */
355 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
356 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
359 {4, /* Bayer 640x480 */
360 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
361 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
364 },
365 [SENSOR_MT9V111] = {
366 {2, /* Bayer 320x240 */
367 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
368 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
371 {4, /* Bayer 640x480 */
372 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
373 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
376 },
377};
378
379struct sensor_s {
380 const char *name;
381 u8 i2c_addr;
382 u8 i2c_dum;
383 u8 gpio[5];
384 u8 cmd_len;
385 const struct ucbus_write_cmd *cmd;
386};
387
388static const struct sensor_s sensor_tb[] = {
389 [SENSOR_ICX098BQ] = {
390 "icx098bp",
391 0x00, 0x00,
392 {0,
393 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
394 SQ930_GPIO_DFL_I2C_SDA,
395 0,
396 SQ930_GPIO_RSTBAR
397 },
398 8, icx098bq_start_0
399 },
400 [SENSOR_LZ24BP] = {
401 "lz24bp",
402 0x00, 0x00,
403 {0,
404 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
405 SQ930_GPIO_DFL_I2C_SDA,
406 0,
407 SQ930_GPIO_RSTBAR
408 },
409 8, lz24bp_start_0
410 },
411 [SENSOR_MI0360] = {
412 "mi0360",
413 0x5d, 0x80,
414 {SQ930_GPIO_RSTBAR,
415 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
416 SQ930_GPIO_DFL_I2C_SDA,
417 0,
418 0
419 },
420 7, mi0360_start_0
421 },
422 [SENSOR_MT9V111] = {
423 "mt9v111",
424 0x5c, 0x7f,
425 {SQ930_GPIO_RSTBAR,
426 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
427 SQ930_GPIO_DFL_I2C_SDA,
428 0,
429 0
430 },
431 7, mi0360_start_0
432 },
433 [SENSOR_OV7660] = {
434 "ov7660",
435 0x21, 0x00,
436 {0,
437 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
438 SQ930_GPIO_DFL_I2C_SDA,
439 0,
440 SQ930_GPIO_RSTBAR
441 },
442 7, ov7660_start_0
443 },
444 [SENSOR_OV9630] = {
445 "ov9630",
446 0x30, 0x00,
447 {0,
448 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
449 SQ930_GPIO_DFL_I2C_SDA,
450 0,
451 SQ930_GPIO_RSTBAR
452 },
453 7, ov9630_start_0
454 },
455};
456
457static void reg_r(struct gspca_dev *gspca_dev,
458 u16 value, int len)
459{
460 int ret;
461
462 if (gspca_dev->usb_err < 0)
463 return;
464 ret = usb_control_msg(gspca_dev->dev,
465 usb_rcvctrlpipe(gspca_dev->dev, 0),
466 0x0c,
467 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
468 value, 0, gspca_dev->usb_buf, len,
469 500);
470 if (ret < 0) {
471 err("reg_r %04x failed %d", value, ret);
472 gspca_dev->usb_err = ret;
473 }
474}
475
476static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
477{
478 int ret;
479
480 if (gspca_dev->usb_err < 0)
481 return;
482 PDEBUG(D_USBO, "reg_w v: %04x i: %04x", value, index);
483 ret = usb_control_msg(gspca_dev->dev,
484 usb_sndctrlpipe(gspca_dev->dev, 0),
485 0x0c, /* request */
486 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
487 value, index, NULL, 0,
488 500);
489 msleep(30);
490 if (ret < 0) {
491 err("reg_w %04x %04x failed %d", value, index, ret);
492 gspca_dev->usb_err = ret;
493 }
494}
495
496static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,
497 const u8 *data, int len)
498{
499 int ret;
500
501 if (gspca_dev->usb_err < 0)
502 return;
503 PDEBUG(D_USBO, "reg_wb v: %04x i: %04x %02x...%02x",
504 value, index, *data, data[len - 1]);
505 memcpy(gspca_dev->usb_buf, data, len);
506 ret = usb_control_msg(gspca_dev->dev,
507 usb_sndctrlpipe(gspca_dev->dev, 0),
508 0x0c, /* request */
509 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
510 value, index, gspca_dev->usb_buf, len,
511 1000);
512 msleep(30);
513 if (ret < 0) {
514 err("reg_wb %04x %04x failed %d", value, index, ret);
515 gspca_dev->usb_err = ret;
516 }
517}
518
519static void i2c_write(struct sd *sd,
520 const struct i2c_write_cmd *cmd,
521 int ncmds)
522{
523 struct gspca_dev *gspca_dev = &sd->gspca_dev;
524 const struct sensor_s *sensor;
525 u16 val, idx;
526 u8 *buf;
527 int ret;
528
529 if (gspca_dev->usb_err < 0)
530 return;
531
532 sensor = &sensor_tb[sd->sensor];
533
534 val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO;
535 idx = (cmd->val & 0xff00) | cmd->reg;
536
537 buf = gspca_dev->usb_buf;
538 *buf++ = sensor->i2c_dum;
539 *buf++ = cmd->val;
540
541 while (--ncmds > 0) {
542 cmd++;
543 *buf++ = cmd->reg;
544 *buf++ = cmd->val >> 8;
545 *buf++ = sensor->i2c_dum;
546 *buf++ = cmd->val;
547 }
548
549 PDEBUG(D_USBO, "i2c_w v: %04x i: %04x %02x...%02x",
550 val, idx, gspca_dev->usb_buf[0], buf[-1]);
551 ret = usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
553 0x0c, /* request */
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
555 val, idx,
556 gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
557 500);
558 if (ret < 0) {
559 err("i2c_write failed %d", ret);
560 gspca_dev->usb_err = ret;
561 }
562}
563
564static void ucbus_write(struct gspca_dev *gspca_dev,
565 const struct ucbus_write_cmd *cmd,
566 int ncmds,
567 int batchsize)
568{
569 u8 *buf;
570 u16 val, idx;
571 int len, ret;
572
573 if (gspca_dev->usb_err < 0)
574 return;
575
576#ifdef GSPCA_DEBUG
577 if ((batchsize - 1) * 3 > USB_BUF_SZ) {
578 err("Bug: usb_buf overflow");
579 gspca_dev->usb_err = -ENOMEM;
580 return;
581 }
582#endif
583
584 for (;;) {
585 len = ncmds;
586 if (len > batchsize)
587 len = batchsize;
588 ncmds -= len;
589
590 val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO;
591 idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8);
592
593 buf = gspca_dev->usb_buf;
594 while (--len > 0) {
595 cmd++;
596 *buf++ = cmd->bw_addr;
597 *buf++ = cmd->bw_addr >> 8;
598 *buf++ = cmd->bw_data;
599 }
600 if (buf != gspca_dev->usb_buf)
601 PDEBUG(D_USBO, "ucbus v: %04x i: %04x %02x...%02x",
602 val, idx,
603 gspca_dev->usb_buf[0], buf[-1]);
604 else
605 PDEBUG(D_USBO, "ucbus v: %04x i: %04x",
606 val, idx);
607 ret = usb_control_msg(gspca_dev->dev,
608 usb_sndctrlpipe(gspca_dev->dev, 0),
609 0x0c, /* request */
610 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
611 val, idx,
612 gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
613 500);
614 if (ret < 0) {
615 err("ucbus_write failed %d", ret);
616 gspca_dev->usb_err = ret;
617 return;
618 }
619 msleep(30);
620 if (ncmds <= 0)
621 break;
622 cmd++;
623 }
624}
625
626static void gpio_set(struct sd *sd, u16 val, u16 mask)
627{
628 struct gspca_dev *gspca_dev = &sd->gspca_dev;
629
630 if (mask & 0x00ff) {
631 sd->gpio[0] &= ~mask;
632 sd->gpio[0] |= val;
633 reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO,
634 ~sd->gpio[0] << 8);
635 }
636 mask >>= 8;
637 val >>= 8;
638 if (mask) {
639 sd->gpio[1] &= ~mask;
640 sd->gpio[1] |= val;
641 reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO,
642 ~sd->gpio[1] << 8);
643 }
644}
645
646static void gpio_init(struct sd *sd,
647 const u8 *gpio)
648{
649 gpio_set(sd, *gpio++, 0x000f);
650 gpio_set(sd, *gpio++, 0x000f);
651 gpio_set(sd, *gpio++, 0x000f);
652 gpio_set(sd, *gpio++, 0x000f);
653 gpio_set(sd, *gpio, 0x000f);
654}
655
656static void bridge_init(struct sd *sd)
657{
658 static const struct ucbus_write_cmd clkfreq_cmd = {
659 0xf031, 0 /* SQ930_CLKFREQ_60MHZ */
660 };
661
662 ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1);
663
664 gpio_set(sd, SQ930_GPIO_POWER, 0xff00);
665}
666
667static void cmos_probe(struct gspca_dev *gspca_dev)
668{
669 struct sd *sd = (struct sd *) gspca_dev;
670 int i;
671 const struct sensor_s *sensor;
672 static const u8 probe_order[] = {
673/* SENSOR_LZ24BP, (tested as ccd) */
674 SENSOR_OV9630,
675 SENSOR_MI0360,
676 SENSOR_OV7660,
677 SENSOR_MT9V111,
678 };
679
680 for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
681 sensor = &sensor_tb[probe_order[i]];
682 ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8);
683 gpio_init(sd, sensor->gpio);
684 msleep(100);
685 reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1);
686 msleep(100);
687 if (gspca_dev->usb_buf[0] != 0)
688 break;
689 }
690 if (i >= ARRAY_SIZE(probe_order)) {
691 err("Unknown sensor");
692 gspca_dev->usb_err = -EINVAL;
693 return;
694 }
695 sd->sensor = probe_order[i];
696 switch (sd->sensor) {
697 case SENSOR_OV7660:
698 case SENSOR_OV9630:
699 err("Sensor %s not yet treated", sensor_tb[sd->sensor].name);
700 gspca_dev->usb_err = -EINVAL;
701 break;
702 }
703}
704
705static void mt9v111_init(struct gspca_dev *gspca_dev)
706{
707 int i, nwait;
708 static const u8 cmd_001b[] = {
709 0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00,
710 0x00, 0x00, 0x00
711 };
712 static const u8 cmd_011b[][7] = {
713 {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00},
714 {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00},
715 {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00},
716 {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00},
717 };
718
719 reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b);
720 for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) {
721 reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i],
722 ARRAY_SIZE(cmd_011b[0]));
723 msleep(400);
724 nwait = 20;
725 for (;;) {
726 reg_r(gspca_dev, 0x031b, 1);
727 if (gspca_dev->usb_buf[0] == 0
728 || gspca_dev->usb_err != 0)
729 break;
730 if (--nwait < 0) {
731 PDEBUG(D_PROBE, "mt9v111_init timeout");
732 gspca_dev->usb_err = -ETIME;
733 return;
734 }
735 msleep(50);
736 }
737 }
738}
739
740static void global_init(struct sd *sd, int first_time)
741{
742 switch (sd->sensor) {
743 case SENSOR_ICX098BQ:
744 if (first_time)
745 ucbus_write(&sd->gspca_dev,
746 icx098bq_start_0,
747 8, 8);
748 gpio_init(sd, sensor_tb[sd->sensor].gpio);
749 break;
750 case SENSOR_LZ24BP:
751 if (sd->type != Creative_live_motion)
752 gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff);
753 else
754 gpio_set(sd, 0, 0x00ff);
755 msleep(50);
756 if (first_time)
757 ucbus_write(&sd->gspca_dev,
758 lz24bp_start_0,
759 8, 8);
760 gpio_init(sd, sensor_tb[sd->sensor].gpio);
761 break;
762 case SENSOR_MI0360:
763 if (first_time)
764 ucbus_write(&sd->gspca_dev,
765 mi0360_start_0,
766 ARRAY_SIZE(mi0360_start_0),
767 8);
768 gpio_init(sd, sensor_tb[sd->sensor].gpio);
769 gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2);
770 break;
771 default:
772/* case SENSOR_MT9V111: */
773 if (first_time)
774 mt9v111_init(&sd->gspca_dev);
775 else
776 gpio_init(sd, sensor_tb[sd->sensor].gpio);
777 break;
778 }
779}
780
781static void lz24bp_ppl(struct sd *sd, u16 ppl)
782{
783 struct ucbus_write_cmd cmds[2] = {
784 {0xf810, ppl >> 8},
785 {0xf811, ppl}
786 };
787
788 ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2);
789}
790
791static void setexposure(struct gspca_dev *gspca_dev)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794 int i, integclks, intstartclk, frameclks, min_frclk;
795 const struct sensor_s *sensor;
796 u16 cmd;
797 u8 buf[15];
798
799 integclks = sd->expo;
800 i = 0;
801 cmd = SQ930_CTRL_SET_EXPOSURE;
802
803 switch (sd->sensor) {
804 case SENSOR_ICX098BQ: /* ccd */
805 case SENSOR_LZ24BP:
806 min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f;
807 if (integclks >= min_frclk) {
808 intstartclk = 0;
809 frameclks = integclks;
810 } else {
811 intstartclk = min_frclk - integclks;
812 frameclks = min_frclk;
813 }
814 buf[i++] = intstartclk >> 8;
815 buf[i++] = intstartclk;
816 buf[i++] = frameclks >> 8;
817 buf[i++] = frameclks;
818 buf[i++] = sd->gain;
819 break;
820 default: /* cmos */
821/* case SENSOR_MI0360: */
822/* case SENSOR_MT9V111: */
823 cmd |= 0x0100;
824 sensor = &sensor_tb[sd->sensor];
825 buf[i++] = sensor->i2c_addr; /* i2c_slave_addr */
826 buf[i++] = 0x08; /* 2 * ni2c */
827 buf[i++] = 0x09; /* reg = shutter width */
828 buf[i++] = integclks >> 8; /* val H */
829 buf[i++] = sensor->i2c_dum;
830 buf[i++] = integclks; /* val L */
831 buf[i++] = 0x35; /* reg = global gain */
832 buf[i++] = 0x00; /* val H */
833 buf[i++] = sensor->i2c_dum;
834 buf[i++] = 0x80 + sd->gain / 2; /* val L */
835 buf[i++] = 0x00;
836 buf[i++] = 0x00;
837 buf[i++] = 0x00;
838 buf[i++] = 0x00;
839 buf[i++] = 0x83;
840 break;
841 }
842 reg_wb(gspca_dev, cmd, 0, buf, i);
843}
844
845/* This function is called at probe time just before sd_init */
846static int sd_config(struct gspca_dev *gspca_dev,
847 const struct usb_device_id *id)
848{
849 struct sd *sd = (struct sd *) gspca_dev;
850 struct cam *cam = &gspca_dev->cam;
851
852 sd->sensor = id->driver_info >> 8;
853 sd->type = id->driver_info;
854
855 cam->cam_mode = vga_mode;
856 cam->nmodes = ARRAY_SIZE(vga_mode);
857
858 cam->bulk = 1;
859
860 sd->gain = GAIN_DEF;
861 sd->expo = EXPO_DEF;
862
863 return 0;
864}
865
866/* this function is called at probe and resume time */
867static int sd_init(struct gspca_dev *gspca_dev)
868{
869 struct sd *sd = (struct sd *) gspca_dev;
870
871 sd->gpio[0] = sd->gpio[1] = 0xff; /* force gpio rewrite */
872
873/*fixme: is this needed for icx098bp and mi0360?
874 if (sd->sensor != SENSOR_LZ24BP)
875 reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000);
876 */
877
878 reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8);
879 if (gspca_dev->usb_err < 0)
880 return gspca_dev->usb_err;
881
882/* it returns:
883 * 03 00 12 93 0b f6 c9 00 live! ultra
884 * 03 00 07 93 0b f6 ca 00 live! ultra for notebook
885 * 03 00 12 93 0b fe c8 00 Trust WB-3500T
886 * 02 00 06 93 0b fe c8 00 Joy-IT 318S
887 * 03 00 12 93 0b f6 cf 00 icam tracer - sensor icx098bq
888 * 02 00 12 93 0b fe cf 00 ProQ Motion Webcam
889 *
890 * byte
891 * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit)
892 * 1: 00
893 * 2: 06 / 07 / 12 = mode webcam? firmware??
894 * 3: 93 chip = 930b (930b or 930c)
895 * 4: 0b
896 * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors)
897 * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam?
898 * 7: 00
899 */
900 PDEBUG(D_PROBE, "info: %02x %02x %02x %02x %02x %02x %02x %02x",
901 gspca_dev->usb_buf[0],
902 gspca_dev->usb_buf[1],
903 gspca_dev->usb_buf[2],
904 gspca_dev->usb_buf[3],
905 gspca_dev->usb_buf[4],
906 gspca_dev->usb_buf[5],
907 gspca_dev->usb_buf[6],
908 gspca_dev->usb_buf[7]);
909
910 bridge_init(sd);
911
912 if (sd->sensor == SENSOR_MI0360) {
913
914 /* no sensor probe for icam tracer */
915 if (gspca_dev->usb_buf[5] == 0xf6) /* if ccd */
916 sd->sensor = SENSOR_ICX098BQ;
917 else
918 cmos_probe(gspca_dev);
919 }
920 if (gspca_dev->usb_err >= 0) {
921 PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
922 global_init(sd, 1);
923 }
924 return gspca_dev->usb_err;
925}
926
927/* send the start/stop commands to the webcam */
928static void send_start(struct gspca_dev *gspca_dev)
929{
930 struct sd *sd = (struct sd *) gspca_dev;
931 const struct cap_s *cap;
932 int mode;
933
934 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
935 cap = &capconfig[sd->sensor][mode];
936 reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START,
937 0x0a00 | cap->cc_sizeid,
938 cap->cc_bytes, 32);
939}
940
941static void send_stop(struct gspca_dev *gspca_dev)
942{
943 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0);
944}
945
946/* function called at start time before URB creation */
947static int sd_isoc_init(struct gspca_dev *gspca_dev)
948{
949 struct sd *sd = (struct sd *) gspca_dev;
950
951 gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */
952 sd->do_ctrl = 0;
953 gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8;
954 return 0;
955}
956
957/* start the capture */
958static int sd_start(struct gspca_dev *gspca_dev)
959{
960 struct sd *sd = (struct sd *) gspca_dev;
961 int mode;
962
963 bridge_init(sd);
964 global_init(sd, 0);
965 msleep(100);
966
967 switch (sd->sensor) {
968 case SENSOR_ICX098BQ:
969 ucbus_write(gspca_dev, icx098bq_start_0,
970 ARRAY_SIZE(icx098bq_start_0),
971 8);
972 ucbus_write(gspca_dev, icx098bq_start_1,
973 ARRAY_SIZE(icx098bq_start_1),
974 5);
975 ucbus_write(gspca_dev, icx098bq_start_2,
976 ARRAY_SIZE(icx098bq_start_2),
977 6);
978 msleep(50);
979
980 /* 1st start */
981 send_start(gspca_dev);
982 gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
983 msleep(70);
984 reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000);
985 gpio_set(sd, 0x7f, 0x00ff);
986
987 /* 2nd start */
988 send_start(gspca_dev);
989 gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
990 goto out;
991 case SENSOR_LZ24BP:
992 ucbus_write(gspca_dev, lz24bp_start_0,
993 ARRAY_SIZE(lz24bp_start_0),
994 8);
995 if (sd->type != Creative_live_motion)
996 ucbus_write(gspca_dev, lz24bp_start_1_gen,
997 ARRAY_SIZE(lz24bp_start_1_gen),
998 5);
999 else
1000 ucbus_write(gspca_dev, lz24bp_start_1_clm,
1001 ARRAY_SIZE(lz24bp_start_1_clm),
1002 5);
1003 ucbus_write(gspca_dev, lz24bp_start_2,
1004 ARRAY_SIZE(lz24bp_start_2),
1005 6);
1006 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1007 lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310);
1008 msleep(10);
1009 break;
1010 case SENSOR_MI0360:
1011 ucbus_write(gspca_dev, mi0360_start_0,
1012 ARRAY_SIZE(mi0360_start_0),
1013 8);
1014 i2c_write(sd, mi0360_init_23,
1015 ARRAY_SIZE(mi0360_init_23));
1016 i2c_write(sd, mi0360_init_24,
1017 ARRAY_SIZE(mi0360_init_24));
1018 i2c_write(sd, mi0360_init_25,
1019 ARRAY_SIZE(mi0360_init_25));
1020 ucbus_write(gspca_dev, mi0360_start_1,
1021 ARRAY_SIZE(mi0360_start_1),
1022 5);
1023 i2c_write(sd, mi0360_start_2,
1024 ARRAY_SIZE(mi0360_start_2));
1025 i2c_write(sd, mi0360_start_3,
1026 ARRAY_SIZE(mi0360_start_3));
1027
1028 /* 1st start */
1029 send_start(gspca_dev);
1030 msleep(60);
1031 send_stop(gspca_dev);
1032
1033 i2c_write(sd,
1034 mi0360_start_4, ARRAY_SIZE(mi0360_start_4));
1035 break;
1036 default:
1037/* case SENSOR_MT9V111: */
1038 ucbus_write(gspca_dev, mi0360_start_0,
1039 ARRAY_SIZE(mi0360_start_0),
1040 8);
1041 i2c_write(sd, mt9v111_init_0,
1042 ARRAY_SIZE(mt9v111_init_0));
1043 i2c_write(sd, mt9v111_init_1,
1044 ARRAY_SIZE(mt9v111_init_1));
1045 i2c_write(sd, mt9v111_init_2,
1046 ARRAY_SIZE(mt9v111_init_2));
1047 ucbus_write(gspca_dev, mt9v111_start_1,
1048 ARRAY_SIZE(mt9v111_start_1),
1049 5);
1050 i2c_write(sd, mt9v111_init_3,
1051 ARRAY_SIZE(mt9v111_init_3));
1052 i2c_write(sd, mt9v111_init_4,
1053 ARRAY_SIZE(mt9v111_init_4));
1054 break;
1055 }
1056
1057 send_start(gspca_dev);
1058out:
1059 msleep(1000);
1060
1061 if (sd->sensor == SENSOR_MT9V111)
1062 gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED);
1063
1064 sd->do_ctrl = 1; /* set the exposure */
1065
1066 return gspca_dev->usb_err;
1067}
1068
1069static void sd_stopN(struct gspca_dev *gspca_dev)
1070{
1071 struct sd *sd = (struct sd *) gspca_dev;
1072
1073 if (sd->sensor == SENSOR_MT9V111)
1074 gpio_set(sd, 0, SQ930_GPIO_DFL_LED);
1075 send_stop(gspca_dev);
1076}
1077
1078/* function called when the application gets a new frame */
1079/* It sets the exposure if required and restart the bulk transfer. */
1080static void sd_dq_callback(struct gspca_dev *gspca_dev)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
1083 int ret;
1084
1085 if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0)
1086 return;
1087 sd->do_ctrl = 0;
1088
1089 setexposure(gspca_dev);
1090
1091 gspca_dev->cam.bulk_nurbs = 1;
1092 ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
1093 if (ret < 0)
1094 err("sd_dq_callback() err %d", ret);
1095
1096 /* wait a little time, otherwise the webcam crashes */
1097 msleep(100);
1098}
1099
1100static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1101 u8 *data, /* isoc packet */
1102 int len) /* iso packet length */
1103{
1104 struct sd *sd = (struct sd *) gspca_dev;
1105
1106 if (sd->do_ctrl)
1107 gspca_dev->cam.bulk_nurbs = 0;
1108 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
1109 gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8);
1110 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1111}
1112
1113static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1114{
1115 struct sd *sd = (struct sd *) gspca_dev;
1116
1117 sd->gain = val;
1118 if (gspca_dev->streaming)
1119 sd->do_ctrl = 1;
1120 return 0;
1121}
1122
1123static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1124{
1125 struct sd *sd = (struct sd *) gspca_dev;
1126
1127 *val = sd->gain;
1128 return 0;
1129}
1130static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val)
1131{
1132 struct sd *sd = (struct sd *) gspca_dev;
1133
1134 sd->expo = val;
1135 if (gspca_dev->streaming)
1136 sd->do_ctrl = 1;
1137 return 0;
1138}
1139
1140static int sd_getexpo(struct gspca_dev *gspca_dev, __s32 *val)
1141{
1142 struct sd *sd = (struct sd *) gspca_dev;
1143
1144 *val = sd->expo;
1145 return 0;
1146}
1147
1148/* sub-driver description */
1149static const struct sd_desc sd_desc = {
1150 .name = MODULE_NAME,
1151 .ctrls = sd_ctrls,
1152 .nctrls = ARRAY_SIZE(sd_ctrls),
1153 .config = sd_config,
1154 .init = sd_init,
1155 .isoc_init = sd_isoc_init,
1156 .start = sd_start,
1157 .stopN = sd_stopN,
1158 .pkt_scan = sd_pkt_scan,
1159 .dq_callback = sd_dq_callback,
1160};
1161
1162/* Table of supported USB devices */
1163#define ST(sensor, type) \
1164 .driver_info = (SENSOR_ ## sensor << 8) \
1165 | (type)
1166static const struct usb_device_id device_table[] = {
1167 {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)},
1168 {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)},
1169 {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)},
1170 {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)},
1171 {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)},
1172 {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)},
1173 {}
1174};
1175MODULE_DEVICE_TABLE(usb, device_table);
1176
1177
1178/* -- device connect -- */
1179static int sd_probe(struct usb_interface *intf,
1180 const struct usb_device_id *id)
1181{
1182 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1183 THIS_MODULE);
1184}
1185
1186static struct usb_driver sd_driver = {
1187 .name = MODULE_NAME,
1188 .id_table = device_table,
1189 .probe = sd_probe,
1190 .disconnect = gspca_disconnect,
1191#ifdef CONFIG_PM
1192 .suspend = gspca_suspend,
1193 .resume = gspca_resume,
1194#endif
1195};
1196
1197/* -- module insert / remove -- */
1198static int __init sd_mod_init(void)
1199{
1200 return usb_register(&sd_driver);
1201}
1202static void __exit sd_mod_exit(void)
1203{
1204 usb_deregister(&sd_driver);
1205}
1206
1207module_init(sd_mod_init);
1208module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
new file mode 100644
index 00000000000..763747700f1
--- /dev/null
+++ b/drivers/media/video/gspca/stk014.c
@@ -0,0 +1,531 @@
1/*
2 * Syntek DV4000 (STK014) subdriver
3 *
4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "stk014"
22
23#include "gspca.h"
24#include "jpeg.h"
25
26MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
27MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
28MODULE_LICENSE("GPL");
29
30/* controls */
31enum e_ctrl {
32 BRIGHTNESS,
33 CONTRAST,
34 COLORS,
35 LIGHTFREQ,
36 NCTRLS /* number of controls */
37};
38
39/* specific webcam descriptor */
40struct sd {
41 struct gspca_dev gspca_dev; /* !! must be the first item */
42
43 struct gspca_ctrl ctrls[NCTRLS];
44
45 u8 quality;
46#define QUALITY_MIN 70
47#define QUALITY_MAX 95
48#define QUALITY_DEF 88
49
50 u8 jpeg_hdr[JPEG_HDR_SZ];
51};
52
53/* V4L2 controls supported by the driver */
54static void setbrightness(struct gspca_dev *gspca_dev);
55static void setcontrast(struct gspca_dev *gspca_dev);
56static void setcolors(struct gspca_dev *gspca_dev);
57static void setlightfreq(struct gspca_dev *gspca_dev);
58
59static const struct ctrl sd_ctrls[NCTRLS] = {
60[BRIGHTNESS] = {
61 {
62 .id = V4L2_CID_BRIGHTNESS,
63 .type = V4L2_CTRL_TYPE_INTEGER,
64 .name = "Brightness",
65 .minimum = 0,
66 .maximum = 255,
67 .step = 1,
68 .default_value = 127,
69 },
70 .set_control = setbrightness
71 },
72[CONTRAST] = {
73 {
74 .id = V4L2_CID_CONTRAST,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Contrast",
77 .minimum = 0,
78 .maximum = 255,
79 .step = 1,
80 .default_value = 127,
81 },
82 .set_control = setcontrast
83 },
84[COLORS] = {
85 {
86 .id = V4L2_CID_SATURATION,
87 .type = V4L2_CTRL_TYPE_INTEGER,
88 .name = "Color",
89 .minimum = 0,
90 .maximum = 255,
91 .step = 1,
92 .default_value = 127,
93 },
94 .set_control = setcolors
95 },
96[LIGHTFREQ] = {
97 {
98 .id = V4L2_CID_POWER_LINE_FREQUENCY,
99 .type = V4L2_CTRL_TYPE_MENU,
100 .name = "Light frequency filter",
101 .minimum = 1,
102 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
103 .step = 1,
104 .default_value = 1,
105 },
106 .set_control = setlightfreq
107 },
108};
109
110static const struct v4l2_pix_format vga_mode[] = {
111 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
112 .bytesperline = 320,
113 .sizeimage = 320 * 240 * 3 / 8 + 590,
114 .colorspace = V4L2_COLORSPACE_JPEG,
115 .priv = 1},
116 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117 .bytesperline = 640,
118 .sizeimage = 640 * 480 * 3 / 8 + 590,
119 .colorspace = V4L2_COLORSPACE_JPEG,
120 .priv = 0},
121};
122
123/* -- read a register -- */
124static u8 reg_r(struct gspca_dev *gspca_dev,
125 __u16 index)
126{
127 struct usb_device *dev = gspca_dev->dev;
128 int ret;
129
130 if (gspca_dev->usb_err < 0)
131 return 0;
132 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
133 0x00,
134 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
135 0x00,
136 index,
137 gspca_dev->usb_buf, 1,
138 500);
139 if (ret < 0) {
140 err("reg_r err %d", ret);
141 gspca_dev->usb_err = ret;
142 return 0;
143 }
144 return gspca_dev->usb_buf[0];
145}
146
147/* -- write a register -- */
148static void reg_w(struct gspca_dev *gspca_dev,
149 __u16 index, __u16 value)
150{
151 struct usb_device *dev = gspca_dev->dev;
152 int ret;
153
154 if (gspca_dev->usb_err < 0)
155 return;
156 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
157 0x01,
158 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159 value,
160 index,
161 NULL,
162 0,
163 500);
164 if (ret < 0) {
165 err("reg_w err %d", ret);
166 gspca_dev->usb_err = ret;
167 }
168}
169
170/* -- get a bulk value (4 bytes) -- */
171static void rcv_val(struct gspca_dev *gspca_dev,
172 int ads)
173{
174 struct usb_device *dev = gspca_dev->dev;
175 int alen, ret;
176
177 reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
178 reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
179 reg_w(gspca_dev, 0x636, ads & 0xff);
180 reg_w(gspca_dev, 0x637, 0);
181 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */
182 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */
183 reg_w(gspca_dev, 0x63a, 0);
184 reg_w(gspca_dev, 0x63b, 0);
185 reg_w(gspca_dev, 0x630, 5);
186 if (gspca_dev->usb_err < 0)
187 return;
188 ret = usb_bulk_msg(dev,
189 usb_rcvbulkpipe(dev, 0x05),
190 gspca_dev->usb_buf,
191 4, /* length */
192 &alen,
193 500); /* timeout in milliseconds */
194 if (ret < 0) {
195 err("rcv_val err %d", ret);
196 gspca_dev->usb_err = ret;
197 }
198}
199
200/* -- send a bulk value -- */
201static void snd_val(struct gspca_dev *gspca_dev,
202 int ads,
203 unsigned int val)
204{
205 struct usb_device *dev = gspca_dev->dev;
206 int alen, ret;
207 __u8 seq = 0;
208
209 if (ads == 0x003f08) {
210 reg_r(gspca_dev, 0x0704);
211 seq = reg_r(gspca_dev, 0x0705);
212 reg_r(gspca_dev, 0x0650);
213 reg_w(gspca_dev, 0x654, seq);
214 } else {
215 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
216 }
217 reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
218 reg_w(gspca_dev, 0x656, ads & 0xff);
219 reg_w(gspca_dev, 0x657, 0);
220 reg_w(gspca_dev, 0x658, 0x04); /* size */
221 reg_w(gspca_dev, 0x659, 0);
222 reg_w(gspca_dev, 0x65a, 0);
223 reg_w(gspca_dev, 0x65b, 0);
224 reg_w(gspca_dev, 0x650, 5);
225 if (gspca_dev->usb_err < 0)
226 return;
227 gspca_dev->usb_buf[0] = val >> 24;
228 gspca_dev->usb_buf[1] = val >> 16;
229 gspca_dev->usb_buf[2] = val >> 8;
230 gspca_dev->usb_buf[3] = val;
231 ret = usb_bulk_msg(dev,
232 usb_sndbulkpipe(dev, 6),
233 gspca_dev->usb_buf,
234 4,
235 &alen,
236 500); /* timeout in milliseconds */
237 if (ret < 0) {
238 err("snd_val err %d", ret);
239 gspca_dev->usb_err = ret;
240 } else {
241 if (ads == 0x003f08) {
242 seq += 4;
243 seq &= 0x3f;
244 reg_w(gspca_dev, 0x705, seq);
245 }
246 }
247}
248
249/* set a camera parameter */
250static void set_par(struct gspca_dev *gspca_dev,
251 int parval)
252{
253 snd_val(gspca_dev, 0x003f08, parval);
254}
255
256static void setbrightness(struct gspca_dev *gspca_dev)
257{
258 struct sd *sd = (struct sd *) gspca_dev;
259 int parval;
260
261 parval = 0x06000000 /* whiteness */
262 + (sd->ctrls[BRIGHTNESS].val << 16);
263 set_par(gspca_dev, parval);
264}
265
266static void setcontrast(struct gspca_dev *gspca_dev)
267{
268 struct sd *sd = (struct sd *) gspca_dev;
269 int parval;
270
271 parval = 0x07000000 /* contrast */
272 + (sd->ctrls[CONTRAST].val << 16);
273 set_par(gspca_dev, parval);
274}
275
276static void setcolors(struct gspca_dev *gspca_dev)
277{
278 struct sd *sd = (struct sd *) gspca_dev;
279 int parval;
280
281 parval = 0x08000000 /* saturation */
282 + (sd->ctrls[COLORS].val << 16);
283 set_par(gspca_dev, parval);
284}
285
286static void setlightfreq(struct gspca_dev *gspca_dev)
287{
288 struct sd *sd = (struct sd *) gspca_dev;
289
290 set_par(gspca_dev, sd->ctrls[LIGHTFREQ].val == 1
291 ? 0x33640000 /* 50 Hz */
292 : 0x33780000); /* 60 Hz */
293}
294
295/* this function is called at probe time */
296static int sd_config(struct gspca_dev *gspca_dev,
297 const struct usb_device_id *id)
298{
299 struct sd *sd = (struct sd *) gspca_dev;
300
301 gspca_dev->cam.cam_mode = vga_mode;
302 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
303 gspca_dev->cam.ctrls = sd->ctrls;
304 sd->quality = QUALITY_DEF;
305 return 0;
306}
307
308/* this function is called at probe and resume time */
309static int sd_init(struct gspca_dev *gspca_dev)
310{
311 u8 ret;
312
313 /* check if the device responds */
314 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
315 ret = reg_r(gspca_dev, 0x0740);
316 if (gspca_dev->usb_err >= 0) {
317 if (ret != 0xff) {
318 err("init reg: 0x%02x", ret);
319 gspca_dev->usb_err = -EIO;
320 }
321 }
322 return gspca_dev->usb_err;
323}
324
325/* -- start the camera -- */
326static int sd_start(struct gspca_dev *gspca_dev)
327{
328 struct sd *sd = (struct sd *) gspca_dev;
329 int ret, value;
330
331 /* create the JPEG header */
332 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
333 0x22); /* JPEG 411 */
334 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
335
336 /* work on alternate 1 */
337 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
338
339 set_par(gspca_dev, 0x10000000);
340 set_par(gspca_dev, 0x00000000);
341 set_par(gspca_dev, 0x8002e001);
342 set_par(gspca_dev, 0x14000000);
343 if (gspca_dev->width > 320)
344 value = 0x8002e001; /* 640x480 */
345 else
346 value = 0x4001f000; /* 320x240 */
347 set_par(gspca_dev, value);
348 ret = usb_set_interface(gspca_dev->dev,
349 gspca_dev->iface,
350 gspca_dev->alt);
351 if (ret < 0) {
352 err("set intf %d %d failed",
353 gspca_dev->iface, gspca_dev->alt);
354 gspca_dev->usb_err = ret;
355 goto out;
356 }
357 reg_r(gspca_dev, 0x0630);
358 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
359 reg_r(gspca_dev, 0x0650);
360 snd_val(gspca_dev, 0x000020, 0xffffffff);
361 reg_w(gspca_dev, 0x0620, 0);
362 reg_w(gspca_dev, 0x0630, 0);
363 reg_w(gspca_dev, 0x0640, 0);
364 reg_w(gspca_dev, 0x0650, 0);
365 reg_w(gspca_dev, 0x0660, 0);
366 setbrightness(gspca_dev); /* whiteness */
367 setcontrast(gspca_dev); /* contrast */
368 setcolors(gspca_dev); /* saturation */
369 set_par(gspca_dev, 0x09800000); /* Red ? */
370 set_par(gspca_dev, 0x0a800000); /* Green ? */
371 set_par(gspca_dev, 0x0b800000); /* Blue ? */
372 set_par(gspca_dev, 0x0d030000); /* Gamma ? */
373 setlightfreq(gspca_dev);
374
375 /* start the video flow */
376 set_par(gspca_dev, 0x01000000);
377 set_par(gspca_dev, 0x01000000);
378 if (gspca_dev->usb_err >= 0)
379 PDEBUG(D_STREAM, "camera started alt: 0x%02x",
380 gspca_dev->alt);
381out:
382 return gspca_dev->usb_err;
383}
384
385static void sd_stopN(struct gspca_dev *gspca_dev)
386{
387 struct usb_device *dev = gspca_dev->dev;
388
389 set_par(gspca_dev, 0x02000000);
390 set_par(gspca_dev, 0x02000000);
391 usb_set_interface(dev, gspca_dev->iface, 1);
392 reg_r(gspca_dev, 0x0630);
393 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
394 reg_r(gspca_dev, 0x0650);
395 snd_val(gspca_dev, 0x000020, 0xffffffff);
396 reg_w(gspca_dev, 0x0620, 0);
397 reg_w(gspca_dev, 0x0630, 0);
398 reg_w(gspca_dev, 0x0640, 0);
399 reg_w(gspca_dev, 0x0650, 0);
400 reg_w(gspca_dev, 0x0660, 0);
401 PDEBUG(D_STREAM, "camera stopped");
402}
403
404static void sd_pkt_scan(struct gspca_dev *gspca_dev,
405 u8 *data, /* isoc packet */
406 int len) /* iso packet length */
407{
408 struct sd *sd = (struct sd *) gspca_dev;
409 static unsigned char ffd9[] = {0xff, 0xd9};
410
411 /* a frame starts with:
412 * - 0xff 0xfe
413 * - 0x08 0x00 - length (little endian ?!)
414 * - 4 bytes = size of whole frame (BE - including header)
415 * - 0x00 0x0c
416 * - 0xff 0xd8
417 * - .. JPEG image with escape sequences (ff 00)
418 * (without ending - ff d9)
419 */
420 if (data[0] == 0xff && data[1] == 0xfe) {
421 gspca_frame_add(gspca_dev, LAST_PACKET,
422 ffd9, 2);
423
424 /* put the JPEG 411 header */
425 gspca_frame_add(gspca_dev, FIRST_PACKET,
426 sd->jpeg_hdr, JPEG_HDR_SZ);
427
428 /* beginning of the frame */
429#define STKHDRSZ 12
430 data += STKHDRSZ;
431 len -= STKHDRSZ;
432 }
433 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
434}
435
436static int sd_querymenu(struct gspca_dev *gspca_dev,
437 struct v4l2_querymenu *menu)
438{
439 static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
440
441 switch (menu->id) {
442 case V4L2_CID_POWER_LINE_FREQUENCY:
443 if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm))
444 break;
445 strcpy((char *) menu->name, freq_nm[menu->index]);
446 return 0;
447 }
448 return -EINVAL;
449}
450
451static int sd_set_jcomp(struct gspca_dev *gspca_dev,
452 struct v4l2_jpegcompression *jcomp)
453{
454 struct sd *sd = (struct sd *) gspca_dev;
455
456 if (jcomp->quality < QUALITY_MIN)
457 sd->quality = QUALITY_MIN;
458 else if (jcomp->quality > QUALITY_MAX)
459 sd->quality = QUALITY_MAX;
460 else
461 sd->quality = jcomp->quality;
462 if (gspca_dev->streaming)
463 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
464 return gspca_dev->usb_err;
465}
466
467static int sd_get_jcomp(struct gspca_dev *gspca_dev,
468 struct v4l2_jpegcompression *jcomp)
469{
470 struct sd *sd = (struct sd *) gspca_dev;
471
472 memset(jcomp, 0, sizeof *jcomp);
473 jcomp->quality = sd->quality;
474 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
475 | V4L2_JPEG_MARKER_DQT;
476 return 0;
477}
478
479/* sub-driver description */
480static const struct sd_desc sd_desc = {
481 .name = MODULE_NAME,
482 .ctrls = sd_ctrls,
483 .nctrls = NCTRLS,
484 .config = sd_config,
485 .init = sd_init,
486 .start = sd_start,
487 .stopN = sd_stopN,
488 .pkt_scan = sd_pkt_scan,
489 .querymenu = sd_querymenu,
490 .get_jcomp = sd_get_jcomp,
491 .set_jcomp = sd_set_jcomp,
492};
493
494/* -- module initialisation -- */
495static const struct usb_device_id device_table[] = {
496 {USB_DEVICE(0x05e1, 0x0893)},
497 {}
498};
499MODULE_DEVICE_TABLE(usb, device_table);
500
501/* -- device connect -- */
502static int sd_probe(struct usb_interface *intf,
503 const struct usb_device_id *id)
504{
505 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
506 THIS_MODULE);
507}
508
509static struct usb_driver sd_driver = {
510 .name = MODULE_NAME,
511 .id_table = device_table,
512 .probe = sd_probe,
513 .disconnect = gspca_disconnect,
514#ifdef CONFIG_PM
515 .suspend = gspca_suspend,
516 .resume = gspca_resume,
517#endif
518};
519
520/* -- module insert / remove -- */
521static int __init sd_mod_init(void)
522{
523 return usb_register(&sd_driver);
524}
525static void __exit sd_mod_exit(void)
526{
527 usb_deregister(&sd_driver);
528}
529
530module_init(sd_mod_init);
531module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c
new file mode 100644
index 00000000000..e2ef41cf72d
--- /dev/null
+++ b/drivers/media/video/gspca/stv0680.c
@@ -0,0 +1,367 @@
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 MODULE_NAME "stv0680"
31
32#include "gspca.h"
33
34MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
35MODULE_DESCRIPTION("STV0680 USB Camera Driver");
36MODULE_LICENSE("GPL");
37
38/* specific webcam descriptor */
39struct sd {
40 struct gspca_dev gspca_dev; /* !! must be the first item */
41 struct v4l2_pix_format mode;
42 u8 orig_mode;
43 u8 video_mode;
44 u8 current_mode;
45};
46
47/* V4L2 controls supported by the driver */
48static const struct ctrl sd_ctrls[] = {
49};
50
51static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
52 int size)
53{
54 int ret = -1;
55 u8 req_type = 0;
56 unsigned int pipe = 0;
57
58 switch (set) {
59 case 0: /* 0xc1 */
60 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
61 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
62 break;
63 case 1: /* 0x41 */
64 req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
65 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
66 break;
67 case 2: /* 0x80 */
68 req_type = USB_DIR_IN | USB_RECIP_DEVICE;
69 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
70 break;
71 case 3: /* 0x40 */
72 req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
73 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
74 break;
75 }
76
77 ret = usb_control_msg(gspca_dev->dev, pipe,
78 req, req_type,
79 val, 0, gspca_dev->usb_buf, size, 500);
80
81 if ((ret < 0) && (req != 0x0a))
82 err("usb_control_msg error %i, request = 0x%x, error = %i",
83 set, req, ret);
84
85 return ret;
86}
87
88static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
89{
90 stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
91 PDEBUG(D_ERR, "last error: %i, command = 0x%x",
92 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
93 return ret;
94}
95
96static int stv0680_get_video_mode(struct gspca_dev *gspca_dev)
97{
98 /* Note not sure if this init of usb_buf is really necessary */
99 memset(gspca_dev->usb_buf, 0, 8);
100 gspca_dev->usb_buf[0] = 0x0f;
101
102 if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) {
103 PDEBUG(D_ERR, "Get_Camera_Mode failed");
104 return stv0680_handle_error(gspca_dev, -EIO);
105 }
106
107 return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */
108}
109
110static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode)
111{
112 struct sd *sd = (struct sd *) gspca_dev;
113
114 if (sd->current_mode == mode)
115 return 0;
116
117 memset(gspca_dev->usb_buf, 0, 8);
118 gspca_dev->usb_buf[0] = mode;
119
120 if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) {
121 PDEBUG(D_ERR, "Set_Camera_Mode failed");
122 return stv0680_handle_error(gspca_dev, -EIO);
123 }
124
125 /* Verify we got what we've asked for */
126 if (stv0680_get_video_mode(gspca_dev) != mode) {
127 PDEBUG(D_ERR, "Error setting camera video mode!");
128 return -EIO;
129 }
130
131 sd->current_mode = mode;
132
133 return 0;
134}
135
136/* this function is called at probe time */
137static int sd_config(struct gspca_dev *gspca_dev,
138 const struct usb_device_id *id)
139{
140 int ret;
141 struct sd *sd = (struct sd *) gspca_dev;
142 struct cam *cam = &gspca_dev->cam;
143
144 /* Give the camera some time to settle, otherwise initalization will
145 fail on hotplug, and yes it really needs a full second. */
146 msleep(1000);
147
148 /* ping camera to be sure STV0680 is present */
149 if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
150 gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
151 PDEBUG(D_ERR, "STV(e): camera ping failed!!");
152 return stv0680_handle_error(gspca_dev, -ENODEV);
153 }
154
155 /* get camera descriptor */
156 if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09)
157 return stv0680_handle_error(gspca_dev, -ENODEV);
158
159 if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
160 gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
161 PDEBUG(D_ERR, "Could not get descriptor 0200.");
162 return stv0680_handle_error(gspca_dev, -ENODEV);
163 }
164 if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02)
165 return stv0680_handle_error(gspca_dev, -ENODEV);
166 if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24)
167 return stv0680_handle_error(gspca_dev, -ENODEV);
168 if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
169 return stv0680_handle_error(gspca_dev, -ENODEV);
170
171 if (!(gspca_dev->usb_buf[7] & 0x09)) {
172 PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode");
173 return -ENODEV;
174 }
175 if (gspca_dev->usb_buf[7] & 0x01)
176 PDEBUG(D_PROBE, "Camera supports CIF mode");
177 if (gspca_dev->usb_buf[7] & 0x02)
178 PDEBUG(D_PROBE, "Camera supports VGA mode");
179 if (gspca_dev->usb_buf[7] & 0x04)
180 PDEBUG(D_PROBE, "Camera supports QCIF mode");
181 if (gspca_dev->usb_buf[7] & 0x08)
182 PDEBUG(D_PROBE, "Camera supports QVGA mode");
183
184 if (gspca_dev->usb_buf[7] & 0x01)
185 sd->video_mode = 0x00; /* CIF */
186 else
187 sd->video_mode = 0x03; /* QVGA */
188
189 /* FW rev, ASIC rev, sensor ID */
190 PDEBUG(D_PROBE, "Firmware rev is %i.%i",
191 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
192 PDEBUG(D_PROBE, "ASIC rev is %i.%i",
193 gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]);
194 PDEBUG(D_PROBE, "Sensor ID is %i",
195 (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4));
196
197
198 ret = stv0680_get_video_mode(gspca_dev);
199 if (ret < 0)
200 return ret;
201 sd->current_mode = sd->orig_mode = ret;
202
203 ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
204 if (ret < 0)
205 return ret;
206
207 /* Get mode details */
208 if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10)
209 return stv0680_handle_error(gspca_dev, -EIO);
210
211 cam->bulk = 1;
212 cam->bulk_nurbs = 1; /* The cam cannot handle more */
213 cam->bulk_size = (gspca_dev->usb_buf[0] << 24) |
214 (gspca_dev->usb_buf[1] << 16) |
215 (gspca_dev->usb_buf[2] << 8) |
216 (gspca_dev->usb_buf[3]);
217 sd->mode.width = (gspca_dev->usb_buf[4] << 8) |
218 (gspca_dev->usb_buf[5]); /* 322, 356, 644 */
219 sd->mode.height = (gspca_dev->usb_buf[6] << 8) |
220 (gspca_dev->usb_buf[7]); /* 242, 292, 484 */
221 sd->mode.pixelformat = V4L2_PIX_FMT_STV0680;
222 sd->mode.field = V4L2_FIELD_NONE;
223 sd->mode.bytesperline = sd->mode.width;
224 sd->mode.sizeimage = cam->bulk_size;
225 sd->mode.colorspace = V4L2_COLORSPACE_SRGB;
226
227 /* origGain = gspca_dev->usb_buf[12]; */
228
229 cam->cam_mode = &sd->mode;
230 cam->nmodes = 1;
231
232
233 ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode);
234 if (ret < 0)
235 return ret;
236
237 if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
238 gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
239 err("Could not get descriptor 0100.");
240 return stv0680_handle_error(gspca_dev, -EIO);
241 }
242
243 return 0;
244}
245
246/* this function is called at probe and resume time */
247static int sd_init(struct gspca_dev *gspca_dev)
248{
249 return 0;
250}
251
252/* -- start the camera -- */
253static int sd_start(struct gspca_dev *gspca_dev)
254{
255 int ret;
256 struct sd *sd = (struct sd *) gspca_dev;
257
258 ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
259 if (ret < 0)
260 return ret;
261
262 if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
263 return stv0680_handle_error(gspca_dev, -EIO);
264
265 /* Start stream at:
266 0x0000 = CIF (352x288)
267 0x0100 = VGA (640x480)
268 0x0300 = QVGA (320x240) */
269 if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0)
270 return stv0680_handle_error(gspca_dev, -EIO);
271
272 return 0;
273}
274
275static void sd_stopN(struct gspca_dev *gspca_dev)
276{
277 /* This is a high priority command; it stops all lower order cmds */
278 if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0)
279 stv0680_handle_error(gspca_dev, -EIO);
280}
281
282static void sd_stop0(struct gspca_dev *gspca_dev)
283{
284 struct sd *sd = (struct sd *) gspca_dev;
285
286 if (!sd->gspca_dev.present)
287 return;
288
289 stv0680_set_video_mode(gspca_dev, sd->orig_mode);
290}
291
292static void sd_pkt_scan(struct gspca_dev *gspca_dev,
293 u8 *data,
294 int len)
295{
296 struct sd *sd = (struct sd *) gspca_dev;
297
298 /* Every now and then the camera sends a 16 byte packet, no idea
299 what it contains, but it is not image data, when this
300 happens the frame received before this packet is corrupt,
301 so discard it. */
302 if (len != sd->mode.sizeimage) {
303 gspca_dev->last_packet_type = DISCARD_PACKET;
304 return;
305 }
306
307 /* Finish the previous frame, we do this upon reception of the next
308 packet, even though it is already complete so that the strange 16
309 byte packets send after a corrupt frame can discard it. */
310 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
311
312 /* Store the just received frame */
313 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
314}
315
316/* sub-driver description */
317static const struct sd_desc sd_desc = {
318 .name = MODULE_NAME,
319 .ctrls = sd_ctrls,
320 .nctrls = ARRAY_SIZE(sd_ctrls),
321 .config = sd_config,
322 .init = sd_init,
323 .start = sd_start,
324 .stopN = sd_stopN,
325 .stop0 = sd_stop0,
326 .pkt_scan = sd_pkt_scan,
327};
328
329/* -- module initialisation -- */
330static const struct usb_device_id device_table[] = {
331 {USB_DEVICE(0x0553, 0x0202)},
332 {USB_DEVICE(0x041e, 0x4007)},
333 {}
334};
335MODULE_DEVICE_TABLE(usb, device_table);
336
337/* -- device connect -- */
338static int sd_probe(struct usb_interface *intf,
339 const struct usb_device_id *id)
340{
341 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
342 THIS_MODULE);
343}
344
345static struct usb_driver sd_driver = {
346 .name = MODULE_NAME,
347 .id_table = device_table,
348 .probe = sd_probe,
349 .disconnect = gspca_disconnect,
350#ifdef CONFIG_PM
351 .suspend = gspca_suspend,
352 .resume = gspca_resume,
353#endif
354};
355
356/* -- module insert / remove -- */
357static int __init sd_mod_init(void)
358{
359 return usb_register(&sd_driver);
360}
361static void __exit sd_mod_exit(void)
362{
363 usb_deregister(&sd_driver);
364}
365
366module_init(sd_mod_init);
367module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/stv06xx/Kconfig b/drivers/media/video/gspca/stv06xx/Kconfig
new file mode 100644
index 00000000000..634ad38d9fb
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile
new file mode 100644
index 00000000000..2f3c3a606ce
--- /dev/null
+++ b/drivers/media/video/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
9EXTRA_CFLAGS += -Idrivers/media/video/gspca
10
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
new file mode 100644
index 00000000000..abf1658fa33
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -0,0 +1,630 @@
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#include <linux/input.h>
31#include "stv06xx_sensor.h"
32
33MODULE_AUTHOR("Erik Andrén");
34MODULE_DESCRIPTION("STV06XX USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37static int dump_bridge;
38static int dump_sensor;
39
40int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
41{
42 int err;
43 struct usb_device *udev = sd->gspca_dev.dev;
44 __u8 *buf = sd->gspca_dev.usb_buf;
45 u8 len = (i2c_data > 0xff) ? 2 : 1;
46
47 buf[0] = i2c_data & 0xff;
48 buf[1] = (i2c_data >> 8) & 0xff;
49
50 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
51 0x04, 0x40, address, 0, buf, len,
52 STV06XX_URB_MSG_TIMEOUT);
53
54 PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d",
55 i2c_data, address, err);
56
57 return (err < 0) ? err : 0;
58}
59
60int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
61{
62 int err;
63 struct usb_device *udev = sd->gspca_dev.dev;
64 __u8 *buf = sd->gspca_dev.usb_buf;
65
66 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
67 0x04, 0xc0, address, 0, buf, 1,
68 STV06XX_URB_MSG_TIMEOUT);
69
70 *i2c_data = buf[0];
71
72 PDEBUG(D_CONF, "Reading 0x%x from address 0x%x, status %d",
73 *i2c_data, address, err);
74
75 return (err < 0) ? err : 0;
76}
77
78/* Wraps the normal write sensor bytes / words functions for writing a
79 single value */
80int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value)
81{
82 if (sd->sensor->i2c_len == 2) {
83 u16 data[2] = { address, value };
84 return stv06xx_write_sensor_words(sd, data, 1);
85 } else {
86 u8 data[2] = { address, value };
87 return stv06xx_write_sensor_bytes(sd, data, 1);
88 }
89}
90
91static int stv06xx_write_sensor_finish(struct sd *sd)
92{
93 int err = 0;
94
95 if (sd->bridge == BRIDGE_STV610) {
96 struct usb_device *udev = sd->gspca_dev.dev;
97 __u8 *buf = sd->gspca_dev.usb_buf;
98
99 buf[0] = 0;
100 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
101 0x04, 0x40, 0x1704, 0, buf, 1,
102 STV06XX_URB_MSG_TIMEOUT);
103 }
104
105 return (err < 0) ? err : 0;
106}
107
108int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
109{
110 int err, i, j;
111 struct usb_device *udev = sd->gspca_dev.dev;
112 __u8 *buf = sd->gspca_dev.usb_buf;
113
114 PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
115 for (i = 0; i < len;) {
116 /* Build the command buffer */
117 memset(buf, 0, I2C_BUFFER_LENGTH);
118 for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) {
119 buf[j] = data[2*i];
120 buf[0x10 + j] = data[2*i+1];
121 PDEBUG(D_CONF, "I2C: Writing 0x%02x to reg 0x%02x",
122 data[2*i+1], data[2*i]);
123 }
124 buf[0x20] = sd->sensor->i2c_addr;
125 buf[0x21] = j - 1; /* Number of commands to send - 1 */
126 buf[0x22] = I2C_WRITE_CMD;
127 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
128 0x04, 0x40, 0x0400, 0, buf,
129 I2C_BUFFER_LENGTH,
130 STV06XX_URB_MSG_TIMEOUT);
131 if (err < 0)
132 return err;
133 }
134 return stv06xx_write_sensor_finish(sd);
135}
136
137int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
138{
139 int err, i, j;
140 struct usb_device *udev = sd->gspca_dev.dev;
141 __u8 *buf = sd->gspca_dev.usb_buf;
142
143 PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
144
145 for (i = 0; i < len;) {
146 /* Build the command buffer */
147 memset(buf, 0, I2C_BUFFER_LENGTH);
148 for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) {
149 buf[j] = data[2*i];
150 buf[0x10 + j * 2] = data[2*i+1];
151 buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8;
152 PDEBUG(D_CONF, "I2C: Writing 0x%04x to reg 0x%02x",
153 data[2*i+1], data[2*i]);
154 }
155 buf[0x20] = sd->sensor->i2c_addr;
156 buf[0x21] = j - 1; /* Number of commands to send - 1 */
157 buf[0x22] = I2C_WRITE_CMD;
158 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
159 0x04, 0x40, 0x0400, 0, buf,
160 I2C_BUFFER_LENGTH,
161 STV06XX_URB_MSG_TIMEOUT);
162 if (err < 0)
163 return err;
164 }
165 return stv06xx_write_sensor_finish(sd);
166}
167
168int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
169{
170 int err;
171 struct usb_device *udev = sd->gspca_dev.dev;
172 __u8 *buf = sd->gspca_dev.usb_buf;
173
174 err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush);
175 if (err < 0)
176 return err;
177
178 /* Clear mem */
179 memset(buf, 0, I2C_BUFFER_LENGTH);
180
181 buf[0] = address;
182 buf[0x20] = sd->sensor->i2c_addr;
183 buf[0x21] = 0;
184
185 /* Read I2C register */
186 buf[0x22] = I2C_READ_CMD;
187
188 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
189 0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
190 STV06XX_URB_MSG_TIMEOUT);
191 if (err < 0) {
192 err("I2C: Read error writing address: %d", err);
193 return err;
194 }
195
196 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
197 0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len,
198 STV06XX_URB_MSG_TIMEOUT);
199 if (sd->sensor->i2c_len == 2)
200 *value = buf[0] | (buf[1] << 8);
201 else
202 *value = buf[0];
203
204 PDEBUG(D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d",
205 *value, address, err);
206
207 return (err < 0) ? err : 0;
208}
209
210/* Dumps all bridge registers */
211static void stv06xx_dump_bridge(struct sd *sd)
212{
213 int i;
214 u8 data, buf;
215
216 info("Dumping all stv06xx bridge registers");
217 for (i = 0x1400; i < 0x160f; i++) {
218 stv06xx_read_bridge(sd, i, &data);
219
220 info("Read 0x%x from address 0x%x", data, i);
221 }
222
223 info("Testing stv06xx bridge registers for writability");
224 for (i = 0x1400; i < 0x160f; i++) {
225 stv06xx_read_bridge(sd, i, &data);
226 buf = data;
227
228 stv06xx_write_bridge(sd, i, 0xff);
229 stv06xx_read_bridge(sd, i, &data);
230 if (data == 0xff)
231 info("Register 0x%x is read/write", i);
232 else if (data != buf)
233 info("Register 0x%x is read/write,"
234 " but only partially", i);
235 else
236 info("Register 0x%x is read-only", i);
237
238 stv06xx_write_bridge(sd, i, buf);
239 }
240}
241
242/* this function is called at probe and resume time */
243static int stv06xx_init(struct gspca_dev *gspca_dev)
244{
245 struct sd *sd = (struct sd *) gspca_dev;
246 int err;
247
248 PDEBUG(D_PROBE, "Initializing camera");
249
250 /* Let the usb init settle for a bit
251 before performing the initialization */
252 msleep(250);
253
254 err = sd->sensor->init(sd);
255
256 if (dump_sensor && sd->sensor->dump)
257 sd->sensor->dump(sd);
258
259 return (err < 0) ? err : 0;
260}
261
262/* Start the camera */
263static int stv06xx_start(struct gspca_dev *gspca_dev)
264{
265 struct sd *sd = (struct sd *) gspca_dev;
266 struct usb_host_interface *alt;
267 struct usb_interface *intf;
268 int err, packet_size;
269
270 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
271 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
272 if (!alt) {
273 PDEBUG(D_ERR, "Couldn't get altsetting");
274 return -EIO;
275 }
276
277 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
278 err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
279 if (err < 0)
280 return err;
281
282 /* Prepare the sensor for start */
283 err = sd->sensor->start(sd);
284 if (err < 0)
285 goto out;
286
287 /* Start isochronous streaming */
288 err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1);
289
290out:
291 if (err < 0)
292 PDEBUG(D_STREAM, "Starting stream failed");
293 else
294 PDEBUG(D_STREAM, "Started streaming");
295
296 return (err < 0) ? err : 0;
297}
298
299static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
300{
301 struct usb_host_interface *alt;
302 struct sd *sd = (struct sd *) gspca_dev;
303
304 /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
305 alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
306 alt->endpoint[0].desc.wMaxPacketSize =
307 cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
308
309 return 0;
310}
311
312static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
313{
314 int ret, packet_size, min_packet_size;
315 struct usb_host_interface *alt;
316 struct sd *sd = (struct sd *) gspca_dev;
317
318 alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
319 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
320 min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
321 if (packet_size <= min_packet_size)
322 return -EIO;
323
324 packet_size -= 100;
325 if (packet_size < min_packet_size)
326 packet_size = min_packet_size;
327 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
328
329 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
330 if (ret < 0)
331 PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
332
333 return ret;
334}
335
336static void stv06xx_stopN(struct gspca_dev *gspca_dev)
337{
338 int err;
339 struct sd *sd = (struct sd *) gspca_dev;
340
341 /* stop ISO-streaming */
342 err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
343 if (err < 0)
344 goto out;
345
346 err = sd->sensor->stop(sd);
347
348out:
349 if (err < 0)
350 PDEBUG(D_STREAM, "Failed to stop stream");
351 else
352 PDEBUG(D_STREAM, "Stopped streaming");
353}
354
355/*
356 * Analyse an USB packet of the data stream and store it appropriately.
357 * Each packet contains an integral number of chunks. Each chunk has
358 * 2-bytes identification, followed by 2-bytes that describe the chunk
359 * length. Known/guessed chunk identifications are:
360 * 8001/8005/C001/C005 - Begin new frame
361 * 8002/8006/C002/C006 - End frame
362 * 0200/4200 - Contains actual image data, bayer or compressed
363 * 0005 - 11 bytes of unknown data
364 * 0100 - 2 bytes of unknown data
365 * The 0005 and 0100 chunks seem to appear only in compressed stream.
366 */
367static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
368 u8 *data, /* isoc packet */
369 int len) /* iso packet length */
370{
371 struct sd *sd = (struct sd *) gspca_dev;
372
373 PDEBUG(D_PACK, "Packet of length %d arrived", len);
374
375 /* A packet may contain several frames
376 loop until the whole packet is reached */
377 while (len) {
378 int id, chunk_len;
379
380 if (len < 4) {
381 PDEBUG(D_PACK, "Packet is smaller than 4 bytes");
382 return;
383 }
384
385 /* Capture the id */
386 id = (data[0] << 8) | data[1];
387
388 /* Capture the chunk length */
389 chunk_len = (data[2] << 8) | data[3];
390 PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len);
391
392 data += 4;
393 len -= 4;
394
395 if (len < chunk_len) {
396 PDEBUG(D_ERR, "URB packet length is smaller"
397 " than the specified chunk length");
398 gspca_dev->last_packet_type = DISCARD_PACKET;
399 return;
400 }
401
402 /* First byte seem to be 02=data 2nd byte is unknown??? */
403 if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200)
404 goto frame_data;
405
406 switch (id) {
407 case 0x0200:
408 case 0x4200:
409frame_data:
410 PDEBUG(D_PACK, "Frame data packet detected");
411
412 if (sd->to_skip) {
413 int skip = (sd->to_skip < chunk_len) ?
414 sd->to_skip : chunk_len;
415 data += skip;
416 len -= skip;
417 chunk_len -= skip;
418 sd->to_skip -= skip;
419 }
420
421 gspca_frame_add(gspca_dev, INTER_PACKET,
422 data, chunk_len);
423 break;
424
425 case 0x8001:
426 case 0x8005:
427 case 0xc001:
428 case 0xc005:
429 PDEBUG(D_PACK, "Starting new frame");
430
431 /* Create a new frame, chunk length should be zero */
432 gspca_frame_add(gspca_dev, FIRST_PACKET,
433 NULL, 0);
434
435 if (sd->bridge == BRIDGE_ST6422)
436 sd->to_skip = gspca_dev->width * 4;
437
438 if (chunk_len)
439 PDEBUG(D_ERR, "Chunk length is "
440 "non-zero on a SOF");
441 break;
442
443 case 0x8002:
444 case 0x8006:
445 case 0xc002:
446 PDEBUG(D_PACK, "End of frame detected");
447
448 /* Complete the last frame (if any) */
449 gspca_frame_add(gspca_dev, LAST_PACKET,
450 NULL, 0);
451
452 if (chunk_len)
453 PDEBUG(D_ERR, "Chunk length is "
454 "non-zero on a EOF");
455 break;
456
457 case 0x0005:
458 PDEBUG(D_PACK, "Chunk 0x005 detected");
459 /* Unknown chunk with 11 bytes of data,
460 occurs just before end of each frame
461 in compressed mode */
462 break;
463
464 case 0x0100:
465 PDEBUG(D_PACK, "Chunk 0x0100 detected");
466 /* Unknown chunk with 2 bytes of data,
467 occurs 2-3 times per USB interrupt */
468 break;
469 case 0x42ff:
470 PDEBUG(D_PACK, "Chunk 0x42ff detected");
471 /* Special chunk seen sometimes on the ST6422 */
472 break;
473 default:
474 PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
475 /* Unknown chunk */
476 }
477 data += chunk_len;
478 len -= chunk_len;
479 }
480}
481
482#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
483static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
484 u8 *data, /* interrupt packet data */
485 int len) /* interrupt packet length */
486{
487 int ret = -EINVAL;
488
489 if (len == 1 && data[0] == 0x80) {
490 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
491 input_sync(gspca_dev->input_dev);
492 ret = 0;
493 }
494
495 if (len == 1 && data[0] == 0x88) {
496 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
497 input_sync(gspca_dev->input_dev);
498 ret = 0;
499 }
500
501 return ret;
502}
503#endif
504
505static int stv06xx_config(struct gspca_dev *gspca_dev,
506 const struct usb_device_id *id);
507
508/* sub-driver description */
509static const struct sd_desc sd_desc = {
510 .name = MODULE_NAME,
511 .config = stv06xx_config,
512 .init = stv06xx_init,
513 .start = stv06xx_start,
514 .stopN = stv06xx_stopN,
515 .pkt_scan = stv06xx_pkt_scan,
516 .isoc_init = stv06xx_isoc_init,
517 .isoc_nego = stv06xx_isoc_nego,
518#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
519 .int_pkt_scan = sd_int_pkt_scan,
520#endif
521};
522
523/* This function is called at probe time */
524static int stv06xx_config(struct gspca_dev *gspca_dev,
525 const struct usb_device_id *id)
526{
527 struct sd *sd = (struct sd *) gspca_dev;
528
529 PDEBUG(D_PROBE, "Configuring camera");
530
531 sd->desc = sd_desc;
532 sd->bridge = id->driver_info;
533 gspca_dev->sd_desc = &sd->desc;
534
535 if (dump_bridge)
536 stv06xx_dump_bridge(sd);
537
538 sd->sensor = &stv06xx_sensor_st6422;
539 if (!sd->sensor->probe(sd))
540 return 0;
541
542 sd->sensor = &stv06xx_sensor_vv6410;
543 if (!sd->sensor->probe(sd))
544 return 0;
545
546 sd->sensor = &stv06xx_sensor_hdcs1x00;
547 if (!sd->sensor->probe(sd))
548 return 0;
549
550 sd->sensor = &stv06xx_sensor_hdcs1020;
551 if (!sd->sensor->probe(sd))
552 return 0;
553
554 sd->sensor = &stv06xx_sensor_pb0100;
555 if (!sd->sensor->probe(sd))
556 return 0;
557
558 sd->sensor = NULL;
559 return -ENODEV;
560}
561
562
563
564/* -- module initialisation -- */
565static const struct usb_device_id device_table[] = {
566 /* QuickCam Express */
567 {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
568 /* LEGO cam / QuickCam Web */
569 {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
570 /* Dexxa WebCam USB */
571 {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
572 /* QuickCam Messenger */
573 {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
574 /* QuickCam Communicate */
575 {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
576 /* QuickCam Messenger (new) */
577 {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
578 {}
579};
580MODULE_DEVICE_TABLE(usb, device_table);
581
582/* -- device connect -- */
583static int sd_probe(struct usb_interface *intf,
584 const struct usb_device_id *id)
585{
586 PDEBUG(D_PROBE, "Probing for a stv06xx device");
587 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
588 THIS_MODULE);
589}
590
591static void sd_disconnect(struct usb_interface *intf)
592{
593 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
594 struct sd *sd = (struct sd *) gspca_dev;
595 PDEBUG(D_PROBE, "Disconnecting the stv06xx device");
596
597 if (sd->sensor->disconnect)
598 sd->sensor->disconnect(sd);
599 gspca_disconnect(intf);
600}
601
602static struct usb_driver sd_driver = {
603 .name = MODULE_NAME,
604 .id_table = device_table,
605 .probe = sd_probe,
606 .disconnect = sd_disconnect,
607#ifdef CONFIG_PM
608 .suspend = gspca_suspend,
609 .resume = gspca_resume,
610#endif
611};
612
613/* -- module insert / remove -- */
614static int __init sd_mod_init(void)
615{
616 return usb_register(&sd_driver);
617}
618static void __exit sd_mod_exit(void)
619{
620 usb_deregister(&sd_driver);
621}
622
623module_init(sd_mod_init);
624module_exit(sd_mod_exit);
625
626module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
627MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
628
629module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
630MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup");
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h
new file mode 100644
index 00000000000..e0f63c51f40
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.h
@@ -0,0 +1,115 @@
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_REG23 0x0423
41
42/* Control registers of the STV0600 ASIC */
43#define STV_I2C_PARTNER 0x1420
44#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421
45#define STV_I2C_READ_WRITE_TOGGLE 0x1422
46#define STV_I2C_FLUSH 0x1423
47#define STV_I2C_SUCC_READ_REG_VALS 0x1424
48
49#define STV_ISO_ENABLE 0x1440
50#define STV_SCAN_RATE 0x1443
51#define STV_LED_CTRL 0x1445
52#define STV_STV0600_EMULATION 0x1446
53#define STV_REG00 0x1500
54#define STV_REG01 0x1501
55#define STV_REG02 0x1502
56#define STV_REG03 0x1503
57#define STV_REG04 0x1504
58
59#define STV_ISO_SIZE_L 0x15c1
60#define STV_ISO_SIZE_H 0x15c2
61
62/* Refers to the CIF 352x288 and QCIF 176x144 */
63/* 1: 288 lines, 2: 144 lines */
64#define STV_Y_CTRL 0x15c3
65
66/* 0xa: 352 columns, 0x6: 176 columns */
67#define STV_X_CTRL 0x1680
68
69#define STV06XX_URB_MSG_TIMEOUT 5000
70
71#define I2C_MAX_BYTES 16
72#define I2C_MAX_WORDS 8
73
74#define I2C_BUFFER_LENGTH 0x23
75#define I2C_READ_CMD 3
76#define I2C_WRITE_CMD 1
77
78#define LED_ON 1
79#define LED_OFF 0
80
81/* STV06xx device descriptor */
82struct sd {
83 struct gspca_dev gspca_dev;
84
85 /* A pointer to the currently connected sensor */
86 const struct stv06xx_sensor *sensor;
87
88 /* A pointer to the sd_desc struct */
89 struct sd_desc desc;
90
91 /* Sensor private data */
92 void *sensor_priv;
93
94 /* The first 4 lines produced by the stv6422 are no good, this keeps
95 track of how many bytes we still need to skip during a frame */
96 int to_skip;
97
98 /* Bridge / Camera type */
99 u8 bridge;
100 #define BRIDGE_STV600 0
101 #define BRIDGE_STV602 1
102 #define BRIDGE_STV610 2
103 #define BRIDGE_ST6422 3 /* With integrated sensor */
104};
105
106int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
107int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data);
108
109int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len);
110int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len);
111
112int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value);
113int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value);
114
115#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
new file mode 100644
index 00000000000..b8156855f2b
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -0,0 +1,611 @@
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#include "stv06xx_hdcs.h"
32
33static const struct ctrl hdcs1x00_ctrl[] = {
34 {
35 {
36 .id = V4L2_CID_EXPOSURE,
37 .type = V4L2_CTRL_TYPE_INTEGER,
38 .name = "exposure",
39 .minimum = 0x00,
40 .maximum = 0xff,
41 .step = 0x1,
42 .default_value = HDCS_DEFAULT_EXPOSURE,
43 .flags = V4L2_CTRL_FLAG_SLIDER
44 },
45 .set = hdcs_set_exposure,
46 .get = hdcs_get_exposure
47 }, {
48 {
49 .id = V4L2_CID_GAIN,
50 .type = V4L2_CTRL_TYPE_INTEGER,
51 .name = "gain",
52 .minimum = 0x00,
53 .maximum = 0xff,
54 .step = 0x1,
55 .default_value = HDCS_DEFAULT_GAIN,
56 .flags = V4L2_CTRL_FLAG_SLIDER
57 },
58 .set = hdcs_set_gain,
59 .get = hdcs_get_gain
60 }
61};
62
63static struct v4l2_pix_format hdcs1x00_mode[] = {
64 {
65 HDCS_1X00_DEF_WIDTH,
66 HDCS_1X00_DEF_HEIGHT,
67 V4L2_PIX_FMT_SGRBG8,
68 V4L2_FIELD_NONE,
69 .sizeimage =
70 HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
71 .bytesperline = HDCS_1X00_DEF_WIDTH,
72 .colorspace = V4L2_COLORSPACE_SRGB,
73 .priv = 1
74 }
75};
76
77static const struct ctrl hdcs1020_ctrl[] = {
78 {
79 {
80 .id = V4L2_CID_EXPOSURE,
81 .type = V4L2_CTRL_TYPE_INTEGER,
82 .name = "exposure",
83 .minimum = 0x00,
84 .maximum = 0xffff,
85 .step = 0x1,
86 .default_value = HDCS_DEFAULT_EXPOSURE,
87 .flags = V4L2_CTRL_FLAG_SLIDER
88 },
89 .set = hdcs_set_exposure,
90 .get = hdcs_get_exposure
91 }, {
92 {
93 .id = V4L2_CID_GAIN,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "gain",
96 .minimum = 0x00,
97 .maximum = 0xff,
98 .step = 0x1,
99 .default_value = HDCS_DEFAULT_GAIN,
100 .flags = V4L2_CTRL_FLAG_SLIDER
101 },
102 .set = hdcs_set_gain,
103 .get = hdcs_get_gain
104 }
105};
106
107static struct v4l2_pix_format hdcs1020_mode[] = {
108 {
109 HDCS_1020_DEF_WIDTH,
110 HDCS_1020_DEF_HEIGHT,
111 V4L2_PIX_FMT_SGRBG8,
112 V4L2_FIELD_NONE,
113 .sizeimage =
114 HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
115 .bytesperline = HDCS_1020_DEF_WIDTH,
116 .colorspace = V4L2_COLORSPACE_SRGB,
117 .priv = 1
118 }
119};
120
121enum hdcs_power_state {
122 HDCS_STATE_SLEEP,
123 HDCS_STATE_IDLE,
124 HDCS_STATE_RUN
125};
126
127/* no lock? */
128struct hdcs {
129 enum hdcs_power_state state;
130 int w, h;
131
132 /* visible area of the sensor array */
133 struct {
134 int left, top;
135 int width, height;
136 int border;
137 } array;
138
139 struct {
140 /* Column timing overhead */
141 u8 cto;
142 /* Column processing overhead */
143 u8 cpo;
144 /* Row sample period constant */
145 u16 rs;
146 /* Exposure reset duration */
147 u16 er;
148 } exp;
149
150 int psmp;
151 u8 exp_cache, gain_cache;
152};
153
154static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
155{
156 u8 regs[I2C_MAX_BYTES * 2];
157 int i;
158
159 if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
160 (reg + len > 0xff)))
161 return -EINVAL;
162
163 for (i = 0; i < len; i++) {
164 regs[2 * i] = reg;
165 regs[2 * i + 1] = vals[i];
166 /* All addresses are shifted left one bit
167 * as bit 0 toggles r/w */
168 reg += 2;
169 }
170
171 return stv06xx_write_sensor_bytes(sd, regs, len);
172}
173
174static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
175{
176 struct hdcs *hdcs = sd->sensor_priv;
177 u8 val;
178 int ret;
179
180 if (hdcs->state == state)
181 return 0;
182
183 /* we need to go idle before running or sleeping */
184 if (hdcs->state != HDCS_STATE_IDLE) {
185 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
186 if (ret)
187 return ret;
188 }
189
190 hdcs->state = HDCS_STATE_IDLE;
191
192 if (state == HDCS_STATE_IDLE)
193 return 0;
194
195 switch (state) {
196 case HDCS_STATE_SLEEP:
197 val = HDCS_SLEEP_MODE;
198 break;
199
200 case HDCS_STATE_RUN:
201 val = HDCS_RUN_ENABLE;
202 break;
203
204 default:
205 return -EINVAL;
206 }
207
208 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
209
210 /* Update the state if the write succeeded */
211 if (!ret)
212 hdcs->state = state;
213
214 return ret;
215}
216
217static int hdcs_reset(struct sd *sd)
218{
219 struct hdcs *hdcs = sd->sensor_priv;
220 int err;
221
222 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
223 if (err < 0)
224 return err;
225
226 err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
227 if (err < 0)
228 hdcs->state = HDCS_STATE_IDLE;
229
230 return err;
231}
232
233static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
234{
235 struct sd *sd = (struct sd *) gspca_dev;
236 struct hdcs *hdcs = sd->sensor_priv;
237
238 *val = hdcs->exp_cache;
239
240 return 0;
241}
242
243static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
244{
245 struct sd *sd = (struct sd *) gspca_dev;
246 struct hdcs *hdcs = sd->sensor_priv;
247 int rowexp, srowexp;
248 int max_srowexp;
249 /* Column time period */
250 int ct;
251 /* Column processing period */
252 int cp;
253 /* Row processing period */
254 int rp;
255 /* Minimum number of column timing periods
256 within the column processing period */
257 int mnct;
258 int cycles, err;
259 u8 exp[14];
260
261 val &= 0xff;
262 hdcs->exp_cache = val;
263
264 cycles = val * HDCS_CLK_FREQ_MHZ * 257;
265
266 ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
267 cp = hdcs->exp.cto + (hdcs->w * ct / 2);
268
269 /* the cycles one row takes */
270 rp = hdcs->exp.rs + cp;
271
272 rowexp = cycles / rp;
273
274 /* the remaining cycles */
275 cycles -= rowexp * rp;
276
277 /* calculate sub-row exposure */
278 if (IS_1020(sd)) {
279 /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
280 srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
281
282 mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
283 max_srowexp = hdcs->w - mnct;
284 } else {
285 /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
286 srowexp = cp - hdcs->exp.er - 6 - cycles;
287
288 mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
289 max_srowexp = cp - mnct * ct - 1;
290 }
291
292 if (srowexp < 0)
293 srowexp = 0;
294 else if (srowexp > max_srowexp)
295 srowexp = max_srowexp;
296
297 if (IS_1020(sd)) {
298 exp[0] = HDCS20_CONTROL;
299 exp[1] = 0x00; /* Stop streaming */
300 exp[2] = HDCS_ROWEXPL;
301 exp[3] = rowexp & 0xff;
302 exp[4] = HDCS_ROWEXPH;
303 exp[5] = rowexp >> 8;
304 exp[6] = HDCS20_SROWEXP;
305 exp[7] = (srowexp >> 2) & 0xff;
306 exp[8] = HDCS20_ERROR;
307 exp[9] = 0x10; /* Clear exposure error flag*/
308 exp[10] = HDCS20_CONTROL;
309 exp[11] = 0x04; /* Restart streaming */
310 err = stv06xx_write_sensor_bytes(sd, exp, 6);
311 } else {
312 exp[0] = HDCS00_CONTROL;
313 exp[1] = 0x00; /* Stop streaming */
314 exp[2] = HDCS_ROWEXPL;
315 exp[3] = rowexp & 0xff;
316 exp[4] = HDCS_ROWEXPH;
317 exp[5] = rowexp >> 8;
318 exp[6] = HDCS00_SROWEXPL;
319 exp[7] = srowexp & 0xff;
320 exp[8] = HDCS00_SROWEXPH;
321 exp[9] = srowexp >> 8;
322 exp[10] = HDCS_STATUS;
323 exp[11] = 0x10; /* Clear exposure error flag*/
324 exp[12] = HDCS00_CONTROL;
325 exp[13] = 0x04; /* Restart streaming */
326 err = stv06xx_write_sensor_bytes(sd, exp, 7);
327 if (err < 0)
328 return err;
329 }
330 PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
331 val, rowexp, srowexp);
332 return err;
333}
334
335static int hdcs_set_gains(struct sd *sd, u8 g)
336{
337 struct hdcs *hdcs = sd->sensor_priv;
338 int err;
339 u8 gains[4];
340
341 hdcs->gain_cache = g;
342
343 /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
344 if (g > 127)
345 g = 0x80 | (g / 2);
346
347 gains[0] = g;
348 gains[1] = g;
349 gains[2] = g;
350 gains[3] = g;
351
352 err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
353 return err;
354}
355
356static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
357{
358 struct sd *sd = (struct sd *) gspca_dev;
359 struct hdcs *hdcs = sd->sensor_priv;
360
361 *val = hdcs->gain_cache;
362
363 return 0;
364}
365
366static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
367{
368 PDEBUG(D_V4L2, "Writing gain %d", val);
369 return hdcs_set_gains((struct sd *) gspca_dev,
370 val & 0xff);
371}
372
373static int hdcs_set_size(struct sd *sd,
374 unsigned int width, unsigned int height)
375{
376 struct hdcs *hdcs = sd->sensor_priv;
377 u8 win[4];
378 unsigned int x, y;
379 int err;
380
381 /* must be multiple of 4 */
382 width = (width + 3) & ~0x3;
383 height = (height + 3) & ~0x3;
384
385 if (width > hdcs->array.width)
386 width = hdcs->array.width;
387
388 if (IS_1020(sd)) {
389 /* the borders are also invalid */
390 if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
391 > hdcs->array.height)
392 height = hdcs->array.height - 2 * hdcs->array.border -
393 HDCS_1020_BOTTOM_Y_SKIP;
394
395 y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
396 + hdcs->array.top;
397 } else {
398 if (height > hdcs->array.height)
399 height = hdcs->array.height;
400
401 y = hdcs->array.top + (hdcs->array.height - height) / 2;
402 }
403
404 x = hdcs->array.left + (hdcs->array.width - width) / 2;
405
406 win[0] = y / 4;
407 win[1] = x / 4;
408 win[2] = (y + height) / 4 - 1;
409 win[3] = (x + width) / 4 - 1;
410
411 err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
412 if (err < 0)
413 return err;
414
415 /* Update the current width and height */
416 hdcs->w = width;
417 hdcs->h = height;
418 return err;
419}
420
421static int hdcs_probe_1x00(struct sd *sd)
422{
423 struct hdcs *hdcs;
424 u16 sensor;
425 int ret;
426
427 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
428 if (ret < 0 || sensor != 0x08)
429 return -ENODEV;
430
431 info("HDCS-1000/1100 sensor detected");
432
433 sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
434 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
435 sd->desc.ctrls = hdcs1x00_ctrl;
436 sd->desc.nctrls = ARRAY_SIZE(hdcs1x00_ctrl);
437
438 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
439 if (!hdcs)
440 return -ENOMEM;
441
442 hdcs->array.left = 8;
443 hdcs->array.top = 8;
444 hdcs->array.width = HDCS_1X00_DEF_WIDTH;
445 hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
446 hdcs->array.border = 4;
447
448 hdcs->exp.cto = 4;
449 hdcs->exp.cpo = 2;
450 hdcs->exp.rs = 186;
451 hdcs->exp.er = 100;
452
453 /*
454 * Frame rate on HDCS-1000 with STV600 depends on PSMP:
455 * 4 = doesn't work at all
456 * 5 = 7.8 fps,
457 * 6 = 6.9 fps,
458 * 8 = 6.3 fps,
459 * 10 = 5.5 fps,
460 * 15 = 4.4 fps,
461 * 31 = 2.8 fps
462 *
463 * Frame rate on HDCS-1000 with STV602 depends on PSMP:
464 * 15 = doesn't work at all
465 * 18 = doesn't work at all
466 * 19 = 7.3 fps
467 * 20 = 7.4 fps
468 * 21 = 7.4 fps
469 * 22 = 7.4 fps
470 * 24 = 6.3 fps
471 * 30 = 5.4 fps
472 */
473 hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
474
475 sd->sensor_priv = hdcs;
476
477 return 0;
478}
479
480static int hdcs_probe_1020(struct sd *sd)
481{
482 struct hdcs *hdcs;
483 u16 sensor;
484 int ret;
485
486 ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
487 if (ret < 0 || sensor != 0x10)
488 return -ENODEV;
489
490 info("HDCS-1020 sensor detected");
491
492 sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
493 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
494 sd->desc.ctrls = hdcs1020_ctrl;
495 sd->desc.nctrls = ARRAY_SIZE(hdcs1020_ctrl);
496
497 hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
498 if (!hdcs)
499 return -ENOMEM;
500
501 /*
502 * From Andrey's test image: looks like HDCS-1020 upper-left
503 * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
504 * visible pixel at 375,299 (x maybe even larger?)
505 */
506 hdcs->array.left = 24;
507 hdcs->array.top = 4;
508 hdcs->array.width = HDCS_1020_DEF_WIDTH;
509 hdcs->array.height = 304;
510 hdcs->array.border = 4;
511
512 hdcs->psmp = 6;
513
514 hdcs->exp.cto = 3;
515 hdcs->exp.cpo = 3;
516 hdcs->exp.rs = 155;
517 hdcs->exp.er = 96;
518
519 sd->sensor_priv = hdcs;
520
521 return 0;
522}
523
524static int hdcs_start(struct sd *sd)
525{
526 PDEBUG(D_STREAM, "Starting stream");
527
528 return hdcs_set_state(sd, HDCS_STATE_RUN);
529}
530
531static int hdcs_stop(struct sd *sd)
532{
533 PDEBUG(D_STREAM, "Halting stream");
534
535 return hdcs_set_state(sd, HDCS_STATE_SLEEP);
536}
537
538static void hdcs_disconnect(struct sd *sd)
539{
540 PDEBUG(D_PROBE, "Disconnecting the sensor");
541 kfree(sd->sensor_priv);
542}
543
544static int hdcs_init(struct sd *sd)
545{
546 struct hdcs *hdcs = sd->sensor_priv;
547 int i, err = 0;
548
549 /* Set the STV0602AA in STV0600 emulation mode */
550 if (sd->bridge == BRIDGE_STV602)
551 stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
552
553 /* Execute the bridge init */
554 for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
555 err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
556 stv_bridge_init[i][1]);
557 }
558 if (err < 0)
559 return err;
560
561 /* sensor soft reset */
562 hdcs_reset(sd);
563
564 /* Execute the sensor init */
565 for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
566 err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
567 stv_sensor_init[i][1]);
568 }
569 if (err < 0)
570 return err;
571
572 /* Enable continuous frame capture, bit 2: stop when frame complete */
573 err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
574 if (err < 0)
575 return err;
576
577 /* Set PGA sample duration
578 (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
579 if (IS_1020(sd))
580 err = stv06xx_write_sensor(sd, HDCS_TCTRL,
581 (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
582 else
583 err = stv06xx_write_sensor(sd, HDCS_TCTRL,
584 (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
585 if (err < 0)
586 return err;
587
588 err = hdcs_set_gains(sd, HDCS_DEFAULT_GAIN);
589 if (err < 0)
590 return err;
591
592 err = hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
593 if (err < 0)
594 return err;
595
596 err = hdcs_set_exposure(&sd->gspca_dev, HDCS_DEFAULT_EXPOSURE);
597 return err;
598}
599
600static int hdcs_dump(struct sd *sd)
601{
602 u16 reg, val;
603
604 info("Dumping sensor registers:");
605
606 for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
607 stv06xx_read_sensor(sd, reg, &val);
608 info("reg 0x%02x = 0x%02x", reg, val);
609 }
610 return 0;
611}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
new file mode 100644
index 00000000000..a14a84a5079
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
@@ -0,0 +1,207 @@
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_stop(struct sd *sd);
135static int hdcs_dump(struct sd *sd);
136static void hdcs_disconnect(struct sd *sd);
137
138static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
139static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
140static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val);
141static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
142
143const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
144 .name = "HP HDCS-1000/1100",
145 .i2c_flush = 0,
146 .i2c_addr = (0x55 << 1),
147 .i2c_len = 1,
148
149 /* FIXME (see if we can lower min_packet_size, needs testing, and also
150 adjusting framerate when the bandwidth gets lower) */
151 .min_packet_size = { 847 },
152 .max_packet_size = { 847 },
153
154 .init = hdcs_init,
155 .probe = hdcs_probe_1x00,
156 .start = hdcs_start,
157 .stop = hdcs_stop,
158 .disconnect = hdcs_disconnect,
159 .dump = hdcs_dump,
160};
161
162const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
163 .name = "HDCS-1020",
164 .i2c_flush = 0,
165 .i2c_addr = (0x55 << 1),
166 .i2c_len = 1,
167
168 /* FIXME (see if we can lower min_packet_size, needs testing, and also
169 adjusting framerate when the bandwidthm gets lower) */
170 .min_packet_size = { 847 },
171 .max_packet_size = { 847 },
172
173 .init = hdcs_init,
174 .probe = hdcs_probe_1020,
175 .start = hdcs_start,
176 .stop = hdcs_stop,
177 .dump = hdcs_dump,
178};
179
180static const u16 stv_bridge_init[][2] = {
181 {STV_ISO_ENABLE, 0},
182 {STV_REG23, 0},
183 {STV_REG00, 0x1d},
184 {STV_REG01, 0xb5},
185 {STV_REG02, 0xa8},
186 {STV_REG03, 0x95},
187 {STV_REG04, 0x07},
188
189 {STV_SCAN_RATE, 0x20},
190 {STV_Y_CTRL, 0x01},
191 {STV_X_CTRL, 0x0a}
192};
193
194static const u8 stv_sensor_init[][2] = {
195 /* Clear status (writing 1 will clear the corresponding status bit) */
196 {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
197 /* Disable all interrupts */
198 {HDCS_IMASK, 0x00},
199 {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)},
200 {HDCS_PDRV, 0x00},
201 {HDCS_ICTRL, BIT(5)},
202 {HDCS_ITMG, BIT(4) | BIT(1)},
203 /* ADC output resolution to 10 bits */
204 {HDCS_ADCCTRL, 10}
205};
206
207#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
new file mode 100644
index 00000000000..75a5b9c2f15
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -0,0 +1,573 @@
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#include "stv06xx_pb0100.h"
48
49static const struct ctrl pb0100_ctrl[] = {
50#define GAIN_IDX 0
51 {
52 {
53 .id = V4L2_CID_GAIN,
54 .type = V4L2_CTRL_TYPE_INTEGER,
55 .name = "Gain",
56 .minimum = 0,
57 .maximum = 255,
58 .step = 1,
59 .default_value = 128
60 },
61 .set = pb0100_set_gain,
62 .get = pb0100_get_gain
63 },
64#define RED_BALANCE_IDX 1
65 {
66 {
67 .id = V4L2_CID_RED_BALANCE,
68 .type = V4L2_CTRL_TYPE_INTEGER,
69 .name = "Red Balance",
70 .minimum = -255,
71 .maximum = 255,
72 .step = 1,
73 .default_value = 0
74 },
75 .set = pb0100_set_red_balance,
76 .get = pb0100_get_red_balance
77 },
78#define BLUE_BALANCE_IDX 2
79 {
80 {
81 .id = V4L2_CID_BLUE_BALANCE,
82 .type = V4L2_CTRL_TYPE_INTEGER,
83 .name = "Blue Balance",
84 .minimum = -255,
85 .maximum = 255,
86 .step = 1,
87 .default_value = 0
88 },
89 .set = pb0100_set_blue_balance,
90 .get = pb0100_get_blue_balance
91 },
92#define EXPOSURE_IDX 3
93 {
94 {
95 .id = V4L2_CID_EXPOSURE,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Exposure",
98 .minimum = 0,
99 .maximum = 511,
100 .step = 1,
101 .default_value = 12
102 },
103 .set = pb0100_set_exposure,
104 .get = pb0100_get_exposure
105 },
106#define AUTOGAIN_IDX 4
107 {
108 {
109 .id = V4L2_CID_AUTOGAIN,
110 .type = V4L2_CTRL_TYPE_BOOLEAN,
111 .name = "Automatic Gain and Exposure",
112 .minimum = 0,
113 .maximum = 1,
114 .step = 1,
115 .default_value = 1
116 },
117 .set = pb0100_set_autogain,
118 .get = pb0100_get_autogain
119 },
120#define AUTOGAIN_TARGET_IDX 5
121 {
122 {
123 .id = V4L2_CTRL_CLASS_USER + 0x1000,
124 .type = V4L2_CTRL_TYPE_INTEGER,
125 .name = "Automatic Gain Target",
126 .minimum = 0,
127 .maximum = 255,
128 .step = 1,
129 .default_value = 128
130 },
131 .set = pb0100_set_autogain_target,
132 .get = pb0100_get_autogain_target
133 },
134#define NATURAL_IDX 6
135 {
136 {
137 .id = V4L2_CTRL_CLASS_USER + 0x1001,
138 .type = V4L2_CTRL_TYPE_BOOLEAN,
139 .name = "Natural Light Source",
140 .minimum = 0,
141 .maximum = 1,
142 .step = 1,
143 .default_value = 1
144 },
145 .set = pb0100_set_natural,
146 .get = pb0100_get_natural
147 }
148};
149
150static struct v4l2_pix_format pb0100_mode[] = {
151/* low res / subsample modes disabled as they are only half res horizontal,
152 halving the vertical resolution does not seem to work */
153 {
154 320,
155 240,
156 V4L2_PIX_FMT_SGRBG8,
157 V4L2_FIELD_NONE,
158 .sizeimage = 320 * 240,
159 .bytesperline = 320,
160 .colorspace = V4L2_COLORSPACE_SRGB,
161 .priv = PB0100_CROP_TO_VGA
162 },
163 {
164 352,
165 288,
166 V4L2_PIX_FMT_SGRBG8,
167 V4L2_FIELD_NONE,
168 .sizeimage = 352 * 288,
169 .bytesperline = 352,
170 .colorspace = V4L2_COLORSPACE_SRGB,
171 .priv = 0
172 }
173};
174
175static int pb0100_probe(struct sd *sd)
176{
177 u16 sensor;
178 int i, err;
179 s32 *sensor_settings;
180
181 err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
182
183 if (err < 0)
184 return -ENODEV;
185
186 if ((sensor >> 8) == 0x64) {
187 sensor_settings = kmalloc(
188 ARRAY_SIZE(pb0100_ctrl) * sizeof(s32),
189 GFP_KERNEL);
190 if (!sensor_settings)
191 return -ENOMEM;
192
193 info("Photobit pb0100 sensor detected");
194
195 sd->gspca_dev.cam.cam_mode = pb0100_mode;
196 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
197 sd->desc.ctrls = pb0100_ctrl;
198 sd->desc.nctrls = ARRAY_SIZE(pb0100_ctrl);
199 for (i = 0; i < sd->desc.nctrls; i++)
200 sensor_settings[i] = pb0100_ctrl[i].qctrl.default_value;
201 sd->sensor_priv = sensor_settings;
202
203 return 0;
204 }
205
206 return -ENODEV;
207}
208
209static int pb0100_start(struct sd *sd)
210{
211 int err, packet_size, max_packet_size;
212 struct usb_host_interface *alt;
213 struct usb_interface *intf;
214 struct cam *cam = &sd->gspca_dev.cam;
215 s32 *sensor_settings = sd->sensor_priv;
216 u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
217
218 intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
219 alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
220 if (!alt)
221 return -ENODEV;
222 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
223
224 /* If we don't have enough bandwidth use a lower framerate */
225 max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
226 if (packet_size < max_packet_size)
227 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
228 else
229 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
230
231 /* Setup sensor window */
232 if (mode & PB0100_CROP_TO_VGA) {
233 stv06xx_write_sensor(sd, PB_RSTART, 30);
234 stv06xx_write_sensor(sd, PB_CSTART, 20);
235 stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
236 stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
237 } else {
238 stv06xx_write_sensor(sd, PB_RSTART, 8);
239 stv06xx_write_sensor(sd, PB_CSTART, 4);
240 stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
241 stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
242 }
243
244 if (mode & PB0100_SUBSAMPLE) {
245 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */
246 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
247
248 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
249 } else {
250 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
251 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
252 /* larger -> slower */
253 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
254 }
255
256 /* set_gain also sets red and blue balance */
257 pb0100_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
258 pb0100_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]);
259 pb0100_set_autogain_target(&sd->gspca_dev,
260 sensor_settings[AUTOGAIN_TARGET_IDX]);
261 pb0100_set_autogain(&sd->gspca_dev, sensor_settings[AUTOGAIN_IDX]);
262
263 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
264 PDEBUG(D_STREAM, "Started stream, status: %d", err);
265
266 return (err < 0) ? err : 0;
267}
268
269static int pb0100_stop(struct sd *sd)
270{
271 int err;
272
273 err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
274
275 if (err < 0)
276 goto out;
277
278 /* Set bit 1 to zero */
279 err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
280
281 PDEBUG(D_STREAM, "Halting stream");
282out:
283 return (err < 0) ? err : 0;
284}
285
286static void pb0100_disconnect(struct sd *sd)
287{
288 sd->sensor = NULL;
289 kfree(sd->sensor_priv);
290}
291
292/* FIXME: Sort the init commands out and put them into tables,
293 this is only for getting the camera to work */
294/* FIXME: No error handling for now,
295 add this once the init has been converted to proper tables */
296static int pb0100_init(struct sd *sd)
297{
298 stv06xx_write_bridge(sd, STV_REG00, 1);
299 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
300
301 /* Reset sensor */
302 stv06xx_write_sensor(sd, PB_RESET, 1);
303 stv06xx_write_sensor(sd, PB_RESET, 0);
304
305 /* Disable chip */
306 stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
307
308 /* Gain stuff...*/
309 stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
310 stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
311
312 /* Set up auto-exposure */
313 /* ADC VREF_HI new setting for a transition
314 from the Expose1 to the Expose2 setting */
315 stv06xx_write_sensor(sd, PB_R28, 12);
316 /* gain max for autoexposure */
317 stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
318 /* gain min for autoexposure */
319 stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
320 /* Maximum frame integration time (programmed into R8)
321 allowed for auto-exposure routine */
322 stv06xx_write_sensor(sd, PB_R54, 3);
323 /* Minimum frame integration time (programmed into R8)
324 allowed for auto-exposure routine */
325 stv06xx_write_sensor(sd, PB_R55, 0);
326 stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
327 /* R15 Expose0 (maximum that auto-exposure may use) */
328 stv06xx_write_sensor(sd, PB_R15, 800);
329 /* R17 Expose2 (minimum that auto-exposure may use) */
330 stv06xx_write_sensor(sd, PB_R17, 10);
331
332 stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
333
334 /* 0x14 */
335 stv06xx_write_sensor(sd, PB_VOFFSET, 0);
336 /* 0x0D */
337 stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
338 /* Set black level (important!) */
339 stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
340
341 /* ??? */
342 stv06xx_write_bridge(sd, STV_REG00, 0x11);
343 stv06xx_write_bridge(sd, STV_REG03, 0x45);
344 stv06xx_write_bridge(sd, STV_REG04, 0x07);
345
346 /* Scan/timing for the sensor */
347 stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
348 stv06xx_write_sensor(sd, PB_CFILLIN, 14);
349 stv06xx_write_sensor(sd, PB_VBL, 0);
350 stv06xx_write_sensor(sd, PB_FINTTIME, 0);
351 stv06xx_write_sensor(sd, PB_RINTTIME, 123);
352
353 stv06xx_write_bridge(sd, STV_REG01, 0xc2);
354 stv06xx_write_bridge(sd, STV_REG02, 0xb0);
355 return 0;
356}
357
358static int pb0100_dump(struct sd *sd)
359{
360 return 0;
361}
362
363static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
364{
365 struct sd *sd = (struct sd *) gspca_dev;
366 s32 *sensor_settings = sd->sensor_priv;
367
368 *val = sensor_settings[GAIN_IDX];
369
370 return 0;
371}
372
373static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
374{
375 int err;
376 struct sd *sd = (struct sd *) gspca_dev;
377 s32 *sensor_settings = sd->sensor_priv;
378
379 if (sensor_settings[AUTOGAIN_IDX])
380 return -EBUSY;
381
382 sensor_settings[GAIN_IDX] = val;
383 err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
384 if (!err)
385 err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
386 PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
387
388 if (!err)
389 err = pb0100_set_red_balance(gspca_dev,
390 sensor_settings[RED_BALANCE_IDX]);
391 if (!err)
392 err = pb0100_set_blue_balance(gspca_dev,
393 sensor_settings[BLUE_BALANCE_IDX]);
394
395 return err;
396}
397
398static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
399{
400 struct sd *sd = (struct sd *) gspca_dev;
401 s32 *sensor_settings = sd->sensor_priv;
402
403 *val = sensor_settings[RED_BALANCE_IDX];
404
405 return 0;
406}
407
408static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
409{
410 int err;
411 struct sd *sd = (struct sd *) gspca_dev;
412 s32 *sensor_settings = sd->sensor_priv;
413
414 if (sensor_settings[AUTOGAIN_IDX])
415 return -EBUSY;
416
417 sensor_settings[RED_BALANCE_IDX] = val;
418 val += sensor_settings[GAIN_IDX];
419 if (val < 0)
420 val = 0;
421 else if (val > 255)
422 val = 255;
423
424 err = stv06xx_write_sensor(sd, PB_RGAIN, val);
425 PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
426
427 return err;
428}
429
430static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
431{
432 struct sd *sd = (struct sd *) gspca_dev;
433 s32 *sensor_settings = sd->sensor_priv;
434
435 *val = sensor_settings[BLUE_BALANCE_IDX];
436
437 return 0;
438}
439
440static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
441{
442 int err;
443 struct sd *sd = (struct sd *) gspca_dev;
444 s32 *sensor_settings = sd->sensor_priv;
445
446 if (sensor_settings[AUTOGAIN_IDX])
447 return -EBUSY;
448
449 sensor_settings[BLUE_BALANCE_IDX] = val;
450 val += sensor_settings[GAIN_IDX];
451 if (val < 0)
452 val = 0;
453 else if (val > 255)
454 val = 255;
455
456 err = stv06xx_write_sensor(sd, PB_BGAIN, val);
457 PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
458
459 return err;
460}
461
462static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
463{
464 struct sd *sd = (struct sd *) gspca_dev;
465 s32 *sensor_settings = sd->sensor_priv;
466
467 *val = sensor_settings[EXPOSURE_IDX];
468
469 return 0;
470}
471
472static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
473{
474 int err;
475 struct sd *sd = (struct sd *) gspca_dev;
476 s32 *sensor_settings = sd->sensor_priv;
477
478 if (sensor_settings[AUTOGAIN_IDX])
479 return -EBUSY;
480
481 sensor_settings[EXPOSURE_IDX] = val;
482 err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
483 PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
484
485 return err;
486}
487
488static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val)
489{
490 struct sd *sd = (struct sd *) gspca_dev;
491 s32 *sensor_settings = sd->sensor_priv;
492
493 *val = sensor_settings[AUTOGAIN_IDX];
494
495 return 0;
496}
497
498static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
499{
500 int err;
501 struct sd *sd = (struct sd *) gspca_dev;
502 s32 *sensor_settings = sd->sensor_priv;
503
504 sensor_settings[AUTOGAIN_IDX] = val;
505 if (sensor_settings[AUTOGAIN_IDX]) {
506 if (sensor_settings[NATURAL_IDX])
507 val = BIT(6)|BIT(4)|BIT(0);
508 else
509 val = BIT(4)|BIT(0);
510 } else
511 val = 0;
512
513 err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
514 PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
515 sensor_settings[AUTOGAIN_IDX], sensor_settings[NATURAL_IDX],
516 err);
517
518 return err;
519}
520
521static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val)
522{
523 struct sd *sd = (struct sd *) gspca_dev;
524 s32 *sensor_settings = sd->sensor_priv;
525
526 *val = sensor_settings[AUTOGAIN_TARGET_IDX];
527
528 return 0;
529}
530
531static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
532{
533 int err, totalpixels, brightpixels, darkpixels;
534 struct sd *sd = (struct sd *) gspca_dev;
535 s32 *sensor_settings = sd->sensor_priv;
536
537 sensor_settings[AUTOGAIN_TARGET_IDX] = val;
538
539 /* Number of pixels counted by the sensor when subsampling the pixels.
540 * Slightly larger than the real value to avoid oscillation */
541 totalpixels = gspca_dev->width * gspca_dev->height;
542 totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
543
544 brightpixels = (totalpixels * val) >> 8;
545 darkpixels = totalpixels - brightpixels;
546 err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
547 if (!err)
548 err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
549
550 PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
551
552 return err;
553}
554
555static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val)
556{
557 struct sd *sd = (struct sd *) gspca_dev;
558 s32 *sensor_settings = sd->sensor_priv;
559
560 *val = sensor_settings[NATURAL_IDX];
561
562 return 0;
563}
564
565static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val)
566{
567 struct sd *sd = (struct sd *) gspca_dev;
568 s32 *sensor_settings = sd->sensor_priv;
569
570 sensor_settings[NATURAL_IDX] = val;
571
572 return pb0100_set_autogain(gspca_dev, sensor_settings[AUTOGAIN_IDX]);
573}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
new file mode 100644
index 00000000000..757de246dc7
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
@@ -0,0 +1,152 @@
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_stop(struct sd *sd);
116static int pb0100_dump(struct sd *sd);
117static void pb0100_disconnect(struct sd *sd);
118
119/* V4L2 controls supported by the driver */
120static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
121static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val);
122static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
123static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
124static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
125static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
126static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
127static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
128static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val);
129static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val);
130static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val);
131static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val);
132static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val);
133static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val);
134
135const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
136 .name = "PB-0100",
137 .i2c_flush = 1,
138 .i2c_addr = 0xba,
139 .i2c_len = 2,
140
141 .min_packet_size = { 635, 847 },
142 .max_packet_size = { 847, 923 },
143
144 .init = pb0100_init,
145 .probe = pb0100_probe,
146 .start = pb0100_start,
147 .stop = pb0100_stop,
148 .dump = pb0100_dump,
149 .disconnect = pb0100_disconnect,
150};
151
152#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
new file mode 100644
index 00000000000..fb229d8ded5
--- /dev/null
+++ b/drivers/media/video/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 /* Executed at device disconnect */
67 void (*disconnect)(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/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
new file mode 100644
index 00000000000..8a456de4970
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -0,0 +1,401 @@
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#include "stv06xx_st6422.h"
30
31/* controls */
32enum e_ctrl {
33 BRIGHTNESS,
34 CONTRAST,
35 GAIN,
36 EXPOSURE,
37 NCTRLS /* number of controls */
38};
39
40/* sensor settings */
41struct st6422_settings {
42 struct gspca_ctrl ctrls[NCTRLS];
43};
44
45static struct v4l2_pix_format st6422_mode[] = {
46 /* Note we actually get 124 lines of data, of which we skip the 4st
47 4 as they are garbage */
48 {
49 162,
50 120,
51 V4L2_PIX_FMT_SGRBG8,
52 V4L2_FIELD_NONE,
53 .sizeimage = 162 * 120,
54 .bytesperline = 162,
55 .colorspace = V4L2_COLORSPACE_SRGB,
56 .priv = 1
57 },
58 /* Note we actually get 248 lines of data, of which we skip the 4st
59 4 as they are garbage, and we tell the app it only gets the
60 first 240 of the 244 lines it actually gets, so that it ignores
61 the last 4. */
62 {
63 324,
64 240,
65 V4L2_PIX_FMT_SGRBG8,
66 V4L2_FIELD_NONE,
67 .sizeimage = 324 * 244,
68 .bytesperline = 324,
69 .colorspace = V4L2_COLORSPACE_SRGB,
70 .priv = 0
71 },
72};
73
74/* V4L2 controls supported by the driver */
75static void st6422_set_brightness(struct gspca_dev *gspca_dev);
76static void st6422_set_contrast(struct gspca_dev *gspca_dev);
77static void st6422_set_gain(struct gspca_dev *gspca_dev);
78static void st6422_set_exposure(struct gspca_dev *gspca_dev);
79
80static const struct ctrl st6422_ctrl[NCTRLS] = {
81[BRIGHTNESS] = {
82 {
83 .id = V4L2_CID_BRIGHTNESS,
84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "Brightness",
86 .minimum = 0,
87 .maximum = 31,
88 .step = 1,
89 .default_value = 3
90 },
91 .set_control = st6422_set_brightness
92 },
93[CONTRAST] = {
94 {
95 .id = V4L2_CID_CONTRAST,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Contrast",
98 .minimum = 0,
99 .maximum = 15,
100 .step = 1,
101 .default_value = 11
102 },
103 .set_control = st6422_set_contrast
104 },
105[GAIN] = {
106 {
107 .id = V4L2_CID_GAIN,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Gain",
110 .minimum = 0,
111 .maximum = 255,
112 .step = 1,
113 .default_value = 64
114 },
115 .set_control = st6422_set_gain
116 },
117[EXPOSURE] = {
118 {
119 .id = V4L2_CID_EXPOSURE,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Exposure",
122 .minimum = 0,
123#define EXPOSURE_MAX 1023
124 .maximum = EXPOSURE_MAX,
125 .step = 1,
126 .default_value = 256
127 },
128 .set_control = st6422_set_exposure
129 },
130};
131
132static int st6422_probe(struct sd *sd)
133{
134 struct st6422_settings *sensor_settings;
135
136 if (sd->bridge != BRIDGE_ST6422)
137 return -ENODEV;
138
139 info("st6422 sensor detected");
140
141 sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
142 if (!sensor_settings)
143 return -ENOMEM;
144
145 sd->gspca_dev.cam.cam_mode = st6422_mode;
146 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
147 sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
148 sd->desc.ctrls = st6422_ctrl;
149 sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
150 sd->sensor_priv = sensor_settings;
151
152 return 0;
153}
154
155static int st6422_init(struct sd *sd)
156{
157 int err = 0, i;
158
159 const u16 st6422_bridge_init[][2] = {
160 { STV_ISO_ENABLE, 0x00 }, /* disable capture */
161 { 0x1436, 0x00 },
162 { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
163 { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
164 { 0x0509, 0x38 }, /* R */
165 { 0x050a, 0x38 }, /* G */
166 { 0x050b, 0x38 }, /* B */
167 { 0x050c, 0x2a },
168 { 0x050d, 0x01 },
169
170
171 { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
172 { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
173 { 0x1438, 0x18 }, /* 640x480 */
174/* 18 bayes */
175/* 10 compressed? */
176
177 { 0x1439, 0x00 },
178/* anti-noise? 0xa2 gives a perfect image */
179
180 { 0x143b, 0x05 },
181 { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
182
183
184/* shutter time 0x0000-0x03FF */
185/* low value give good picures on moving objects (but requires much light) */
186/* high value gives good picures in darkness (but tends to be overexposed) */
187 { 0x143e, 0x01 },
188 { 0x143d, 0x00 },
189
190 { 0x1442, 0xe2 },
191/* write: 1x1x xxxx */
192/* read: 1x1x xxxx */
193/* bit 5 == button pressed and hold if 0 */
194/* write 0xe2,0xea */
195
196/* 0x144a */
197/* 0x00 init */
198/* bit 7 == button has been pressed, but not handled */
199
200/* interrupt */
201/* if(urb->iso_frame_desc[i].status == 0x80) { */
202/* if(urb->iso_frame_desc[i].status == 0x88) { */
203
204 { 0x1500, 0xd0 },
205 { 0x1500, 0xd0 },
206 { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
207
208 { 0x1501, 0xaf },
209/* high val-> light area gets darker */
210/* low val -> light area gets lighter */
211 { 0x1502, 0xc2 },
212/* high val-> light area gets darker */
213/* low val -> light area gets lighter */
214 { 0x1503, 0x45 },
215/* high val-> light area gets darker */
216/* low val -> light area gets lighter */
217 { 0x1505, 0x02 },
218/* 2 : 324x248 80352 bytes */
219/* 7 : 248x162 40176 bytes */
220/* c+f: 162*124 20088 bytes */
221
222 { 0x150e, 0x8e },
223 { 0x150f, 0x37 },
224 { 0x15c0, 0x00 },
225 { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
226
227
228 { 0x143f, 0x01 }, /* commit settings */
229
230 };
231
232 for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
233 err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
234 st6422_bridge_init[i][1]);
235 }
236
237 return err;
238}
239
240static void st6422_disconnect(struct sd *sd)
241{
242 sd->sensor = NULL;
243 kfree(sd->sensor_priv);
244}
245
246static int setbrightness(struct sd *sd)
247{
248 struct st6422_settings *sensor_settings = sd->sensor_priv;
249
250 /* val goes from 0 -> 31 */
251 return stv06xx_write_bridge(sd, 0x1432,
252 sensor_settings->ctrls[BRIGHTNESS].val);
253}
254
255static int setcontrast(struct sd *sd)
256{
257 struct st6422_settings *sensor_settings = sd->sensor_priv;
258
259 /* Val goes from 0 -> 15 */
260 return stv06xx_write_bridge(sd, 0x143a,
261 sensor_settings->ctrls[CONTRAST].val | 0xf0);
262}
263
264static int setgain(struct sd *sd)
265{
266 struct st6422_settings *sensor_settings = sd->sensor_priv;
267 u8 gain;
268 int err;
269
270 gain = sensor_settings->ctrls[GAIN].val;
271
272 /* Set red, green, blue, gain */
273 err = stv06xx_write_bridge(sd, 0x0509, gain);
274 if (err < 0)
275 return err;
276
277 err = stv06xx_write_bridge(sd, 0x050a, gain);
278 if (err < 0)
279 return err;
280
281 err = stv06xx_write_bridge(sd, 0x050b, gain);
282 if (err < 0)
283 return err;
284
285 /* 2 mystery writes */
286 err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
287 if (err < 0)
288 return err;
289
290 return stv06xx_write_bridge(sd, 0x050d, 0x01);
291}
292
293static int setexposure(struct sd *sd)
294{
295 struct st6422_settings *sensor_settings = sd->sensor_priv;
296 u16 expo;
297 int err;
298
299 expo = sensor_settings->ctrls[EXPOSURE].val;
300 err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
301 if (err < 0)
302 return err;
303
304 return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
305}
306
307static int st6422_start(struct sd *sd)
308{
309 int err;
310 struct cam *cam = &sd->gspca_dev.cam;
311
312 if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
313 err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
314 else
315 err = stv06xx_write_bridge(sd, 0x1505, 0x02);
316 if (err < 0)
317 return err;
318
319 err = setbrightness(sd);
320 if (err < 0)
321 return err;
322
323 err = setcontrast(sd);
324 if (err < 0)
325 return err;
326
327 err = setexposure(sd);
328 if (err < 0)
329 return err;
330
331 err = setgain(sd);
332 if (err < 0)
333 return err;
334
335 /* commit settings */
336 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
337 return (err < 0) ? err : 0;
338}
339
340static int st6422_stop(struct sd *sd)
341{
342 PDEBUG(D_STREAM, "Halting stream");
343
344 return 0;
345}
346
347static void st6422_set_brightness(struct gspca_dev *gspca_dev)
348{
349 int err;
350 struct sd *sd = (struct sd *) gspca_dev;
351
352 err = setbrightness(sd);
353
354 /* commit settings */
355 if (err >= 0)
356 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
357
358 gspca_dev->usb_err = err;
359}
360
361static void st6422_set_contrast(struct gspca_dev *gspca_dev)
362{
363 int err;
364 struct sd *sd = (struct sd *) gspca_dev;
365
366 err = setcontrast(sd);
367
368 /* commit settings */
369 if (err >= 0)
370 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
371
372 gspca_dev->usb_err = err;
373}
374
375static void st6422_set_gain(struct gspca_dev *gspca_dev)
376{
377 int err;
378 struct sd *sd = (struct sd *) gspca_dev;
379
380 err = setgain(sd);
381
382 /* commit settings */
383 if (err >= 0)
384 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
385
386 gspca_dev->usb_err = err;
387}
388
389static void st6422_set_exposure(struct gspca_dev *gspca_dev)
390{
391 int err;
392 struct sd *sd = (struct sd *) gspca_dev;
393
394 err = setexposure(sd);
395
396 /* commit settings */
397 if (err >= 0)
398 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
399
400 gspca_dev->usb_err = err;
401}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
new file mode 100644
index 00000000000..d7498e06432
--- /dev/null
+++ b/drivers/media/video/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_stop(struct sd *sd);
38static void st6422_disconnect(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 .probe = st6422_probe,
47 .start = st6422_start,
48 .stop = st6422_stop,
49 .disconnect = st6422_disconnect,
50};
51
52#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
new file mode 100644
index 00000000000..f8398434c32
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
@@ -0,0 +1,392 @@
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#include "stv06xx_vv6410.h"
31
32static struct v4l2_pix_format vv6410_mode[] = {
33 {
34 356,
35 292,
36 V4L2_PIX_FMT_SGRBG8,
37 V4L2_FIELD_NONE,
38 .sizeimage = 356 * 292,
39 .bytesperline = 356,
40 .colorspace = V4L2_COLORSPACE_SRGB,
41 .priv = 0
42 }
43};
44
45static const struct ctrl vv6410_ctrl[] = {
46#define HFLIP_IDX 0
47 {
48 {
49 .id = V4L2_CID_HFLIP,
50 .type = V4L2_CTRL_TYPE_BOOLEAN,
51 .name = "horizontal flip",
52 .minimum = 0,
53 .maximum = 1,
54 .step = 1,
55 .default_value = 0
56 },
57 .set = vv6410_set_hflip,
58 .get = vv6410_get_hflip
59 },
60#define VFLIP_IDX 1
61 {
62 {
63 .id = V4L2_CID_VFLIP,
64 .type = V4L2_CTRL_TYPE_BOOLEAN,
65 .name = "vertical flip",
66 .minimum = 0,
67 .maximum = 1,
68 .step = 1,
69 .default_value = 0
70 },
71 .set = vv6410_set_vflip,
72 .get = vv6410_get_vflip
73 },
74#define GAIN_IDX 2
75 {
76 {
77 .id = V4L2_CID_GAIN,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "analog gain",
80 .minimum = 0,
81 .maximum = 15,
82 .step = 1,
83 .default_value = 10
84 },
85 .set = vv6410_set_analog_gain,
86 .get = vv6410_get_analog_gain
87 },
88#define EXPOSURE_IDX 3
89 {
90 {
91 .id = V4L2_CID_EXPOSURE,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "exposure",
94 .minimum = 0,
95 .maximum = 32768,
96 .step = 1,
97 .default_value = 20000
98 },
99 .set = vv6410_set_exposure,
100 .get = vv6410_get_exposure
101 }
102 };
103
104static int vv6410_probe(struct sd *sd)
105{
106 u16 data;
107 int err, i;
108 s32 *sensor_settings;
109
110 err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
111 if (err < 0)
112 return -ENODEV;
113
114 if (data == 0x19) {
115 info("vv6410 sensor detected");
116
117 sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
118 GFP_KERNEL);
119 if (!sensor_settings)
120 return -ENOMEM;
121
122 sd->gspca_dev.cam.cam_mode = vv6410_mode;
123 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
124 sd->desc.ctrls = vv6410_ctrl;
125 sd->desc.nctrls = ARRAY_SIZE(vv6410_ctrl);
126
127 for (i = 0; i < sd->desc.nctrls; i++)
128 sensor_settings[i] = vv6410_ctrl[i].qctrl.default_value;
129 sd->sensor_priv = sensor_settings;
130 return 0;
131 }
132 return -ENODEV;
133}
134
135static int vv6410_init(struct sd *sd)
136{
137 int err = 0, i;
138 s32 *sensor_settings = sd->sensor_priv;
139
140 for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
141 /* if NULL then len contains single value */
142 if (stv_bridge_init[i].data == NULL) {
143 err = stv06xx_write_bridge(sd,
144 stv_bridge_init[i].start,
145 stv_bridge_init[i].len);
146 } else {
147 int j;
148 for (j = 0; j < stv_bridge_init[i].len; j++)
149 err = stv06xx_write_bridge(sd,
150 stv_bridge_init[i].start + j,
151 stv_bridge_init[i].data[j]);
152 }
153 }
154
155 if (err < 0)
156 return err;
157
158 err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
159 ARRAY_SIZE(vv6410_sensor_init));
160 if (err < 0)
161 return err;
162
163 err = vv6410_set_exposure(&sd->gspca_dev,
164 sensor_settings[EXPOSURE_IDX]);
165 if (err < 0)
166 return err;
167
168 err = vv6410_set_analog_gain(&sd->gspca_dev,
169 sensor_settings[GAIN_IDX]);
170
171 return (err < 0) ? err : 0;
172}
173
174static void vv6410_disconnect(struct sd *sd)
175{
176 sd->sensor = NULL;
177 kfree(sd->sensor_priv);
178}
179
180static int vv6410_start(struct sd *sd)
181{
182 int err;
183 struct cam *cam = &sd->gspca_dev.cam;
184 u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
185
186 if (priv & VV6410_CROP_TO_QVGA) {
187 PDEBUG(D_CONF, "Cropping to QVGA");
188 stv06xx_write_sensor(sd, VV6410_XENDH, 320 - 1);
189 stv06xx_write_sensor(sd, VV6410_YENDH, 240 - 1);
190 } else {
191 stv06xx_write_sensor(sd, VV6410_XENDH, 360 - 1);
192 stv06xx_write_sensor(sd, VV6410_YENDH, 294 - 1);
193 }
194
195 if (priv & VV6410_SUBSAMPLE) {
196 PDEBUG(D_CONF, "Enabling subsampling");
197 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
198 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
199
200 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
201 } else {
202 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
203 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
204
205 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
206 }
207
208 /* Turn on LED */
209 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
210 if (err < 0)
211 return err;
212
213 err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
214 if (err < 0)
215 return err;
216
217 PDEBUG(D_STREAM, "Starting stream");
218
219 return 0;
220}
221
222static int vv6410_stop(struct sd *sd)
223{
224 int err;
225
226 /* Turn off LED */
227 err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
228 if (err < 0)
229 return err;
230
231 err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
232 if (err < 0)
233 return err;
234
235 PDEBUG(D_STREAM, "Halting stream");
236
237 return (err < 0) ? err : 0;
238}
239
240static int vv6410_dump(struct sd *sd)
241{
242 u8 i;
243 int err = 0;
244
245 info("Dumping all vv6410 sensor registers");
246 for (i = 0; i < 0xff && !err; i++) {
247 u16 data;
248 err = stv06xx_read_sensor(sd, i, &data);
249 info("Register 0x%x contained 0x%x", i, data);
250 }
251 return (err < 0) ? err : 0;
252}
253
254static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
255{
256 struct sd *sd = (struct sd *) gspca_dev;
257 s32 *sensor_settings = sd->sensor_priv;
258
259 *val = sensor_settings[HFLIP_IDX];
260 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
261
262 return 0;
263}
264
265static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
266{
267 int err;
268 u16 i2c_data;
269 struct sd *sd = (struct sd *) gspca_dev;
270 s32 *sensor_settings = sd->sensor_priv;
271
272 sensor_settings[HFLIP_IDX] = val;
273 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
274 if (err < 0)
275 return err;
276
277 if (val)
278 i2c_data |= VV6410_HFLIP;
279 else
280 i2c_data &= ~VV6410_HFLIP;
281
282 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
283 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
284
285 return (err < 0) ? err : 0;
286}
287
288static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
289{
290 struct sd *sd = (struct sd *) gspca_dev;
291 s32 *sensor_settings = sd->sensor_priv;
292
293 *val = sensor_settings[VFLIP_IDX];
294 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
295
296 return 0;
297}
298
299static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
300{
301 int err;
302 u16 i2c_data;
303 struct sd *sd = (struct sd *) gspca_dev;
304 s32 *sensor_settings = sd->sensor_priv;
305
306 sensor_settings[VFLIP_IDX] = val;
307 err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
308 if (err < 0)
309 return err;
310
311 if (val)
312 i2c_data |= VV6410_VFLIP;
313 else
314 i2c_data &= ~VV6410_VFLIP;
315
316 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
317 err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
318
319 return (err < 0) ? err : 0;
320}
321
322static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val)
323{
324 struct sd *sd = (struct sd *) gspca_dev;
325 s32 *sensor_settings = sd->sensor_priv;
326
327 *val = sensor_settings[GAIN_IDX];
328
329 PDEBUG(D_V4L2, "Read analog gain %d", *val);
330
331 return 0;
332}
333
334static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
335{
336 int err;
337 struct sd *sd = (struct sd *) gspca_dev;
338 s32 *sensor_settings = sd->sensor_priv;
339
340 sensor_settings[GAIN_IDX] = val;
341 PDEBUG(D_V4L2, "Set analog gain to %d", val);
342 err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
343
344 return (err < 0) ? err : 0;
345}
346
347static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
348{
349 struct sd *sd = (struct sd *) gspca_dev;
350 s32 *sensor_settings = sd->sensor_priv;
351
352 *val = sensor_settings[EXPOSURE_IDX];
353
354 PDEBUG(D_V4L2, "Read exposure %d", *val);
355
356 return 0;
357}
358
359static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
360{
361 int err;
362 struct sd *sd = (struct sd *) gspca_dev;
363 s32 *sensor_settings = sd->sensor_priv;
364 unsigned int fine, coarse;
365
366 sensor_settings[EXPOSURE_IDX] = val;
367
368 val = (val * val >> 14) + val / 4;
369
370 fine = val % VV6410_CIF_LINELENGTH;
371 coarse = min(512, val / VV6410_CIF_LINELENGTH);
372
373 PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
374 coarse, fine);
375
376 err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
377 if (err < 0)
378 goto out;
379
380 err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
381 if (err < 0)
382 goto out;
383
384 err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
385 if (err < 0)
386 goto out;
387
388 err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
389
390out:
391 return err;
392}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
new file mode 100644
index 00000000000..7fe3587f5f7
--- /dev/null
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -0,0 +1,259 @@
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_stop(struct sd *sd);
182static int vv6410_dump(struct sd *sd);
183static void vv6410_disconnect(struct sd *sd);
184
185/* V4L2 controls supported by the driver */
186static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
187static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
188static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
189static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
190static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
191static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
192static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
193static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
194
195const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
196 .name = "ST VV6410",
197 .i2c_flush = 5,
198 .i2c_addr = 0x20,
199 .i2c_len = 1,
200 /* FIXME (see if we can lower packet_size-s, needs testing, and also
201 adjusting framerate when the bandwidth gets lower) */
202 .min_packet_size = { 1023 },
203 .max_packet_size = { 1023 },
204 .init = vv6410_init,
205 .probe = vv6410_probe,
206 .start = vv6410_start,
207 .stop = vv6410_stop,
208 .dump = vv6410_dump,
209 .disconnect = vv6410_disconnect,
210};
211
212/* If NULL, only single value to write, stored in len */
213struct stv_init {
214 const u8 *data;
215 u16 start;
216 u8 len;
217};
218
219static const u8 x1500[] = { /* 0x1500 - 0x150f */
220 0x0b, 0xa7, 0xb7, 0x00, 0x00
221};
222
223static const u8 x1536[] = { /* 0x1536 - 0x153b */
224 0x02, 0x00, 0x60, 0x01, 0x20, 0x01
225};
226
227static const struct stv_init stv_bridge_init[] = {
228 /* This reg is written twice. Some kind of reset? */
229 {NULL, 0x1620, 0x80},
230 {NULL, 0x1620, 0x00},
231 {NULL, 0x1443, 0x00},
232 {NULL, 0x1423, 0x04},
233 {x1500, 0x1500, ARRAY_SIZE(x1500)},
234 {x1536, 0x1536, ARRAY_SIZE(x1536)},
235};
236
237static const u8 vv6410_sensor_init[][2] = {
238 /* Setup registers */
239 {VV6410_SETUP0, VV6410_SOFT_RESET},
240 {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
241 /* Use shuffled read-out mode */
242 {VV6410_SETUP1, BIT(6)},
243 /* All modes to 1 */
244 {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
245 {VV6410_PINMAPPING, 0x00},
246 /* Pre-clock generator divide off */
247 {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
248
249 {VV6410_CLKDIV, VV6410_CLK_DIV_2},
250
251 /* System registers */
252 /* Enable voltage doubler */
253 {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
254 {VV6410_AT0, 0x00},
255 /* Power up audio, differential */
256 {VV6410_AT1, BIT(4)|BIT(0)},
257};
258
259#endif
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
new file mode 100644
index 00000000000..6ec23290218
--- /dev/null
+++ b/drivers/media/video/gspca/sunplus.c
@@ -0,0 +1,1223 @@
1/*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sunplus"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28MODULE_DESCRIPTION("GSPCA/SPCA5xx 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 s8 brightness;
36 u8 contrast;
37 u8 colors;
38 u8 autogain;
39 u8 quality;
40#define QUALITY_MIN 70
41#define QUALITY_MAX 95
42#define QUALITY_DEF 85
43
44 u8 bridge;
45#define BRIDGE_SPCA504 0
46#define BRIDGE_SPCA504B 1
47#define BRIDGE_SPCA504C 2
48#define BRIDGE_SPCA533 3
49#define BRIDGE_SPCA536 4
50 u8 subtype;
51#define AiptekMiniPenCam13 1
52#define LogitechClickSmart420 2
53#define LogitechClickSmart820 3
54#define MegapixV4 4
55#define MegaImageVI 5
56
57 u8 jpeg_hdr[JPEG_HDR_SZ];
58};
59
60/* V4L2 controls supported by the driver */
61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69
70static const struct ctrl sd_ctrls[] = {
71 {
72 {
73 .id = V4L2_CID_BRIGHTNESS,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Brightness",
76 .minimum = -128,
77 .maximum = 127,
78 .step = 1,
79#define BRIGHTNESS_DEF 0
80 .default_value = BRIGHTNESS_DEF,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85 {
86 {
87 .id = V4L2_CID_CONTRAST,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Contrast",
90 .minimum = 0,
91 .maximum = 0xff,
92 .step = 1,
93#define CONTRAST_DEF 0x20
94 .default_value = CONTRAST_DEF,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99 {
100 {
101 .id = V4L2_CID_SATURATION,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Color",
104 .minimum = 0,
105 .maximum = 0xff,
106 .step = 1,
107#define COLOR_DEF 0x1a
108 .default_value = COLOR_DEF,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113 {
114 {
115 .id = V4L2_CID_AUTOGAIN,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "Auto Gain",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121#define AUTOGAIN_DEF 1
122 .default_value = AUTOGAIN_DEF,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
129static const struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 2},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 1},
140};
141
142static const struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 2},
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .bytesperline = 464,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
152 .priv = 1},
153};
154
155static const struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .bytesperline = 176,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
160 .priv = 4},
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .bytesperline = 320,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
165 .priv = 3},
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .bytesperline = 352,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
170 .priv = 2},
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
175 .priv = 1},
176};
177
178#define SPCA50X_OFFSET_DATA 10
179#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181#define SPCA504_PCCAM600_OFFSET_MODE 5
182#define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184#define SPCA533_OFFSET_DATA 16
185#define SPCA533_OFFSET_FRAMSEQ 15
186/* Frame packet header offsets for the spca536 */
187#define SPCA536_OFFSET_DATA 4
188#define SPCA536_OFFSET_FRAMSEQ 1
189
190struct cmd {
191 u8 req;
192 u16 val;
193 u16 idx;
194};
195
196/* Initialisation data for the Creative PC-CAM 600 */
197static const struct cmd spca504_pccam600_init_data[] = {
198/* {0xa0, 0x0000, 0x0503}, * capture mode */
199 {0x00, 0x0000, 0x2000},
200 {0x00, 0x0013, 0x2301},
201 {0x00, 0x0003, 0x2000},
202 {0x00, 0x0001, 0x21ac},
203 {0x00, 0x0001, 0x21a6},
204 {0x00, 0x0000, 0x21a7}, /* brightness */
205 {0x00, 0x0020, 0x21a8}, /* contrast */
206 {0x00, 0x0001, 0x21ac}, /* sat/hue */
207 {0x00, 0x0000, 0x21ad}, /* hue */
208 {0x00, 0x001a, 0x21ae}, /* saturation */
209 {0x00, 0x0002, 0x21a3}, /* gamma */
210 {0x30, 0x0154, 0x0008},
211 {0x30, 0x0004, 0x0006},
212 {0x30, 0x0258, 0x0009},
213 {0x30, 0x0004, 0x0000},
214 {0x30, 0x0093, 0x0004},
215 {0x30, 0x0066, 0x0005},
216 {0x00, 0x0000, 0x2000},
217 {0x00, 0x0013, 0x2301},
218 {0x00, 0x0003, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
221};
222
223/* Creative PC-CAM 600 specific open data, sent before using the
224 * generic initialisation data from spca504_open_data.
225 */
226static const struct cmd spca504_pccam600_open_data[] = {
227 {0x00, 0x0001, 0x2501},
228 {0x20, 0x0500, 0x0001}, /* snapshot mode */
229 {0x00, 0x0003, 0x2880},
230 {0x00, 0x0001, 0x2881},
231};
232
233/* Initialisation data for the logitech clicksmart 420 */
234static const struct cmd spca504A_clicksmart420_init_data[] = {
235/* {0xa0, 0x0000, 0x0503}, * capture mode */
236 {0x00, 0x0000, 0x2000},
237 {0x00, 0x0013, 0x2301},
238 {0x00, 0x0003, 0x2000},
239 {0x00, 0x0001, 0x21ac},
240 {0x00, 0x0001, 0x21a6},
241 {0x00, 0x0000, 0x21a7}, /* brightness */
242 {0x00, 0x0020, 0x21a8}, /* contrast */
243 {0x00, 0x0001, 0x21ac}, /* sat/hue */
244 {0x00, 0x0000, 0x21ad}, /* hue */
245 {0x00, 0x001a, 0x21ae}, /* saturation */
246 {0x00, 0x0002, 0x21a3}, /* gamma */
247 {0x30, 0x0004, 0x000a},
248 {0xb0, 0x0001, 0x0000},
249
250 {0xa1, 0x0080, 0x0001},
251 {0x30, 0x0049, 0x0000},
252 {0x30, 0x0060, 0x0005},
253 {0x0c, 0x0004, 0x0000},
254 {0x00, 0x0000, 0x0000},
255 {0x00, 0x0000, 0x2000},
256 {0x00, 0x0013, 0x2301},
257 {0x00, 0x0003, 0x2000},
258};
259
260/* clicksmart 420 open data ? */
261static const struct cmd spca504A_clicksmart420_open_data[] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267
268 {0xa0, 0x0000, 0x0503},
269};
270
271static const u8 qtable_creative_pccam[2][64] = {
272 { /* Q-table Y-components */
273 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
274 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
275 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
276 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
277 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
278 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
279 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
280 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
281 { /* Q-table C-components */
282 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
283 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
284 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
285 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
290};
291
292/* FIXME: This Q-table is identical to the Creative PC-CAM one,
293 * except for one byte. Possibly a typo?
294 * NWG: 18/05/2003.
295 */
296static const u8 qtable_spca504_default[2][64] = {
297 { /* Q-table Y-components */
298 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
299 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
300 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
301 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
302 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
303 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
304 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
305 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
306 },
307 { /* Q-table C-components */
308 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
309 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
310 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
316};
317
318/* read <len> bytes to gspca_dev->usb_buf */
319static void reg_r(struct gspca_dev *gspca_dev,
320 u8 req,
321 u16 index,
322 u16 len)
323{
324 int ret;
325
326#ifdef GSPCA_DEBUG
327 if (len > USB_BUF_SZ) {
328 err("reg_r: buffer overflow");
329 return;
330 }
331#endif
332 if (gspca_dev->usb_err < 0)
333 return;
334 ret = usb_control_msg(gspca_dev->dev,
335 usb_rcvctrlpipe(gspca_dev->dev, 0),
336 req,
337 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
338 0, /* value */
339 index,
340 len ? gspca_dev->usb_buf : NULL, len,
341 500);
342 if (ret < 0) {
343 err("reg_r err %d", ret);
344 gspca_dev->usb_err = ret;
345 }
346}
347
348/* write one byte */
349static void reg_w_1(struct gspca_dev *gspca_dev,
350 u8 req,
351 u16 value,
352 u16 index,
353 u16 byte)
354{
355 int ret;
356
357 if (gspca_dev->usb_err < 0)
358 return;
359 gspca_dev->usb_buf[0] = byte;
360 ret = usb_control_msg(gspca_dev->dev,
361 usb_sndctrlpipe(gspca_dev->dev, 0),
362 req,
363 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
364 value, index,
365 gspca_dev->usb_buf, 1,
366 500);
367 if (ret < 0) {
368 err("reg_w_1 err %d", ret);
369 gspca_dev->usb_err = ret;
370 }
371}
372
373/* write req / index / value */
374static void reg_w_riv(struct gspca_dev *gspca_dev,
375 u8 req, u16 index, u16 value)
376{
377 struct usb_device *dev = gspca_dev->dev;
378 int ret;
379
380 if (gspca_dev->usb_err < 0)
381 return;
382 ret = usb_control_msg(dev,
383 usb_sndctrlpipe(dev, 0),
384 req,
385 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
386 value, index, NULL, 0, 500);
387 if (ret < 0) {
388 err("reg_w_riv err %d", ret);
389 gspca_dev->usb_err = ret;
390 return;
391 }
392 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
393 req, index, value);
394}
395
396static void write_vector(struct gspca_dev *gspca_dev,
397 const struct cmd *data, int ncmds)
398{
399 while (--ncmds >= 0) {
400 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
401 data++;
402 }
403}
404
405static void setup_qtable(struct gspca_dev *gspca_dev,
406 const u8 qtable[2][64])
407{
408 int i;
409
410 /* loop over y components */
411 for (i = 0; i < 64; i++)
412 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
413
414 /* loop over c components */
415 for (i = 0; i < 64; i++)
416 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
417}
418
419static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
420 u8 req, u16 idx, u16 val)
421{
422 reg_w_riv(gspca_dev, req, idx, val);
423 reg_r(gspca_dev, 0x01, 0x0001, 1);
424 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
425 reg_w_riv(gspca_dev, req, idx, val);
426
427 msleep(200);
428 reg_r(gspca_dev, 0x01, 0x0001, 1);
429 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
430}
431
432#ifdef GSPCA_DEBUG
433static void spca504_read_info(struct gspca_dev *gspca_dev)
434{
435 int i;
436 u8 info[6];
437
438 for (i = 0; i < 6; i++) {
439 reg_r(gspca_dev, 0, i, 1);
440 info[i] = gspca_dev->usb_buf[0];
441 }
442 PDEBUG(D_STREAM,
443 "Read info: %d %d %d %d %d %d."
444 " Should be 1,0,2,2,0,0",
445 info[0], info[1], info[2],
446 info[3], info[4], info[5]);
447}
448#endif
449
450static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
451 u8 req,
452 u16 idx, u16 val, u8 endcode, u8 count)
453{
454 u16 status;
455
456 reg_w_riv(gspca_dev, req, idx, val);
457 reg_r(gspca_dev, 0x01, 0x0001, 1);
458 if (gspca_dev->usb_err < 0)
459 return;
460 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
461 gspca_dev->usb_buf[0], endcode);
462 if (!count)
463 return;
464 count = 200;
465 while (--count > 0) {
466 msleep(10);
467 /* gsmart mini2 write a each wait setting 1 ms is enough */
468/* reg_w_riv(gspca_dev, req, idx, val); */
469 reg_r(gspca_dev, 0x01, 0x0001, 1);
470 status = gspca_dev->usb_buf[0];
471 if (status == endcode) {
472 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
473 status, 200 - count);
474 break;
475 }
476 }
477}
478
479static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
480{
481 int count = 10;
482
483 while (--count > 0) {
484 reg_r(gspca_dev, 0x21, 0, 1);
485 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
486 break;
487 msleep(10);
488 }
489}
490
491static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
492{
493 int count = 50;
494
495 while (--count > 0) {
496 reg_r(gspca_dev, 0x21, 1, 1);
497 if (gspca_dev->usb_buf[0] != 0) {
498 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
499 reg_r(gspca_dev, 0x21, 1, 1);
500 spca504B_PollingDataReady(gspca_dev);
501 break;
502 }
503 msleep(10);
504 }
505}
506
507#ifdef GSPCA_DEBUG
508static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
509{
510 u8 *data;
511
512 data = gspca_dev->usb_buf;
513 reg_r(gspca_dev, 0x20, 0, 5);
514 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
515 data[0], data[1], data[2], data[3], data[4]);
516 reg_r(gspca_dev, 0x23, 0, 64);
517 reg_r(gspca_dev, 0x23, 1, 64);
518}
519#endif
520
521static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
522{
523 struct sd *sd = (struct sd *) gspca_dev;
524 u8 Size;
525
526 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
527 switch (sd->bridge) {
528 case BRIDGE_SPCA533:
529 reg_w_riv(gspca_dev, 0x31, 0, 0);
530 spca504B_WaitCmdStatus(gspca_dev);
531 spca504B_PollingDataReady(gspca_dev);
532#ifdef GSPCA_DEBUG
533 spca50x_GetFirmware(gspca_dev);
534#endif
535 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
536 reg_r(gspca_dev, 0x24, 8, 1);
537
538 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
539 reg_r(gspca_dev, 0x25, 4, 1); /* size */
540 spca504B_PollingDataReady(gspca_dev);
541
542 /* Init the cam width height with some values get on init ? */
543 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
544 spca504B_WaitCmdStatus(gspca_dev);
545 spca504B_PollingDataReady(gspca_dev);
546 break;
547 default:
548/* case BRIDGE_SPCA504B: */
549/* case BRIDGE_SPCA536: */
550 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
551 reg_r(gspca_dev, 0x25, 4, 1); /* size */
552 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
553 reg_r(gspca_dev, 0x27, 0, 1); /* type */
554 spca504B_PollingDataReady(gspca_dev);
555 break;
556 case BRIDGE_SPCA504:
557 Size += 3;
558 if (sd->subtype == AiptekMiniPenCam13) {
559 /* spca504a aiptek */
560 spca504A_acknowledged_command(gspca_dev,
561 0x08, Size, 0,
562 0x80 | (Size & 0x0f), 1);
563 spca504A_acknowledged_command(gspca_dev,
564 1, 3, 0, 0x9f, 0);
565 } else {
566 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
567 }
568 break;
569 case BRIDGE_SPCA504C:
570 /* capture mode */
571 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
572 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
573 break;
574 }
575}
576
577static void spca504_wait_status(struct gspca_dev *gspca_dev)
578{
579 int cnt;
580
581 cnt = 256;
582 while (--cnt > 0) {
583 /* With this we get the status, when return 0 it's all ok */
584 reg_r(gspca_dev, 0x06, 0x00, 1);
585 if (gspca_dev->usb_buf[0] == 0)
586 return;
587 msleep(10);
588 }
589}
590
591static void spca504B_setQtable(struct gspca_dev *gspca_dev)
592{
593 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
594 reg_r(gspca_dev, 0x26, 0, 1);
595 spca504B_PollingDataReady(gspca_dev);
596}
597
598static void setbrightness(struct gspca_dev *gspca_dev)
599{
600 struct sd *sd = (struct sd *) gspca_dev;
601 u16 reg;
602
603 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
604 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
605}
606
607static void setcontrast(struct gspca_dev *gspca_dev)
608{
609 struct sd *sd = (struct sd *) gspca_dev;
610 u16 reg;
611
612 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
613 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
614}
615
616static void setcolors(struct gspca_dev *gspca_dev)
617{
618 struct sd *sd = (struct sd *) gspca_dev;
619 u16 reg;
620
621 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
622 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
623}
624
625static void init_ctl_reg(struct gspca_dev *gspca_dev)
626{
627 struct sd *sd = (struct sd *) gspca_dev;
628 int pollreg = 1;
629
630 setbrightness(gspca_dev);
631 setcontrast(gspca_dev);
632 setcolors(gspca_dev);
633
634 switch (sd->bridge) {
635 case BRIDGE_SPCA504:
636 case BRIDGE_SPCA504C:
637 pollreg = 0;
638 /* fall thru */
639 default:
640/* case BRIDGE_SPCA533: */
641/* case BRIDGE_SPCA504B: */
642 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
643 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
644 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
645 break;
646 case BRIDGE_SPCA536:
647 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
648 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
649 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
650 break;
651 }
652 if (pollreg)
653 spca504B_PollingDataReady(gspca_dev);
654}
655
656/* this function is called at probe time */
657static int sd_config(struct gspca_dev *gspca_dev,
658 const struct usb_device_id *id)
659{
660 struct sd *sd = (struct sd *) gspca_dev;
661 struct cam *cam;
662
663 cam = &gspca_dev->cam;
664
665 sd->bridge = id->driver_info >> 8;
666 sd->subtype = id->driver_info;
667
668 if (sd->subtype == AiptekMiniPenCam13) {
669
670 /* try to get the firmware as some cam answer 2.0.1.2.2
671 * and should be a spca504b then overwrite that setting */
672 reg_r(gspca_dev, 0x20, 0, 1);
673 switch (gspca_dev->usb_buf[0]) {
674 case 1:
675 break; /* (right bridge/subtype) */
676 case 2:
677 sd->bridge = BRIDGE_SPCA504B;
678 sd->subtype = 0;
679 break;
680 default:
681 return -ENODEV;
682 }
683 }
684
685 switch (sd->bridge) {
686 default:
687/* case BRIDGE_SPCA504B: */
688/* case BRIDGE_SPCA504: */
689/* case BRIDGE_SPCA536: */
690 cam->cam_mode = vga_mode;
691 cam->nmodes = ARRAY_SIZE(vga_mode);
692 break;
693 case BRIDGE_SPCA533:
694 cam->cam_mode = custom_mode;
695 if (sd->subtype == MegaImageVI) /* 320x240 only */
696 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
697 else
698 cam->nmodes = ARRAY_SIZE(custom_mode);
699 break;
700 case BRIDGE_SPCA504C:
701 cam->cam_mode = vga_mode2;
702 cam->nmodes = ARRAY_SIZE(vga_mode2);
703 break;
704 }
705 sd->brightness = BRIGHTNESS_DEF;
706 sd->contrast = CONTRAST_DEF;
707 sd->colors = COLOR_DEF;
708 sd->autogain = AUTOGAIN_DEF;
709 sd->quality = QUALITY_DEF;
710 return 0;
711}
712
713/* this function is called at probe and resume time */
714static int sd_init(struct gspca_dev *gspca_dev)
715{
716 struct sd *sd = (struct sd *) gspca_dev;
717
718 switch (sd->bridge) {
719 case BRIDGE_SPCA504B:
720 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
721 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
722 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
723 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
724 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
725 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
726 /* fall thru */
727 case BRIDGE_SPCA533:
728 spca504B_PollingDataReady(gspca_dev);
729#ifdef GSPCA_DEBUG
730 spca50x_GetFirmware(gspca_dev);
731#endif
732 break;
733 case BRIDGE_SPCA536:
734#ifdef GSPCA_DEBUG
735 spca50x_GetFirmware(gspca_dev);
736#endif
737 reg_r(gspca_dev, 0x00, 0x5002, 1);
738 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
739 reg_r(gspca_dev, 0x24, 0, 1);
740 spca504B_PollingDataReady(gspca_dev);
741 reg_w_riv(gspca_dev, 0x34, 0, 0);
742 spca504B_WaitCmdStatus(gspca_dev);
743 break;
744 case BRIDGE_SPCA504C: /* pccam600 */
745 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
746 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
747 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
748 spca504_wait_status(gspca_dev);
749 if (sd->subtype == LogitechClickSmart420)
750 write_vector(gspca_dev,
751 spca504A_clicksmart420_open_data,
752 ARRAY_SIZE(spca504A_clicksmart420_open_data));
753 else
754 write_vector(gspca_dev, spca504_pccam600_open_data,
755 ARRAY_SIZE(spca504_pccam600_open_data));
756 setup_qtable(gspca_dev, qtable_creative_pccam);
757 break;
758 default:
759/* case BRIDGE_SPCA504: */
760 PDEBUG(D_STREAM, "Opening SPCA504");
761 if (sd->subtype == AiptekMiniPenCam13) {
762#ifdef GSPCA_DEBUG
763 spca504_read_info(gspca_dev);
764#endif
765
766 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
767 spca504A_acknowledged_command(gspca_dev, 0x24,
768 8, 3, 0x9e, 1);
769 /* Twice sequential need status 0xff->0x9e->0x9d */
770 spca504A_acknowledged_command(gspca_dev, 0x24,
771 8, 3, 0x9e, 0);
772
773 spca504A_acknowledged_command(gspca_dev, 0x24,
774 0, 0, 0x9d, 1);
775 /******************************/
776 /* spca504a aiptek */
777 spca504A_acknowledged_command(gspca_dev, 0x08,
778 6, 0, 0x86, 1);
779/* reg_write (dev, 0, 0x2000, 0); */
780/* reg_write (dev, 0, 0x2883, 1); */
781/* spca504A_acknowledged_command (gspca_dev, 0x08,
782 6, 0, 0x86, 1); */
783/* spca504A_acknowledged_command (gspca_dev, 0x24,
784 0, 0, 0x9D, 1); */
785 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
786 /* L92 sno1t.txt */
787 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
788 spca504A_acknowledged_command(gspca_dev, 0x01,
789 0x0f, 0, 0xff, 0);
790 }
791 /* setup qtable */
792 reg_w_riv(gspca_dev, 0, 0x2000, 0);
793 reg_w_riv(gspca_dev, 0, 0x2883, 1);
794 setup_qtable(gspca_dev, qtable_spca504_default);
795 break;
796 }
797 return gspca_dev->usb_err;
798}
799
800static int sd_start(struct gspca_dev *gspca_dev)
801{
802 struct sd *sd = (struct sd *) gspca_dev;
803 int enable;
804
805 /* create the JPEG header */
806 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
807 0x22); /* JPEG 411 */
808 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
809
810 if (sd->bridge == BRIDGE_SPCA504B)
811 spca504B_setQtable(gspca_dev);
812 spca504B_SetSizeType(gspca_dev);
813 switch (sd->bridge) {
814 default:
815/* case BRIDGE_SPCA504B: */
816/* case BRIDGE_SPCA533: */
817/* case BRIDGE_SPCA536: */
818 switch (sd->subtype) {
819 case MegapixV4:
820 case LogitechClickSmart820:
821 case MegaImageVI:
822 reg_w_riv(gspca_dev, 0xf0, 0, 0);
823 spca504B_WaitCmdStatus(gspca_dev);
824 reg_r(gspca_dev, 0xf0, 4, 0);
825 spca504B_WaitCmdStatus(gspca_dev);
826 break;
827 default:
828 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
829 spca504B_WaitCmdStatus(gspca_dev);
830 spca504B_PollingDataReady(gspca_dev);
831 break;
832 }
833 break;
834 case BRIDGE_SPCA504:
835 if (sd->subtype == AiptekMiniPenCam13) {
836#ifdef GSPCA_DEBUG
837 spca504_read_info(gspca_dev);
838#endif
839
840 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
841 spca504A_acknowledged_command(gspca_dev, 0x24,
842 8, 3, 0x9e, 1);
843 /* Twice sequential need status 0xff->0x9e->0x9d */
844 spca504A_acknowledged_command(gspca_dev, 0x24,
845 8, 3, 0x9e, 0);
846 spca504A_acknowledged_command(gspca_dev, 0x24,
847 0, 0, 0x9d, 1);
848 } else {
849 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
850#ifdef GSPCA_DEBUG
851 spca504_read_info(gspca_dev);
852#endif
853 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
854 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
855 }
856 spca504B_SetSizeType(gspca_dev);
857 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
858 /* L92 sno1t.txt */
859 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
860 break;
861 case BRIDGE_SPCA504C:
862 if (sd->subtype == LogitechClickSmart420) {
863 write_vector(gspca_dev,
864 spca504A_clicksmart420_init_data,
865 ARRAY_SIZE(spca504A_clicksmart420_init_data));
866 } else {
867 write_vector(gspca_dev, spca504_pccam600_init_data,
868 ARRAY_SIZE(spca504_pccam600_init_data));
869 }
870 enable = (sd->autogain ? 0x04 : 0x01);
871 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
872 /* auto exposure */
873 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
874 /* auto whiteness */
875
876 /* set default exposure compensation and whiteness balance */
877 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
878 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
879 spca504B_SetSizeType(gspca_dev);
880 break;
881 }
882 init_ctl_reg(gspca_dev);
883 return gspca_dev->usb_err;
884}
885
886static void sd_stopN(struct gspca_dev *gspca_dev)
887{
888 struct sd *sd = (struct sd *) gspca_dev;
889
890 switch (sd->bridge) {
891 default:
892/* case BRIDGE_SPCA533: */
893/* case BRIDGE_SPCA536: */
894/* case BRIDGE_SPCA504B: */
895 reg_w_riv(gspca_dev, 0x31, 0, 0);
896 spca504B_WaitCmdStatus(gspca_dev);
897 spca504B_PollingDataReady(gspca_dev);
898 break;
899 case BRIDGE_SPCA504:
900 case BRIDGE_SPCA504C:
901 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
902
903 if (sd->subtype == AiptekMiniPenCam13) {
904 /* spca504a aiptek */
905/* spca504A_acknowledged_command(gspca_dev, 0x08,
906 6, 0, 0x86, 1); */
907 spca504A_acknowledged_command(gspca_dev, 0x24,
908 0x00, 0x00, 0x9d, 1);
909 spca504A_acknowledged_command(gspca_dev, 0x01,
910 0x0f, 0x00, 0xff, 1);
911 } else {
912 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
913 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
914 }
915 break;
916 }
917}
918
919static void sd_pkt_scan(struct gspca_dev *gspca_dev,
920 u8 *data, /* isoc packet */
921 int len) /* iso packet length */
922{
923 struct sd *sd = (struct sd *) gspca_dev;
924 int i, sof = 0;
925 static u8 ffd9[] = {0xff, 0xd9};
926
927/* frames are jpeg 4.1.1 without 0xff escape */
928 switch (sd->bridge) {
929 case BRIDGE_SPCA533:
930 if (data[0] == 0xff) {
931 if (data[1] != 0x01) { /* drop packet */
932/* gspca_dev->last_packet_type = DISCARD_PACKET; */
933 return;
934 }
935 sof = 1;
936 data += SPCA533_OFFSET_DATA;
937 len -= SPCA533_OFFSET_DATA;
938 } else {
939 data += 1;
940 len -= 1;
941 }
942 break;
943 case BRIDGE_SPCA536:
944 if (data[0] == 0xff) {
945 sof = 1;
946 data += SPCA536_OFFSET_DATA;
947 len -= SPCA536_OFFSET_DATA;
948 } else {
949 data += 2;
950 len -= 2;
951 }
952 break;
953 default:
954/* case BRIDGE_SPCA504: */
955/* case BRIDGE_SPCA504B: */
956 switch (data[0]) {
957 case 0xfe: /* start of frame */
958 sof = 1;
959 data += SPCA50X_OFFSET_DATA;
960 len -= SPCA50X_OFFSET_DATA;
961 break;
962 case 0xff: /* drop packet */
963/* gspca_dev->last_packet_type = DISCARD_PACKET; */
964 return;
965 default:
966 data += 1;
967 len -= 1;
968 break;
969 }
970 break;
971 case BRIDGE_SPCA504C:
972 switch (data[0]) {
973 case 0xfe: /* start of frame */
974 sof = 1;
975 data += SPCA504_PCCAM600_OFFSET_DATA;
976 len -= SPCA504_PCCAM600_OFFSET_DATA;
977 break;
978 case 0xff: /* drop packet */
979/* gspca_dev->last_packet_type = DISCARD_PACKET; */
980 return;
981 default:
982 data += 1;
983 len -= 1;
984 break;
985 }
986 break;
987 }
988 if (sof) { /* start of frame */
989 gspca_frame_add(gspca_dev, LAST_PACKET,
990 ffd9, 2);
991
992 /* put the JPEG header in the new frame */
993 gspca_frame_add(gspca_dev, FIRST_PACKET,
994 sd->jpeg_hdr, JPEG_HDR_SZ);
995 }
996
997 /* add 0x00 after 0xff */
998 i = 0;
999 do {
1000 if (data[i] == 0xff) {
1001 gspca_frame_add(gspca_dev, INTER_PACKET,
1002 data, i + 1);
1003 len -= i;
1004 data += i;
1005 *data = 0x00;
1006 i = 0;
1007 }
1008 i++;
1009 } while (i < len);
1010 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1011}
1012
1013static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1014{
1015 struct sd *sd = (struct sd *) gspca_dev;
1016
1017 sd->brightness = val;
1018 if (gspca_dev->streaming)
1019 setbrightness(gspca_dev);
1020 return gspca_dev->usb_err;
1021}
1022
1023static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1024{
1025 struct sd *sd = (struct sd *) gspca_dev;
1026
1027 *val = sd->brightness;
1028 return 0;
1029}
1030
1031static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1032{
1033 struct sd *sd = (struct sd *) gspca_dev;
1034
1035 sd->contrast = val;
1036 if (gspca_dev->streaming)
1037 setcontrast(gspca_dev);
1038 return gspca_dev->usb_err;
1039}
1040
1041static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1042{
1043 struct sd *sd = (struct sd *) gspca_dev;
1044
1045 *val = sd->contrast;
1046 return 0;
1047}
1048
1049static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052
1053 sd->colors = val;
1054 if (gspca_dev->streaming)
1055 setcolors(gspca_dev);
1056 return gspca_dev->usb_err;
1057}
1058
1059static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1060{
1061 struct sd *sd = (struct sd *) gspca_dev;
1062
1063 *val = sd->colors;
1064 return 0;
1065}
1066
1067static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1068{
1069 struct sd *sd = (struct sd *) gspca_dev;
1070
1071 sd->autogain = val;
1072 return 0;
1073}
1074
1075static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1076{
1077 struct sd *sd = (struct sd *) gspca_dev;
1078
1079 *val = sd->autogain;
1080 return 0;
1081}
1082
1083static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1084 struct v4l2_jpegcompression *jcomp)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
1088 if (jcomp->quality < QUALITY_MIN)
1089 sd->quality = QUALITY_MIN;
1090 else if (jcomp->quality > QUALITY_MAX)
1091 sd->quality = QUALITY_MAX;
1092 else
1093 sd->quality = jcomp->quality;
1094 if (gspca_dev->streaming)
1095 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1096 return gspca_dev->usb_err;
1097}
1098
1099static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1100 struct v4l2_jpegcompression *jcomp)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 memset(jcomp, 0, sizeof *jcomp);
1105 jcomp->quality = sd->quality;
1106 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1107 | V4L2_JPEG_MARKER_DQT;
1108 return 0;
1109}
1110
1111/* sub-driver description */
1112static const struct sd_desc sd_desc = {
1113 .name = MODULE_NAME,
1114 .ctrls = sd_ctrls,
1115 .nctrls = ARRAY_SIZE(sd_ctrls),
1116 .config = sd_config,
1117 .init = sd_init,
1118 .start = sd_start,
1119 .stopN = sd_stopN,
1120 .pkt_scan = sd_pkt_scan,
1121 .get_jcomp = sd_get_jcomp,
1122 .set_jcomp = sd_set_jcomp,
1123};
1124
1125/* -- module initialisation -- */
1126#define BS(bridge, subtype) \
1127 .driver_info = (BRIDGE_ ## bridge << 8) \
1128 | (subtype)
1129static const struct usb_device_id device_table[] = {
1130 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1131 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1132 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1133 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1134 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1135 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1136 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1137 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1138 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1139 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1140 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1141 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1142 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1143 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1144 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1145 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1146 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1147 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1148 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1149 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1150 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1151 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1152 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1153 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1154 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1155 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1156 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1157 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1158 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1159 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1160 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1161 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1162 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1163 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1164 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1165 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1166 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1167 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1168 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1169 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1170 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1171 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1172 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1173 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1174 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1175 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1176 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1177 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1178 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1179 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1180 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1181 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1182 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1183 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1184 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1185 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1186 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1187 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1188 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1189 {}
1190};
1191MODULE_DEVICE_TABLE(usb, device_table);
1192
1193/* -- device connect -- */
1194static int sd_probe(struct usb_interface *intf,
1195 const struct usb_device_id *id)
1196{
1197 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1198 THIS_MODULE);
1199}
1200
1201static struct usb_driver sd_driver = {
1202 .name = MODULE_NAME,
1203 .id_table = device_table,
1204 .probe = sd_probe,
1205 .disconnect = gspca_disconnect,
1206#ifdef CONFIG_PM
1207 .suspend = gspca_suspend,
1208 .resume = gspca_resume,
1209#endif
1210};
1211
1212/* -- module insert / remove -- */
1213static int __init sd_mod_init(void)
1214{
1215 return usb_register(&sd_driver);
1216}
1217static void __exit sd_mod_exit(void)
1218{
1219 usb_deregister(&sd_driver);
1220}
1221
1222module_init(sd_mod_init);
1223module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
new file mode 100644
index 00000000000..d1d733b9359
--- /dev/null
+++ b/drivers/media/video/gspca/t613.c
@@ -0,0 +1,1450 @@
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 MODULE_NAME "t613"
30
31#include <linux/slab.h>
32#include "gspca.h"
33
34#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
35
36MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
37MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
38MODULE_LICENSE("GPL");
39
40struct sd {
41 struct gspca_dev gspca_dev; /* !! must be the first item */
42
43 u8 brightness;
44 u8 contrast;
45 u8 colors;
46 u8 autogain;
47 u8 gamma;
48 u8 sharpness;
49 u8 freq;
50 u8 red_gain;
51 u8 blue_gain;
52 u8 green_gain;
53 u8 awb; /* set default r/g/b and activate */
54 u8 mirror;
55 u8 effect;
56
57 u8 sensor;
58};
59enum sensors {
60 SENSOR_OM6802,
61 SENSOR_OTHER,
62 SENSOR_TAS5130A,
63 SENSOR_LT168G, /* must verify if this is the actual model */
64};
65
66/* V4L2 controls supported by the driver */
67static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
81
82static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
90
91static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val);
93static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
95
96static const struct ctrl sd_ctrls[] = {
97 {
98 {
99 .id = V4L2_CID_BRIGHTNESS,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "Brightness",
102 .minimum = 0,
103 .maximum = 14,
104 .step = 1,
105#define BRIGHTNESS_DEF 8
106 .default_value = BRIGHTNESS_DEF,
107 },
108 .set = sd_setbrightness,
109 .get = sd_getbrightness,
110 },
111 {
112 {
113 .id = V4L2_CID_CONTRAST,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "Contrast",
116 .minimum = 0,
117 .maximum = 0x0d,
118 .step = 1,
119#define CONTRAST_DEF 0x07
120 .default_value = CONTRAST_DEF,
121 },
122 .set = sd_setcontrast,
123 .get = sd_getcontrast,
124 },
125 {
126 {
127 .id = V4L2_CID_SATURATION,
128 .type = V4L2_CTRL_TYPE_INTEGER,
129 .name = "Color",
130 .minimum = 0,
131 .maximum = 0x0f,
132 .step = 1,
133#define COLORS_DEF 0x05
134 .default_value = COLORS_DEF,
135 },
136 .set = sd_setcolors,
137 .get = sd_getcolors,
138 },
139#define GAMMA_MAX 16
140#define GAMMA_DEF 10
141 {
142 {
143 .id = V4L2_CID_GAMMA, /* (gamma on win) */
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Gamma",
146 .minimum = 0,
147 .maximum = GAMMA_MAX - 1,
148 .step = 1,
149 .default_value = GAMMA_DEF,
150 },
151 .set = sd_setgamma,
152 .get = sd_getgamma,
153 },
154 {
155 {
156 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight,
157 * some apps dont bring up the
158 * backligth_compensation control) */
159 .type = V4L2_CTRL_TYPE_INTEGER,
160 .name = "Low Light",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164#define AUTOGAIN_DEF 0x01
165 .default_value = AUTOGAIN_DEF,
166 },
167 .set = sd_setlowlight,
168 .get = sd_getlowlight,
169 },
170 {
171 {
172 .id = V4L2_CID_HFLIP,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "Mirror Image",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178#define MIRROR_DEF 0
179 .default_value = MIRROR_DEF,
180 },
181 .set = sd_setmirror,
182 .get = sd_getmirror
183 },
184 {
185 {
186 .id = V4L2_CID_POWER_LINE_FREQUENCY,
187 .type = V4L2_CTRL_TYPE_MENU,
188 .name = "Light Frequency Filter",
189 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
190 .maximum = 2,
191 .step = 1,
192#define FREQ_DEF 1
193 .default_value = FREQ_DEF,
194 },
195 .set = sd_setfreq,
196 .get = sd_getfreq},
197
198 {
199 {
200 .id = V4L2_CID_AUTO_WHITE_BALANCE,
201 .type = V4L2_CTRL_TYPE_INTEGER,
202 .name = "Auto White Balance",
203 .minimum = 0,
204 .maximum = 1,
205 .step = 1,
206#define AWB_DEF 0
207 .default_value = AWB_DEF,
208 },
209 .set = sd_setawb,
210 .get = sd_getawb
211 },
212 {
213 {
214 .id = V4L2_CID_SHARPNESS,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .name = "Sharpness",
217 .minimum = 0,
218 .maximum = 15,
219 .step = 1,
220#define SHARPNESS_DEF 0x06
221 .default_value = SHARPNESS_DEF,
222 },
223 .set = sd_setsharpness,
224 .get = sd_getsharpness,
225 },
226 {
227 {
228 .id = V4L2_CID_EFFECTS,
229 .type = V4L2_CTRL_TYPE_MENU,
230 .name = "Webcam Effects",
231 .minimum = 0,
232 .maximum = 4,
233 .step = 1,
234#define EFFECTS_DEF 0
235 .default_value = EFFECTS_DEF,
236 },
237 .set = sd_seteffect,
238 .get = sd_geteffect
239 },
240 {
241 {
242 .id = V4L2_CID_BLUE_BALANCE,
243 .type = V4L2_CTRL_TYPE_INTEGER,
244 .name = "Blue Balance",
245 .minimum = 0x10,
246 .maximum = 0x40,
247 .step = 1,
248#define BLUE_GAIN_DEF 0x20
249 .default_value = BLUE_GAIN_DEF,
250 },
251 .set = sd_setblue_gain,
252 .get = sd_getblue_gain,
253 },
254 {
255 {
256 .id = V4L2_CID_RED_BALANCE,
257 .type = V4L2_CTRL_TYPE_INTEGER,
258 .name = "Red Balance",
259 .minimum = 0x10,
260 .maximum = 0x40,
261 .step = 1,
262#define RED_GAIN_DEF 0x20
263 .default_value = RED_GAIN_DEF,
264 },
265 .set = sd_setred_gain,
266 .get = sd_getred_gain,
267 },
268 {
269 {
270 .id = V4L2_CID_GAIN,
271 .type = V4L2_CTRL_TYPE_INTEGER,
272 .name = "Gain",
273 .minimum = 0x10,
274 .maximum = 0x40,
275 .step = 1,
276#define GAIN_DEF 0x20
277 .default_value = GAIN_DEF,
278 },
279 .set = sd_setgain,
280 .get = sd_getgain,
281 },
282};
283
284static const struct v4l2_pix_format vga_mode_t16[] = {
285 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
286 .bytesperline = 160,
287 .sizeimage = 160 * 120 * 4 / 8 + 590,
288 .colorspace = V4L2_COLORSPACE_JPEG,
289 .priv = 4},
290 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
291 .bytesperline = 176,
292 .sizeimage = 176 * 144 * 3 / 8 + 590,
293 .colorspace = V4L2_COLORSPACE_JPEG,
294 .priv = 3},
295 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
296 .bytesperline = 320,
297 .sizeimage = 320 * 240 * 3 / 8 + 590,
298 .colorspace = V4L2_COLORSPACE_JPEG,
299 .priv = 2},
300 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
301 .bytesperline = 352,
302 .sizeimage = 352 * 288 * 3 / 8 + 590,
303 .colorspace = V4L2_COLORSPACE_JPEG,
304 .priv = 1},
305 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
306 .bytesperline = 640,
307 .sizeimage = 640 * 480 * 3 / 8 + 590,
308 .colorspace = V4L2_COLORSPACE_JPEG,
309 .priv = 0},
310};
311
312/* sensor specific data */
313struct additional_sensor_data {
314 const u8 n3[6];
315 const u8 *n4, n4sz;
316 const u8 reg80, reg8e;
317 const u8 nset8[6];
318 const u8 data1[10];
319 const u8 data2[9];
320 const u8 data3[9];
321 const u8 data5[6];
322 const u8 stream[4];
323};
324
325static const u8 n4_om6802[] = {
326 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
327 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
328 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
329 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
330 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
331 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
332 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
333 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
334 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
335};
336static const u8 n4_other[] = {
337 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
338 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
339 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
340 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
341 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
342 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
343 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
344 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
345};
346static const u8 n4_tas5130a[] = {
347 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
348 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
349 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
350 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
351 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
352 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
353 0xc6, 0xda
354};
355static const u8 n4_lt168g[] = {
356 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
357 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
358 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
359 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
360 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
361 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
362 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
363 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
364 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
365};
366
367static const struct additional_sensor_data sensor_data[] = {
368[SENSOR_OM6802] = {
369 .n3 =
370 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
371 .n4 = n4_om6802,
372 .n4sz = sizeof n4_om6802,
373 .reg80 = 0x3c,
374 .reg8e = 0x33,
375 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
376 .data1 =
377 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
378 0xb3, 0xfc},
379 .data2 =
380 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
381 0xff},
382 .data3 =
383 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
384 0xff},
385 .data5 = /* this could be removed later */
386 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
387 .stream =
388 {0x0b, 0x04, 0x0a, 0x78},
389 },
390[SENSOR_OTHER] = {
391 .n3 =
392 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
393 .n4 = n4_other,
394 .n4sz = sizeof n4_other,
395 .reg80 = 0xac,
396 .reg8e = 0xb8,
397 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
398 .data1 =
399 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
400 0xe8, 0xfc},
401 .data2 =
402 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
403 0xd9},
404 .data3 =
405 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
406 0xd9},
407 .data5 =
408 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
409 .stream =
410 {0x0b, 0x04, 0x0a, 0x00},
411 },
412[SENSOR_TAS5130A] = {
413 .n3 =
414 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
415 .n4 = n4_tas5130a,
416 .n4sz = sizeof n4_tas5130a,
417 .reg80 = 0x3c,
418 .reg8e = 0xb4,
419 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
420 .data1 =
421 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
422 0xc8, 0xfc},
423 .data2 =
424 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
425 0xe0},
426 .data3 =
427 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
428 0xe0},
429 .data5 =
430 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
431 .stream =
432 {0x0b, 0x04, 0x0a, 0x40},
433 },
434[SENSOR_LT168G] = {
435 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
436 .n4 = n4_lt168g,
437 .n4sz = sizeof n4_lt168g,
438 .reg80 = 0x7c,
439 .reg8e = 0xb3,
440 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
441 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
442 0xb0, 0xf4},
443 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
444 0xff},
445 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
446 0xff},
447 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
448 .stream = {0x0b, 0x04, 0x0a, 0x28},
449 },
450};
451
452#define MAX_EFFECTS 7
453/* easily done by soft, this table could be removed,
454 * i keep it here just in case */
455static char *effects_control[MAX_EFFECTS] = {
456 "Normal",
457 "Emboss", /* disabled */
458 "Monochrome",
459 "Sepia",
460 "Sketch",
461 "Sun Effect", /* disabled */
462 "Negative",
463};
464static const u8 effects_table[MAX_EFFECTS][6] = {
465 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
466 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
467 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
468 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
469 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
470 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
471 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
472};
473
474static const u8 gamma_table[GAMMA_MAX][17] = {
475/* gamma table from cam1690.ini */
476 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */
477 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
478 0xff},
479 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */
480 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
481 0xff},
482 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */
483 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
484 0xff},
485 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */
486 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
487 0xff},
488 {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */
489 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
490 0xff},
491 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */
492 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
493 0xff},
494 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */
495 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
496 0xff},
497 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */
498 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
499 0xff},
500 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */
501 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
502 0xff},
503 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */
504 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
505 0xff},
506 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */
507 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
508 0xff},
509 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */
510 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
511 0xff},
512 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */
513 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
514 0xff},
515 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */
516 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
517 0xff},
518 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */
519 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
520 0xff},
521 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */
522 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
523 0xff}
524};
525
526static const u8 tas5130a_sensor_init[][8] = {
527 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
528 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
529 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
530};
531
532static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
533
534/* read 1 byte */
535static u8 reg_r(struct gspca_dev *gspca_dev,
536 u16 index)
537{
538 usb_control_msg(gspca_dev->dev,
539 usb_rcvctrlpipe(gspca_dev->dev, 0),
540 0, /* request */
541 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
542 0, /* value */
543 index,
544 gspca_dev->usb_buf, 1, 500);
545 return gspca_dev->usb_buf[0];
546}
547
548static void reg_w(struct gspca_dev *gspca_dev,
549 u16 index)
550{
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
553 0,
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
555 0, index,
556 NULL, 0, 500);
557}
558
559static void reg_w_buf(struct gspca_dev *gspca_dev,
560 const u8 *buffer, u16 len)
561{
562 if (len <= USB_BUF_SZ) {
563 memcpy(gspca_dev->usb_buf, buffer, len);
564 usb_control_msg(gspca_dev->dev,
565 usb_sndctrlpipe(gspca_dev->dev, 0),
566 0,
567 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
568 0x01, 0,
569 gspca_dev->usb_buf, len, 500);
570 } else {
571 u8 *tmpbuf;
572
573 tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
574 if (!tmpbuf) {
575 err("Out of memory");
576 return;
577 }
578 usb_control_msg(gspca_dev->dev,
579 usb_sndctrlpipe(gspca_dev->dev, 0),
580 0,
581 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
582 0x01, 0,
583 tmpbuf, len, 500);
584 kfree(tmpbuf);
585 }
586}
587
588/* write values to consecutive registers */
589static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
590 u8 reg,
591 const u8 *buffer, u16 len)
592{
593 int i;
594 u8 *p, *tmpbuf;
595
596 if (len * 2 <= USB_BUF_SZ) {
597 p = tmpbuf = gspca_dev->usb_buf;
598 } else {
599 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
600 if (!tmpbuf) {
601 err("Out of memory");
602 return;
603 }
604 }
605 i = len;
606 while (--i >= 0) {
607 *p++ = reg++;
608 *p++ = *buffer++;
609 }
610 usb_control_msg(gspca_dev->dev,
611 usb_sndctrlpipe(gspca_dev->dev, 0),
612 0,
613 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
614 0x01, 0,
615 tmpbuf, len * 2, 500);
616 if (len * 2 > USB_BUF_SZ)
617 kfree(tmpbuf);
618}
619
620static void om6802_sensor_init(struct gspca_dev *gspca_dev)
621{
622 int i;
623 const u8 *p;
624 u8 byte;
625 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
626 static const u8 sensor_init[] = {
627 0xdf, 0x6d,
628 0xdd, 0x18,
629 0x5a, 0xe0,
630 0x5c, 0x07,
631 0x5d, 0xb0,
632 0x5e, 0x1e,
633 0x60, 0x71,
634 0xef, 0x00,
635 0xe9, 0x00,
636 0xea, 0x00,
637 0x90, 0x24,
638 0x91, 0xb2,
639 0x82, 0x32,
640 0xfd, 0x41,
641 0x00 /* table end */
642 };
643
644 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
645 msleep(100);
646 i = 4;
647 while (--i > 0) {
648 byte = reg_r(gspca_dev, 0x0060);
649 if (!(byte & 0x01))
650 break;
651 msleep(100);
652 }
653 byte = reg_r(gspca_dev, 0x0063);
654 if (byte != 0x17) {
655 err("Bad sensor reset %02x", byte);
656 /* continue? */
657 }
658
659 p = sensor_init;
660 while (*p != 0) {
661 val[1] = *p++;
662 val[3] = *p++;
663 if (*p == 0)
664 reg_w(gspca_dev, 0x3c80);
665 reg_w_buf(gspca_dev, val, sizeof val);
666 i = 4;
667 while (--i >= 0) {
668 msleep(15);
669 byte = reg_r(gspca_dev, 0x60);
670 if (!(byte & 0x01))
671 break;
672 }
673 }
674 msleep(15);
675 reg_w(gspca_dev, 0x3c80);
676}
677
678/* this function is called at probe time */
679static int sd_config(struct gspca_dev *gspca_dev,
680 const struct usb_device_id *id)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct cam *cam;
684
685 cam = &gspca_dev->cam;
686
687 cam->cam_mode = vga_mode_t16;
688 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
689
690 sd->brightness = BRIGHTNESS_DEF;
691 sd->contrast = CONTRAST_DEF;
692 sd->colors = COLORS_DEF;
693 sd->gamma = GAMMA_DEF;
694 sd->autogain = AUTOGAIN_DEF;
695 sd->mirror = MIRROR_DEF;
696 sd->freq = FREQ_DEF;
697 sd->awb = AWB_DEF;
698 sd->sharpness = SHARPNESS_DEF;
699 sd->effect = EFFECTS_DEF;
700 sd->red_gain = RED_GAIN_DEF;
701 sd->blue_gain = BLUE_GAIN_DEF;
702 sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF;
703
704 return 0;
705}
706
707static void setbrightness(struct gspca_dev *gspca_dev)
708{
709 struct sd *sd = (struct sd *) gspca_dev;
710 unsigned int brightness;
711 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
712
713 brightness = sd->brightness;
714 if (brightness < 7) {
715 set6[1] = 0x26;
716 set6[3] = 0x70 - brightness * 0x10;
717 } else {
718 set6[3] = 0x00 + ((brightness - 7) * 0x10);
719 }
720
721 reg_w_buf(gspca_dev, set6, sizeof set6);
722}
723
724static void setcontrast(struct gspca_dev *gspca_dev)
725{
726 struct sd *sd = (struct sd *) gspca_dev;
727 unsigned int contrast = sd->contrast;
728 u16 reg_to_write;
729
730 if (contrast < 7)
731 reg_to_write = 0x8ea9 - contrast * 0x200;
732 else
733 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
734
735 reg_w(gspca_dev, reg_to_write);
736}
737
738static void setcolors(struct gspca_dev *gspca_dev)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741 u16 reg_to_write;
742
743 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */
744 reg_w(gspca_dev, reg_to_write);
745}
746
747static void setgamma(struct gspca_dev *gspca_dev)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750
751 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
752 reg_w_ixbuf(gspca_dev, 0x90,
753 gamma_table[sd->gamma], sizeof gamma_table[0]);
754}
755
756static void setRGB(struct gspca_dev *gspca_dev)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759 u8 all_gain_reg[6] =
760 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00};
761
762 all_gain_reg[1] = sd->red_gain;
763 all_gain_reg[3] = sd->blue_gain;
764 all_gain_reg[5] = sd->green_gain;
765 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
766}
767
768/* Generic fnc for r/b balance, exposure and awb */
769static void setawb(struct gspca_dev *gspca_dev)
770{
771 struct sd *sd = (struct sd *) gspca_dev;
772 u16 reg80;
773
774 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80;
775
776 /* on awb leave defaults values */
777 if (!sd->awb) {
778 /* shoud we wait here.. */
779 /* update and reset RGB gains with webcam values */
780 sd->red_gain = reg_r(gspca_dev, 0x0087);
781 sd->blue_gain = reg_r(gspca_dev, 0x0088);
782 sd->green_gain = reg_r(gspca_dev, 0x0089);
783 reg80 &= ~0x0400; /* AWB off */
784 }
785 reg_w(gspca_dev, reg80);
786 reg_w(gspca_dev, reg80);
787}
788
789static void init_gains(struct gspca_dev *gspca_dev)
790{
791 struct sd *sd = (struct sd *) gspca_dev;
792 u16 reg80;
793 u8 all_gain_reg[8] =
794 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00};
795
796 all_gain_reg[1] = sd->red_gain;
797 all_gain_reg[3] = sd->blue_gain;
798 all_gain_reg[5] = sd->green_gain;
799 reg80 = sensor_data[sd->sensor].reg80;
800 if (!sd->awb)
801 reg80 &= ~0x04;
802 all_gain_reg[7] = reg80;
803 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
804
805 reg_w(gspca_dev, (sd->red_gain << 8) + 0x87);
806 reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88);
807 reg_w(gspca_dev, (sd->green_gain << 8) + 0x89);
808}
809
810static void setsharpness(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813 u16 reg_to_write;
814
815 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
816
817 reg_w(gspca_dev, reg_to_write);
818}
819
820static void setfreq(struct gspca_dev *gspca_dev)
821{
822 struct sd *sd = (struct sd *) gspca_dev;
823 u8 reg66;
824 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
825
826 switch (sd->sensor) {
827 case SENSOR_LT168G:
828 if (sd->freq != 0)
829 freq[3] = 0xa8;
830 reg66 = 0x41;
831 break;
832 case SENSOR_OM6802:
833 reg66 = 0xca;
834 break;
835 default:
836 reg66 = 0x40;
837 break;
838 }
839 switch (sd->freq) {
840 case 0: /* no flicker */
841 freq[3] = 0xf0;
842 break;
843 case 2: /* 60Hz */
844 reg66 &= ~0x40;
845 break;
846 }
847 freq[1] = reg66;
848
849 reg_w_buf(gspca_dev, freq, sizeof freq);
850}
851
852/* this function is called at probe and resume time */
853static int sd_init(struct gspca_dev *gspca_dev)
854{
855 /* some of this registers are not really neded, because
856 * they are overriden by setbrigthness, setcontrast, etc,
857 * but wont hurt anyway, and can help someone with similar webcam
858 * to see the initial parameters.*/
859 struct sd *sd = (struct sd *) gspca_dev;
860 const struct additional_sensor_data *sensor;
861 int i;
862 u16 sensor_id;
863 u8 test_byte = 0;
864
865 static const u8 read_indexs[] =
866 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
867 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
868 static const u8 n1[] =
869 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
870 static const u8 n2[] =
871 {0x08, 0x00};
872
873 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
874 | reg_r(gspca_dev, 0x07);
875 switch (sensor_id & 0xff0f) {
876 case 0x0801:
877 PDEBUG(D_PROBE, "sensor tas5130a");
878 sd->sensor = SENSOR_TAS5130A;
879 break;
880 case 0x0802:
881 PDEBUG(D_PROBE, "sensor lt168g");
882 sd->sensor = SENSOR_LT168G;
883 break;
884 case 0x0803:
885 PDEBUG(D_PROBE, "sensor 'other'");
886 sd->sensor = SENSOR_OTHER;
887 break;
888 case 0x0807:
889 PDEBUG(D_PROBE, "sensor om6802");
890 sd->sensor = SENSOR_OM6802;
891 break;
892 default:
893 err("unknown sensor %04x", sensor_id);
894 return -EINVAL;
895 }
896
897 if (sd->sensor == SENSOR_OM6802) {
898 reg_w_buf(gspca_dev, n1, sizeof n1);
899 i = 5;
900 while (--i >= 0) {
901 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
902 test_byte = reg_r(gspca_dev, 0x0063);
903 msleep(100);
904 if (test_byte == 0x17)
905 break; /* OK */
906 }
907 if (i < 0) {
908 err("Bad sensor reset %02x", test_byte);
909 return -EIO;
910 }
911 reg_w_buf(gspca_dev, n2, sizeof n2);
912 }
913
914 i = 0;
915 while (read_indexs[i] != 0x00) {
916 test_byte = reg_r(gspca_dev, read_indexs[i]);
917 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
918 test_byte);
919 i++;
920 }
921
922 sensor = &sensor_data[sd->sensor];
923 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
924 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
925
926 if (sd->sensor == SENSOR_LT168G) {
927 test_byte = reg_r(gspca_dev, 0x80);
928 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
929 test_byte);
930 reg_w(gspca_dev, 0x6c80);
931 }
932
933 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
934 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
935 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
936
937 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
938 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
939 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
940
941 setbrightness(gspca_dev);
942 setcontrast(gspca_dev);
943 setgamma(gspca_dev);
944 setcolors(gspca_dev);
945 setsharpness(gspca_dev);
946 init_gains(gspca_dev);
947 setfreq(gspca_dev);
948
949 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
950 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
951 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
952
953 if (sd->sensor == SENSOR_LT168G) {
954 test_byte = reg_r(gspca_dev, 0x80);
955 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
956 test_byte);
957 reg_w(gspca_dev, 0x6c80);
958 }
959
960 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
961 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
962 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
963
964 return 0;
965}
966
967static void setmirror(struct gspca_dev *gspca_dev)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970 u8 hflipcmd[8] =
971 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
972
973 if (sd->mirror)
974 hflipcmd[3] = 0x01;
975
976 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
977}
978
979static void seteffect(struct gspca_dev *gspca_dev)
980{
981 struct sd *sd = (struct sd *) gspca_dev;
982
983 reg_w_buf(gspca_dev, effects_table[sd->effect],
984 sizeof effects_table[0]);
985 if (sd->effect == 1 || sd->effect == 5) {
986 PDEBUG(D_CONF,
987 "This effect have been disabled for webcam \"safety\"");
988 return;
989 }
990
991 if (sd->effect == 1 || sd->effect == 4)
992 reg_w(gspca_dev, 0x4aa6);
993 else
994 reg_w(gspca_dev, 0xfaa6);
995}
996
997/* Is this really needed?
998 * i added some module parameters for test with some users */
999static void poll_sensor(struct gspca_dev *gspca_dev)
1000{
1001 static const u8 poll1[] =
1002 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
1003 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
1004 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
1005 0x60, 0x14};
1006 static const u8 poll2[] =
1007 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
1008 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
1009 static const u8 noise03[] = /* (some differences / ms-drv) */
1010 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
1011 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
1012 0xc2, 0x80, 0xc3, 0x10};
1013
1014 PDEBUG(D_STREAM, "[Sensor requires polling]");
1015 reg_w_buf(gspca_dev, poll1, sizeof poll1);
1016 reg_w_buf(gspca_dev, poll2, sizeof poll2);
1017 reg_w_buf(gspca_dev, noise03, sizeof noise03);
1018}
1019
1020static int sd_start(struct gspca_dev *gspca_dev)
1021{
1022 struct sd *sd = (struct sd *) gspca_dev;
1023 const struct additional_sensor_data *sensor;
1024 int i, mode;
1025 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
1026 static const u8 t3[] =
1027 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
1028
1029 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1030 switch (mode) {
1031 case 0: /* 640x480 (0x00) */
1032 break;
1033 case 1: /* 352x288 */
1034 t2[1] = 0x40;
1035 break;
1036 case 2: /* 320x240 */
1037 t2[1] = 0x10;
1038 break;
1039 case 3: /* 176x144 */
1040 t2[1] = 0x50;
1041 break;
1042 default:
1043/* case 4: * 160x120 */
1044 t2[1] = 0x20;
1045 break;
1046 }
1047
1048 switch (sd->sensor) {
1049 case SENSOR_OM6802:
1050 om6802_sensor_init(gspca_dev);
1051 break;
1052 case SENSOR_TAS5130A:
1053 i = 0;
1054 for (;;) {
1055 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1056 sizeof tas5130a_sensor_init[0]);
1057 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
1058 break;
1059 i++;
1060 }
1061 reg_w(gspca_dev, 0x3c80);
1062 /* just in case and to keep sync with logs (for mine) */
1063 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
1064 sizeof tas5130a_sensor_init[0]);
1065 reg_w(gspca_dev, 0x3c80);
1066 break;
1067 }
1068 sensor = &sensor_data[sd->sensor];
1069 setfreq(gspca_dev);
1070 reg_r(gspca_dev, 0x0012);
1071 reg_w_buf(gspca_dev, t2, sizeof t2);
1072 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
1073 reg_w(gspca_dev, 0x0013);
1074 msleep(15);
1075 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1076 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
1077
1078 if (sd->sensor == SENSOR_OM6802)
1079 poll_sensor(gspca_dev);
1080
1081 return 0;
1082}
1083
1084static void sd_stopN(struct gspca_dev *gspca_dev)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
1088 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1089 sizeof sensor_data[sd->sensor].stream);
1090 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
1091 sizeof sensor_data[sd->sensor].stream);
1092 if (sd->sensor == SENSOR_OM6802) {
1093 msleep(20);
1094 reg_w(gspca_dev, 0x0309);
1095 }
1096}
1097
1098static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1099 u8 *data, /* isoc packet */
1100 int len) /* iso packet length */
1101{
1102 int pkt_type;
1103
1104 if (data[0] == 0x5a) {
1105 /* Control Packet, after this came the header again,
1106 * but extra bytes came in the packet before this,
1107 * sometimes an EOF arrives, sometimes not... */
1108 return;
1109 }
1110 data += 2;
1111 len -= 2;
1112 if (data[0] == 0xff && data[1] == 0xd8)
1113 pkt_type = FIRST_PACKET;
1114 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
1115 pkt_type = LAST_PACKET;
1116 else
1117 pkt_type = INTER_PACKET;
1118 gspca_frame_add(gspca_dev, pkt_type, data, len);
1119}
1120
1121static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val)
1122{
1123 struct sd *sd = (struct sd *) gspca_dev;
1124
1125 sd->blue_gain = val;
1126 if (gspca_dev->streaming)
1127 reg_w(gspca_dev, (val << 8) + 0x88);
1128 return 0;
1129}
1130
1131static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val)
1132{
1133 struct sd *sd = (struct sd *) gspca_dev;
1134
1135 *val = sd->blue_gain;
1136 return 0;
1137}
1138
1139static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val)
1140{
1141 struct sd *sd = (struct sd *) gspca_dev;
1142
1143 sd->red_gain = val;
1144 if (gspca_dev->streaming)
1145 reg_w(gspca_dev, (val << 8) + 0x87);
1146
1147 return 0;
1148}
1149
1150static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val)
1151{
1152 struct sd *sd = (struct sd *) gspca_dev;
1153
1154 *val = sd->red_gain;
1155 return 0;
1156}
1157
1158static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1159{
1160 struct sd *sd = (struct sd *) gspca_dev;
1161 u16 psg, nsg;
1162
1163 psg = sd->red_gain + sd->blue_gain + sd->green_gain;
1164 nsg = val * 3;
1165 sd->red_gain = sd->red_gain * nsg / psg;
1166 if (sd->red_gain > 0x40)
1167 sd->red_gain = 0x40;
1168 else if (sd->red_gain < 0x10)
1169 sd->red_gain = 0x10;
1170 sd->blue_gain = sd->blue_gain * nsg / psg;
1171 if (sd->blue_gain > 0x40)
1172 sd->blue_gain = 0x40;
1173 else if (sd->blue_gain < 0x10)
1174 sd->blue_gain = 0x10;
1175 sd->green_gain = sd->green_gain * nsg / psg;
1176 if (sd->green_gain > 0x40)
1177 sd->green_gain = 0x40;
1178 else if (sd->green_gain < 0x10)
1179 sd->green_gain = 0x10;
1180
1181 if (gspca_dev->streaming)
1182 setRGB(gspca_dev);
1183 return 0;
1184}
1185
1186static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1187{
1188 struct sd *sd = (struct sd *) gspca_dev;
1189
1190 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3;
1191 return 0;
1192}
1193
1194static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1195{
1196 struct sd *sd = (struct sd *) gspca_dev;
1197
1198 sd->brightness = val;
1199 if (gspca_dev->streaming)
1200 setbrightness(gspca_dev);
1201 return 0;
1202}
1203
1204static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1205{
1206 struct sd *sd = (struct sd *) gspca_dev;
1207
1208 *val = sd->brightness;
1209 return *val;
1210}
1211
1212static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
1213{
1214 struct sd *sd = (struct sd *) gspca_dev;
1215
1216 sd->awb = val;
1217 if (gspca_dev->streaming)
1218 setawb(gspca_dev);
1219 return 0;
1220}
1221
1222static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
1223{
1224 struct sd *sd = (struct sd *) gspca_dev;
1225
1226 *val = sd->awb;
1227 return *val;
1228}
1229
1230static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val)
1231{
1232 struct sd *sd = (struct sd *) gspca_dev;
1233
1234 sd->mirror = val;
1235 if (gspca_dev->streaming)
1236 setmirror(gspca_dev);
1237 return 0;
1238}
1239
1240static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val)
1241{
1242 struct sd *sd = (struct sd *) gspca_dev;
1243
1244 *val = sd->mirror;
1245 return *val;
1246}
1247
1248static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1249{
1250 struct sd *sd = (struct sd *) gspca_dev;
1251
1252 sd->effect = val;
1253 if (gspca_dev->streaming)
1254 seteffect(gspca_dev);
1255 return 0;
1256}
1257
1258static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1259{
1260 struct sd *sd = (struct sd *) gspca_dev;
1261
1262 *val = sd->effect;
1263 return *val;
1264}
1265
1266static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1267{
1268 struct sd *sd = (struct sd *) gspca_dev;
1269
1270 sd->contrast = val;
1271 if (gspca_dev->streaming)
1272 setcontrast(gspca_dev);
1273 return 0;
1274}
1275
1276static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1277{
1278 struct sd *sd = (struct sd *) gspca_dev;
1279
1280 *val = sd->contrast;
1281 return *val;
1282}
1283
1284static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287
1288 sd->colors = val;
1289 if (gspca_dev->streaming)
1290 setcolors(gspca_dev);
1291 return 0;
1292}
1293
1294static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1295{
1296 struct sd *sd = (struct sd *) gspca_dev;
1297
1298 *val = sd->colors;
1299 return 0;
1300}
1301
1302static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1303{
1304 struct sd *sd = (struct sd *) gspca_dev;
1305
1306 sd->gamma = val;
1307 if (gspca_dev->streaming)
1308 setgamma(gspca_dev);
1309 return 0;
1310}
1311
1312static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1313{
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
1316 *val = sd->gamma;
1317 return 0;
1318}
1319
1320static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1321{
1322 struct sd *sd = (struct sd *) gspca_dev;
1323
1324 sd->freq = val;
1325 if (gspca_dev->streaming)
1326 setfreq(gspca_dev);
1327 return 0;
1328}
1329
1330static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 *val = sd->freq;
1335 return 0;
1336}
1337
1338static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1339{
1340 struct sd *sd = (struct sd *) gspca_dev;
1341
1342 sd->sharpness = val;
1343 if (gspca_dev->streaming)
1344 setsharpness(gspca_dev);
1345 return 0;
1346}
1347
1348static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1349{
1350 struct sd *sd = (struct sd *) gspca_dev;
1351
1352 *val = sd->sharpness;
1353 return 0;
1354}
1355
1356/* Low Light set here......*/
1357static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1358{
1359 struct sd *sd = (struct sd *) gspca_dev;
1360
1361 sd->autogain = val;
1362 if (val != 0)
1363 reg_w(gspca_dev, 0xf48e);
1364 else
1365 reg_w(gspca_dev, 0xb48e);
1366 return 0;
1367}
1368
1369static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1370{
1371 struct sd *sd = (struct sd *) gspca_dev;
1372
1373 *val = sd->autogain;
1374 return 0;
1375}
1376
1377static int sd_querymenu(struct gspca_dev *gspca_dev,
1378 struct v4l2_querymenu *menu)
1379{
1380 static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
1381
1382 switch (menu->id) {
1383 case V4L2_CID_POWER_LINE_FREQUENCY:
1384 if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm))
1385 break;
1386 strcpy((char *) menu->name, freq_nm[menu->index]);
1387 return 0;
1388 case V4L2_CID_EFFECTS:
1389 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1390 strlcpy((char *) menu->name,
1391 effects_control[menu->index],
1392 sizeof menu->name);
1393 return 0;
1394 }
1395 break;
1396 }
1397 return -EINVAL;
1398}
1399
1400/* sub-driver description */
1401static const struct sd_desc sd_desc = {
1402 .name = MODULE_NAME,
1403 .ctrls = sd_ctrls,
1404 .nctrls = ARRAY_SIZE(sd_ctrls),
1405 .config = sd_config,
1406 .init = sd_init,
1407 .start = sd_start,
1408 .stopN = sd_stopN,
1409 .pkt_scan = sd_pkt_scan,
1410 .querymenu = sd_querymenu,
1411};
1412
1413/* -- module initialisation -- */
1414static const struct usb_device_id device_table[] = {
1415 {USB_DEVICE(0x17a1, 0x0128)},
1416 {}
1417};
1418MODULE_DEVICE_TABLE(usb, device_table);
1419
1420/* -- device connect -- */
1421static int sd_probe(struct usb_interface *intf,
1422 const struct usb_device_id *id)
1423{
1424 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1425 THIS_MODULE);
1426}
1427
1428static struct usb_driver sd_driver = {
1429 .name = MODULE_NAME,
1430 .id_table = device_table,
1431 .probe = sd_probe,
1432 .disconnect = gspca_disconnect,
1433#ifdef CONFIG_PM
1434 .suspend = gspca_suspend,
1435 .resume = gspca_resume,
1436#endif
1437};
1438
1439/* -- module insert / remove -- */
1440static int __init sd_mod_init(void)
1441{
1442 return usb_register(&sd_driver);
1443}
1444static void __exit sd_mod_exit(void)
1445{
1446 usb_deregister(&sd_driver);
1447}
1448
1449module_init(sd_mod_init);
1450module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
new file mode 100644
index 00000000000..933ef2ca658
--- /dev/null
+++ b/drivers/media/video/gspca/tv8532.c
@@ -0,0 +1,433 @@
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 __u16 exposure;
34 __u16 gain;
35
36 __u8 packet;
37};
38
39/* V4L2 controls supported by the driver */
40static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
41static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
42static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
43static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
44
45static const struct ctrl sd_ctrls[] = {
46 {
47 {
48 .id = V4L2_CID_EXPOSURE,
49 .type = V4L2_CTRL_TYPE_INTEGER,
50 .name = "Exposure",
51 .minimum = 1,
52 .maximum = 0x18f,
53 .step = 1,
54#define EXPOSURE_DEF 0x18f
55 .default_value = EXPOSURE_DEF,
56 },
57 .set = sd_setexposure,
58 .get = sd_getexposure,
59 },
60 {
61 {
62 .id = V4L2_CID_GAIN,
63 .type = V4L2_CTRL_TYPE_INTEGER,
64 .name = "Gain",
65 .minimum = 0,
66 .maximum = 0x7ff,
67 .step = 1,
68#define GAIN_DEF 0x100
69 .default_value = GAIN_DEF,
70 },
71 .set = sd_setgain,
72 .get = sd_getgain,
73 },
74};
75
76static const struct v4l2_pix_format sif_mode[] = {
77 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
78 .bytesperline = 176,
79 .sizeimage = 176 * 144,
80 .colorspace = V4L2_COLORSPACE_SRGB,
81 .priv = 1},
82 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
83 .bytesperline = 352,
84 .sizeimage = 352 * 288,
85 .colorspace = V4L2_COLORSPACE_SRGB,
86 .priv = 0},
87};
88
89/* TV-8532A (ICM532A) registers (LE) */
90#define R00_PART_CONTROL 0x00
91#define LATENT_CHANGE 0x80
92#define EXPO_CHANGE 0x04
93#define R01_TIMING_CONTROL_LOW 0x01
94#define CMD_EEprom_Open 0x30
95#define CMD_EEprom_Close 0x29
96#define R03_TABLE_ADDR 0x03
97#define R04_WTRAM_DATA_L 0x04
98#define R05_WTRAM_DATA_M 0x05
99#define R06_WTRAM_DATA_H 0x06
100#define R07_TABLE_LEN 0x07
101#define R08_RAM_WRITE_ACTION 0x08
102#define R0C_AD_WIDTHL 0x0c
103#define R0D_AD_WIDTHH 0x0d
104#define R0E_AD_HEIGHTL 0x0e
105#define R0F_AD_HEIGHTH 0x0f
106#define R10_AD_COL_BEGINL 0x10
107#define R11_AD_COL_BEGINH 0x11
108#define MIRROR 0x04 /* [10] */
109#define R14_AD_ROW_BEGINL 0x14
110#define R15_AD_ROWBEGINH 0x15
111#define R1C_AD_EXPOSE_TIMEL 0x1c
112#define R20_GAIN_G1L 0x20
113#define R21_GAIN_G1H 0x21
114#define R22_GAIN_RL 0x22
115#define R23_GAIN_RH 0x23
116#define R24_GAIN_BL 0x24
117#define R25_GAIN_BH 0x25
118#define R26_GAIN_G2L 0x26
119#define R27_GAIN_G2H 0x27
120#define R28_QUANT 0x28
121#define R29_LINE 0x29
122#define R2C_POLARITY 0x2c
123#define R2D_POINT 0x2d
124#define R2E_POINTH 0x2e
125#define R2F_POINTB 0x2f
126#define R30_POINTBH 0x30
127#define R31_UPD 0x31
128#define R2A_HIGH_BUDGET 0x2a
129#define R2B_LOW_BUDGET 0x2b
130#define R34_VID 0x34
131#define R35_VIDH 0x35
132#define R36_PID 0x36
133#define R37_PIDH 0x37
134#define R39_Test1 0x39 /* GPIO */
135#define R3B_Test3 0x3b /* GPIO */
136#define R83_AD_IDH 0x83
137#define R91_AD_SLOPEREG 0x91
138#define R94_AD_BITCONTROL 0x94
139
140static const u8 eeprom_data[][3] = {
141/* dataH dataM dataL */
142 {0x01, 0x00, 0x01},
143 {0x01, 0x80, 0x11},
144 {0x05, 0x00, 0x14},
145 {0x05, 0x00, 0x1c},
146 {0x0d, 0x00, 0x1e},
147 {0x05, 0x00, 0x1f},
148 {0x05, 0x05, 0x19},
149 {0x05, 0x01, 0x1b},
150 {0x05, 0x09, 0x1e},
151 {0x0d, 0x89, 0x2e},
152 {0x05, 0x89, 0x2f},
153 {0x05, 0x0d, 0xd9},
154 {0x05, 0x09, 0xf1},
155};
156
157
158/* write 1 byte */
159static void reg_w1(struct gspca_dev *gspca_dev,
160 __u16 index, __u8 value)
161{
162 gspca_dev->usb_buf[0] = value;
163 usb_control_msg(gspca_dev->dev,
164 usb_sndctrlpipe(gspca_dev->dev, 0),
165 0x02,
166 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
167 0, /* value */
168 index, gspca_dev->usb_buf, 1, 500);
169}
170
171/* write 2 bytes */
172static void reg_w2(struct gspca_dev *gspca_dev,
173 u16 index, u16 value)
174{
175 gspca_dev->usb_buf[0] = value;
176 gspca_dev->usb_buf[1] = value >> 8;
177 usb_control_msg(gspca_dev->dev,
178 usb_sndctrlpipe(gspca_dev->dev, 0),
179 0x02,
180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
181 0, /* value */
182 index, gspca_dev->usb_buf, 2, 500);
183}
184
185static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
186{
187 int i;
188
189 reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open);
190 for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) {
191 reg_w1(gspca_dev, R03_TABLE_ADDR, i);
192 reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]);
193 reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]);
194 reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]);
195 reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0);
196 }
197 reg_w1(gspca_dev, R07_TABLE_LEN, i);
198 reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close);
199}
200
201/* this function is called at probe time */
202static int sd_config(struct gspca_dev *gspca_dev,
203 const struct usb_device_id *id)
204{
205 struct sd *sd = (struct sd *) gspca_dev;
206 struct cam *cam;
207
208 cam = &gspca_dev->cam;
209 cam->cam_mode = sif_mode;
210 cam->nmodes = ARRAY_SIZE(sif_mode);
211
212 sd->exposure = EXPOSURE_DEF;
213 sd->gain = GAIN_DEF;
214 return 0;
215}
216
217static void tv_8532_setReg(struct gspca_dev *gspca_dev)
218{
219 reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */
220 /******************************************************/
221 reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90);
222 reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01);
223 reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f);
224 reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44);
225 /* begin active line */
226 reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00);
227 /* mirror and digital gain */
228 reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a);
229
230 reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02);
231 reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00);
232 reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
233 /* = 0x84 */
234}
235
236/* this function is called at probe and resume time */
237static int sd_init(struct gspca_dev *gspca_dev)
238{
239 tv_8532WriteEEprom(gspca_dev);
240
241 return 0;
242}
243
244static void setexposure(struct gspca_dev *gspca_dev)
245{
246 struct sd *sd = (struct sd *) gspca_dev;
247
248 reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->exposure);
249 reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
250 /* 0x84 */
251}
252
253static void setgain(struct gspca_dev *gspca_dev)
254{
255 struct sd *sd = (struct sd *) gspca_dev;
256
257 reg_w2(gspca_dev, R20_GAIN_G1L, sd->gain);
258 reg_w2(gspca_dev, R22_GAIN_RL, sd->gain);
259 reg_w2(gspca_dev, R24_GAIN_BL, sd->gain);
260 reg_w2(gspca_dev, R26_GAIN_G2L, sd->gain);
261}
262
263/* -- start the camera -- */
264static int sd_start(struct gspca_dev *gspca_dev)
265{
266 struct sd *sd = (struct sd *) gspca_dev;
267
268 reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */
269 reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03);
270
271 /************************************************/
272 reg_w1(gspca_dev, R28_QUANT, 0x90);
273 /* 0x72 compressed mode 0x28 */
274 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
275 /* 176x144 */
276 reg_w1(gspca_dev, R29_LINE, 0x41);
277 /* CIF - 2 lines/packet */
278 } else {
279 /* 352x288 */
280 reg_w1(gspca_dev, R29_LINE, 0x81);
281 /* CIF - 2 lines/packet */
282 }
283 /************************************************/
284 reg_w1(gspca_dev, R2C_POLARITY, 0x10); /* slow clock */
285 reg_w1(gspca_dev, R2D_POINT, 0x14);
286 reg_w1(gspca_dev, R2E_POINTH, 0x01);
287 reg_w1(gspca_dev, R2F_POINTB, 0x12);
288 reg_w1(gspca_dev, R30_POINTBH, 0x01);
289
290 tv_8532_setReg(gspca_dev);
291
292 setexposure(gspca_dev);
293 setgain(gspca_dev);
294
295 /************************************************/
296 reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */
297 msleep(200);
298 reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */
299
300 gspca_dev->empty_packet = 0; /* check the empty packets */
301 sd->packet = 0; /* ignore the first packets */
302
303 return 0;
304}
305
306static void sd_stopN(struct gspca_dev *gspca_dev)
307{
308 reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */
309}
310
311static void sd_pkt_scan(struct gspca_dev *gspca_dev,
312 u8 *data, /* isoc packet */
313 int len) /* iso packet length */
314{
315 struct sd *sd = (struct sd *) gspca_dev;
316 int packet_type0, packet_type1;
317
318 packet_type0 = packet_type1 = INTER_PACKET;
319 if (gspca_dev->empty_packet) {
320 gspca_dev->empty_packet = 0;
321 sd->packet = gspca_dev->height / 2;
322 packet_type0 = FIRST_PACKET;
323 } else if (sd->packet == 0)
324 return; /* 2 more lines in 352x288 ! */
325 sd->packet--;
326 if (sd->packet == 0)
327 packet_type1 = LAST_PACKET;
328
329 /* each packet contains:
330 * - header 2 bytes
331 * - RGRG line
332 * - 4 bytes
333 * - GBGB line
334 * - 4 bytes
335 */
336 gspca_frame_add(gspca_dev, packet_type0,
337 data + 2, gspca_dev->width);
338 gspca_frame_add(gspca_dev, packet_type1,
339 data + gspca_dev->width + 5, gspca_dev->width);
340}
341
342static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
343{
344 struct sd *sd = (struct sd *) gspca_dev;
345
346 sd->exposure = val;
347 if (gspca_dev->streaming)
348 setexposure(gspca_dev);
349 return 0;
350}
351
352static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
353{
354 struct sd *sd = (struct sd *) gspca_dev;
355
356 *val = sd->exposure;
357 return 0;
358}
359
360static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
361{
362 struct sd *sd = (struct sd *) gspca_dev;
363
364 sd->gain = val;
365 if (gspca_dev->streaming)
366 setgain(gspca_dev);
367 return 0;
368}
369
370static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
371{
372 struct sd *sd = (struct sd *) gspca_dev;
373
374 *val = sd->gain;
375 return 0;
376}
377
378/* sub-driver description */
379static const struct sd_desc sd_desc = {
380 .name = MODULE_NAME,
381 .ctrls = sd_ctrls,
382 .nctrls = ARRAY_SIZE(sd_ctrls),
383 .config = sd_config,
384 .init = sd_init,
385 .start = sd_start,
386 .stopN = sd_stopN,
387 .pkt_scan = sd_pkt_scan,
388};
389
390/* -- module initialisation -- */
391static const struct usb_device_id device_table[] = {
392 {USB_DEVICE(0x046d, 0x0920)},
393 {USB_DEVICE(0x046d, 0x0921)},
394 {USB_DEVICE(0x0545, 0x808b)},
395 {USB_DEVICE(0x0545, 0x8333)},
396 {USB_DEVICE(0x0923, 0x010f)},
397 {}
398};
399
400MODULE_DEVICE_TABLE(usb, device_table);
401
402/* -- device connect -- */
403static int sd_probe(struct usb_interface *intf,
404 const struct usb_device_id *id)
405{
406 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
407 THIS_MODULE);
408}
409
410static struct usb_driver sd_driver = {
411 .name = MODULE_NAME,
412 .id_table = device_table,
413 .probe = sd_probe,
414 .disconnect = gspca_disconnect,
415#ifdef CONFIG_PM
416 .suspend = gspca_suspend,
417 .resume = gspca_resume,
418#endif
419};
420
421/* -- module insert / remove -- */
422static int __init sd_mod_init(void)
423{
424 return usb_register(&sd_driver);
425}
426
427static void __exit sd_mod_exit(void)
428{
429 usb_deregister(&sd_driver);
430}
431
432module_init(sd_mod_init);
433module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
new file mode 100644
index 00000000000..6caed734a06
--- /dev/null
+++ b/drivers/media/video/gspca/vc032x.c
@@ -0,0 +1,4243 @@
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 MODULE_NAME "vc032x"
24
25#include "gspca.h"
26
27MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
28MODULE_DESCRIPTION("GSPCA/VC032X 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 brightness;
36 u8 contrast;
37 u8 colors;
38 u8 hflip;
39 u8 vflip;
40 u8 lightfreq;
41 s8 sharpness;
42 u16 exposure;
43 u8 gain;
44 u8 autogain;
45 u8 backlight;
46
47 u8 image_offset;
48
49 u8 bridge;
50 u8 sensor;
51 u8 flags;
52#define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */
53#define FL_HFLIP 0x02 /* mirrored by default */
54#define FL_VFLIP 0x04 /* vertical flipped by default */
55};
56enum bridges {
57 BRIDGE_VC0321,
58 BRIDGE_VC0323,
59};
60enum sensors {
61 SENSOR_HV7131R,
62 SENSOR_MI0360,
63 SENSOR_MI1310_SOC,
64 SENSOR_MI1320,
65 SENSOR_MI1320_SOC,
66 SENSOR_OV7660,
67 SENSOR_OV7670,
68 SENSOR_PO1200,
69 SENSOR_PO3130NC,
70 SENSOR_POxxxx,
71 NSENSORS
72};
73
74/* V4L2 controls supported by the driver */
75static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
83static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
91static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
93static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
95static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val);
96static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val);
97
98static const struct ctrl sd_ctrls[] = {
99#define BRIGHTNESS_IDX 0
100 {
101 {
102 .id = V4L2_CID_BRIGHTNESS,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Brightness",
105 .minimum = 0,
106 .maximum = 255,
107 .step = 1,
108#define BRIGHTNESS_DEF 128
109 .default_value = BRIGHTNESS_DEF,
110 },
111 .set = sd_setbrightness,
112 .get = sd_getbrightness,
113 },
114#define CONTRAST_IDX 1
115 {
116 {
117 .id = V4L2_CID_CONTRAST,
118 .type = V4L2_CTRL_TYPE_INTEGER,
119 .name = "Contrast",
120 .minimum = 0,
121 .maximum = 255,
122 .step = 1,
123#define CONTRAST_DEF 127
124 .default_value = CONTRAST_DEF,
125 },
126 .set = sd_setcontrast,
127 .get = sd_getcontrast,
128 },
129#define COLORS_IDX 2
130 {
131 {
132 .id = V4L2_CID_SATURATION,
133 .type = V4L2_CTRL_TYPE_INTEGER,
134 .name = "Saturation",
135 .minimum = 1,
136 .maximum = 127,
137 .step = 1,
138#define COLOR_DEF 63
139 .default_value = COLOR_DEF,
140 },
141 .set = sd_setcolors,
142 .get = sd_getcolors,
143 },
144/* next 2 controls work with some sensors only */
145#define HFLIP_IDX 3
146 {
147 {
148 .id = V4L2_CID_HFLIP,
149 .type = V4L2_CTRL_TYPE_BOOLEAN,
150 .name = "Mirror",
151 .minimum = 0,
152 .maximum = 1,
153 .step = 1,
154#define HFLIP_DEF 0
155 .default_value = HFLIP_DEF,
156 },
157 .set = sd_sethflip,
158 .get = sd_gethflip,
159 },
160#define VFLIP_IDX 4
161 {
162 {
163 .id = V4L2_CID_VFLIP,
164 .type = V4L2_CTRL_TYPE_BOOLEAN,
165 .name = "Vflip",
166 .minimum = 0,
167 .maximum = 1,
168 .step = 1,
169#define VFLIP_DEF 0
170 .default_value = VFLIP_DEF,
171 },
172 .set = sd_setvflip,
173 .get = sd_getvflip,
174 },
175#define LIGHTFREQ_IDX 5
176 {
177 {
178 .id = V4L2_CID_POWER_LINE_FREQUENCY,
179 .type = V4L2_CTRL_TYPE_MENU,
180 .name = "Light frequency filter",
181 .minimum = 0,
182 .maximum = 2, /* 0: No, 1: 50Hz, 2:60Hz */
183 .step = 1,
184#define FREQ_DEF 1
185 .default_value = FREQ_DEF,
186 },
187 .set = sd_setfreq,
188 .get = sd_getfreq,
189 },
190#define SHARPNESS_IDX 6
191 {
192 {
193 .id = V4L2_CID_SHARPNESS,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Sharpness",
196 .minimum = -1,
197 .maximum = 2,
198 .step = 1,
199#define SHARPNESS_DEF -1
200 .default_value = SHARPNESS_DEF,
201 },
202 .set = sd_setsharpness,
203 .get = sd_getsharpness,
204 },
205#define GAIN_IDX 7
206 {
207 {
208 .id = V4L2_CID_GAIN,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "Gain",
211 .minimum = 0,
212 .maximum = 78,
213 .step = 1,
214#define GAIN_DEF 0
215 .default_value = GAIN_DEF,
216 },
217 .set = sd_setgain,
218 .get = sd_getgain,
219 },
220#define EXPOSURE_IDX 8
221 {
222 {
223 .id = V4L2_CID_EXPOSURE,
224 .type = V4L2_CTRL_TYPE_INTEGER,
225 .name = "Exposure",
226#define EXPOSURE_DEF 450
227 .minimum = 0,
228 .maximum = 4095,
229 .step = 1,
230 .default_value = EXPOSURE_DEF,
231 },
232 .set = sd_setexposure,
233 .get = sd_getexposure,
234 },
235#define AUTOGAIN_IDX 9
236 {
237 {
238 .id = V4L2_CID_AUTOGAIN,
239 .type = V4L2_CTRL_TYPE_BOOLEAN,
240 .name = "Automatic Gain and Exposure",
241 .minimum = 0,
242 .maximum = 1,
243 .step = 1,
244#define AUTOGAIN_DEF 1
245 .default_value = AUTOGAIN_DEF,
246 },
247 .set = sd_setautogain,
248 .get = sd_getautogain,
249 },
250#define BACKLIGHT_IDX 10
251 {
252 {
253 .id = V4L2_CID_BACKLIGHT_COMPENSATION,
254 .type = V4L2_CTRL_TYPE_BOOLEAN,
255 .name = "Backlight Compensation",
256 .minimum = 0,
257 .maximum = 15,
258 .step = 1,
259#define BACKLIGHT_DEF 15
260 .default_value = BACKLIGHT_DEF,
261 },
262 .set = sd_setbacklight,
263 .get = sd_getbacklight,
264 },
265};
266
267/* table of the disabled controls */
268static u32 ctrl_dis[NSENSORS] = {
269 [SENSOR_HV7131R] =
270 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
271 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
272 | (1 << SHARPNESS_IDX)
273 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
274 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
275 [SENSOR_MI0360] =
276 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
277 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
278 | (1 << SHARPNESS_IDX)
279 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
280 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
281 [SENSOR_MI1310_SOC] =
282 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
283 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
284 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
285 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
286 [SENSOR_MI1320] =
287 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
288 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
289 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
290 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
291 [SENSOR_MI1320_SOC] =
292 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
293 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
294 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
295 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
296 [SENSOR_OV7660] =
297 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
298 | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
299 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
300 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
301 [SENSOR_OV7670] =
302 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
303 | (1 << SHARPNESS_IDX)
304 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
305 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
306 [SENSOR_PO1200] =
307 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
308 | (1 << LIGHTFREQ_IDX)
309 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
310 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
311 [SENSOR_PO3130NC] =
312 (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
313 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
314 | (1 << SHARPNESS_IDX)
315 | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
316 | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
317 [SENSOR_POxxxx] =
318 (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX),
319};
320
321static const struct v4l2_pix_format vc0321_mode[] = {
322 {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
323 .bytesperline = 320,
324 .sizeimage = 320 * 240 * 2,
325 .colorspace = V4L2_COLORSPACE_SRGB,
326 .priv = 1},
327 {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
328 .bytesperline = 640,
329 .sizeimage = 640 * 480 * 2,
330 .colorspace = V4L2_COLORSPACE_SRGB,
331 .priv = 0},
332};
333static const struct v4l2_pix_format vc0323_mode[] = {
334 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
335 .bytesperline = 320,
336 .sizeimage = 320 * 240 * 3 / 8 + 590,
337 .colorspace = V4L2_COLORSPACE_JPEG,
338 .priv = 1},
339 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
340 .bytesperline = 640,
341 .sizeimage = 640 * 480 * 3 / 8 + 590,
342 .colorspace = V4L2_COLORSPACE_JPEG,
343 .priv = 0},
344 {1280, 960, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */
345 .bytesperline = 1280,
346 .sizeimage = 1280 * 960 * 3 / 8 + 590,
347 .colorspace = V4L2_COLORSPACE_JPEG,
348 .priv = 2},
349};
350static const struct v4l2_pix_format bi_mode[] = {
351 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
352 .bytesperline = 320,
353 .sizeimage = 320 * 240 * 2,
354 .colorspace = V4L2_COLORSPACE_SRGB,
355 .priv = 2},
356 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
357 .bytesperline = 640,
358 .sizeimage = 640 * 480 * 2,
359 .colorspace = V4L2_COLORSPACE_SRGB,
360 .priv = 1},
361 {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
362 .bytesperline = 1280,
363 .sizeimage = 1280 * 1024 * 2,
364 .colorspace = V4L2_COLORSPACE_SRGB,
365 .priv = 0},
366};
367static const struct v4l2_pix_format svga_mode[] = {
368 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
369 .bytesperline = 800,
370 .sizeimage = 800 * 600 * 1 / 4 + 590,
371 .colorspace = V4L2_COLORSPACE_JPEG,
372 .priv = 0},
373};
374
375/* OV7660/7670 registers */
376#define OV7660_REG_MVFP 0x1e
377#define OV7660_MVFP_MIRROR 0x20
378#define OV7660_MVFP_VFLIP 0x10
379
380static const u8 mi0360_matrix[9] = {
381 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50
382};
383
384static const u8 mi0360_initVGA_JPG[][4] = {
385 {0xb0, 0x03, 0x19, 0xcc},
386 {0xb0, 0x04, 0x02, 0xcc},
387 {0xb3, 0x00, 0x24, 0xcc},
388 {0xb3, 0x00, 0x25, 0xcc},
389 {0xb3, 0x08, 0x01, 0xcc},
390 {0xb3, 0x09, 0x0c, 0xcc},
391 {0xb3, 0x05, 0x01, 0xcc},
392 {0xb3, 0x06, 0x03, 0xcc},
393 {0xb3, 0x03, 0x0a, 0xcc},
394 {0xb3, 0x20, 0x00, 0xcc},
395 {0xb3, 0x21, 0x00, 0xcc},
396 {0xb3, 0x22, 0x01, 0xcc},
397 {0xb3, 0x23, 0xe0, 0xcc},
398 {0xb3, 0x04, 0x05, 0xcc},
399 {0xb3, 0x14, 0x00, 0xcc},
400 {0xb3, 0x15, 0x00, 0xcc},
401 {0xb3, 0x16, 0x02, 0xcc},
402 {0xb3, 0x17, 0x7f, 0xcc},
403 {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */
404 {0xb3, 0x34, 0x02, 0xcc},
405 {0xb3, 0x00, 0x25, 0xcc},
406 {0xbc, 0x00, 0x71, 0xcc},
407 {0xb8, 0x00, 0x13, 0xcc},
408 {0xb8, 0x27, 0x20, 0xcc},
409 {0xb8, 0x2c, 0x50, 0xcc},
410 {0xb8, 0x2d, 0xf8, 0xcc},
411 {0xb8, 0x2e, 0xf8, 0xcc},
412 {0xb8, 0x2f, 0xf8, 0xcc},
413 {0xb8, 0x30, 0x50, 0xcc},
414 {0xb8, 0x31, 0xf8, 0xcc},
415 {0xb8, 0x32, 0xf8, 0xcc},
416 {0xb8, 0x33, 0xf8, 0xcc},
417 {0xb8, 0x34, 0x50, 0xcc},
418 {0xb8, 0x35, 0x00, 0xcc},
419 {0xb8, 0x36, 0x00, 0xcc},
420 {0xb8, 0x37, 0x00, 0xcc},
421 {0xb8, 0x01, 0x79, 0xcc},
422 {0xb8, 0x08, 0xe0, 0xcc},
423 {0xb3, 0x01, 0x41, 0xcc},
424 {0xb8, 0x01, 0x79, 0xcc},
425 {0xb8, 0x14, 0x18, 0xcc},
426 {0xb8, 0xb2, 0x0a, 0xcc},
427 {0xb8, 0xb4, 0x0a, 0xcc},
428 {0xb8, 0xb5, 0x0a, 0xcc},
429 {0xb8, 0xfe, 0x00, 0xcc},
430 {0xb8, 0xff, 0x28, 0xcc},
431 {0xb9, 0x00, 0x28, 0xcc},
432 {0xb9, 0x01, 0x28, 0xcc},
433 {0xb9, 0x02, 0x28, 0xcc},
434 {0xb9, 0x03, 0x00, 0xcc},
435 {0xb9, 0x04, 0x00, 0xcc},
436 {0xb9, 0x05, 0x3c, 0xcc},
437 {0xb9, 0x06, 0x3c, 0xcc},
438 {0xb9, 0x07, 0x3c, 0xcc},
439 {0xb9, 0x08, 0x3c, 0xcc},
440 {0xb8, 0x8e, 0x00, 0xcc},
441 {0xb8, 0x8f, 0xff, 0xcc},
442 {0xb8, 0x81, 0x09, 0xcc},
443 {0x31, 0x00, 0x00, 0xbb},
444 {0x09, 0x01, 0xc7, 0xbb},
445 {0x34, 0x01, 0x00, 0xbb},
446 {0x2b, 0x00, 0x28, 0xbb},
447 {0x2c, 0x00, 0x30, 0xbb},
448 {0x2d, 0x00, 0x30, 0xbb},
449 {0x2e, 0x00, 0x28, 0xbb},
450 {0x62, 0x04, 0x11, 0xbb},
451 {0x03, 0x01, 0xe0, 0xbb},
452 {0x2c, 0x00, 0x2c, 0xbb},
453 {0x20, 0xd0, 0x00, 0xbb},
454 {0x01, 0x00, 0x08, 0xbb},
455 {0x06, 0x00, 0x10, 0xbb},
456 {0x05, 0x00, 0x20, 0xbb},
457 {0x20, 0x00, 0x00, 0xbb},
458 {0xb6, 0x00, 0x00, 0xcc},
459 {0xb6, 0x03, 0x02, 0xcc},
460 {0xb6, 0x02, 0x80, 0xcc},
461 {0xb6, 0x05, 0x01, 0xcc},
462 {0xb6, 0x04, 0xe0, 0xcc},
463 {0xb6, 0x12, 0x78, 0xcc},
464 {0xb6, 0x18, 0x02, 0xcc},
465 {0xb6, 0x17, 0x58, 0xcc},
466 {0xb6, 0x16, 0x00, 0xcc},
467 {0xb6, 0x22, 0x12, 0xcc},
468 {0xb6, 0x23, 0x0b, 0xcc},
469 {0xb3, 0x02, 0x02, 0xcc},
470 {0xbf, 0xc0, 0x39, 0xcc},
471 {0xbf, 0xc1, 0x04, 0xcc},
472 {0xbf, 0xcc, 0x10, 0xcc},
473 {0xb9, 0x12, 0x00, 0xcc},
474 {0xb9, 0x13, 0x0a, 0xcc},
475 {0xb9, 0x14, 0x0a, 0xcc},
476 {0xb9, 0x15, 0x0a, 0xcc},
477 {0xb9, 0x16, 0x0a, 0xcc},
478 {0xb9, 0x18, 0x00, 0xcc},
479 {0xb9, 0x19, 0x0f, 0xcc},
480 {0xb9, 0x1a, 0x0f, 0xcc},
481 {0xb9, 0x1b, 0x0f, 0xcc},
482 {0xb9, 0x1c, 0x0f, 0xcc},
483 {0xb8, 0x8e, 0x00, 0xcc},
484 {0xb8, 0x8f, 0xff, 0xcc},
485 {0xb6, 0x12, 0xf8, 0xcc},
486 {0xb8, 0x0c, 0x20, 0xcc},
487 {0xb8, 0x0d, 0x70, 0xcc},
488 {0xb6, 0x13, 0x13, 0xcc},
489 {0x35, 0x00, 0x60, 0xbb},
490 {0xb3, 0x5c, 0x01, 0xcc},
491 {}
492};
493static const u8 mi0360_initQVGA_JPG[][4] = {
494 {0xb0, 0x03, 0x19, 0xcc},
495 {0xb0, 0x04, 0x02, 0xcc},
496 {0xb3, 0x00, 0x24, 0xcc},
497 {0xb3, 0x00, 0x25, 0xcc},
498 {0xb3, 0x08, 0x01, 0xcc},
499 {0xb3, 0x09, 0x0c, 0xcc},
500 {0xb3, 0x05, 0x01, 0xcc},
501 {0xb3, 0x06, 0x03, 0xcc},
502 {0xb3, 0x03, 0x0a, 0xcc},
503 {0xb3, 0x20, 0x00, 0xcc},
504 {0xb3, 0x21, 0x00, 0xcc},
505 {0xb3, 0x22, 0x01, 0xcc},
506 {0xb3, 0x23, 0xe0, 0xcc},
507 {0xb3, 0x04, 0x05, 0xcc},
508 {0xb3, 0x14, 0x00, 0xcc},
509 {0xb3, 0x15, 0x00, 0xcc},
510 {0xb3, 0x16, 0x02, 0xcc},
511 {0xb3, 0x17, 0x7f, 0xcc},
512 {0xb3, 0x35, 0xdd, 0xcc},
513 {0xb3, 0x34, 0x02, 0xcc},
514 {0xb3, 0x00, 0x25, 0xcc},
515 {0xbc, 0x00, 0xd1, 0xcc},
516 {0xb8, 0x00, 0x13, 0xcc},
517 {0xb8, 0x27, 0x20, 0xcc},
518 {0xb8, 0x2c, 0x50, 0xcc},
519 {0xb8, 0x2d, 0xf8, 0xcc},
520 {0xb8, 0x2e, 0xf8, 0xcc},
521 {0xb8, 0x2f, 0xf8, 0xcc},
522 {0xb8, 0x30, 0x50, 0xcc},
523 {0xb8, 0x31, 0xf8, 0xcc},
524 {0xb8, 0x32, 0xf8, 0xcc},
525 {0xb8, 0x33, 0xf8, 0xcc},
526 {0xb8, 0x34, 0x50, 0xcc},
527 {0xb8, 0x35, 0x00, 0xcc},
528 {0xb8, 0x36, 0x00, 0xcc},
529 {0xb8, 0x37, 0x00, 0xcc},
530 {0xb8, 0x01, 0x79, 0xcc},
531 {0xb8, 0x08, 0xe0, 0xcc},
532 {0xb3, 0x01, 0x41, 0xcc},
533 {0xb8, 0x01, 0x79, 0xcc},
534 {0xb8, 0x14, 0x18, 0xcc},
535 {0xb8, 0xb2, 0x0a, 0xcc},
536 {0xb8, 0xb4, 0x0a, 0xcc},
537 {0xb8, 0xb5, 0x0a, 0xcc},
538 {0xb8, 0xfe, 0x00, 0xcc},
539 {0xb8, 0xff, 0x28, 0xcc},
540 {0xb9, 0x00, 0x28, 0xcc},
541 {0xb9, 0x01, 0x28, 0xcc},
542 {0xb9, 0x02, 0x28, 0xcc},
543 {0xb9, 0x03, 0x00, 0xcc},
544 {0xb9, 0x04, 0x00, 0xcc},
545 {0xb9, 0x05, 0x3c, 0xcc},
546 {0xb9, 0x06, 0x3c, 0xcc},
547 {0xb9, 0x07, 0x3c, 0xcc},
548 {0xb9, 0x08, 0x3c, 0xcc},
549 {0xb8, 0x8e, 0x00, 0xcc},
550 {0xb8, 0x8f, 0xff, 0xcc},
551 {0xb8, 0x81, 0x09, 0xcc},
552 {0x31, 0x00, 0x00, 0xbb},
553 {0x09, 0x01, 0xc7, 0xbb},
554 {0x34, 0x01, 0x00, 0xbb},
555 {0x2b, 0x00, 0x28, 0xbb},
556 {0x2c, 0x00, 0x30, 0xbb},
557 {0x2d, 0x00, 0x30, 0xbb},
558 {0x2e, 0x00, 0x28, 0xbb},
559 {0x62, 0x04, 0x11, 0xbb},
560 {0x03, 0x01, 0xe0, 0xbb},
561 {0x2c, 0x00, 0x2c, 0xbb},
562 {0x20, 0xd0, 0x00, 0xbb},
563 {0x01, 0x00, 0x08, 0xbb},
564 {0x06, 0x00, 0x10, 0xbb},
565 {0x05, 0x00, 0x20, 0xbb},
566 {0x20, 0x00, 0x00, 0xbb},
567 {0xb6, 0x00, 0x00, 0xcc},
568 {0xb6, 0x03, 0x01, 0xcc},
569 {0xb6, 0x02, 0x40, 0xcc},
570 {0xb6, 0x05, 0x00, 0xcc},
571 {0xb6, 0x04, 0xf0, 0xcc},
572 {0xb6, 0x12, 0x78, 0xcc},
573 {0xb6, 0x18, 0x00, 0xcc},
574 {0xb6, 0x17, 0x96, 0xcc},
575 {0xb6, 0x16, 0x00, 0xcc},
576 {0xb6, 0x22, 0x12, 0xcc},
577 {0xb6, 0x23, 0x0b, 0xcc},
578 {0xb3, 0x02, 0x02, 0xcc},
579 {0xbf, 0xc0, 0x39, 0xcc},
580 {0xbf, 0xc1, 0x04, 0xcc},
581 {0xbf, 0xcc, 0x10, 0xcc},
582 {0xb9, 0x12, 0x00, 0xcc},
583 {0xb9, 0x13, 0x0a, 0xcc},
584 {0xb9, 0x14, 0x0a, 0xcc},
585 {0xb9, 0x15, 0x0a, 0xcc},
586 {0xb9, 0x16, 0x0a, 0xcc},
587 {0xb9, 0x18, 0x00, 0xcc},
588 {0xb9, 0x19, 0x0f, 0xcc},
589 {0xb9, 0x1a, 0x0f, 0xcc},
590 {0xb9, 0x1b, 0x0f, 0xcc},
591 {0xb9, 0x1c, 0x0f, 0xcc},
592 {0xb8, 0x8e, 0x00, 0xcc},
593 {0xb8, 0x8f, 0xff, 0xcc},
594 {0xb6, 0x12, 0xf8, 0xcc},
595 {0xb6, 0x13, 0x13, 0xcc},
596 {0xbc, 0x02, 0x18, 0xcc},
597 {0xbc, 0x03, 0x50, 0xcc},
598 {0xbc, 0x04, 0x18, 0xcc},
599 {0xbc, 0x05, 0x00, 0xcc},
600 {0xbc, 0x06, 0x00, 0xcc},
601 {0xbc, 0x08, 0x30, 0xcc},
602 {0xbc, 0x09, 0x40, 0xcc},
603 {0xbc, 0x0a, 0x10, 0xcc},
604 {0xb8, 0x0c, 0x20, 0xcc},
605 {0xb8, 0x0d, 0x70, 0xcc},
606 {0xbc, 0x0b, 0x00, 0xcc},
607 {0xbc, 0x0c, 0x00, 0xcc},
608 {0x35, 0x00, 0xef, 0xbb},
609 {0xb3, 0x5c, 0x01, 0xcc},
610 {}
611};
612
613static const u8 mi1310_socinitVGA_JPG[][4] = {
614 {0xb0, 0x03, 0x19, 0xcc},
615 {0xb0, 0x04, 0x02, 0xcc},
616 {0xb3, 0x00, 0x64, 0xcc},
617 {0xb3, 0x00, 0x65, 0xcc},
618 {0xb3, 0x05, 0x00, 0xcc},
619 {0xb3, 0x06, 0x00, 0xcc},
620 {0xb3, 0x08, 0x01, 0xcc},
621 {0xb3, 0x09, 0x0c, 0xcc},
622 {0xb3, 0x34, 0x02, 0xcc},
623 {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */
624 {0xb3, 0x02, 0x00, 0xcc},
625 {0xb3, 0x03, 0x0a, 0xcc},
626 {0xb3, 0x04, 0x05, 0xcc},
627 {0xb3, 0x20, 0x00, 0xcc},
628 {0xb3, 0x21, 0x00, 0xcc},
629 {0xb3, 0x22, 0x03, 0xcc},
630 {0xb3, 0x23, 0xc0, 0xcc},
631 {0xb3, 0x14, 0x00, 0xcc},
632 {0xb3, 0x15, 0x00, 0xcc},
633 {0xb3, 0x16, 0x04, 0xcc},
634 {0xb3, 0x17, 0xff, 0xcc},
635 {0xb3, 0x00, 0x65, 0xcc},
636 {0xb8, 0x00, 0x00, 0xcc},
637 {0xbc, 0x00, 0xd0, 0xcc},
638 {0xbc, 0x01, 0x01, 0xcc},
639 {0xf0, 0x00, 0x02, 0xbb},
640 {0xc8, 0x9f, 0x0b, 0xbb},
641 {0x5b, 0x00, 0x01, 0xbb},
642 {0x2f, 0xde, 0x20, 0xbb},
643 {0xf0, 0x00, 0x00, 0xbb},
644 {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
645 {0xf0, 0x00, 0x01, 0xbb},
646 {0x05, 0x00, 0x07, 0xbb},
647 {0x34, 0x00, 0x00, 0xbb},
648 {0x35, 0xff, 0x00, 0xbb},
649 {0xdc, 0x07, 0x02, 0xbb},
650 {0xdd, 0x3c, 0x18, 0xbb},
651 {0xde, 0x92, 0x6d, 0xbb},
652 {0xdf, 0xcd, 0xb1, 0xbb},
653 {0xe0, 0xff, 0xe7, 0xbb},
654 {0x06, 0xf0, 0x0d, 0xbb},
655 {0x06, 0x70, 0x0e, 0xbb},
656 {0x4c, 0x00, 0x01, 0xbb},
657 {0x4d, 0x00, 0x01, 0xbb},
658 {0xf0, 0x00, 0x02, 0xbb},
659 {0x2e, 0x0c, 0x55, 0xbb},
660 {0x21, 0xb6, 0x6e, 0xbb},
661 {0x36, 0x30, 0x10, 0xbb},
662 {0x37, 0x00, 0xc1, 0xbb},
663 {0xf0, 0x00, 0x00, 0xbb},
664 {0x07, 0x00, 0x84, 0xbb},
665 {0x08, 0x02, 0x4a, 0xbb},
666 {0x05, 0x01, 0x10, 0xbb},
667 {0x06, 0x00, 0x39, 0xbb},
668 {0xf0, 0x00, 0x02, 0xbb},
669 {0x58, 0x02, 0x67, 0xbb},
670 {0x57, 0x02, 0x00, 0xbb},
671 {0x5a, 0x02, 0x67, 0xbb},
672 {0x59, 0x02, 0x00, 0xbb},
673 {0x5c, 0x12, 0x0d, 0xbb},
674 {0x5d, 0x16, 0x11, 0xbb},
675 {0x39, 0x06, 0x18, 0xbb},
676 {0x3a, 0x06, 0x18, 0xbb},
677 {0x3b, 0x06, 0x18, 0xbb},
678 {0x3c, 0x06, 0x18, 0xbb},
679 {0x64, 0x7b, 0x5b, 0xbb},
680 {0xf0, 0x00, 0x02, 0xbb},
681 {0x36, 0x30, 0x10, 0xbb},
682 {0x37, 0x00, 0xc0, 0xbb},
683 {0xbc, 0x0e, 0x00, 0xcc},
684 {0xbc, 0x0f, 0x05, 0xcc},
685 {0xbc, 0x10, 0xc0, 0xcc},
686 {0xbc, 0x11, 0x03, 0xcc},
687 {0xb6, 0x00, 0x00, 0xcc},
688 {0xb6, 0x03, 0x02, 0xcc},
689 {0xb6, 0x02, 0x80, 0xcc},
690 {0xb6, 0x05, 0x01, 0xcc},
691 {0xb6, 0x04, 0xe0, 0xcc},
692 {0xb6, 0x12, 0xf8, 0xcc},
693 {0xb6, 0x13, 0x25, 0xcc},
694 {0xb6, 0x18, 0x02, 0xcc},
695 {0xb6, 0x17, 0x58, 0xcc},
696 {0xb6, 0x16, 0x00, 0xcc},
697 {0xb6, 0x22, 0x12, 0xcc},
698 {0xb6, 0x23, 0x0b, 0xcc},
699 {0xbf, 0xc0, 0x39, 0xcc},
700 {0xbf, 0xc1, 0x04, 0xcc},
701 {0xbf, 0xcc, 0x00, 0xcc},
702 {0xbc, 0x02, 0x18, 0xcc},
703 {0xbc, 0x03, 0x50, 0xcc},
704 {0xbc, 0x04, 0x18, 0xcc},
705 {0xbc, 0x05, 0x00, 0xcc},
706 {0xbc, 0x06, 0x00, 0xcc},
707 {0xbc, 0x08, 0x30, 0xcc},
708 {0xbc, 0x09, 0x40, 0xcc},
709 {0xbc, 0x0a, 0x10, 0xcc},
710 {0xbc, 0x0b, 0x00, 0xcc},
711 {0xbc, 0x0c, 0x00, 0xcc},
712 {0xb3, 0x5c, 0x01, 0xcc},
713 {0xf0, 0x00, 0x01, 0xbb},
714 {0x80, 0x00, 0x03, 0xbb},
715 {0x81, 0xc7, 0x14, 0xbb},
716 {0x82, 0xeb, 0xe8, 0xbb},
717 {0x83, 0xfe, 0xf4, 0xbb},
718 {0x84, 0xcd, 0x10, 0xbb},
719 {0x85, 0xf3, 0xee, 0xbb},
720 {0x86, 0xff, 0xf1, 0xbb},
721 {0x87, 0xcd, 0x10, 0xbb},
722 {0x88, 0xf3, 0xee, 0xbb},
723 {0x89, 0x01, 0xf1, 0xbb},
724 {0x8a, 0xe5, 0x17, 0xbb},
725 {0x8b, 0xe8, 0xe2, 0xbb},
726 {0x8c, 0xf7, 0xed, 0xbb},
727 {0x8d, 0x00, 0xff, 0xbb},
728 {0x8e, 0xec, 0x10, 0xbb},
729 {0x8f, 0xf0, 0xed, 0xbb},
730 {0x90, 0xf9, 0xf2, 0xbb},
731 {0x91, 0x00, 0x00, 0xbb},
732 {0x92, 0xe9, 0x0d, 0xbb},
733 {0x93, 0xf4, 0xf2, 0xbb},
734 {0x94, 0xfb, 0xf5, 0xbb},
735 {0x95, 0x00, 0xff, 0xbb},
736 {0xb6, 0x0f, 0x08, 0xbb},
737 {0xb7, 0x3d, 0x16, 0xbb},
738 {0xb8, 0x0c, 0x04, 0xbb},
739 {0xb9, 0x1c, 0x07, 0xbb},
740 {0xba, 0x0a, 0x03, 0xbb},
741 {0xbb, 0x1b, 0x09, 0xbb},
742 {0xbc, 0x17, 0x0d, 0xbb},
743 {0xbd, 0x23, 0x1d, 0xbb},
744 {0xbe, 0x00, 0x28, 0xbb},
745 {0xbf, 0x11, 0x09, 0xbb},
746 {0xc0, 0x16, 0x15, 0xbb},
747 {0xc1, 0x00, 0x1b, 0xbb},
748 {0xc2, 0x0e, 0x07, 0xbb},
749 {0xc3, 0x14, 0x10, 0xbb},
750 {0xc4, 0x00, 0x17, 0xbb},
751 {0x06, 0x74, 0x8e, 0xbb},
752 {0xf0, 0x00, 0x01, 0xbb},
753 {0x06, 0xf4, 0x8e, 0xbb},
754 {0x00, 0x00, 0x50, 0xdd},
755 {0x06, 0x74, 0x8e, 0xbb},
756 {0xf0, 0x00, 0x02, 0xbb},
757 {0x24, 0x50, 0x20, 0xbb},
758 {0xf0, 0x00, 0x02, 0xbb},
759 {0x34, 0x0c, 0x50, 0xbb},
760 {0xb3, 0x01, 0x41, 0xcc},
761 {0xf0, 0x00, 0x00, 0xbb},
762 {0x03, 0x03, 0xc0, 0xbb},
763 {},
764};
765static const u8 mi1310_socinitQVGA_JPG[][4] = {
766 {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc},
767 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
768 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc},
769 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
770 {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc},
771 {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc},
772 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
773 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc},
774 {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
775 {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc},
776 {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
777 {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc},
778 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb},
779 {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
780 {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
781 {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
782 {0xf0, 0x00, 0x01, 0xbb},
783 {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb},
784 {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb},
785 {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb},
786 {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb},
787 {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb},
788 {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb},
789 {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb},
790 {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
791 {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
792 {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb},
793 {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb},
794 {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb},
795 {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb},
796 {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
797 {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb},
798 {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb},
799 {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb},
800 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
801 {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
802 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
803 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
804 {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc},
805 {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc},
806 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc},
807 {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc},
808 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
809 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
810 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
811 {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb},
812 {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb},
813 {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb},
814 {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb},
815 {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb},
816 {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb},
817 {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb},
818 {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb},
819 {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb},
820 {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
821 {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb},
822 {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb},
823 {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb},
824 {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb},
825 {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb},
826 {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb},
827 {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb},
828 {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb},
829 {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb},
830 {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb},
831 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb},
832 {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb},
833 {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb},
834 {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb},
835 {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
836 {0x03, 0x03, 0xc0, 0xbb},
837 {},
838};
839static const u8 mi1310_soc_InitSXGA_JPG[][4] = {
840 {0xb0, 0x03, 0x19, 0xcc},
841 {0xb0, 0x04, 0x02, 0xcc},
842 {0xb3, 0x00, 0x64, 0xcc},
843 {0xb3, 0x00, 0x65, 0xcc},
844 {0xb3, 0x05, 0x00, 0xcc},
845 {0xb3, 0x06, 0x00, 0xcc},
846 {0xb3, 0x08, 0x01, 0xcc},
847 {0xb3, 0x09, 0x0c, 0xcc},
848 {0xb3, 0x34, 0x02, 0xcc},
849 {0xb3, 0x35, 0xdd, 0xcc},
850 {0xb3, 0x02, 0x00, 0xcc},
851 {0xb3, 0x03, 0x0a, 0xcc},
852 {0xb3, 0x04, 0x0d, 0xcc},
853 {0xb3, 0x20, 0x00, 0xcc},
854 {0xb3, 0x21, 0x00, 0xcc},
855 {0xb3, 0x22, 0x03, 0xcc},
856 {0xb3, 0x23, 0xc0, 0xcc},
857 {0xb3, 0x14, 0x00, 0xcc},
858 {0xb3, 0x15, 0x00, 0xcc},
859 {0xb3, 0x16, 0x04, 0xcc},
860 {0xb3, 0x17, 0xff, 0xcc},
861 {0xb3, 0x00, 0x65, 0xcc},
862 {0xb8, 0x00, 0x00, 0xcc},
863 {0xbc, 0x00, 0x70, 0xcc},
864 {0xbc, 0x01, 0x01, 0xcc},
865 {0xf0, 0x00, 0x02, 0xbb},
866 {0xc8, 0x9f, 0x0b, 0xbb},
867 {0x5b, 0x00, 0x01, 0xbb},
868 {0xf0, 0x00, 0x00, 0xbb},
869 {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */
870 {0xf0, 0x00, 0x01, 0xbb},
871 {0x05, 0x00, 0x07, 0xbb},
872 {0x34, 0x00, 0x00, 0xbb},
873 {0x35, 0xff, 0x00, 0xbb},
874 {0xdc, 0x07, 0x02, 0xbb},
875 {0xdd, 0x3c, 0x18, 0xbb},
876 {0xde, 0x92, 0x6d, 0xbb},
877 {0xdf, 0xcd, 0xb1, 0xbb},
878 {0xe0, 0xff, 0xe7, 0xbb},
879 {0x06, 0xf0, 0x0d, 0xbb},
880 {0x06, 0x70, 0x0e, 0xbb},
881 {0x4c, 0x00, 0x01, 0xbb},
882 {0x4d, 0x00, 0x01, 0xbb},
883 {0xf0, 0x00, 0x02, 0xbb},
884 {0x2e, 0x0c, 0x60, 0xbb},
885 {0x21, 0xb6, 0x6e, 0xbb},
886 {0x37, 0x01, 0x40, 0xbb},
887 {0xf0, 0x00, 0x00, 0xbb},
888 {0x07, 0x00, 0x84, 0xbb},
889 {0x08, 0x02, 0x4a, 0xbb},
890 {0x05, 0x01, 0x10, 0xbb},
891 {0x06, 0x00, 0x39, 0xbb},
892 {0xf0, 0x00, 0x02, 0xbb},
893 {0x58, 0x02, 0x67, 0xbb},
894 {0x57, 0x02, 0x00, 0xbb},
895 {0x5a, 0x02, 0x67, 0xbb},
896 {0x59, 0x02, 0x00, 0xbb},
897 {0x5c, 0x12, 0x0d, 0xbb},
898 {0x5d, 0x16, 0x11, 0xbb},
899 {0x39, 0x06, 0x18, 0xbb},
900 {0x3a, 0x06, 0x18, 0xbb},
901 {0x3b, 0x06, 0x18, 0xbb},
902 {0x3c, 0x06, 0x18, 0xbb},
903 {0x64, 0x7b, 0x5b, 0xbb},
904 {0xb6, 0x00, 0x00, 0xcc},
905 {0xb6, 0x03, 0x05, 0xcc},
906 {0xb6, 0x02, 0x00, 0xcc},
907 {0xb6, 0x05, 0x03, 0xcc},
908 {0xb6, 0x04, 0xc0, 0xcc},
909 {0xb6, 0x12, 0xf8, 0xcc},
910 {0xb6, 0x13, 0x29, 0xcc},
911 {0xb6, 0x18, 0x09, 0xcc},
912 {0xb6, 0x17, 0x60, 0xcc},
913 {0xb6, 0x16, 0x00, 0xcc},
914 {0xb6, 0x22, 0x12, 0xcc},
915 {0xb6, 0x23, 0x0b, 0xcc},
916 {0xbf, 0xc0, 0x39, 0xcc},
917 {0xbf, 0xc1, 0x04, 0xcc},
918 {0xbf, 0xcc, 0x00, 0xcc},
919 {0xb3, 0x01, 0x41, 0xcc},
920 {0x00, 0x00, 0x80, 0xdd},
921 {0xf0, 0x00, 0x02, 0xbb},
922 {0x00, 0x00, 0x10, 0xdd},
923 {0x22, 0xa0, 0x78, 0xbb},
924 {0x23, 0xa0, 0x78, 0xbb},
925 {0x24, 0x7f, 0x00, 0xbb},
926 {0x28, 0xea, 0x02, 0xbb},
927 {0x29, 0x86, 0x7a, 0xbb},
928 {0x5e, 0x52, 0x4c, 0xbb},
929 {0x5f, 0x20, 0x24, 0xbb},
930 {0x60, 0x00, 0x02, 0xbb},
931 {0x02, 0x00, 0xee, 0xbb},
932 {0x03, 0x39, 0x23, 0xbb},
933 {0x04, 0x07, 0x24, 0xbb},
934 {0x09, 0x00, 0xc0, 0xbb},
935 {0x0a, 0x00, 0x79, 0xbb},
936 {0x0b, 0x00, 0x04, 0xbb},
937 {0x0c, 0x00, 0x5c, 0xbb},
938 {0x0d, 0x00, 0xd9, 0xbb},
939 {0x0e, 0x00, 0x53, 0xbb},
940 {0x0f, 0x00, 0x21, 0xbb},
941 {0x10, 0x00, 0xa4, 0xbb},
942 {0x11, 0x00, 0xe5, 0xbb},
943 {0x15, 0x00, 0x00, 0xbb},
944 {0x16, 0x00, 0x00, 0xbb},
945 {0x17, 0x00, 0x00, 0xbb},
946 {0x18, 0x00, 0x00, 0xbb},
947 {0x19, 0x00, 0x00, 0xbb},
948 {0x1a, 0x00, 0x00, 0xbb},
949 {0x1b, 0x00, 0x00, 0xbb},
950 {0x1c, 0x00, 0x00, 0xbb},
951 {0x1d, 0x00, 0x00, 0xbb},
952 {0x1e, 0x00, 0x00, 0xbb},
953 {0xf0, 0x00, 0x01, 0xbb},
954 {0x00, 0x00, 0x20, 0xdd},
955 {0x06, 0xf0, 0x8e, 0xbb},
956 {0x00, 0x00, 0x80, 0xdd},
957 {0x06, 0x70, 0x8e, 0xbb},
958 {0xf0, 0x00, 0x02, 0xbb},
959 {0x00, 0x00, 0x20, 0xdd},
960 {0x5e, 0x6a, 0x53, 0xbb},
961 {0x5f, 0x40, 0x2c, 0xbb},
962 {0xf0, 0x00, 0x01, 0xbb},
963 {0x00, 0x00, 0x20, 0xdd},
964 {0x58, 0x00, 0x00, 0xbb},
965 {0x53, 0x09, 0x03, 0xbb},
966 {0x54, 0x31, 0x18, 0xbb},
967 {0x55, 0x8b, 0x5f, 0xbb},
968 {0x56, 0xc0, 0xa9, 0xbb},
969 {0x57, 0xe0, 0xd2, 0xbb},
970 {0xe1, 0x00, 0x00, 0xbb},
971 {0xdc, 0x09, 0x03, 0xbb},
972 {0xdd, 0x31, 0x18, 0xbb},
973 {0xde, 0x8b, 0x5f, 0xbb},
974 {0xdf, 0xc0, 0xa9, 0xbb},
975 {0xe0, 0xe0, 0xd2, 0xbb},
976 {0xb3, 0x5c, 0x01, 0xcc},
977 {0xf0, 0x00, 0x01, 0xbb},
978 {0x06, 0xf0, 0x8e, 0xbb},
979 {0xf0, 0x00, 0x02, 0xbb},
980 {0x2f, 0xde, 0x20, 0xbb},
981 {0xf0, 0x00, 0x02, 0xbb},
982 {0x24, 0x50, 0x20, 0xbb},
983 {0xbc, 0x0e, 0x00, 0xcc},
984 {0xbc, 0x0f, 0x05, 0xcc},
985 {0xbc, 0x10, 0xc0, 0xcc},
986 {0xf0, 0x00, 0x02, 0xbb},
987 {0x34, 0x0c, 0x50, 0xbb},
988 {0xbc, 0x11, 0x03, 0xcc},
989 {0xf0, 0x00, 0x01, 0xbb},
990 {0x80, 0x00, 0x03, 0xbb},
991 {0x81, 0xc7, 0x14, 0xbb},
992 {0x82, 0xeb, 0xe8, 0xbb},
993 {0x83, 0xfe, 0xf4, 0xbb},
994 {0x84, 0xcd, 0x10, 0xbb},
995 {0x85, 0xf3, 0xee, 0xbb},
996 {0x86, 0xff, 0xf1, 0xbb},
997 {0x87, 0xcd, 0x10, 0xbb},
998 {0x88, 0xf3, 0xee, 0xbb},
999 {0x89, 0x01, 0xf1, 0xbb},
1000 {0x8a, 0xe5, 0x17, 0xbb},
1001 {0x8b, 0xe8, 0xe2, 0xbb},
1002 {0x8c, 0xf7, 0xed, 0xbb},
1003 {0x8d, 0x00, 0xff, 0xbb},
1004 {0x8e, 0xec, 0x10, 0xbb},
1005 {0x8f, 0xf0, 0xed, 0xbb},
1006 {0x90, 0xf9, 0xf2, 0xbb},
1007 {0x91, 0x00, 0x00, 0xbb},
1008 {0x92, 0xe9, 0x0d, 0xbb},
1009 {0x93, 0xf4, 0xf2, 0xbb},
1010 {0x94, 0xfb, 0xf5, 0xbb},
1011 {0x95, 0x00, 0xff, 0xbb},
1012 {0xb6, 0x0f, 0x08, 0xbb},
1013 {0xb7, 0x3d, 0x16, 0xbb},
1014 {0xb8, 0x0c, 0x04, 0xbb},
1015 {0xb9, 0x1c, 0x07, 0xbb},
1016 {0xba, 0x0a, 0x03, 0xbb},
1017 {0xbb, 0x1b, 0x09, 0xbb},
1018 {0xbc, 0x17, 0x0d, 0xbb},
1019 {0xbd, 0x23, 0x1d, 0xbb},
1020 {0xbe, 0x00, 0x28, 0xbb},
1021 {0xbf, 0x11, 0x09, 0xbb},
1022 {0xc0, 0x16, 0x15, 0xbb},
1023 {0xc1, 0x00, 0x1b, 0xbb},
1024 {0xc2, 0x0e, 0x07, 0xbb},
1025 {0xc3, 0x14, 0x10, 0xbb},
1026 {0xc4, 0x00, 0x17, 0xbb},
1027 {0x06, 0x74, 0x8e, 0xbb},
1028 {0xf0, 0x00, 0x00, 0xbb},
1029 {0x03, 0x03, 0xc0, 0xbb},
1030 {}
1031};
1032
1033static const u8 mi1320_gamma[17] = {
1034 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1035 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1036};
1037static const u8 mi1320_matrix[9] = {
1038 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52
1039};
1040static const u8 mi1320_initVGA_data[][4] = {
1041 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
1042 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
1043 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
1044 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
1045 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
1046 {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
1047 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
1048 {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */
1049 {0xb3, 0x02, 0x00, 0xcc},
1050 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
1051 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
1052 {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc},
1053 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1054 {0xb3, 0x16, 0x04, 0xcc}, {0xb3, 0x17, 0xff, 0xcc},
1055 {0xb3, 0x00, 0x67, 0xcc}, {0xbc, 0x00, 0xd0, 0xcc},
1056 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
1057 {0x0d, 0x00, 0x09, 0xbb}, {0x00, 0x01, 0x00, 0xdd},
1058 {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
1059 {0xa1, 0x05, 0x00, 0xbb}, {0xa4, 0x03, 0xc0, 0xbb},
1060 {0xf0, 0x00, 0x02, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
1061 {0xc8, 0x9f, 0x0b, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
1062 {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
1063 {0x20, 0x01, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
1064 {0xf0, 0x00, 0x01, 0xbb}, {0x9d, 0x3c, 0xa0, 0xbb},
1065 {0x47, 0x30, 0x30, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
1066 {0x0a, 0x80, 0x11, 0xbb}, {0x35, 0x00, 0x22, 0xbb},
1067 {0xf0, 0x00, 0x02, 0xbb}, {0x9d, 0xc5, 0x05, 0xbb},
1068 {0xdc, 0x0f, 0xfc, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
1069 {0x06, 0x74, 0x0e, 0xbb}, {0x80, 0x00, 0x06, 0xbb},
1070 {0x81, 0x04, 0x00, 0xbb}, {0x82, 0x01, 0x02, 0xbb},
1071 {0x83, 0x03, 0x02, 0xbb}, {0x84, 0x05, 0x00, 0xbb},
1072 {0x85, 0x01, 0x00, 0xbb}, {0x86, 0x03, 0x02, 0xbb},
1073 {0x87, 0x05, 0x00, 0xbb}, {0x88, 0x01, 0x00, 0xbb},
1074 {0x89, 0x02, 0x02, 0xbb}, {0x8a, 0xfd, 0x04, 0xbb},
1075 {0x8b, 0xfc, 0xfd, 0xbb}, {0x8c, 0xff, 0xfd, 0xbb},
1076 {0x8d, 0x00, 0x00, 0xbb}, {0x8e, 0xfe, 0x05, 0xbb},
1077 {0x8f, 0xfc, 0xfd, 0xbb}, {0x90, 0xfe, 0xfd, 0xbb},
1078 {0x91, 0x00, 0x00, 0xbb}, {0x92, 0xfe, 0x03, 0xbb},
1079 {0x93, 0xfd, 0xfe, 0xbb}, {0x94, 0xff, 0xfd, 0xbb},
1080 {0x95, 0x00, 0x00, 0xbb}, {0xb6, 0x07, 0x05, 0xbb},
1081 {0xb7, 0x13, 0x06, 0xbb}, {0xb8, 0x08, 0x06, 0xbb},
1082 {0xb9, 0x14, 0x08, 0xbb}, {0xba, 0x06, 0x05, 0xbb},
1083 {0xbb, 0x13, 0x06, 0xbb}, {0xbc, 0x03, 0x01, 0xbb},
1084 {0xbd, 0x03, 0x04, 0xbb}, {0xbe, 0x00, 0x02, 0xbb},
1085 {0xbf, 0x03, 0x01, 0xbb}, {0xc0, 0x02, 0x04, 0xbb},
1086 {0xc1, 0x00, 0x04, 0xbb}, {0xc2, 0x02, 0x01, 0xbb},
1087 {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb},
1088 {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb},
1089 {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb},
1090 {0x08, 0x00, 0x27, 0xbb},
1091 {0x20, 0x01, 0x00, 0xbb}, /* h/v flips - was 03 */
1092 {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb},
1093 {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
1094 {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb},
1095 {0x3a, 0x06, 0x1b, 0xbb}, {0x3b, 0x00, 0x95, 0xbb},
1096 {0x3c, 0x04, 0xdb, 0xbb}, {0x57, 0x02, 0x00, 0xbb},
1097 {0x58, 0x02, 0x66, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
1098 {0x5a, 0x01, 0x33, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
1099 {0x5d, 0x16, 0x11, 0xbb}, {0x64, 0x5e, 0x1c, 0xbb},
1100 {0xf0, 0x00, 0x02, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
1101 {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
1102 {0x36, 0x68, 0x10, 0xbb}, {0x00, 0x00, 0x30, 0xdd},
1103 {0x37, 0x82, 0x00, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
1104 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
1105 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
1106 {0xb6, 0x03, 0x05, 0xcc}, {0xb6, 0x02, 0x00, 0xcc},
1107 {0xb6, 0x05, 0x04, 0xcc}, {0xb6, 0x04, 0x00, 0xcc},
1108 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x29, 0xcc},
1109 {0xb6, 0x18, 0x0a, 0xcc}, {0xb6, 0x17, 0x00, 0xcc},
1110 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
1111 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x26, 0xcc},
1112 {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc},
1113 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
1114 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
1115 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
1116 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
1117 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
1118 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
1119 {}
1120};
1121static const u8 mi1320_initQVGA_data[][4] = {
1122 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
1123 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
1124 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
1125 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
1126 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x01, 0xcc},
1127 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
1128 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
1129 {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
1130 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
1131 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
1132 {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
1133 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1134 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1135 {0xb3, 0x00, 0x65, 0xcc}, {0xb8, 0x00, 0x00, 0xcc},
1136 {0xbc, 0x00, 0xd0, 0xcc}, {0xbc, 0x01, 0x01, 0xcc},
1137 {0xf0, 0x00, 0x00, 0xbb}, {0x0d, 0x00, 0x09, 0xbb},
1138 {0x00, 0x01, 0x00, 0xdd}, {0x0d, 0x00, 0x08, 0xbb},
1139 {0xf0, 0x00, 0x00, 0xbb}, {0x02, 0x00, 0x64, 0xbb},
1140 {0x05, 0x01, 0x78, 0xbb}, {0x06, 0x00, 0x11, 0xbb},
1141 {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb},
1142 {0x20, 0x01, 0x00, 0xbb}, {0x21, 0x80, 0x00, 0xbb},
1143 {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb},
1144 {0x59, 0x00, 0xff, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
1145 {0x9d, 0x3c, 0xa0, 0xbb}, {0x47, 0x30, 0x30, 0xbb},
1146 {0xf0, 0x00, 0x00, 0xbb}, {0x0a, 0x80, 0x11, 0xbb},
1147 {0x35, 0x00, 0x22, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
1148 {0x9d, 0xc5, 0x05, 0xbb}, {0xdc, 0x0f, 0xfc, 0xbb},
1149 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0x74, 0x0e, 0xbb},
1150 {0x80, 0x00, 0x06, 0xbb}, {0x81, 0x04, 0x00, 0xbb},
1151 {0x82, 0x01, 0x02, 0xbb}, {0x83, 0x03, 0x02, 0xbb},
1152 {0x84, 0x05, 0x00, 0xbb}, {0x85, 0x01, 0x00, 0xbb},
1153 {0x86, 0x03, 0x02, 0xbb}, {0x87, 0x05, 0x00, 0xbb},
1154 {0x88, 0x01, 0x00, 0xbb}, {0x89, 0x02, 0x02, 0xbb},
1155 {0x8a, 0xfd, 0x04, 0xbb}, {0x8b, 0xfc, 0xfd, 0xbb},
1156 {0x8c, 0xff, 0xfd, 0xbb}, {0x8d, 0x00, 0x00, 0xbb},
1157 {0x8e, 0xfe, 0x05, 0xbb}, {0x8f, 0xfc, 0xfd, 0xbb},
1158 {0x90, 0xfe, 0xfd, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
1159 {0x92, 0xfe, 0x03, 0xbb}, {0x93, 0xfd, 0xfe, 0xbb},
1160 {0x94, 0xff, 0xfd, 0xbb}, {0x95, 0x00, 0x00, 0xbb},
1161 {0xb6, 0x07, 0x05, 0xbb}, {0xb7, 0x13, 0x06, 0xbb},
1162 {0xb8, 0x08, 0x06, 0xbb}, {0xb9, 0x14, 0x08, 0xbb},
1163 {0xba, 0x06, 0x05, 0xbb}, {0xbb, 0x13, 0x06, 0xbb},
1164 {0xbc, 0x03, 0x01, 0xbb}, {0xbd, 0x03, 0x04, 0xbb},
1165 {0xbe, 0x00, 0x02, 0xbb}, {0xbf, 0x03, 0x01, 0xbb},
1166 {0xc0, 0x02, 0x04, 0xbb}, {0xc1, 0x00, 0x04, 0xbb},
1167 {0xc2, 0x02, 0x01, 0xbb}, {0xc3, 0x01, 0x03, 0xbb},
1168 {0xc4, 0x00, 0x04, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
1169 {0xc8, 0x00, 0x00, 0xbb}, {0x2e, 0x00, 0x00, 0xbb},
1170 {0x2e, 0x0c, 0x5b, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
1171 {0x39, 0x03, 0xca, 0xbb}, {0x3a, 0x06, 0x80, 0xbb},
1172 {0x3b, 0x01, 0x52, 0xbb}, {0x3c, 0x05, 0x40, 0xbb},
1173 {0x57, 0x01, 0x9c, 0xbb}, {0x58, 0x01, 0xee, 0xbb},
1174 {0x59, 0x00, 0xf0, 0xbb}, {0x5a, 0x01, 0x20, 0xbb},
1175 {0x5c, 0x1d, 0x17, 0xbb}, {0x5d, 0x22, 0x1c, 0xbb},
1176 {0x64, 0x1e, 0x1c, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
1177 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x68, 0x10, 0xbb},
1178 {0x00, 0x00, 0x30, 0xdd}, {0x37, 0x81, 0x00, 0xbb},
1179 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
1180 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
1181 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
1182 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
1183 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
1184 {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc},
1185 {0xbf, 0xcc, 0x04, 0xcc}, {0xb3, 0x5c, 0x01, 0xcc},
1186 {0xb3, 0x01, 0x41, 0xcc},
1187 {}
1188};
1189
1190static const u8 mi1320_soc_InitVGA[][4] = {
1191 {0xb3, 0x01, 0x01, 0xcc},
1192 {0xb0, 0x03, 0x19, 0xcc},
1193 {0xb0, 0x04, 0x02, 0xcc},
1194 {0x00, 0x00, 0x30, 0xdd},
1195 {0xb3, 0x00, 0x64, 0xcc},
1196 {0xb3, 0x00, 0x67, 0xcc},
1197 {0xb3, 0x05, 0x01, 0xcc},
1198 {0xb3, 0x06, 0x01, 0xcc},
1199 {0xb3, 0x08, 0x01, 0xcc},
1200 {0xb3, 0x09, 0x0c, 0xcc},
1201 {0xb3, 0x34, 0x02, 0xcc},
1202 {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */
1203 {0xb3, 0x02, 0x00, 0xcc},
1204 {0xb3, 0x03, 0x0a, 0xcc},
1205 {0xb3, 0x04, 0x05, 0xcc},
1206 {0xb3, 0x20, 0x00, 0xcc},
1207 {0xb3, 0x21, 0x00, 0xcc},
1208 {0xb3, 0x22, 0x01, 0xcc},
1209 {0xb3, 0x23, 0xe0, 0xcc},
1210 {0xb3, 0x14, 0x00, 0xcc},
1211 {0xb3, 0x15, 0x00, 0xcc},
1212 {0xb3, 0x16, 0x02, 0xcc},
1213 {0xb3, 0x17, 0x7f, 0xcc},
1214 {0xb3, 0x00, 0x67, 0xcc},
1215 {0xb8, 0x00, 0x00, 0xcc},
1216 {0xbc, 0x00, 0x71, 0xcc},
1217 {0xbc, 0x01, 0x01, 0xcc},
1218 {0xb3, 0x5c, 0x01, 0xcc},
1219 {0xf0, 0x00, 0x02, 0xbb},
1220 {0x00, 0x00, 0x10, 0xdd},
1221 {0xc8, 0x00, 0x00, 0xbb},
1222 {0x00, 0x00, 0x30, 0xdd},
1223 {0xf0, 0x00, 0x00, 0xbb},
1224 {0x00, 0x00, 0x10, 0xdd},
1225 {0x07, 0x00, 0xe0, 0xbb},
1226 {0x08, 0x00, 0x0b, 0xbb},
1227 {0x21, 0x00, 0x0c, 0xbb},
1228 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1229 {0xbf, 0xc0, 0x26, 0xcc},
1230 {0xbf, 0xc1, 0x02, 0xcc},
1231 {0xbf, 0xcc, 0x04, 0xcc},
1232 {0xb3, 0x01, 0x41, 0xcc},
1233 {0xf0, 0x00, 0x00, 0xbb},
1234 {0x05, 0x01, 0x78, 0xbb},
1235 {0x06, 0x00, 0x11, 0xbb},
1236 {0x07, 0x01, 0x42, 0xbb},
1237 {0x08, 0x00, 0x11, 0xbb},
1238 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1239 {0x21, 0x80, 0x00, 0xbb},
1240 {0x22, 0x0d, 0x0f, 0xbb},
1241 {0x24, 0x80, 0x00, 0xbb},
1242 {0x59, 0x00, 0xff, 0xbb},
1243 {0xf0, 0x00, 0x02, 0xbb},
1244 {0x39, 0x03, 0xca, 0xbb},
1245 {0x3a, 0x06, 0x80, 0xbb},
1246 {0x3b, 0x01, 0x52, 0xbb},
1247 {0x3c, 0x05, 0x40, 0xbb},
1248 {0x57, 0x01, 0x9c, 0xbb},
1249 {0x58, 0x01, 0xee, 0xbb},
1250 {0x59, 0x00, 0xf0, 0xbb},
1251 {0x5a, 0x01, 0x20, 0xbb},
1252 {0x5c, 0x1d, 0x17, 0xbb},
1253 {0x5d, 0x22, 0x1c, 0xbb},
1254 {0x64, 0x1e, 0x1c, 0xbb},
1255 {0x5b, 0x00, 0x00, 0xbb},
1256 {0xf0, 0x00, 0x02, 0xbb},
1257 {0x22, 0xa0, 0x78, 0xbb},
1258 {0x23, 0xa0, 0x78, 0xbb},
1259 {0x24, 0x7f, 0x00, 0xbb},
1260 {0x28, 0xea, 0x02, 0xbb},
1261 {0x29, 0x86, 0x7a, 0xbb},
1262 {0x5e, 0x52, 0x4c, 0xbb},
1263 {0x5f, 0x20, 0x24, 0xbb},
1264 {0x60, 0x00, 0x02, 0xbb},
1265 {0x02, 0x00, 0xee, 0xbb},
1266 {0x03, 0x39, 0x23, 0xbb},
1267 {0x04, 0x07, 0x24, 0xbb},
1268 {0x09, 0x00, 0xc0, 0xbb},
1269 {0x0a, 0x00, 0x79, 0xbb},
1270 {0x0b, 0x00, 0x04, 0xbb},
1271 {0x0c, 0x00, 0x5c, 0xbb},
1272 {0x0d, 0x00, 0xd9, 0xbb},
1273 {0x0e, 0x00, 0x53, 0xbb},
1274 {0x0f, 0x00, 0x21, 0xbb},
1275 {0x10, 0x00, 0xa4, 0xbb},
1276 {0x11, 0x00, 0xe5, 0xbb},
1277 {0x15, 0x00, 0x00, 0xbb},
1278 {0x16, 0x00, 0x00, 0xbb},
1279 {0x17, 0x00, 0x00, 0xbb},
1280 {0x18, 0x00, 0x00, 0xbb},
1281 {0x19, 0x00, 0x00, 0xbb},
1282 {0x1a, 0x00, 0x00, 0xbb},
1283 {0x1b, 0x00, 0x00, 0xbb},
1284 {0x1c, 0x00, 0x00, 0xbb},
1285 {0x1d, 0x00, 0x00, 0xbb},
1286 {0x1e, 0x00, 0x00, 0xbb},
1287 {0xf0, 0x00, 0x01, 0xbb},
1288 {0x06, 0xe0, 0x0e, 0xbb},
1289 {0x06, 0x60, 0x0e, 0xbb},
1290 {0xb3, 0x5c, 0x01, 0xcc},
1291 {}
1292};
1293static const u8 mi1320_soc_InitQVGA[][4] = {
1294 {0xb3, 0x01, 0x01, 0xcc},
1295 {0xb0, 0x03, 0x19, 0xcc},
1296 {0xb0, 0x04, 0x02, 0xcc},
1297 {0x00, 0x00, 0x30, 0xdd},
1298 {0xb3, 0x00, 0x64, 0xcc},
1299 {0xb3, 0x00, 0x67, 0xcc},
1300 {0xb3, 0x05, 0x01, 0xcc},
1301 {0xb3, 0x06, 0x01, 0xcc},
1302 {0xb3, 0x08, 0x01, 0xcc},
1303 {0xb3, 0x09, 0x0c, 0xcc},
1304 {0xb3, 0x34, 0x02, 0xcc},
1305 {0xb3, 0x35, 0xc8, 0xcc},
1306 {0xb3, 0x02, 0x00, 0xcc},
1307 {0xb3, 0x03, 0x0a, 0xcc},
1308 {0xb3, 0x04, 0x05, 0xcc},
1309 {0xb3, 0x20, 0x00, 0xcc},
1310 {0xb3, 0x21, 0x00, 0xcc},
1311 {0xb3, 0x22, 0x01, 0xcc},
1312 {0xb3, 0x23, 0xe0, 0xcc},
1313 {0xb3, 0x14, 0x00, 0xcc},
1314 {0xb3, 0x15, 0x00, 0xcc},
1315 {0xb3, 0x16, 0x02, 0xcc},
1316 {0xb3, 0x17, 0x7f, 0xcc},
1317 {0xb3, 0x00, 0x67, 0xcc},
1318 {0xb8, 0x00, 0x00, 0xcc},
1319 {0xbc, 0x00, 0xd1, 0xcc},
1320 {0xbc, 0x01, 0x01, 0xcc},
1321 {0xb3, 0x5c, 0x01, 0xcc},
1322 {0xf0, 0x00, 0x02, 0xbb},
1323 {0x00, 0x00, 0x10, 0xdd},
1324 {0xc8, 0x00, 0x00, 0xbb},
1325 {0x00, 0x00, 0x30, 0xdd},
1326 {0xf0, 0x00, 0x00, 0xbb},
1327 {0x00, 0x00, 0x10, 0xdd},
1328 {0x07, 0x00, 0xe0, 0xbb},
1329 {0x08, 0x00, 0x0b, 0xbb},
1330 {0x21, 0x00, 0x0c, 0xbb},
1331 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1332 {0xbf, 0xc0, 0x26, 0xcc},
1333 {0xbf, 0xc1, 0x02, 0xcc},
1334 {0xbf, 0xcc, 0x04, 0xcc},
1335 {0xbc, 0x02, 0x18, 0xcc},
1336 {0xbc, 0x03, 0x50, 0xcc},
1337 {0xbc, 0x04, 0x18, 0xcc},
1338 {0xbc, 0x05, 0x00, 0xcc},
1339 {0xbc, 0x06, 0x00, 0xcc},
1340 {0xbc, 0x08, 0x30, 0xcc},
1341 {0xbc, 0x09, 0x40, 0xcc},
1342 {0xbc, 0x0a, 0x10, 0xcc},
1343 {0xbc, 0x0b, 0x00, 0xcc},
1344 {0xbc, 0x0c, 0x00, 0xcc},
1345 {0xb3, 0x01, 0x41, 0xcc},
1346 {0xf0, 0x00, 0x00, 0xbb},
1347 {0x05, 0x01, 0x78, 0xbb},
1348 {0x06, 0x00, 0x11, 0xbb},
1349 {0x07, 0x01, 0x42, 0xbb},
1350 {0x08, 0x00, 0x11, 0xbb},
1351 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1352 {0x21, 0x80, 0x00, 0xbb},
1353 {0x22, 0x0d, 0x0f, 0xbb},
1354 {0x24, 0x80, 0x00, 0xbb},
1355 {0x59, 0x00, 0xff, 0xbb},
1356 {0xf0, 0x00, 0x02, 0xbb},
1357 {0x39, 0x03, 0xca, 0xbb},
1358 {0x3a, 0x06, 0x80, 0xbb},
1359 {0x3b, 0x01, 0x52, 0xbb},
1360 {0x3c, 0x05, 0x40, 0xbb},
1361 {0x57, 0x01, 0x9c, 0xbb},
1362 {0x58, 0x01, 0xee, 0xbb},
1363 {0x59, 0x00, 0xf0, 0xbb},
1364 {0x5a, 0x01, 0x20, 0xbb},
1365 {0x5c, 0x1d, 0x17, 0xbb},
1366 {0x5d, 0x22, 0x1c, 0xbb},
1367 {0x64, 0x1e, 0x1c, 0xbb},
1368 {0x5b, 0x00, 0x00, 0xbb},
1369 {0xf0, 0x00, 0x02, 0xbb},
1370 {0x22, 0xa0, 0x78, 0xbb},
1371 {0x23, 0xa0, 0x78, 0xbb},
1372 {0x24, 0x7f, 0x00, 0xbb},
1373 {0x28, 0xea, 0x02, 0xbb},
1374 {0x29, 0x86, 0x7a, 0xbb},
1375 {0x5e, 0x52, 0x4c, 0xbb},
1376 {0x5f, 0x20, 0x24, 0xbb},
1377 {0x60, 0x00, 0x02, 0xbb},
1378 {0x02, 0x00, 0xee, 0xbb},
1379 {0x03, 0x39, 0x23, 0xbb},
1380 {0x04, 0x07, 0x24, 0xbb},
1381 {0x09, 0x00, 0xc0, 0xbb},
1382 {0x0a, 0x00, 0x79, 0xbb},
1383 {0x0b, 0x00, 0x04, 0xbb},
1384 {0x0c, 0x00, 0x5c, 0xbb},
1385 {0x0d, 0x00, 0xd9, 0xbb},
1386 {0x0e, 0x00, 0x53, 0xbb},
1387 {0x0f, 0x00, 0x21, 0xbb},
1388 {0x10, 0x00, 0xa4, 0xbb},
1389 {0x11, 0x00, 0xe5, 0xbb},
1390 {0x15, 0x00, 0x00, 0xbb},
1391 {0x16, 0x00, 0x00, 0xbb},
1392 {0x17, 0x00, 0x00, 0xbb},
1393 {0x18, 0x00, 0x00, 0xbb},
1394 {0x19, 0x00, 0x00, 0xbb},
1395 {0x1a, 0x00, 0x00, 0xbb},
1396 {0x1b, 0x00, 0x00, 0xbb},
1397 {0x1c, 0x00, 0x00, 0xbb},
1398 {0x1d, 0x00, 0x00, 0xbb},
1399 {0x1e, 0x00, 0x00, 0xbb},
1400 {0xf0, 0x00, 0x01, 0xbb},
1401 {0x06, 0xe0, 0x0e, 0xbb},
1402 {0x06, 0x60, 0x0e, 0xbb},
1403 {0xb3, 0x5c, 0x01, 0xcc},
1404 {}
1405};
1406static const u8 mi1320_soc_InitSXGA[][4] = {
1407 {0xb3, 0x01, 0x01, 0xcc},
1408 {0xb0, 0x03, 0x19, 0xcc},
1409 {0x00, 0x00, 0x30, 0xdd},
1410 {0xb3, 0x00, 0x64, 0xcc},
1411 {0xb3, 0x00, 0x67, 0xcc},
1412 {0xb3, 0x05, 0x01, 0xcc},
1413 {0xb3, 0x06, 0x01, 0xcc},
1414 {0xb3, 0x08, 0x01, 0xcc},
1415 {0xb3, 0x09, 0x0c, 0xcc},
1416 {0xb3, 0x34, 0x02, 0xcc},
1417 {0xb3, 0x35, 0xc8, 0xcc},
1418 {0xb3, 0x02, 0x00, 0xcc},
1419 {0xb3, 0x03, 0x0a, 0xcc},
1420 {0xb3, 0x04, 0x05, 0xcc},
1421 {0xb3, 0x20, 0x00, 0xcc},
1422 {0xb3, 0x21, 0x00, 0xcc},
1423 {0xb3, 0x22, 0x04, 0xcc},
1424 {0xb3, 0x23, 0x00, 0xcc},
1425 {0xb3, 0x14, 0x00, 0xcc},
1426 {0xb3, 0x15, 0x00, 0xcc},
1427 {0xb3, 0x16, 0x04, 0xcc},
1428 {0xb3, 0x17, 0xff, 0xcc},
1429 {0xb3, 0x00, 0x67, 0xcc},
1430 {0xbc, 0x00, 0x71, 0xcc},
1431 {0xbc, 0x01, 0x01, 0xcc},
1432 {0xb3, 0x5c, 0x01, 0xcc},
1433 {0xf0, 0x00, 0x02, 0xbb},
1434 {0x00, 0x00, 0x30, 0xdd},
1435 {0xc8, 0x9f, 0x0b, 0xbb},
1436 {0x00, 0x00, 0x20, 0xdd},
1437 {0x5b, 0x00, 0x01, 0xbb},
1438 {0x00, 0x00, 0x20, 0xdd},
1439 {0xf0, 0x00, 0x00, 0xbb},
1440 {0x00, 0x00, 0x30, 0xdd},
1441 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1442 {0x00, 0x00, 0x20, 0xdd},
1443 {0xbf, 0xc0, 0x26, 0xcc},
1444 {0xbf, 0xc1, 0x02, 0xcc},
1445 {0xbf, 0xcc, 0x04, 0xcc},
1446 {0xb3, 0x01, 0x41, 0xcc},
1447 {0xf0, 0x00, 0x00, 0xbb},
1448 {0x05, 0x01, 0x78, 0xbb},
1449 {0x06, 0x00, 0x11, 0xbb},
1450 {0x07, 0x01, 0x42, 0xbb},
1451 {0x08, 0x00, 0x11, 0xbb},
1452 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1453 {0x21, 0x80, 0x00, 0xbb},
1454 {0x22, 0x0d, 0x0f, 0xbb},
1455 {0x24, 0x80, 0x00, 0xbb},
1456 {0x59, 0x00, 0xff, 0xbb},
1457 {0xf0, 0x00, 0x02, 0xbb},
1458 {0x39, 0x03, 0xca, 0xbb},
1459 {0x3a, 0x06, 0x80, 0xbb},
1460 {0x3b, 0x01, 0x52, 0xbb},
1461 {0x3c, 0x05, 0x40, 0xbb},
1462 {0x57, 0x01, 0x9c, 0xbb},
1463 {0x58, 0x01, 0xee, 0xbb},
1464 {0x59, 0x00, 0xf0, 0xbb},
1465 {0x5a, 0x01, 0x20, 0xbb},
1466 {0x5c, 0x1d, 0x17, 0xbb},
1467 {0x5d, 0x22, 0x1c, 0xbb},
1468 {0x64, 0x1e, 0x1c, 0xbb},
1469 {0x5b, 0x00, 0x00, 0xbb},
1470 {0xf0, 0x00, 0x02, 0xbb},
1471 {0x22, 0xa0, 0x78, 0xbb},
1472 {0x23, 0xa0, 0x78, 0xbb},
1473 {0x24, 0x7f, 0x00, 0xbb},
1474 {0x28, 0xea, 0x02, 0xbb},
1475 {0x29, 0x86, 0x7a, 0xbb},
1476 {0x5e, 0x52, 0x4c, 0xbb},
1477 {0x5f, 0x20, 0x24, 0xbb},
1478 {0x60, 0x00, 0x02, 0xbb},
1479 {0x02, 0x00, 0xee, 0xbb},
1480 {0x03, 0x39, 0x23, 0xbb},
1481 {0x04, 0x07, 0x24, 0xbb},
1482 {0x09, 0x00, 0xc0, 0xbb},
1483 {0x0a, 0x00, 0x79, 0xbb},
1484 {0x0b, 0x00, 0x04, 0xbb},
1485 {0x0c, 0x00, 0x5c, 0xbb},
1486 {0x0d, 0x00, 0xd9, 0xbb},
1487 {0x0e, 0x00, 0x53, 0xbb},
1488 {0x0f, 0x00, 0x21, 0xbb},
1489 {0x10, 0x00, 0xa4, 0xbb},
1490 {0x11, 0x00, 0xe5, 0xbb},
1491 {0x15, 0x00, 0x00, 0xbb},
1492 {0x16, 0x00, 0x00, 0xbb},
1493 {0x17, 0x00, 0x00, 0xbb},
1494 {0x18, 0x00, 0x00, 0xbb},
1495 {0x19, 0x00, 0x00, 0xbb},
1496 {0x1a, 0x00, 0x00, 0xbb},
1497 {0x1b, 0x00, 0x00, 0xbb},
1498 {0x1c, 0x00, 0x00, 0xbb},
1499 {0x1d, 0x00, 0x00, 0xbb},
1500 {0x1e, 0x00, 0x00, 0xbb},
1501 {0xf0, 0x00, 0x01, 0xbb},
1502 {0x06, 0xe0, 0x0e, 0xbb},
1503 {0x06, 0x60, 0x0e, 0xbb},
1504 {0xb3, 0x5c, 0x01, 0xcc},
1505 {0xf0, 0x00, 0x00, 0xbb},
1506 {0x05, 0x01, 0x13, 0xbb},
1507 {0x06, 0x00, 0x11, 0xbb},
1508 {0x07, 0x00, 0x85, 0xbb},
1509 {0x08, 0x00, 0x27, 0xbb},
1510 {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */
1511 {0x21, 0x80, 0x00, 0xbb},
1512 {0x22, 0x0d, 0x0f, 0xbb},
1513 {0x24, 0x80, 0x00, 0xbb},
1514 {0x59, 0x00, 0xff, 0xbb},
1515 {0xf0, 0x00, 0x02, 0xbb},
1516 {0x39, 0x03, 0x0d, 0xbb},
1517 {0x3a, 0x06, 0x1b, 0xbb},
1518 {0x3b, 0x00, 0x95, 0xbb},
1519 {0x3c, 0x04, 0xdb, 0xbb},
1520 {0x57, 0x02, 0x00, 0xbb},
1521 {0x58, 0x02, 0x66, 0xbb},
1522 {0x59, 0x00, 0xff, 0xbb},
1523 {0x5a, 0x01, 0x33, 0xbb},
1524 {0x5c, 0x12, 0x0d, 0xbb},
1525 {0x5d, 0x16, 0x11, 0xbb},
1526 {0x64, 0x5e, 0x1c, 0xbb},
1527 {}
1528};
1529static const u8 po3130_gamma[17] = {
1530 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1531 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1532};
1533static const u8 po3130_matrix[9] = {
1534 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
1535};
1536
1537static const u8 po3130_initVGA_data[][4] = {
1538 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1539 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
1540 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
1541 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
1542 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
1543 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
1544 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
1545 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
1546 {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc},
1547 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1548 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1549 {0xb3, 0x34, 0x01, 0xcc},
1550 {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */
1551 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc},
1552 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
1553 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1554 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
1555 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
1556 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
1557 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
1558 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
1559 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
1560 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
1561 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
1562 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
1563 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
1564 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
1565 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
1566 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
1567 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
1568 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
1569 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
1570 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
1571 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
1572 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
1573 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
1574 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
1575 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
1576 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
1577 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
1578 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
1579 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
1580 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
1581 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
1582 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
1583 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
1584 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
1585 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1586 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1587 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1588 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1589 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1590 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1591 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
1592 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
1593 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
1594 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
1595 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
1596 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
1597 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
1598 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1599 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1600 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1601 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1602 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1603 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1604 {0x00, 0x7e, 0xea, 0xaa},
1605 {0x00, 0x4c, 0x07, 0xaa},
1606 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
1607 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
1608/* {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
1609 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, */
1610 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
1611 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
1612 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
1613 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
1614 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
1615 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
1616 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
1617 {0xb9, 0x08, 0x3c, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
1618 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
1619 {}
1620};
1621static const u8 po3130_rundata[][4] = {
1622 {0x00, 0x47, 0x45, 0xaa}, {0x00, 0x48, 0x9b, 0xaa},
1623 {0x00, 0x49, 0x3a, 0xaa}, {0x00, 0x4a, 0x01, 0xaa},
1624 {0x00, 0x44, 0x40, 0xaa},
1625/* {0x00, 0xd5, 0x7c, 0xaa}, */
1626 {0x00, 0xad, 0x04, 0xaa}, {0x00, 0xae, 0x00, 0xaa},
1627 {0x00, 0xb0, 0x78, 0xaa}, {0x00, 0x98, 0x02, 0xaa},
1628 {0x00, 0x94, 0x25, 0xaa}, {0x00, 0x95, 0x25, 0xaa},
1629 {0x00, 0x59, 0x68, 0xaa}, {0x00, 0x44, 0x20, 0xaa},
1630 {0x00, 0x17, 0x50, 0xaa}, {0x00, 0x19, 0x50, 0xaa},
1631 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0xd1, 0x3c, 0xaa},
1632 {0x00, 0x1e, 0x06, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
1633 {}
1634};
1635
1636static const u8 po3130_initQVGA_data[][4] = {
1637 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1638 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x09, 0xcc},
1639 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
1640 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
1641 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
1642 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
1643 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
1644 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
1645 {0xb3, 0x23, 0xe0, 0xcc}, {0xb8, 0x08, 0xe0, 0xcc},
1646 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1647 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1648 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
1649 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
1650 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
1651 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1652 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
1653 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
1654 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
1655 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
1656 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
1657 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
1658 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
1659 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
1660 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
1661 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
1662 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
1663 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
1664 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
1665 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
1666 {0x00, 0x59, 0x6f, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
1667 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
1668 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
1669 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
1670 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
1671 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
1672 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
1673 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
1674 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
1675 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
1676 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
1677 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
1678 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
1679 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
1680 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
1681 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
1682 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
1683 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1684 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1685 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1686 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1687 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1688 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1689 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
1690 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
1691 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
1692 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
1693 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
1694 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
1695 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
1696 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
1697 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
1698 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
1699 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
1700 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
1701 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
1702 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0x4c, 0x07, 0xaa},
1703 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
1704 {0x00, 0x59, 0x66, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
1705 {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
1706 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
1707 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
1708 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
1709 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
1710 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
1711 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
1712 {0xb9, 0x08, 0x3c, 0xcc}, {0xbc, 0x02, 0x18, 0xcc},
1713 {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc},
1714 {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
1715 {0xbc, 0x08, 0x30, 0xcc}, {0xbc, 0x09, 0x40, 0xcc},
1716 {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc},
1717 {0xbc, 0x0c, 0x00, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
1718 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
1719 {}
1720};
1721
1722static const u8 hv7131r_gamma[17] = {
1723 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1724 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1725};
1726static const u8 hv7131r_matrix[9] = {
1727 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
1728};
1729static const u8 hv7131r_initVGA_data[][4] = {
1730 {0xb3, 0x01, 0x01, 0xcc},
1731 {0xb0, 0x03, 0x19, 0xcc},
1732 {0xb0, 0x04, 0x02, 0xcc},
1733 {0x00, 0x00, 0x20, 0xdd},
1734 {0xb3, 0x00, 0x24, 0xcc},
1735 {0xb3, 0x00, 0x25, 0xcc},
1736 {0xb3, 0x08, 0x01, 0xcc},
1737 {0xb3, 0x09, 0x0c, 0xcc},
1738 {0xb3, 0x05, 0x01, 0xcc},
1739 {0xb3, 0x06, 0x03, 0xcc},
1740 {0xb3, 0x01, 0x45, 0xcc},
1741 {0xb3, 0x03, 0x0b, 0xcc},
1742 {0xb3, 0x04, 0x05, 0xcc},
1743 {0xb3, 0x20, 0x00, 0xcc},
1744 {0xb3, 0x21, 0x00, 0xcc},
1745 {0xb3, 0x22, 0x01, 0xcc},
1746 {0xb3, 0x23, 0xe0, 0xcc},
1747 {0xb3, 0x14, 0x00, 0xcc},
1748 {0xb3, 0x15, 0x02, 0xcc},
1749 {0xb3, 0x16, 0x02, 0xcc},
1750 {0xb3, 0x17, 0x7f, 0xcc},
1751 {0xb3, 0x34, 0x01, 0xcc},
1752 {0xb3, 0x35, 0x91, 0xcc}, /* i2c add: 11 */
1753 {0xb3, 0x00, 0x27, 0xcc},
1754 {0xbc, 0x00, 0x73, 0xcc},
1755 {0xb8, 0x00, 0x23, 0xcc},
1756 {0xb8, 0x2c, 0x50, 0xcc},
1757 {0xb8, 0x2d, 0xf8, 0xcc},
1758 {0xb8, 0x2e, 0xf8, 0xcc},
1759 {0xb8, 0x2f, 0xf8, 0xcc},
1760 {0xb8, 0x30, 0x50, 0xcc},
1761 {0xb8, 0x31, 0xf8, 0xcc},
1762 {0xb8, 0x32, 0xf8, 0xcc},
1763 {0xb8, 0x33, 0xf8, 0xcc},
1764 {0xb8, 0x34, 0x58, 0xcc},
1765 {0xb8, 0x35, 0x00, 0xcc},
1766 {0xb8, 0x36, 0x00, 0xcc},
1767 {0xb8, 0x37, 0x00, 0xcc},
1768 {0xb8, 0x27, 0x20, 0xcc},
1769 {0xb8, 0x01, 0x7d, 0xcc},
1770 {0xb8, 0x81, 0x09, 0xcc},
1771 {0xb3, 0x01, 0x41, 0xcc},
1772 {0xb8, 0x8e, 0x00, 0xcc},
1773 {0xb8, 0x8f, 0xff, 0xcc},
1774 {0x00, 0x01, 0x0c, 0xaa},
1775 {0x00, 0x14, 0x01, 0xaa},
1776 {0x00, 0x15, 0xe6, 0xaa},
1777 {0x00, 0x16, 0x02, 0xaa},
1778 {0x00, 0x17, 0x86, 0xaa},
1779 {0x00, 0x23, 0x00, 0xaa},
1780 {0x00, 0x25, 0x03, 0xaa},
1781 {0x00, 0x26, 0xa9, 0xaa},
1782 {0x00, 0x27, 0x80, 0xaa},
1783 {0x00, 0x30, 0x18, 0xaa},
1784 {0xb6, 0x00, 0x00, 0xcc},
1785 {0xb6, 0x03, 0x02, 0xcc},
1786 {0xb6, 0x02, 0x80, 0xcc},
1787 {0xb6, 0x05, 0x01, 0xcc},
1788 {0xb6, 0x04, 0xe0, 0xcc},
1789 {0xb6, 0x12, 0x78, 0xcc},
1790 {0xb6, 0x18, 0x02, 0xcc},
1791 {0xb6, 0x17, 0x58, 0xcc},
1792 {0xb6, 0x16, 0x00, 0xcc},
1793 {0xb6, 0x22, 0x12, 0xcc},
1794 {0xb6, 0x23, 0x0b, 0xcc},
1795 {0xb3, 0x02, 0x02, 0xcc},
1796 {0xbf, 0xc0, 0x39, 0xcc},
1797 {0xbf, 0xc1, 0x04, 0xcc},
1798 {0xbf, 0xcc, 0x10, 0xcc},
1799 {0xb6, 0x12, 0xf8, 0xcc},
1800 {0xb6, 0x13, 0x13, 0xcc},
1801 {0xb9, 0x12, 0x00, 0xcc},
1802 {0xb9, 0x13, 0x0a, 0xcc},
1803 {0xb9, 0x14, 0x0a, 0xcc},
1804 {0xb9, 0x15, 0x0a, 0xcc},
1805 {0xb9, 0x16, 0x0a, 0xcc},
1806 {0xb8, 0x0c, 0x20, 0xcc},
1807 {0xb8, 0x0d, 0x70, 0xcc},
1808 {0xb9, 0x18, 0x00, 0xcc},
1809 {0xb9, 0x19, 0x0f, 0xcc},
1810 {0xb9, 0x1a, 0x0f, 0xcc},
1811 {0xb9, 0x1b, 0x0f, 0xcc},
1812 {0xb9, 0x1c, 0x0f, 0xcc},
1813 {0xb3, 0x5c, 0x01, 0xcc},
1814 {}
1815};
1816
1817static const u8 hv7131r_initQVGA_data[][4] = {
1818 {0xb3, 0x01, 0x01, 0xcc},
1819 {0xb0, 0x03, 0x19, 0xcc},
1820 {0xb0, 0x04, 0x02, 0xcc},
1821 {0x00, 0x00, 0x20, 0xdd},
1822 {0xb3, 0x00, 0x24, 0xcc},
1823 {0xb3, 0x00, 0x25, 0xcc},
1824 {0xb3, 0x08, 0x01, 0xcc},
1825 {0xb3, 0x09, 0x0c, 0xcc},
1826 {0xb3, 0x05, 0x01, 0xcc},
1827 {0xb3, 0x06, 0x03, 0xcc},
1828 {0xb3, 0x01, 0x45, 0xcc},
1829 {0xb3, 0x03, 0x0b, 0xcc},
1830 {0xb3, 0x04, 0x05, 0xcc},
1831 {0xb3, 0x20, 0x00, 0xcc},
1832 {0xb3, 0x21, 0x00, 0xcc},
1833 {0xb3, 0x22, 0x01, 0xcc},
1834 {0xb3, 0x23, 0xe0, 0xcc},
1835 {0xb3, 0x14, 0x00, 0xcc},
1836 {0xb3, 0x15, 0x02, 0xcc},
1837 {0xb3, 0x16, 0x02, 0xcc},
1838 {0xb3, 0x17, 0x7f, 0xcc},
1839 {0xb3, 0x34, 0x01, 0xcc},
1840 {0xb3, 0x35, 0x91, 0xcc},
1841 {0xb3, 0x00, 0x27, 0xcc},
1842 {0xbc, 0x00, 0xd3, 0xcc},
1843 {0xb8, 0x00, 0x23, 0xcc},
1844 {0xb8, 0x2c, 0x50, 0xcc},
1845 {0xb8, 0x2d, 0xf8, 0xcc},
1846 {0xb8, 0x2e, 0xf8, 0xcc},
1847 {0xb8, 0x2f, 0xf8, 0xcc},
1848 {0xb8, 0x30, 0x50, 0xcc},
1849 {0xb8, 0x31, 0xf8, 0xcc},
1850 {0xb8, 0x32, 0xf8, 0xcc},
1851 {0xb8, 0x33, 0xf8, 0xcc},
1852 {0xb8, 0x34, 0x58, 0xcc},
1853 {0xb8, 0x35, 0x00, 0xcc},
1854 {0xb8, 0x36, 0x00, 0xcc},
1855 {0xb8, 0x37, 0x00, 0xcc},
1856 {0xb8, 0x27, 0x20, 0xcc},
1857 {0xb8, 0x01, 0x7d, 0xcc},
1858 {0xb8, 0x81, 0x09, 0xcc},
1859 {0xb3, 0x01, 0x41, 0xcc},
1860 {0xb8, 0x8e, 0x00, 0xcc},
1861 {0xb8, 0x8f, 0xff, 0xcc},
1862 {0x00, 0x01, 0x0c, 0xaa},
1863 {0x00, 0x14, 0x01, 0xaa},
1864 {0x00, 0x15, 0xe6, 0xaa},
1865 {0x00, 0x16, 0x02, 0xaa},
1866 {0x00, 0x17, 0x86, 0xaa},
1867 {0x00, 0x23, 0x00, 0xaa},
1868 {0x00, 0x25, 0x03, 0xaa},
1869 {0x00, 0x26, 0xa9, 0xaa},
1870 {0x00, 0x27, 0x80, 0xaa},
1871 {0x00, 0x30, 0x18, 0xaa},
1872 {0xb6, 0x00, 0x00, 0xcc},
1873 {0xb6, 0x03, 0x01, 0xcc},
1874 {0xb6, 0x02, 0x40, 0xcc},
1875 {0xb6, 0x05, 0x00, 0xcc},
1876 {0xb6, 0x04, 0xf0, 0xcc},
1877 {0xb6, 0x12, 0x78, 0xcc},
1878 {0xb6, 0x18, 0x00, 0xcc},
1879 {0xb6, 0x17, 0x96, 0xcc},
1880 {0xb6, 0x16, 0x00, 0xcc},
1881 {0xb6, 0x22, 0x12, 0xcc},
1882 {0xb6, 0x23, 0x0b, 0xcc},
1883 {0xb3, 0x02, 0x02, 0xcc},
1884 {0xbf, 0xc0, 0x39, 0xcc},
1885 {0xbf, 0xc1, 0x04, 0xcc},
1886 {0xbf, 0xcc, 0x10, 0xcc},
1887 {0xbc, 0x02, 0x18, 0xcc},
1888 {0xbc, 0x03, 0x50, 0xcc},
1889 {0xbc, 0x04, 0x18, 0xcc},
1890 {0xbc, 0x05, 0x00, 0xcc},
1891 {0xbc, 0x06, 0x00, 0xcc},
1892 {0xbc, 0x08, 0x30, 0xcc},
1893 {0xbc, 0x09, 0x40, 0xcc},
1894 {0xbc, 0x0a, 0x10, 0xcc},
1895 {0xbc, 0x0b, 0x00, 0xcc},
1896 {0xbc, 0x0c, 0x00, 0xcc},
1897 {0xb9, 0x12, 0x00, 0xcc},
1898 {0xb9, 0x13, 0x0a, 0xcc},
1899 {0xb9, 0x14, 0x0a, 0xcc},
1900 {0xb9, 0x15, 0x0a, 0xcc},
1901 {0xb9, 0x16, 0x0a, 0xcc},
1902 {0xb9, 0x18, 0x00, 0xcc},
1903 {0xb9, 0x19, 0x0f, 0xcc},
1904 {0xb8, 0x0c, 0x20, 0xcc},
1905 {0xb8, 0x0d, 0x70, 0xcc},
1906 {0xb9, 0x1a, 0x0f, 0xcc},
1907 {0xb9, 0x1b, 0x0f, 0xcc},
1908 {0xb9, 0x1c, 0x0f, 0xcc},
1909 {0xb6, 0x12, 0xf8, 0xcc},
1910 {0xb6, 0x13, 0x13, 0xcc},
1911 {0xb3, 0x5c, 0x01, 0xcc},
1912 {}
1913};
1914
1915static const u8 ov7660_gamma[17] = {
1916 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
1917 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
1918};
1919static const u8 ov7660_matrix[9] = {
1920 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62
1921};
1922static const u8 ov7660_initVGA_data[][4] = {
1923 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1924 {0x00, 0x00, 0x50, 0xdd},
1925 {0xb0, 0x03, 0x01, 0xcc},
1926 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
1927 {0xb3, 0x05, 0x01, 0xcc},
1928 {0xb3, 0x06, 0x03, 0xcc},
1929 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
1930 {0xb3, 0x05, 0x00, 0xcc},
1931 {0xb3, 0x06, 0x01, 0xcc},
1932 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
1933 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1934 {0xb3, 0x21, 0x00, 0xcc},
1935 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
1936 {0xb3, 0x1f, 0x02, 0xcc},
1937 {0xb3, 0x34, 0x01, 0xcc},
1938 {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
1939 {0xb3, 0x00, 0x26, 0xcc},
1940 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
1941 {0xb8, 0x01, 0x7d, 0xcc},
1942 {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1943 {0xb8, 0x27, 0x20, 0xcc},
1944 {0xb8, 0x8f, 0x50, 0xcc},
1945 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
1946 {0x00, 0x12, 0x80, 0xaa},
1947 {0x00, 0x12, 0x05, 0xaa},
1948 {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */
1949 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
1950 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
1951 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
1952 {0x00, 0x13, 0xa7, 0xaa},
1953 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
1954 {0x00, 0x36, 0x00, 0xaa},
1955 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
1956 {0x00, 0x39, 0x43, 0xaa},
1957 {0x00, 0x8d, 0xcf, 0xaa},
1958 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
1959 {0x00, 0x0f, 0x62, 0xaa},
1960 {0x00, 0x35, 0x84, 0xaa},
1961 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
1962 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
1963 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
1964 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
1965 {0x00, 0x01, 0x80, 0xaa},
1966 {0x00, 0x02, 0x80, 0xaa},
1967 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
1968 {0xb9, 0x00, 0x28, 0xcc},
1969 {0xb9, 0x01, 0x28, 0xcc}, {0xb9, 0x02, 0x28, 0xcc},
1970 {0xb9, 0x03, 0x00, 0xcc},
1971 {0xb9, 0x04, 0x00, 0xcc},
1972 {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
1973 {0xb9, 0x07, 0x3c, 0xcc},
1974 {0xb9, 0x08, 0x3c, 0xcc},
1975
1976 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
1977
1978 {0x00, 0x29, 0x3c, 0xaa}, {0xb3, 0x01, 0x45, 0xcc},
1979 {}
1980};
1981static const u8 ov7660_initQVGA_data[][4] = {
1982 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
1983 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
1984 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
1985 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x03, 0xcc},
1986 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
1987 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
1988 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
1989 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1990 {0xb3, 0x21, 0x00, 0xcc},
1991 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
1992 {0xb3, 0x1f, 0x02, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
1993 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
1994 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
1995 {0xb8, 0x01, 0x7d, 0xcc},
1996/* sizer */
1997 {0xbc, 0x00, 0xd3, 0xcc},
1998 {0xb8, 0x81, 0x09, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
1999 {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x8f, 0x50, 0xcc},
2000 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
2001 {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa},
2002 {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */
2003 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
2004 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
2005 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
2006 {0x00, 0x13, 0xa7, 0xaa},
2007 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
2008 {0x00, 0x36, 0x00, 0xaa},
2009 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
2010 {0x00, 0x39, 0x43, 0xaa}, {0x00, 0x8d, 0xcf, 0xaa},
2011 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
2012 {0x00, 0x0f, 0x62, 0xaa}, {0x00, 0x35, 0x84, 0xaa},
2013 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
2014 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
2015 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
2016 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
2017 {0x00, 0x01, 0x80, 0xaa},
2018 {0x00, 0x02, 0x80, 0xaa},
2019/* sizer filters */
2020 {0xbc, 0x02, 0x08, 0xcc},
2021 {0xbc, 0x03, 0x70, 0xcc},
2022 {0xb8, 0x35, 0x00, 0xcc},
2023 {0xb8, 0x36, 0x00, 0xcc},
2024 {0xb8, 0x37, 0x00, 0xcc},
2025 {0xbc, 0x04, 0x08, 0xcc},
2026 {0xbc, 0x05, 0x00, 0xcc},
2027 {0xbc, 0x06, 0x00, 0xcc},
2028 {0xbc, 0x08, 0x3c, 0xcc},
2029 {0xbc, 0x09, 0x40, 0xcc},
2030 {0xbc, 0x0a, 0x04, 0xcc},
2031 {0xbc, 0x0b, 0x00, 0xcc},
2032 {0xbc, 0x0c, 0x00, 0xcc},
2033/* */
2034 {0xb8, 0xfe, 0x00, 0xcc},
2035 {0xb8, 0xff, 0x28, 0xcc},
2036/* */
2037 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
2038 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
2039 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
2040 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
2041 {0xb9, 0x08, 0x3c, 0xcc},
2042/* */
2043 {0xb8, 0x8e, 0x00, 0xcc},
2044 {0xb8, 0x8f, 0xff, 0xcc}, /* ff */
2045 {0x00, 0x29, 0x3c, 0xaa},
2046 {0xb3, 0x01, 0x45, 0xcc}, /* 45 */
2047 {}
2048};
2049
2050static const u8 ov7660_50HZ[][4] = {
2051 {0x00, 0x3b, 0x08, 0xaa},
2052 {0x00, 0x9d, 0x40, 0xaa},
2053 {0x00, 0x13, 0xa7, 0xaa},
2054 {}
2055};
2056
2057static const u8 ov7660_60HZ[][4] = {
2058 {0x00, 0x3b, 0x00, 0xaa},
2059 {0x00, 0x9e, 0x40, 0xaa},
2060 {0x00, 0x13, 0xa7, 0xaa},
2061 {}
2062};
2063
2064static const u8 ov7660_NoFliker[][4] = {
2065 {0x00, 0x13, 0x87, 0xaa},
2066 {}
2067};
2068
2069static const u8 ov7670_InitVGA[][4] = {
2070 {0xb3, 0x01, 0x05, 0xcc},
2071 {0x00, 0x00, 0x30, 0xdd},
2072 {0xb0, 0x03, 0x19, 0xcc},
2073 {0x00, 0x00, 0x10, 0xdd},
2074 {0xb0, 0x04, 0x02, 0xcc},
2075 {0x00, 0x00, 0x10, 0xdd},
2076 {0xb3, 0x00, 0x66, 0xcc},
2077 {0xb3, 0x00, 0x67, 0xcc},
2078 {0xb0, 0x16, 0x01, 0xcc},
2079 {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
2080 {0xb3, 0x34, 0x01, 0xcc},
2081 {0xb3, 0x05, 0x01, 0xcc},
2082 {0xb3, 0x06, 0x01, 0xcc},
2083 {0xb3, 0x08, 0x01, 0xcc},
2084 {0xb3, 0x09, 0x0c, 0xcc},
2085 {0xb3, 0x02, 0x02, 0xcc},
2086 {0xb3, 0x03, 0x1f, 0xcc},
2087 {0xb3, 0x14, 0x00, 0xcc},
2088 {0xb3, 0x15, 0x00, 0xcc},
2089 {0xb3, 0x16, 0x02, 0xcc},
2090 {0xb3, 0x17, 0x7f, 0xcc},
2091 {0xb3, 0x04, 0x05, 0xcc},
2092 {0xb3, 0x20, 0x00, 0xcc},
2093 {0xb3, 0x21, 0x00, 0xcc},
2094 {0xb3, 0x22, 0x01, 0xcc},
2095 {0xb3, 0x23, 0xe0, 0xcc},
2096 {0xbc, 0x00, 0x41, 0xcc},
2097 {0xbc, 0x01, 0x01, 0xcc},
2098 {0x00, 0x12, 0x80, 0xaa},
2099 {0x00, 0x00, 0x20, 0xdd},
2100 {0x00, 0x12, 0x00, 0xaa},
2101 {0x00, 0x11, 0x40, 0xaa},
2102 {0x00, 0x6b, 0x0a, 0xaa},
2103 {0x00, 0x3a, 0x04, 0xaa},
2104 {0x00, 0x40, 0xc0, 0xaa},
2105 {0x00, 0x8c, 0x00, 0xaa},
2106 {0x00, 0x7a, 0x29, 0xaa},
2107 {0x00, 0x7b, 0x0e, 0xaa},
2108 {0x00, 0x7c, 0x1a, 0xaa},
2109 {0x00, 0x7d, 0x31, 0xaa},
2110 {0x00, 0x7e, 0x53, 0xaa},
2111 {0x00, 0x7f, 0x60, 0xaa},
2112 {0x00, 0x80, 0x6b, 0xaa},
2113 {0x00, 0x81, 0x73, 0xaa},
2114 {0x00, 0x82, 0x7b, 0xaa},
2115 {0x00, 0x83, 0x82, 0xaa},
2116 {0x00, 0x84, 0x89, 0xaa},
2117 {0x00, 0x85, 0x96, 0xaa},
2118 {0x00, 0x86, 0xa1, 0xaa},
2119 {0x00, 0x87, 0xb7, 0xaa},
2120 {0x00, 0x88, 0xcc, 0xaa},
2121 {0x00, 0x89, 0xe1, 0xaa},
2122 {0x00, 0x13, 0xe0, 0xaa},
2123 {0x00, 0x00, 0x00, 0xaa},
2124 {0x00, 0x10, 0x00, 0xaa},
2125 {0x00, 0x0d, 0x40, 0xaa},
2126 {0x00, 0x14, 0x28, 0xaa},
2127 {0x00, 0xa5, 0x05, 0xaa},
2128 {0x00, 0xab, 0x07, 0xaa},
2129 {0x00, 0x24, 0x95, 0xaa},
2130 {0x00, 0x25, 0x33, 0xaa},
2131 {0x00, 0x26, 0xe3, 0xaa},
2132 {0x00, 0x9f, 0x88, 0xaa},
2133 {0x00, 0xa0, 0x78, 0xaa},
2134 {0x00, 0x55, 0x90, 0xaa},
2135 {0x00, 0xa1, 0x03, 0xaa},
2136 {0x00, 0xa6, 0xe0, 0xaa},
2137 {0x00, 0xa7, 0xd8, 0xaa},
2138 {0x00, 0xa8, 0xf0, 0xaa},
2139 {0x00, 0xa9, 0x90, 0xaa},
2140 {0x00, 0xaa, 0x14, 0xaa},
2141 {0x00, 0x13, 0xe5, 0xaa},
2142 {0x00, 0x0e, 0x61, 0xaa},
2143 {0x00, 0x0f, 0x4b, 0xaa},
2144 {0x00, 0x16, 0x02, 0xaa},
2145 {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */
2146 {0x00, 0x21, 0x02, 0xaa},
2147 {0x00, 0x22, 0x91, 0xaa},
2148 {0x00, 0x29, 0x07, 0xaa},
2149 {0x00, 0x33, 0x0b, 0xaa},
2150 {0x00, 0x35, 0x0b, 0xaa},
2151 {0x00, 0x37, 0x1d, 0xaa},
2152 {0x00, 0x38, 0x71, 0xaa},
2153 {0x00, 0x39, 0x2a, 0xaa},
2154 {0x00, 0x3c, 0x78, 0xaa},
2155 {0x00, 0x4d, 0x40, 0xaa},
2156 {0x00, 0x4e, 0x20, 0xaa},
2157 {0x00, 0x74, 0x19, 0xaa},
2158 {0x00, 0x8d, 0x4f, 0xaa},
2159 {0x00, 0x8e, 0x00, 0xaa},
2160 {0x00, 0x8f, 0x00, 0xaa},
2161 {0x00, 0x90, 0x00, 0xaa},
2162 {0x00, 0x91, 0x00, 0xaa},
2163 {0x00, 0x96, 0x00, 0xaa},
2164 {0x00, 0x9a, 0x80, 0xaa},
2165 {0x00, 0xb0, 0x84, 0xaa},
2166 {0x00, 0xb1, 0x0c, 0xaa},
2167 {0x00, 0xb2, 0x0e, 0xaa},
2168 {0x00, 0xb3, 0x82, 0xaa},
2169 {0x00, 0xb8, 0x0a, 0xaa},
2170 {0x00, 0x43, 0x14, 0xaa},
2171 {0x00, 0x44, 0xf0, 0xaa},
2172 {0x00, 0x45, 0x45, 0xaa},
2173 {0x00, 0x46, 0x63, 0xaa},
2174 {0x00, 0x47, 0x2d, 0xaa},
2175 {0x00, 0x48, 0x46, 0xaa},
2176 {0x00, 0x59, 0x88, 0xaa},
2177 {0x00, 0x5a, 0xa0, 0xaa},
2178 {0x00, 0x5b, 0xc6, 0xaa},
2179 {0x00, 0x5c, 0x7d, 0xaa},
2180 {0x00, 0x5d, 0x5f, 0xaa},
2181 {0x00, 0x5e, 0x19, 0xaa},
2182 {0x00, 0x6c, 0x0a, 0xaa},
2183 {0x00, 0x6d, 0x55, 0xaa},
2184 {0x00, 0x6e, 0x11, 0xaa},
2185 {0x00, 0x6f, 0x9e, 0xaa},
2186 {0x00, 0x69, 0x00, 0xaa},
2187 {0x00, 0x6a, 0x40, 0xaa},
2188 {0x00, 0x01, 0x40, 0xaa},
2189 {0x00, 0x02, 0x40, 0xaa},
2190 {0x00, 0x13, 0xe7, 0xaa},
2191 {0x00, 0x5f, 0xf0, 0xaa},
2192 {0x00, 0x60, 0xf0, 0xaa},
2193 {0x00, 0x61, 0xf0, 0xaa},
2194 {0x00, 0x27, 0xa0, 0xaa},
2195 {0x00, 0x28, 0x80, 0xaa},
2196 {0x00, 0x2c, 0x90, 0xaa},
2197 {0x00, 0x4f, 0x66, 0xaa},
2198 {0x00, 0x50, 0x66, 0xaa},
2199 {0x00, 0x51, 0x00, 0xaa},
2200 {0x00, 0x52, 0x22, 0xaa},
2201 {0x00, 0x53, 0x5e, 0xaa},
2202 {0x00, 0x54, 0x80, 0xaa},
2203 {0x00, 0x58, 0x9e, 0xaa},
2204 {0x00, 0x41, 0x08, 0xaa},
2205 {0x00, 0x3f, 0x00, 0xaa},
2206 {0x00, 0x75, 0x85, 0xaa},
2207 {0x00, 0x76, 0xe1, 0xaa},
2208 {0x00, 0x4c, 0x00, 0xaa},
2209 {0x00, 0x77, 0x0a, 0xaa},
2210 {0x00, 0x3d, 0x88, 0xaa},
2211 {0x00, 0x4b, 0x09, 0xaa},
2212 {0x00, 0xc9, 0x60, 0xaa},
2213 {0x00, 0x41, 0x38, 0xaa},
2214 {0x00, 0x62, 0x30, 0xaa},
2215 {0x00, 0x63, 0x30, 0xaa},
2216 {0x00, 0x64, 0x08, 0xaa},
2217 {0x00, 0x94, 0x07, 0xaa},
2218 {0x00, 0x95, 0x0b, 0xaa},
2219 {0x00, 0x65, 0x00, 0xaa},
2220 {0x00, 0x66, 0x05, 0xaa},
2221 {0x00, 0x56, 0x50, 0xaa},
2222 {0x00, 0x34, 0x11, 0xaa},
2223 {0x00, 0xa4, 0x88, 0xaa},
2224 {0x00, 0x96, 0x00, 0xaa},
2225 {0x00, 0x97, 0x30, 0xaa},
2226 {0x00, 0x98, 0x20, 0xaa},
2227 {0x00, 0x99, 0x30, 0xaa},
2228 {0x00, 0x9a, 0x84, 0xaa},
2229 {0x00, 0x9b, 0x29, 0xaa},
2230 {0x00, 0x9c, 0x03, 0xaa},
2231 {0x00, 0x78, 0x04, 0xaa},
2232 {0x00, 0x79, 0x01, 0xaa},
2233 {0x00, 0xc8, 0xf0, 0xaa},
2234 {0x00, 0x79, 0x0f, 0xaa},
2235 {0x00, 0xc8, 0x00, 0xaa},
2236 {0x00, 0x79, 0x10, 0xaa},
2237 {0x00, 0xc8, 0x7e, 0xaa},
2238 {0x00, 0x79, 0x0a, 0xaa},
2239 {0x00, 0xc8, 0x80, 0xaa},
2240 {0x00, 0x79, 0x0b, 0xaa},
2241 {0x00, 0xc8, 0x01, 0xaa},
2242 {0x00, 0x79, 0x0c, 0xaa},
2243 {0x00, 0xc8, 0x0f, 0xaa},
2244 {0x00, 0x79, 0x0d, 0xaa},
2245 {0x00, 0xc8, 0x20, 0xaa},
2246 {0x00, 0x79, 0x09, 0xaa},
2247 {0x00, 0xc8, 0x80, 0xaa},
2248 {0x00, 0x79, 0x02, 0xaa},
2249 {0x00, 0xc8, 0xc0, 0xaa},
2250 {0x00, 0x79, 0x03, 0xaa},
2251 {0x00, 0xc8, 0x40, 0xaa},
2252 {0x00, 0x79, 0x05, 0xaa},
2253 {0x00, 0xc8, 0x30, 0xaa},
2254 {0x00, 0x79, 0x26, 0xaa},
2255 {0x00, 0x11, 0x40, 0xaa},
2256 {0x00, 0x3a, 0x04, 0xaa},
2257 {0x00, 0x12, 0x00, 0xaa},
2258 {0x00, 0x40, 0xc0, 0xaa},
2259 {0x00, 0x8c, 0x00, 0xaa},
2260 {0x00, 0x17, 0x14, 0xaa},
2261 {0x00, 0x18, 0x02, 0xaa},
2262 {0x00, 0x32, 0x92, 0xaa},
2263 {0x00, 0x19, 0x02, 0xaa},
2264 {0x00, 0x1a, 0x7a, 0xaa},
2265 {0x00, 0x03, 0x0a, 0xaa},
2266 {0x00, 0x0c, 0x00, 0xaa},
2267 {0x00, 0x3e, 0x00, 0xaa},
2268 {0x00, 0x70, 0x3a, 0xaa},
2269 {0x00, 0x71, 0x35, 0xaa},
2270 {0x00, 0x72, 0x11, 0xaa},
2271 {0x00, 0x73, 0xf0, 0xaa},
2272 {0x00, 0xa2, 0x02, 0xaa},
2273 {0x00, 0xb1, 0x00, 0xaa},
2274 {0x00, 0xb1, 0x0c, 0xaa},
2275 {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */
2276 {0x00, 0xaa, 0x14, 0xaa},
2277 {0x00, 0x24, 0x80, 0xaa},
2278 {0x00, 0x25, 0x74, 0xaa},
2279 {0x00, 0x26, 0xd3, 0xaa},
2280 {0x00, 0x0d, 0x00, 0xaa},
2281 {0x00, 0x14, 0x18, 0xaa},
2282 {0x00, 0x9d, 0x99, 0xaa},
2283 {0x00, 0x9e, 0x7f, 0xaa},
2284 {0x00, 0x64, 0x08, 0xaa},
2285 {0x00, 0x94, 0x07, 0xaa},
2286 {0x00, 0x95, 0x06, 0xaa},
2287 {0x00, 0x66, 0x05, 0xaa},
2288 {0x00, 0x41, 0x08, 0xaa},
2289 {0x00, 0x3f, 0x00, 0xaa},
2290 {0x00, 0x75, 0x07, 0xaa},
2291 {0x00, 0x76, 0xe1, 0xaa},
2292 {0x00, 0x4c, 0x00, 0xaa},
2293 {0x00, 0x77, 0x00, 0xaa},
2294 {0x00, 0x3d, 0xc2, 0xaa},
2295 {0x00, 0x4b, 0x09, 0xaa},
2296 {0x00, 0xc9, 0x60, 0xaa},
2297 {0x00, 0x41, 0x38, 0xaa},
2298 {0xbf, 0xc0, 0x26, 0xcc},
2299 {0xbf, 0xc1, 0x02, 0xcc},
2300 {0xbf, 0xcc, 0x04, 0xcc},
2301 {0xb3, 0x5c, 0x01, 0xcc},
2302 {0xb3, 0x01, 0x45, 0xcc},
2303 {0x00, 0x77, 0x05, 0xaa},
2304 {},
2305};
2306
2307static const u8 ov7670_InitQVGA[][4] = {
2308 {0xb3, 0x01, 0x05, 0xcc},
2309 {0x00, 0x00, 0x30, 0xdd},
2310 {0xb0, 0x03, 0x19, 0xcc},
2311 {0x00, 0x00, 0x10, 0xdd},
2312 {0xb0, 0x04, 0x02, 0xcc},
2313 {0x00, 0x00, 0x10, 0xdd},
2314 {0xb3, 0x00, 0x66, 0xcc},
2315 {0xb3, 0x00, 0x67, 0xcc},
2316 {0xb0, 0x16, 0x01, 0xcc},
2317 {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */
2318 {0xb3, 0x34, 0x01, 0xcc},
2319 {0xb3, 0x05, 0x01, 0xcc},
2320 {0xb3, 0x06, 0x01, 0xcc},
2321 {0xb3, 0x08, 0x01, 0xcc},
2322 {0xb3, 0x09, 0x0c, 0xcc},
2323 {0xb3, 0x02, 0x02, 0xcc},
2324 {0xb3, 0x03, 0x1f, 0xcc},
2325 {0xb3, 0x14, 0x00, 0xcc},
2326 {0xb3, 0x15, 0x00, 0xcc},
2327 {0xb3, 0x16, 0x02, 0xcc},
2328 {0xb3, 0x17, 0x7f, 0xcc},
2329 {0xb3, 0x04, 0x05, 0xcc},
2330 {0xb3, 0x20, 0x00, 0xcc},
2331 {0xb3, 0x21, 0x00, 0xcc},
2332 {0xb3, 0x22, 0x01, 0xcc},
2333 {0xb3, 0x23, 0xe0, 0xcc},
2334 {0xbc, 0x00, 0xd1, 0xcc},
2335 {0xbc, 0x01, 0x01, 0xcc},
2336 {0x00, 0x12, 0x80, 0xaa},
2337 {0x00, 0x00, 0x20, 0xdd},
2338 {0x00, 0x12, 0x00, 0xaa},
2339 {0x00, 0x11, 0x40, 0xaa},
2340 {0x00, 0x6b, 0x0a, 0xaa},
2341 {0x00, 0x3a, 0x04, 0xaa},
2342 {0x00, 0x40, 0xc0, 0xaa},
2343 {0x00, 0x8c, 0x00, 0xaa},
2344 {0x00, 0x7a, 0x29, 0xaa},
2345 {0x00, 0x7b, 0x0e, 0xaa},
2346 {0x00, 0x7c, 0x1a, 0xaa},
2347 {0x00, 0x7d, 0x31, 0xaa},
2348 {0x00, 0x7e, 0x53, 0xaa},
2349 {0x00, 0x7f, 0x60, 0xaa},
2350 {0x00, 0x80, 0x6b, 0xaa},
2351 {0x00, 0x81, 0x73, 0xaa},
2352 {0x00, 0x82, 0x7b, 0xaa},
2353 {0x00, 0x83, 0x82, 0xaa},
2354 {0x00, 0x84, 0x89, 0xaa},
2355 {0x00, 0x85, 0x96, 0xaa},
2356 {0x00, 0x86, 0xa1, 0xaa},
2357 {0x00, 0x87, 0xb7, 0xaa},
2358 {0x00, 0x88, 0xcc, 0xaa},
2359 {0x00, 0x89, 0xe1, 0xaa},
2360 {0x00, 0x13, 0xe0, 0xaa},
2361 {0x00, 0x00, 0x00, 0xaa},
2362 {0x00, 0x10, 0x00, 0xaa},
2363 {0x00, 0x0d, 0x40, 0xaa},
2364 {0x00, 0x14, 0x28, 0xaa},
2365 {0x00, 0xa5, 0x05, 0xaa},
2366 {0x00, 0xab, 0x07, 0xaa},
2367 {0x00, 0x24, 0x95, 0xaa},
2368 {0x00, 0x25, 0x33, 0xaa},
2369 {0x00, 0x26, 0xe3, 0xaa},
2370 {0x00, 0x9f, 0x88, 0xaa},
2371 {0x00, 0xa0, 0x78, 0xaa},
2372 {0x00, 0x55, 0x90, 0xaa},
2373 {0x00, 0xa1, 0x03, 0xaa},
2374 {0x00, 0xa6, 0xe0, 0xaa},
2375 {0x00, 0xa7, 0xd8, 0xaa},
2376 {0x00, 0xa8, 0xf0, 0xaa},
2377 {0x00, 0xa9, 0x90, 0xaa},
2378 {0x00, 0xaa, 0x14, 0xaa},
2379 {0x00, 0x13, 0xe5, 0xaa},
2380 {0x00, 0x0e, 0x61, 0xaa},
2381 {0x00, 0x0f, 0x4b, 0xaa},
2382 {0x00, 0x16, 0x02, 0xaa},
2383 {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */
2384 {0x00, 0x21, 0x02, 0xaa},
2385 {0x00, 0x22, 0x91, 0xaa},
2386 {0x00, 0x29, 0x07, 0xaa},
2387 {0x00, 0x33, 0x0b, 0xaa},
2388 {0x00, 0x35, 0x0b, 0xaa},
2389 {0x00, 0x37, 0x1d, 0xaa},
2390 {0x00, 0x38, 0x71, 0xaa},
2391 {0x00, 0x39, 0x2a, 0xaa},
2392 {0x00, 0x3c, 0x78, 0xaa},
2393 {0x00, 0x4d, 0x40, 0xaa},
2394 {0x00, 0x4e, 0x20, 0xaa},
2395 {0x00, 0x74, 0x19, 0xaa},
2396 {0x00, 0x8d, 0x4f, 0xaa},
2397 {0x00, 0x8e, 0x00, 0xaa},
2398 {0x00, 0x8f, 0x00, 0xaa},
2399 {0x00, 0x90, 0x00, 0xaa},
2400 {0x00, 0x91, 0x00, 0xaa},
2401 {0x00, 0x96, 0x00, 0xaa},
2402 {0x00, 0x9a, 0x80, 0xaa},
2403 {0x00, 0xb0, 0x84, 0xaa},
2404 {0x00, 0xb1, 0x0c, 0xaa},
2405 {0x00, 0xb2, 0x0e, 0xaa},
2406 {0x00, 0xb3, 0x82, 0xaa},
2407 {0x00, 0xb8, 0x0a, 0xaa},
2408 {0x00, 0x43, 0x14, 0xaa},
2409 {0x00, 0x44, 0xf0, 0xaa},
2410 {0x00, 0x45, 0x45, 0xaa},
2411 {0x00, 0x46, 0x63, 0xaa},
2412 {0x00, 0x47, 0x2d, 0xaa},
2413 {0x00, 0x48, 0x46, 0xaa},
2414 {0x00, 0x59, 0x88, 0xaa},
2415 {0x00, 0x5a, 0xa0, 0xaa},
2416 {0x00, 0x5b, 0xc6, 0xaa},
2417 {0x00, 0x5c, 0x7d, 0xaa},
2418 {0x00, 0x5d, 0x5f, 0xaa},
2419 {0x00, 0x5e, 0x19, 0xaa},
2420 {0x00, 0x6c, 0x0a, 0xaa},
2421 {0x00, 0x6d, 0x55, 0xaa},
2422 {0x00, 0x6e, 0x11, 0xaa},
2423 {0x00, 0x6f, 0x9e, 0xaa},
2424 {0x00, 0x69, 0x00, 0xaa},
2425 {0x00, 0x6a, 0x40, 0xaa},
2426 {0x00, 0x01, 0x40, 0xaa},
2427 {0x00, 0x02, 0x40, 0xaa},
2428 {0x00, 0x13, 0xe7, 0xaa},
2429 {0x00, 0x5f, 0xf0, 0xaa},
2430 {0x00, 0x60, 0xf0, 0xaa},
2431 {0x00, 0x61, 0xf0, 0xaa},
2432 {0x00, 0x27, 0xa0, 0xaa},
2433 {0x00, 0x28, 0x80, 0xaa},
2434 {0x00, 0x2c, 0x90, 0xaa},
2435 {0x00, 0x4f, 0x66, 0xaa},
2436 {0x00, 0x50, 0x66, 0xaa},
2437 {0x00, 0x51, 0x00, 0xaa},
2438 {0x00, 0x52, 0x22, 0xaa},
2439 {0x00, 0x53, 0x5e, 0xaa},
2440 {0x00, 0x54, 0x80, 0xaa},
2441 {0x00, 0x58, 0x9e, 0xaa},
2442 {0x00, 0x41, 0x08, 0xaa},
2443 {0x00, 0x3f, 0x00, 0xaa},
2444 {0x00, 0x75, 0x85, 0xaa},
2445 {0x00, 0x76, 0xe1, 0xaa},
2446 {0x00, 0x4c, 0x00, 0xaa},
2447 {0x00, 0x77, 0x0a, 0xaa},
2448 {0x00, 0x3d, 0x88, 0xaa},
2449 {0x00, 0x4b, 0x09, 0xaa},
2450 {0x00, 0xc9, 0x60, 0xaa},
2451 {0x00, 0x41, 0x38, 0xaa},
2452 {0x00, 0x62, 0x30, 0xaa},
2453 {0x00, 0x63, 0x30, 0xaa},
2454 {0x00, 0x64, 0x08, 0xaa},
2455 {0x00, 0x94, 0x07, 0xaa},
2456 {0x00, 0x95, 0x0b, 0xaa},
2457 {0x00, 0x65, 0x00, 0xaa},
2458 {0x00, 0x66, 0x05, 0xaa},
2459 {0x00, 0x56, 0x50, 0xaa},
2460 {0x00, 0x34, 0x11, 0xaa},
2461 {0x00, 0xa4, 0x88, 0xaa},
2462 {0x00, 0x96, 0x00, 0xaa},
2463 {0x00, 0x97, 0x30, 0xaa},
2464 {0x00, 0x98, 0x20, 0xaa},
2465 {0x00, 0x99, 0x30, 0xaa},
2466 {0x00, 0x9a, 0x84, 0xaa},
2467 {0x00, 0x9b, 0x29, 0xaa},
2468 {0x00, 0x9c, 0x03, 0xaa},
2469 {0x00, 0x78, 0x04, 0xaa},
2470 {0x00, 0x79, 0x01, 0xaa},
2471 {0x00, 0xc8, 0xf0, 0xaa},
2472 {0x00, 0x79, 0x0f, 0xaa},
2473 {0x00, 0xc8, 0x00, 0xaa},
2474 {0x00, 0x79, 0x10, 0xaa},
2475 {0x00, 0xc8, 0x7e, 0xaa},
2476 {0x00, 0x79, 0x0a, 0xaa},
2477 {0x00, 0xc8, 0x80, 0xaa},
2478 {0x00, 0x79, 0x0b, 0xaa},
2479 {0x00, 0xc8, 0x01, 0xaa},
2480 {0x00, 0x79, 0x0c, 0xaa},
2481 {0x00, 0xc8, 0x0f, 0xaa},
2482 {0x00, 0x79, 0x0d, 0xaa},
2483 {0x00, 0xc8, 0x20, 0xaa},
2484 {0x00, 0x79, 0x09, 0xaa},
2485 {0x00, 0xc8, 0x80, 0xaa},
2486 {0x00, 0x79, 0x02, 0xaa},
2487 {0x00, 0xc8, 0xc0, 0xaa},
2488 {0x00, 0x79, 0x03, 0xaa},
2489 {0x00, 0xc8, 0x40, 0xaa},
2490 {0x00, 0x79, 0x05, 0xaa},
2491 {0x00, 0xc8, 0x30, 0xaa},
2492 {0x00, 0x79, 0x26, 0xaa},
2493 {0x00, 0x11, 0x40, 0xaa},
2494 {0x00, 0x3a, 0x04, 0xaa},
2495 {0x00, 0x12, 0x00, 0xaa},
2496 {0x00, 0x40, 0xc0, 0xaa},
2497 {0x00, 0x8c, 0x00, 0xaa},
2498 {0x00, 0x17, 0x14, 0xaa},
2499 {0x00, 0x18, 0x02, 0xaa},
2500 {0x00, 0x32, 0x92, 0xaa},
2501 {0x00, 0x19, 0x02, 0xaa},
2502 {0x00, 0x1a, 0x7a, 0xaa},
2503 {0x00, 0x03, 0x0a, 0xaa},
2504 {0x00, 0x0c, 0x00, 0xaa},
2505 {0x00, 0x3e, 0x00, 0xaa},
2506 {0x00, 0x70, 0x3a, 0xaa},
2507 {0x00, 0x71, 0x35, 0xaa},
2508 {0x00, 0x72, 0x11, 0xaa},
2509 {0x00, 0x73, 0xf0, 0xaa},
2510 {0x00, 0xa2, 0x02, 0xaa},
2511 {0x00, 0xb1, 0x00, 0xaa},
2512 {0x00, 0xb1, 0x0c, 0xaa},
2513 {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */
2514 {0x00, 0xaa, 0x14, 0xaa},
2515 {0x00, 0x24, 0x80, 0xaa},
2516 {0x00, 0x25, 0x74, 0xaa},
2517 {0x00, 0x26, 0xd3, 0xaa},
2518 {0x00, 0x0d, 0x00, 0xaa},
2519 {0x00, 0x14, 0x18, 0xaa},
2520 {0x00, 0x9d, 0x99, 0xaa},
2521 {0x00, 0x9e, 0x7f, 0xaa},
2522 {0x00, 0x64, 0x08, 0xaa},
2523 {0x00, 0x94, 0x07, 0xaa},
2524 {0x00, 0x95, 0x06, 0xaa},
2525 {0x00, 0x66, 0x05, 0xaa},
2526 {0x00, 0x41, 0x08, 0xaa},
2527 {0x00, 0x3f, 0x00, 0xaa},
2528 {0x00, 0x75, 0x07, 0xaa},
2529 {0x00, 0x76, 0xe1, 0xaa},
2530 {0x00, 0x4c, 0x00, 0xaa},
2531 {0x00, 0x77, 0x00, 0xaa},
2532 {0x00, 0x3d, 0xc2, 0xaa},
2533 {0x00, 0x4b, 0x09, 0xaa},
2534 {0x00, 0xc9, 0x60, 0xaa},
2535 {0x00, 0x41, 0x38, 0xaa},
2536 {0xbc, 0x02, 0x18, 0xcc},
2537 {0xbc, 0x03, 0x50, 0xcc},
2538 {0xbc, 0x04, 0x18, 0xcc},
2539 {0xbc, 0x05, 0x00, 0xcc},
2540 {0xbc, 0x06, 0x00, 0xcc},
2541 {0xbc, 0x08, 0x30, 0xcc},
2542 {0xbc, 0x09, 0x40, 0xcc},
2543 {0xbc, 0x0a, 0x10, 0xcc},
2544 {0xbc, 0x0b, 0x00, 0xcc},
2545 {0xbc, 0x0c, 0x00, 0xcc},
2546 {0xbf, 0xc0, 0x26, 0xcc},
2547 {0xbf, 0xc1, 0x02, 0xcc},
2548 {0xbf, 0xcc, 0x04, 0xcc},
2549 {0xb3, 0x5c, 0x01, 0xcc},
2550 {0xb3, 0x01, 0x45, 0xcc},
2551 {0x00, 0x77, 0x05, 0xaa},
2552 {},
2553};
2554
2555/* PO1200 - values from usbvm326.inf and ms-win trace */
2556static const u8 po1200_gamma[17] = {
2557 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
2558 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
2559};
2560static const u8 po1200_matrix[9] = {
2561 0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e
2562};
2563static const u8 po1200_initVGA_data[][4] = {
2564 {0xb0, 0x03, 0x19, 0xcc}, /* reset? */
2565 {0xb0, 0x03, 0x19, 0xcc},
2566/* {0x00, 0x00, 0x33, 0xdd}, */
2567 {0xb0, 0x04, 0x02, 0xcc},
2568 {0xb0, 0x02, 0x02, 0xcc},
2569 {0xb3, 0x5d, 0x00, 0xcc},
2570 {0xb3, 0x01, 0x01, 0xcc},
2571 {0xb3, 0x00, 0x64, 0xcc},
2572 {0xb3, 0x00, 0x65, 0xcc},
2573 {0xb3, 0x05, 0x01, 0xcc},
2574 {0xb3, 0x06, 0x01, 0xcc},
2575 {0xb3, 0x5c, 0x01, 0xcc},
2576 {0xb3, 0x08, 0x01, 0xcc},
2577 {0xb3, 0x09, 0x0c, 0xcc},
2578 {0xb3, 0x00, 0x67, 0xcc},
2579 {0xb3, 0x02, 0xb2, 0xcc},
2580 {0xb3, 0x03, 0x18, 0xcc},
2581 {0xb3, 0x04, 0x15, 0xcc},
2582 {0xb3, 0x20, 0x00, 0xcc},
2583 {0xb3, 0x21, 0x00, 0xcc},
2584 {0xb3, 0x22, 0x02, 0xcc},
2585 {0xb3, 0x23, 0x58, 0xcc},
2586 {0xb3, 0x14, 0x00, 0xcc},
2587 {0xb3, 0x15, 0x00, 0xcc},
2588 {0xb3, 0x16, 0x03, 0xcc},
2589 {0xb3, 0x17, 0x1f, 0xcc},
2590 {0xbc, 0x00, 0x71, 0xcc},
2591 {0xbc, 0x01, 0x01, 0xcc},
2592 {0xb0, 0x54, 0x13, 0xcc},
2593 {0xb3, 0x00, 0x67, 0xcc},
2594 {0xb3, 0x34, 0x01, 0xcc},
2595 {0xb3, 0x35, 0xdc, 0xcc}, /* i2c add: 5c */
2596 {0x00, 0x03, 0x00, 0xaa},
2597 {0x00, 0x12, 0x05, 0xaa},
2598 {0x00, 0x13, 0x02, 0xaa},
2599 {0x00, 0x1e, 0xc6, 0xaa}, /* h/v flip */
2600 {0x00, 0x21, 0x00, 0xaa},
2601 {0x00, 0x25, 0x02, 0xaa},
2602 {0x00, 0x3c, 0x4f, 0xaa},
2603 {0x00, 0x3f, 0xe0, 0xaa},
2604 {0x00, 0x42, 0xff, 0xaa},
2605 {0x00, 0x45, 0x34, 0xaa},
2606 {0x00, 0x55, 0xfe, 0xaa},
2607 {0x00, 0x59, 0xd3, 0xaa},
2608 {0x00, 0x5e, 0x04, 0xaa},
2609 {0x00, 0x61, 0xb8, 0xaa}, /* sharpness */
2610 {0x00, 0x62, 0x02, 0xaa},
2611 {0x00, 0xa7, 0x31, 0xaa},
2612 {0x00, 0xa9, 0x66, 0xaa},
2613 {0x00, 0xb0, 0x00, 0xaa},
2614 {0x00, 0xb1, 0x00, 0xaa},
2615 {0x00, 0xb3, 0x11, 0xaa},
2616 {0x00, 0xb6, 0x26, 0xaa},
2617 {0x00, 0xb7, 0x20, 0xaa},
2618 {0x00, 0xba, 0x04, 0xaa},
2619 {0x00, 0x88, 0x42, 0xaa},
2620 {0x00, 0x89, 0x9a, 0xaa},
2621 {0x00, 0x8a, 0x88, 0xaa},
2622 {0x00, 0x8b, 0x8e, 0xaa},
2623 {0x00, 0x8c, 0x3e, 0xaa},
2624 {0x00, 0x8d, 0x90, 0xaa},
2625 {0x00, 0x8e, 0x87, 0xaa},
2626 {0x00, 0x8f, 0x96, 0xaa},
2627 {0x00, 0x90, 0x3d, 0xaa},
2628 {0x00, 0x64, 0x00, 0xaa},
2629 {0x00, 0x65, 0x10, 0xaa},
2630 {0x00, 0x66, 0x20, 0xaa},
2631 {0x00, 0x67, 0x2b, 0xaa},
2632 {0x00, 0x68, 0x36, 0xaa},
2633 {0x00, 0x69, 0x49, 0xaa},
2634 {0x00, 0x6a, 0x5a, 0xaa},
2635 {0x00, 0x6b, 0x7f, 0xaa},
2636 {0x00, 0x6c, 0x9b, 0xaa},
2637 {0x00, 0x6d, 0xba, 0xaa},
2638 {0x00, 0x6e, 0xd4, 0xaa},
2639 {0x00, 0x6f, 0xea, 0xaa},
2640 {0x00, 0x70, 0x00, 0xaa},
2641 {0x00, 0x71, 0x10, 0xaa},
2642 {0x00, 0x72, 0x20, 0xaa},
2643 {0x00, 0x73, 0x2b, 0xaa},
2644 {0x00, 0x74, 0x36, 0xaa},
2645 {0x00, 0x75, 0x49, 0xaa},
2646 {0x00, 0x76, 0x5a, 0xaa},
2647 {0x00, 0x77, 0x7f, 0xaa},
2648 {0x00, 0x78, 0x9b, 0xaa},
2649 {0x00, 0x79, 0xba, 0xaa},
2650 {0x00, 0x7a, 0xd4, 0xaa},
2651 {0x00, 0x7b, 0xea, 0xaa},
2652 {0x00, 0x7c, 0x00, 0xaa},
2653 {0x00, 0x7d, 0x10, 0xaa},
2654 {0x00, 0x7e, 0x20, 0xaa},
2655 {0x00, 0x7f, 0x2b, 0xaa},
2656 {0x00, 0x80, 0x36, 0xaa},
2657 {0x00, 0x81, 0x49, 0xaa},
2658 {0x00, 0x82, 0x5a, 0xaa},
2659 {0x00, 0x83, 0x7f, 0xaa},
2660 {0x00, 0x84, 0x9b, 0xaa},
2661 {0x00, 0x85, 0xba, 0xaa},
2662 {0x00, 0x86, 0xd4, 0xaa},
2663 {0x00, 0x87, 0xea, 0xaa},
2664 {0x00, 0x57, 0x2a, 0xaa},
2665 {0x00, 0x03, 0x01, 0xaa},
2666 {0x00, 0x04, 0x10, 0xaa},
2667 {0x00, 0x05, 0x10, 0xaa},
2668 {0x00, 0x06, 0x10, 0xaa},
2669 {0x00, 0x07, 0x10, 0xaa},
2670 {0x00, 0x08, 0x13, 0xaa},
2671 {0x00, 0x0a, 0x00, 0xaa},
2672 {0x00, 0x0b, 0x10, 0xaa},
2673 {0x00, 0x0c, 0x20, 0xaa},
2674 {0x00, 0x0d, 0x18, 0xaa},
2675 {0x00, 0x22, 0x01, 0xaa},
2676 {0x00, 0x23, 0x60, 0xaa},
2677 {0x00, 0x25, 0x08, 0xaa},
2678 {0x00, 0x26, 0x82, 0xaa},
2679 {0x00, 0x2e, 0x0f, 0xaa},
2680 {0x00, 0x2f, 0x1e, 0xaa},
2681 {0x00, 0x30, 0x2d, 0xaa},
2682 {0x00, 0x31, 0x3c, 0xaa},
2683 {0x00, 0x32, 0x4b, 0xaa},
2684 {0x00, 0x33, 0x5a, 0xaa},
2685 {0x00, 0x34, 0x69, 0xaa},
2686 {0x00, 0x35, 0x78, 0xaa},
2687 {0x00, 0x36, 0x87, 0xaa},
2688 {0x00, 0x37, 0x96, 0xaa},
2689 {0x00, 0x38, 0xa5, 0xaa},
2690 {0x00, 0x39, 0xb4, 0xaa},
2691 {0x00, 0x3a, 0xc3, 0xaa},
2692 {0x00, 0x3b, 0xd2, 0xaa},
2693 {0x00, 0x3c, 0xe1, 0xaa},
2694 {0x00, 0x3e, 0xff, 0xaa},
2695 {0x00, 0x3f, 0xff, 0xaa},
2696 {0x00, 0x40, 0xff, 0xaa},
2697 {0x00, 0x41, 0xff, 0xaa},
2698 {0x00, 0x42, 0xff, 0xaa},
2699 {0x00, 0x43, 0xff, 0xaa},
2700 {0x00, 0x03, 0x00, 0xaa},
2701 {0x00, 0x03, 0x00, 0xaa},
2702 {0x00, 0x20, 0xc4, 0xaa},
2703 {0x00, 0x13, 0x03, 0xaa},
2704 {0x00, 0x3c, 0x50, 0xaa},
2705 {0x00, 0x61, 0x6a, 0xaa}, /* sharpness? */
2706 {0x00, 0x51, 0x5b, 0xaa},
2707 {0x00, 0x52, 0x91, 0xaa},
2708 {0x00, 0x53, 0x4c, 0xaa},
2709 {0x00, 0x54, 0x50, 0xaa},
2710 {0x00, 0x56, 0x02, 0xaa},
2711 {0xb6, 0x00, 0x00, 0xcc},
2712 {0xb6, 0x03, 0x03, 0xcc},
2713 {0xb6, 0x02, 0x20, 0xcc},
2714 {0xb6, 0x05, 0x02, 0xcc},
2715 {0xb6, 0x04, 0x58, 0xcc},
2716 {0xb6, 0x12, 0xf8, 0xcc},
2717 {0xb6, 0x13, 0x21, 0xcc},
2718 {0xb6, 0x18, 0x03, 0xcc},
2719 {0xb6, 0x17, 0xa9, 0xcc},
2720 {0xb6, 0x16, 0x80, 0xcc},
2721 {0xb6, 0x22, 0x12, 0xcc},
2722 {0xb6, 0x23, 0x0b, 0xcc},
2723 {0xbf, 0xc0, 0x39, 0xcc},
2724 {0xbf, 0xc1, 0x04, 0xcc},
2725 {0xbf, 0xcc, 0x00, 0xcc},
2726 {0xb8, 0x06, 0x20, 0xcc},
2727 {0xb8, 0x07, 0x03, 0xcc},
2728 {0xb8, 0x08, 0x58, 0xcc},
2729 {0xb8, 0x09, 0x02, 0xcc},
2730 {0xb3, 0x01, 0x41, 0xcc},
2731 {0x00, 0x03, 0x00, 0xaa},
2732 {0x00, 0xd9, 0x0f, 0xaa},
2733 {0x00, 0xda, 0xaa, 0xaa},
2734 {0x00, 0xd9, 0x10, 0xaa},
2735 {0x00, 0xda, 0xaa, 0xaa},
2736 {0x00, 0xd9, 0x11, 0xaa},
2737 {0x00, 0xda, 0x00, 0xaa},
2738 {0x00, 0xd9, 0x12, 0xaa},
2739 {0x00, 0xda, 0xff, 0xaa},
2740 {0x00, 0xd9, 0x13, 0xaa},
2741 {0x00, 0xda, 0xff, 0xaa},
2742 {0x00, 0xe8, 0x11, 0xaa},
2743 {0x00, 0xe9, 0x12, 0xaa},
2744 {0x00, 0xea, 0x5c, 0xaa},
2745 {0x00, 0xeb, 0xff, 0xaa},
2746 {0x00, 0xd8, 0x80, 0xaa},
2747 {0x00, 0xe6, 0x02, 0xaa},
2748 {0x00, 0xd6, 0x40, 0xaa},
2749 {0x00, 0xe3, 0x05, 0xaa},
2750 {0x00, 0xe0, 0x40, 0xaa},
2751 {0x00, 0xde, 0x03, 0xaa},
2752 {0x00, 0xdf, 0x03, 0xaa},
2753 {0x00, 0xdb, 0x02, 0xaa},
2754 {0x00, 0xdc, 0x00, 0xaa},
2755 {0x00, 0xdd, 0x03, 0xaa},
2756 {0x00, 0xe1, 0x08, 0xaa},
2757 {0x00, 0xe2, 0x01, 0xaa},
2758 {0x00, 0xd6, 0x40, 0xaa},
2759 {0x00, 0xe4, 0x40, 0xaa},
2760 {0x00, 0xa8, 0x8f, 0xaa},
2761 {0x00, 0xb4, 0x16, 0xaa},
2762 {0xb0, 0x02, 0x06, 0xcc},
2763 {0xb0, 0x18, 0x06, 0xcc},
2764 {0xb0, 0x19, 0x06, 0xcc},
2765 {0xb3, 0x5d, 0x18, 0xcc},
2766 {0xb3, 0x05, 0x00, 0xcc},
2767 {0xb3, 0x06, 0x00, 0xcc},
2768 {0x00, 0xb4, 0x0e, 0xaa},
2769 {0x00, 0xb5, 0x49, 0xaa},
2770 {0x00, 0xb6, 0x1c, 0xaa},
2771 {0x00, 0xb7, 0x96, 0xaa},
2772/* end of usbvm326.inf - start of ms-win trace */
2773 {0xb6, 0x12, 0xf8, 0xcc},
2774 {0xb6, 0x13, 0x3d, 0xcc},
2775/*read b306*/
2776 {0x00, 0x03, 0x00, 0xaa},
2777 {0x00, 0x1a, 0x09, 0xaa},
2778 {0x00, 0x1b, 0x8a, 0xaa},
2779/*read b827*/
2780 {0xb8, 0x27, 0x00, 0xcc},
2781 {0xb8, 0x26, 0x60, 0xcc},
2782 {0xb8, 0x26, 0x60, 0xcc},
2783/*gamma - to do?*/
2784 {0x00, 0x03, 0x00, 0xaa},
2785 {0x00, 0xae, 0x84, 0xaa},
2786/*gamma again*/
2787 {0x00, 0x03, 0x00, 0xaa},
2788 {0x00, 0x96, 0xa0, 0xaa},
2789/*matrix*/
2790 {0x00, 0x03, 0x00, 0xaa},
2791 {0x00, 0x91, 0x35, 0xaa},
2792 {0x00, 0x92, 0x22, 0xaa},
2793/*gamma*/
2794 {0x00, 0x03, 0x00, 0xaa},
2795 {0x00, 0x95, 0x85, 0xaa},
2796/*matrix*/
2797 {0x00, 0x03, 0x00, 0xaa},
2798 {0x00, 0x4d, 0x20, 0xaa},
2799 {0xb8, 0x22, 0x40, 0xcc},
2800 {0xb8, 0x23, 0x40, 0xcc},
2801 {0xb8, 0x24, 0x40, 0xcc},
2802 {0xb8, 0x81, 0x09, 0xcc},
2803 {0x00, 0x00, 0x64, 0xdd},
2804 {0x00, 0x03, 0x01, 0xaa},
2805/*read 46*/
2806 {0x00, 0x46, 0x3c, 0xaa},
2807 {0x00, 0x03, 0x00, 0xaa},
2808 {0x00, 0x16, 0x40, 0xaa},
2809 {0x00, 0x17, 0x40, 0xaa},
2810 {0x00, 0x18, 0x40, 0xaa},
2811 {0x00, 0x19, 0x41, 0xaa},
2812 {0x00, 0x03, 0x01, 0xaa},
2813 {0x00, 0x46, 0x3c, 0xaa},
2814 {0x00, 0x00, 0x18, 0xdd},
2815/*read bfff*/
2816 {0x00, 0x03, 0x00, 0xaa},
2817 {0x00, 0xb4, 0x1c, 0xaa},
2818 {0x00, 0xb5, 0x92, 0xaa},
2819 {0x00, 0xb6, 0x39, 0xaa},
2820 {0x00, 0xb7, 0x24, 0xaa},
2821/*write 89 0400 1415*/
2822 {}
2823};
2824
2825static const u8 poxxxx_init_common[][4] = {
2826 {0xb3, 0x00, 0x04, 0xcc},
2827 {0x00, 0x00, 0x10, 0xdd},
2828 {0xb3, 0x00, 0x64, 0xcc},
2829 {0x00, 0x00, 0x10, 0xdd},
2830 {0xb3, 0x00, 0x65, 0xcc},
2831 {0x00, 0x00, 0x10, 0xdd},
2832 {0xb3, 0x00, 0x67, 0xcc},
2833 {0xb0, 0x03, 0x09, 0xcc},
2834 {0xb3, 0x05, 0x00, 0xcc},
2835 {0xb3, 0x06, 0x00, 0xcc},
2836 {0xb3, 0x5c, 0x01, 0xcc},
2837 {0xb3, 0x08, 0x01, 0xcc},
2838 {0xb3, 0x09, 0x0c, 0xcc},
2839 {0xb3, 0x34, 0x01, 0xcc},
2840 {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */
2841 {0xb3, 0x02, 0xb0, 0xcc},
2842 {0xb3, 0x03, 0x18, 0xcc},
2843 {0xb3, 0x04, 0x15, 0xcc},
2844 {0xb3, 0x20, 0x00, 0xcc},
2845 {0xb3, 0x21, 0x00, 0xcc},
2846 {0xb3, 0x22, 0x04, 0xcc}, /* sensor height = 1024 */
2847 {0xb3, 0x23, 0x00, 0xcc},
2848 {0xb3, 0x14, 0x00, 0xcc},
2849 {0xb3, 0x15, 0x00, 0xcc},
2850 {0xb3, 0x16, 0x04, 0xcc}, /* sensor width = 1280 */
2851 {0xb3, 0x17, 0xff, 0xcc},
2852 {0xb3, 0x2c, 0x03, 0xcc},
2853 {0xb3, 0x2d, 0x56, 0xcc},
2854 {0xb3, 0x2e, 0x02, 0xcc},
2855 {0xb3, 0x2f, 0x0a, 0xcc},
2856 {0xb3, 0x40, 0x00, 0xcc},
2857 {0xb3, 0x41, 0x34, 0xcc},
2858 {0xb3, 0x42, 0x01, 0xcc},
2859 {0xb3, 0x43, 0xe0, 0xcc},
2860 {0xbc, 0x00, 0x71, 0xcc},
2861 {0xbc, 0x01, 0x01, 0xcc},
2862 {0xb3, 0x01, 0x41, 0xcc},
2863 {0xb3, 0x4d, 0x00, 0xcc},
2864 {0x00, 0x0b, 0x2a, 0xaa},
2865 {0x00, 0x0e, 0x03, 0xaa},
2866 {0x00, 0x0f, 0xea, 0xaa},
2867 {0x00, 0x12, 0x08, 0xaa},
2868 {0x00, 0x1e, 0x06, 0xaa},
2869 {0x00, 0x21, 0x00, 0xaa},
2870 {0x00, 0x31, 0x1f, 0xaa},
2871 {0x00, 0x33, 0x38, 0xaa},
2872 {0x00, 0x36, 0xc0, 0xaa},
2873 {0x00, 0x37, 0xc8, 0xaa},
2874 {0x00, 0x3b, 0x36, 0xaa},
2875 {0x00, 0x4b, 0xfe, 0xaa},
2876 {0x00, 0x4d, 0x2e, 0xaa},
2877 {0x00, 0x51, 0x1c, 0xaa},
2878 {0x00, 0x52, 0x01, 0xaa},
2879 {0x00, 0x55, 0x0a, 0xaa},
2880 {0x00, 0x56, 0x0a, 0xaa},
2881 {0x00, 0x57, 0x07, 0xaa},
2882 {0x00, 0x58, 0x07, 0xaa},
2883 {0x00, 0x59, 0x04, 0xaa},
2884 {0x00, 0x70, 0x68, 0xaa},
2885 {0x00, 0x71, 0x04, 0xaa},
2886 {0x00, 0x72, 0x10, 0xaa},
2887 {0x00, 0x80, 0x71, 0xaa},
2888 {0x00, 0x81, 0x08, 0xaa},
2889 {0x00, 0x82, 0x00, 0xaa},
2890 {0x00, 0x83, 0x55, 0xaa},
2891 {0x00, 0x84, 0x06, 0xaa},
2892 {0x00, 0x85, 0x06, 0xaa},
2893 {0x00, 0x8b, 0x25, 0xaa},
2894 {0x00, 0x8c, 0x00, 0xaa},
2895 {0x00, 0x8d, 0x86, 0xaa},
2896 {0x00, 0x8e, 0x82, 0xaa},
2897 {0x00, 0x8f, 0x2d, 0xaa},
2898 {0x00, 0x90, 0x8b, 0xaa},
2899 {0x00, 0x91, 0x81, 0xaa},
2900 {0x00, 0x92, 0x81, 0xaa},
2901 {0x00, 0x93, 0x23, 0xaa},
2902 {0x00, 0xa3, 0x2a, 0xaa},
2903 {0x00, 0xa4, 0x03, 0xaa},
2904 {0x00, 0xa5, 0xea, 0xaa},
2905 {0x00, 0xb0, 0x68, 0xaa},
2906 {0x00, 0xbc, 0x04, 0xaa},
2907 {0x00, 0xbe, 0x3b, 0xaa},
2908 {0x00, 0x4e, 0x40, 0xaa},
2909 {0x00, 0x06, 0x04, 0xaa},
2910 {0x00, 0x07, 0x03, 0xaa},
2911 {0x00, 0xcd, 0x18, 0xaa},
2912 {0x00, 0x28, 0x03, 0xaa},
2913 {0x00, 0x29, 0xef, 0xaa},
2914/* reinit on alt 2 (qvga) or alt7 (vga) */
2915 {0xb3, 0x05, 0x00, 0xcc},
2916 {0xb3, 0x06, 0x00, 0xcc},
2917 {0xb8, 0x00, 0x01, 0xcc},
2918
2919 {0x00, 0x1d, 0x85, 0xaa},
2920 {0x00, 0x1e, 0xc6, 0xaa},
2921 {0x00, 0x00, 0x40, 0xdd},
2922 {0x00, 0x1d, 0x05, 0xaa},
2923 {}
2924};
2925static const u8 poxxxx_gamma[][4] = {
2926 {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */
2927 {0x00, 0x73, 0x00, 0xaa},
2928 {0x00, 0x74, 0x0a, 0xaa},
2929 {0x00, 0x75, 0x16, 0xaa},
2930 {0x00, 0x76, 0x25, 0xaa},
2931 {0x00, 0x77, 0x34, 0xaa},
2932 {0x00, 0x78, 0x49, 0xaa},
2933 {0x00, 0x79, 0x5a, 0xaa},
2934 {0x00, 0x7a, 0x7f, 0xaa},
2935 {0x00, 0x7b, 0x9b, 0xaa},
2936 {0x00, 0x7c, 0xba, 0xaa},
2937 {0x00, 0x7d, 0xd4, 0xaa},
2938 {0x00, 0x7e, 0xea, 0xaa},
2939
2940 {0x00, 0xd6, 0x62, 0xaa}, /* gamma 1 */
2941 {0x00, 0x73, 0x00, 0xaa},
2942 {0x00, 0x74, 0x0a, 0xaa},
2943 {0x00, 0x75, 0x16, 0xaa},
2944 {0x00, 0x76, 0x25, 0xaa},
2945 {0x00, 0x77, 0x34, 0xaa},
2946 {0x00, 0x78, 0x49, 0xaa},
2947 {0x00, 0x79, 0x5a, 0xaa},
2948 {0x00, 0x7a, 0x7f, 0xaa},
2949 {0x00, 0x7b, 0x9b, 0xaa},
2950 {0x00, 0x7c, 0xba, 0xaa},
2951 {0x00, 0x7d, 0xd4, 0xaa},
2952 {0x00, 0x7e, 0xea, 0xaa},
2953
2954 {0x00, 0xd6, 0xa2, 0xaa}, /* gamma 2 */
2955 {0x00, 0x73, 0x00, 0xaa},
2956 {0x00, 0x74, 0x0a, 0xaa},
2957 {0x00, 0x75, 0x16, 0xaa},
2958 {0x00, 0x76, 0x25, 0xaa},
2959 {0x00, 0x77, 0x34, 0xaa},
2960 {0x00, 0x78, 0x49, 0xaa},
2961 {0x00, 0x79, 0x5a, 0xaa},
2962 {0x00, 0x7a, 0x7f, 0xaa},
2963 {0x00, 0x7b, 0x9b, 0xaa},
2964 {0x00, 0x7c, 0xba, 0xaa},
2965 {0x00, 0x7d, 0xd4, 0xaa},
2966 {0x00, 0x7e, 0xea, 0xaa},
2967 {}
2968};
2969static const u8 poxxxx_init_start_3[][4] = {
2970 {0x00, 0xb8, 0x28, 0xaa},
2971 {0x00, 0xb9, 0x1e, 0xaa},
2972 {0x00, 0xb6, 0x14, 0xaa},
2973 {0x00, 0xb7, 0x0f, 0xaa},
2974 {0x00, 0x5c, 0x10, 0xaa},
2975 {0x00, 0x5d, 0x18, 0xaa},
2976 {0x00, 0x5e, 0x24, 0xaa},
2977 {0x00, 0x5f, 0x24, 0xaa},
2978 {0x00, 0x86, 0x1a, 0xaa},
2979 {0x00, 0x60, 0x00, 0xaa},
2980 {0x00, 0x61, 0x1b, 0xaa},
2981 {0x00, 0x62, 0x30, 0xaa},
2982 {0x00, 0x63, 0x40, 0xaa},
2983 {0x00, 0x87, 0x1a, 0xaa},
2984 {0x00, 0x64, 0x00, 0xaa},
2985 {0x00, 0x65, 0x08, 0xaa},
2986 {0x00, 0x66, 0x10, 0xaa},
2987 {0x00, 0x67, 0x20, 0xaa},
2988 {0x00, 0x88, 0x10, 0xaa},
2989 {0x00, 0x68, 0x00, 0xaa},
2990 {0x00, 0x69, 0x08, 0xaa},
2991 {0x00, 0x6a, 0x0f, 0xaa},
2992 {0x00, 0x6b, 0x0f, 0xaa},
2993 {0x00, 0x89, 0x07, 0xaa},
2994 {0x00, 0xd5, 0x4c, 0xaa},
2995 {0x00, 0x0a, 0x00, 0xaa},
2996 {0x00, 0x0b, 0x2a, 0xaa},
2997 {0x00, 0x0e, 0x03, 0xaa},
2998 {0x00, 0x0f, 0xea, 0xaa},
2999 {0x00, 0xa2, 0x00, 0xaa},
3000 {0x00, 0xa3, 0x2a, 0xaa},
3001 {0x00, 0xa4, 0x03, 0xaa},
3002 {0x00, 0xa5, 0xea, 0xaa},
3003 {}
3004};
3005static const u8 poxxxx_initVGA[][4] = {
3006 {0x00, 0x20, 0x11, 0xaa},
3007 {0x00, 0x33, 0x38, 0xaa},
3008 {0x00, 0xbb, 0x0d, 0xaa},
3009 {0xb3, 0x22, 0x01, 0xcc}, /* change to 640x480 */
3010 {0xb3, 0x23, 0xe0, 0xcc},
3011 {0xb3, 0x16, 0x02, 0xcc},
3012 {0xb3, 0x17, 0x7f, 0xcc},
3013 {0xb3, 0x02, 0xb0, 0xcc},
3014 {0xb3, 0x06, 0x00, 0xcc},
3015 {0xb3, 0x5c, 0x01, 0xcc},
3016 {0x00, 0x04, 0x06, 0xaa},
3017 {0x00, 0x05, 0x3f, 0xaa},
3018 {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */
3019 {}
3020};
3021static const u8 poxxxx_initQVGA[][4] = {
3022 {0x00, 0x20, 0x33, 0xaa},
3023 {0x00, 0x33, 0x38, 0xaa},
3024 {0x00, 0xbb, 0x0d, 0xaa},
3025 {0xb3, 0x22, 0x00, 0xcc}, /* change to 320x240 */
3026 {0xb3, 0x23, 0xf0, 0xcc},
3027 {0xb3, 0x16, 0x01, 0xcc},
3028 {0xb3, 0x17, 0x3f, 0xcc},
3029 {0xb3, 0x02, 0xb0, 0xcc},
3030 {0xb3, 0x06, 0x01, 0xcc},
3031 {0xb3, 0x5c, 0x00, 0xcc},
3032 {0x00, 0x04, 0x06, 0xaa},
3033 {0x00, 0x05, 0x3f, 0xaa},
3034 {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */
3035 {}
3036};
3037static const u8 poxxxx_init_end_1[][4] = {
3038 {0x00, 0x47, 0x25, 0xaa},
3039 {0x00, 0x48, 0x80, 0xaa},
3040 {0x00, 0x49, 0x1f, 0xaa},
3041 {0x00, 0x4a, 0x40, 0xaa},
3042 {0x00, 0x44, 0x40, 0xaa},
3043 {0x00, 0xab, 0x4a, 0xaa},
3044 {0x00, 0xb1, 0x00, 0xaa},
3045 {0x00, 0xb2, 0x04, 0xaa},
3046 {0x00, 0xb3, 0x08, 0xaa},
3047 {0x00, 0xb4, 0x0b, 0xaa},
3048 {0x00, 0xb5, 0x0d, 0xaa},
3049 {}
3050};
3051static const u8 poxxxx_init_end_2[][4] = {
3052 {0x00, 0x1d, 0x85, 0xaa},
3053 {0x00, 0x1e, 0x06, 0xaa},
3054 {0x00, 0x1d, 0x05, 0xaa},
3055 {}
3056};
3057
3058struct sensor_info {
3059 s8 sensorId;
3060 u8 I2cAdd;
3061 u8 IdAdd;
3062 u16 VpId;
3063 u8 m1;
3064 u8 m2;
3065 u8 op;
3066};
3067
3068/* probe values */
3069static const struct sensor_info vc0321_probe_data[] = {
3070/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
3071/* 0 OV9640 */
3072 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
3073/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
3074 {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
3075/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
3076 {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
3077/* 3 MI1310 */
3078 {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
3079/* 4 MI360 - tested in vc032x_probe_sensor */
3080/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
3081/* 5 7131R */
3082 {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
3083/* 6 OV7649 */
3084 {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
3085/* 7 PAS302BCW */
3086 {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
3087/* 8 OV7660 */
3088 {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
3089/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
3090/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
3091/* 10 PO1030KC */
3092 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
3093/* 11 MI1310_SOC */
3094 {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
3095/* 12 OV9650 */
3096 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
3097/* 13 S5K532 */
3098 {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
3099/* 14 MI360_SOC - ??? */
3100/* 15 PO1200N */
3101 {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
3102/* 16 PO3030K */
3103 {-1, 0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01},
3104/* 17 PO2030 */
3105 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
3106/* ?? */
3107 {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
3108 {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
3109};
3110static const struct sensor_info vc0323_probe_data[] = {
3111/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
3112/* 0 OV9640 */
3113 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
3114/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
3115 {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
3116/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
3117 {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
3118/* 3 MI1310 */
3119 {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
3120/* 4 MI360 - tested in vc032x_probe_sensor */
3121/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
3122/* 5 7131R */
3123 {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
3124/* 6 OV7649 */
3125 {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
3126/* 7 PAS302BCW */
3127 {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
3128/* 8 OV7660 */
3129 {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
3130/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
3131/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
3132/* 10 PO1030KC */
3133 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
3134/* 11 MI1310_SOC */
3135 {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
3136/* 12 OV9650 */
3137 {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
3138/* 13 S5K532 */
3139 {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
3140/* 14 MI360_SOC - ??? */
3141/* 15 PO1200N */
3142 {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
3143/* 16 ?? */
3144 {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
3145/* 17 PO2030 */
3146 {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
3147/* ?? */
3148 {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
3149 {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
3150/*fixme: not in the ms-win probe - may be found before? */
3151 {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
3152};
3153
3154/* read 'len' bytes in gspca_dev->usb_buf */
3155static void reg_r_i(struct gspca_dev *gspca_dev,
3156 u16 req,
3157 u16 index,
3158 u16 len)
3159{
3160 int ret;
3161
3162 if (gspca_dev->usb_err < 0)
3163 return;
3164 ret = usb_control_msg(gspca_dev->dev,
3165 usb_rcvctrlpipe(gspca_dev->dev, 0),
3166 req,
3167 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
3168 1, /* value */
3169 index, gspca_dev->usb_buf, len,
3170 500);
3171 if (ret < 0) {
3172 err("reg_r err %d", ret);
3173 gspca_dev->usb_err = ret;
3174 }
3175}
3176static void reg_r(struct gspca_dev *gspca_dev,
3177 u16 req,
3178 u16 index,
3179 u16 len)
3180{
3181 reg_r_i(gspca_dev, req, index, len);
3182#ifdef GSPCA_DEBUG
3183 if (gspca_dev->usb_err < 0)
3184 return;
3185 if (len == 1)
3186 PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index,
3187 gspca_dev->usb_buf[0]);
3188 else
3189 PDEBUG(D_USBI, "GET %02x 0001 %04x %02x %02x %02x",
3190 req, index,
3191 gspca_dev->usb_buf[0],
3192 gspca_dev->usb_buf[1],
3193 gspca_dev->usb_buf[2]);
3194#endif
3195}
3196
3197static void reg_w_i(struct gspca_dev *gspca_dev,
3198 u16 req,
3199 u16 value,
3200 u16 index)
3201{
3202 int ret;
3203
3204 if (gspca_dev->usb_err < 0)
3205 return;
3206 ret = usb_control_msg(gspca_dev->dev,
3207 usb_sndctrlpipe(gspca_dev->dev, 0),
3208 req,
3209 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
3210 value, index, NULL, 0,
3211 500);
3212 if (ret < 0) {
3213 err("reg_w err %d", ret);
3214 gspca_dev->usb_err = ret;
3215 }
3216}
3217static void reg_w(struct gspca_dev *gspca_dev,
3218 u16 req,
3219 u16 value,
3220 u16 index)
3221{
3222#ifdef GSPCA_DEBUG
3223 if (gspca_dev->usb_err < 0)
3224 return;
3225 PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
3226#endif
3227 reg_w_i(gspca_dev, req, value, index);
3228}
3229
3230static u16 read_sensor_register(struct gspca_dev *gspca_dev,
3231 u16 address)
3232{
3233 u8 ldata, mdata, hdata;
3234 int retry = 50;
3235
3236 reg_r(gspca_dev, 0xa1, 0xb33f, 1);
3237 if (!(gspca_dev->usb_buf[0] & 0x02)) {
3238 err("I2c Bus Busy Wait %02x",
3239 gspca_dev->usb_buf[0]);
3240 return 0;
3241 }
3242 reg_w(gspca_dev, 0xa0, address, 0xb33a);
3243 reg_w(gspca_dev, 0xa0, 0x02, 0xb339);
3244
3245 do {
3246 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
3247 if (gspca_dev->usb_buf[0] == 0x00)
3248 break;
3249 msleep(40);
3250 } while (--retry >= 0);
3251
3252 reg_r(gspca_dev, 0xa1, 0xb33e, 1);
3253 ldata = gspca_dev->usb_buf[0];
3254 reg_r(gspca_dev, 0xa1, 0xb33d, 1);
3255 mdata = gspca_dev->usb_buf[0];
3256 reg_r(gspca_dev, 0xa1, 0xb33c, 1);
3257 hdata = gspca_dev->usb_buf[0];
3258 if (hdata != 0 && mdata != 0 && ldata != 0)
3259 PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x",
3260 hdata, mdata, ldata);
3261 reg_r(gspca_dev, 0xa1, 0xb334, 1);
3262 if (gspca_dev->usb_buf[0] == 0x02)
3263 return (hdata << 8) + mdata;
3264 return hdata;
3265}
3266
3267static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
3268{
3269 struct sd *sd = (struct sd *) gspca_dev;
3270 int i, n;
3271 u16 value;
3272 const struct sensor_info *ptsensor_info;
3273
3274/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/
3275 if (sd->flags & FL_SAMSUNG) {
3276 reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
3277 reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
3278 /* select the back sensor */
3279 }
3280
3281 reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
3282 PDEBUG(D_PROBE, "vc032%d check sensor header %02x",
3283 sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]);
3284 if (sd->bridge == BRIDGE_VC0321) {
3285 ptsensor_info = vc0321_probe_data;
3286 n = ARRAY_SIZE(vc0321_probe_data);
3287 } else {
3288 ptsensor_info = vc0323_probe_data;
3289 n = ARRAY_SIZE(vc0323_probe_data);
3290 }
3291 for (i = 0; i < n; i++) {
3292 reg_w(gspca_dev, 0xa0, 0x02, 0xb334);
3293 reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300);
3294 reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300);
3295 reg_w(gspca_dev, 0xa0, 0x01, 0xb308);
3296 reg_w(gspca_dev, 0xa0, 0x0c, 0xb309);
3297 reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
3298 reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301);
3299 value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd);
3300 if (value == 0 && ptsensor_info->IdAdd == 0x82)
3301 value = read_sensor_register(gspca_dev, 0x83);
3302 if (value != 0) {
3303 PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
3304 value, i);
3305 if (value == ptsensor_info->VpId)
3306 return ptsensor_info->sensorId;
3307
3308 switch (value) {
3309 case 0x3130:
3310 return SENSOR_PO3130NC;
3311 case 0x7673:
3312 return SENSOR_OV7670;
3313 case 0x8243:
3314 return SENSOR_MI0360;
3315 }
3316 }
3317 ptsensor_info++;
3318 }
3319 return -1;
3320}
3321
3322static void i2c_write(struct gspca_dev *gspca_dev,
3323 u8 reg, const u8 *val,
3324 u8 size) /* 1 or 2 */
3325{
3326 int retry;
3327
3328#ifdef GSPCA_DEBUG
3329 if (gspca_dev->usb_err < 0)
3330 return;
3331 if (size == 1)
3332 PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val);
3333 else
3334 PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]);
3335#endif
3336 reg_r_i(gspca_dev, 0xa1, 0xb33f, 1);
3337/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
3338 reg_w_i(gspca_dev, 0xa0, size, 0xb334);
3339 reg_w_i(gspca_dev, 0xa0, reg, 0xb33a);
3340 reg_w_i(gspca_dev, 0xa0, val[0], 0xb336);
3341 if (size > 1)
3342 reg_w_i(gspca_dev, 0xa0, val[1], 0xb337);
3343 reg_w_i(gspca_dev, 0xa0, 0x01, 0xb339);
3344 retry = 4;
3345 do {
3346 reg_r_i(gspca_dev, 0xa1, 0xb33b, 1);
3347 if (gspca_dev->usb_buf[0] == 0)
3348 break;
3349 msleep(20);
3350 } while (--retry > 0);
3351 if (retry <= 0)
3352 err("i2c_write timeout");
3353}
3354
3355static void put_tab_to_reg(struct gspca_dev *gspca_dev,
3356 const u8 *tab, u8 tabsize, u16 addr)
3357{
3358 int j;
3359 u16 ad = addr;
3360
3361 for (j = 0; j < tabsize; j++)
3362 reg_w(gspca_dev, 0xa0, tab[j], ad++);
3363}
3364
3365static void usb_exchange(struct gspca_dev *gspca_dev,
3366 const u8 data[][4])
3367{
3368 int i = 0;
3369
3370 for (;;) {
3371 switch (data[i][3]) {
3372 default:
3373 return;
3374 case 0xcc: /* normal write */
3375 reg_w(gspca_dev, 0xa0, data[i][2],
3376 (data[i][0]) << 8 | data[i][1]);
3377 break;
3378 case 0xaa: /* i2c op */
3379 i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
3380 break;
3381 case 0xbb: /* i2c op */
3382 i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
3383 break;
3384 case 0xdd:
3385 msleep(data[i][1] * 256 + data[i][2] + 10);
3386 break;
3387 }
3388 i++;
3389 }
3390 /*not reached*/
3391}
3392
3393
3394/* this function is called at probe time */
3395static int sd_config(struct gspca_dev *gspca_dev,
3396 const struct usb_device_id *id)
3397{
3398 struct sd *sd = (struct sd *) gspca_dev;
3399
3400 sd->bridge = id->driver_info >> 8;
3401 sd->flags = id->driver_info & 0xff;
3402
3403 if (id->idVendor == 0x046d &&
3404 (id->idProduct == 0x0892 || id->idProduct == 0x0896))
3405 sd->sensor = SENSOR_POxxxx; /* no probe */
3406
3407 sd->brightness = BRIGHTNESS_DEF;
3408 sd->contrast = CONTRAST_DEF;
3409 sd->colors = COLOR_DEF;
3410 sd->hflip = HFLIP_DEF;
3411 sd->vflip = VFLIP_DEF;
3412 sd->lightfreq = FREQ_DEF;
3413 sd->sharpness = SHARPNESS_DEF;
3414 sd->gain = GAIN_DEF;
3415 sd->exposure = EXPOSURE_DEF;
3416 sd->autogain = AUTOGAIN_DEF;
3417 sd->backlight = BACKLIGHT_DEF;
3418
3419 return 0;
3420}
3421
3422/* this function is called at probe and resume time */
3423static int sd_init(struct gspca_dev *gspca_dev)
3424{
3425 struct sd *sd = (struct sd *) gspca_dev;
3426 struct cam *cam;
3427 int sensor;
3428 /* number of packets per ISOC message */
3429 static u8 npkt[NSENSORS] = {
3430 [SENSOR_HV7131R] = 64,
3431 [SENSOR_MI0360] = 32,
3432 [SENSOR_MI1310_SOC] = 32,
3433 [SENSOR_MI1320] = 64,
3434 [SENSOR_MI1320_SOC] = 128,
3435 [SENSOR_OV7660] = 32,
3436 [SENSOR_OV7670] = 64,
3437 [SENSOR_PO1200] = 128,
3438 [SENSOR_PO3130NC] = 128,
3439 [SENSOR_POxxxx] = 128,
3440 };
3441
3442 if (sd->sensor != SENSOR_POxxxx)
3443 sensor = vc032x_probe_sensor(gspca_dev);
3444 else
3445 sensor = sd->sensor;
3446
3447 switch (sensor) {
3448 case -1:
3449 err("Unknown sensor...");
3450 return -EINVAL;
3451 case SENSOR_HV7131R:
3452 PDEBUG(D_PROBE, "Find Sensor HV7131R");
3453 break;
3454 case SENSOR_MI0360:
3455 PDEBUG(D_PROBE, "Find Sensor MI0360");
3456 sd->bridge = BRIDGE_VC0323;
3457 break;
3458 case SENSOR_MI1310_SOC:
3459 PDEBUG(D_PROBE, "Find Sensor MI1310_SOC");
3460 break;
3461 case SENSOR_MI1320:
3462 PDEBUG(D_PROBE, "Find Sensor MI1320");
3463 break;
3464 case SENSOR_MI1320_SOC:
3465 PDEBUG(D_PROBE, "Find Sensor MI1320_SOC");
3466 break;
3467 case SENSOR_OV7660:
3468 PDEBUG(D_PROBE, "Find Sensor OV7660");
3469 break;
3470 case SENSOR_OV7670:
3471 PDEBUG(D_PROBE, "Find Sensor OV7670");
3472 break;
3473 case SENSOR_PO1200:
3474 PDEBUG(D_PROBE, "Find Sensor PO1200");
3475 break;
3476 case SENSOR_PO3130NC:
3477 PDEBUG(D_PROBE, "Find Sensor PO3130NC");
3478 break;
3479 case SENSOR_POxxxx:
3480 PDEBUG(D_PROBE, "Sensor POxxxx");
3481 break;
3482 }
3483 sd->sensor = sensor;
3484
3485 cam = &gspca_dev->cam;
3486 if (sd->bridge == BRIDGE_VC0321) {
3487 cam->cam_mode = vc0321_mode;
3488 cam->nmodes = ARRAY_SIZE(vc0321_mode);
3489 } else {
3490 switch (sensor) {
3491 case SENSOR_PO1200:
3492 cam->cam_mode = svga_mode;
3493 cam->nmodes = ARRAY_SIZE(svga_mode);
3494 break;
3495 case SENSOR_MI1310_SOC:
3496 cam->cam_mode = vc0323_mode;
3497 cam->nmodes = ARRAY_SIZE(vc0323_mode);
3498 break;
3499 case SENSOR_MI1320_SOC:
3500 cam->cam_mode = bi_mode;
3501 cam->nmodes = ARRAY_SIZE(bi_mode);
3502 break;
3503 case SENSOR_OV7670:
3504 cam->cam_mode = bi_mode;
3505 cam->nmodes = ARRAY_SIZE(bi_mode) - 1;
3506 break;
3507 default:
3508 cam->cam_mode = vc0323_mode;
3509 cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
3510 break;
3511 }
3512 }
3513 cam->npkt = npkt[sd->sensor];
3514 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
3515
3516 if (sd->sensor == SENSOR_OV7670)
3517 sd->flags |= FL_HFLIP | FL_VFLIP;
3518
3519 if (sd->bridge == BRIDGE_VC0321) {
3520 reg_r(gspca_dev, 0x8a, 0, 3);
3521 reg_w(gspca_dev, 0x87, 0x00, 0x0f0f);
3522 reg_r(gspca_dev, 0x8b, 0, 3);
3523 reg_w(gspca_dev, 0x88, 0x00, 0x0202);
3524 if (sd->sensor == SENSOR_POxxxx) {
3525 reg_r(gspca_dev, 0xa1, 0xb300, 1);
3526 if (gspca_dev->usb_buf[0] != 0) {
3527 reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
3528 reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
3529 }
3530 reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
3531 }
3532 }
3533 return gspca_dev->usb_err;
3534}
3535
3536static void setbrightness(struct gspca_dev *gspca_dev)
3537{
3538 struct sd *sd = (struct sd *) gspca_dev;
3539 u8 data;
3540
3541 if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX))
3542 return;
3543 data = sd->brightness;
3544 if (data >= 0x80)
3545 data &= 0x7f;
3546 else
3547 data = 0xff ^ data;
3548 i2c_write(gspca_dev, 0x98, &data, 1);
3549}
3550
3551static void setcontrast(struct gspca_dev *gspca_dev)
3552{
3553 struct sd *sd = (struct sd *) gspca_dev;
3554
3555 if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX))
3556 return;
3557 i2c_write(gspca_dev, 0x99, &sd->contrast, 1);
3558}
3559
3560static void setcolors(struct gspca_dev *gspca_dev)
3561{
3562 struct sd *sd = (struct sd *) gspca_dev;
3563 u8 data;
3564
3565 if (gspca_dev->ctrl_dis & (1 << COLORS_IDX))
3566 return;
3567 data = sd->colors - (sd->colors >> 3) - 1;
3568 i2c_write(gspca_dev, 0x94, &data, 1);
3569 i2c_write(gspca_dev, 0x95, &sd->colors, 1);
3570}
3571
3572static void sethvflip(struct gspca_dev *gspca_dev)
3573{
3574 struct sd *sd = (struct sd *) gspca_dev;
3575 u8 data[2], hflip, vflip;
3576
3577 hflip = sd->hflip;
3578 if (sd->flags & FL_HFLIP)
3579 hflip = !hflip;
3580 vflip = sd->vflip;
3581 if (sd->flags & FL_VFLIP)
3582 vflip = !vflip;
3583 switch (sd->sensor) {
3584 case SENSOR_MI1310_SOC:
3585 case SENSOR_MI1320:
3586 case SENSOR_MI1320_SOC:
3587 data[0] = data[1] = 0; /* select page 0 */
3588 i2c_write(gspca_dev, 0xf0, data, 2);
3589 data[0] = sd->sensor == SENSOR_MI1310_SOC ? 0x03 : 0x01;
3590 data[1] = 0x02 * hflip
3591 | 0x01 * vflip;
3592 i2c_write(gspca_dev, 0x20, data, 2);
3593 break;
3594 case SENSOR_OV7660:
3595 case SENSOR_OV7670:
3596 data[0] = sd->sensor == SENSOR_OV7660 ? 0x01 : 0x07;
3597 data[0] |= OV7660_MVFP_MIRROR * hflip
3598 | OV7660_MVFP_VFLIP * vflip;
3599 i2c_write(gspca_dev, OV7660_REG_MVFP, data, 1);
3600 break;
3601 case SENSOR_PO1200:
3602 data[0] = 0;
3603 i2c_write(gspca_dev, 0x03, data, 1);
3604 data[0] = 0x80 * hflip
3605 | 0x40 * vflip
3606 | 0x06;
3607 i2c_write(gspca_dev, 0x1e, data, 1);
3608 break;
3609 }
3610}
3611
3612static void setlightfreq(struct gspca_dev *gspca_dev)
3613{
3614 struct sd *sd = (struct sd *) gspca_dev;
3615 static const u8 (*ov7660_freq_tb[3])[4] =
3616 {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
3617
3618 if (sd->sensor != SENSOR_OV7660)
3619 return;
3620 usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]);
3621}
3622
3623static void setsharpness(struct gspca_dev *gspca_dev)
3624{
3625 struct sd *sd = (struct sd *) gspca_dev;
3626 u8 data;
3627
3628 switch (sd->sensor) {
3629 case SENSOR_PO1200:
3630 data = 0;
3631 i2c_write(gspca_dev, 0x03, &data, 1);
3632 if (sd->sharpness < 0)
3633 data = 0x6a;
3634 else
3635 data = 0xb5 + sd->sharpness * 3;
3636 i2c_write(gspca_dev, 0x61, &data, 1);
3637 break;
3638 case SENSOR_POxxxx:
3639 if (sd->sharpness < 0)
3640 data = 0x7e; /* def = max */
3641 else
3642 data = 0x60 + sd->sharpness * 0x0f;
3643 i2c_write(gspca_dev, 0x59, &data, 1);
3644 break;
3645 }
3646}
3647static void setgain(struct gspca_dev *gspca_dev)
3648{
3649 struct sd *sd = (struct sd *) gspca_dev;
3650
3651 if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
3652 return;
3653 i2c_write(gspca_dev, 0x15, &sd->gain, 1);
3654}
3655
3656static void setexposure(struct gspca_dev *gspca_dev)
3657{
3658 struct sd *sd = (struct sd *) gspca_dev;
3659 u8 data;
3660
3661 if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
3662 return;
3663 data = sd->exposure >> 8;
3664 i2c_write(gspca_dev, 0x1a, &data, 1);
3665 data = sd->exposure;
3666 i2c_write(gspca_dev, 0x1b, &data, 1);
3667}
3668
3669static void setautogain(struct gspca_dev *gspca_dev)
3670{
3671 struct sd *sd = (struct sd *) gspca_dev;
3672 static const u8 data[2] = {0x28, 0x3c};
3673
3674 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
3675 return;
3676 i2c_write(gspca_dev, 0xd1, &data[sd->autogain], 1);
3677}
3678
3679static void setgamma(struct gspca_dev *gspca_dev)
3680{
3681/*fixme:to do */
3682 usb_exchange(gspca_dev, poxxxx_gamma);
3683}
3684
3685static void setbacklight(struct gspca_dev *gspca_dev)
3686{
3687 struct sd *sd = (struct sd *) gspca_dev;
3688 u16 v;
3689 u8 data;
3690
3691 data = (sd->backlight << 4) | 0x0f;
3692 i2c_write(gspca_dev, 0xaa, &data, 1);
3693 v = 613 + 12 * sd->backlight;
3694 data = v >> 8;
3695 i2c_write(gspca_dev, 0xc4, &data, 1);
3696 data = v;
3697 i2c_write(gspca_dev, 0xc5, &data, 1);
3698 v = 1093 - 12 * sd->backlight;
3699 data = v >> 8;
3700 i2c_write(gspca_dev, 0xc6, &data, 1);
3701 data = v;
3702 i2c_write(gspca_dev, 0xc7, &data, 1);
3703 v = 342 + 9 * sd->backlight;
3704 data = v >> 8;
3705 i2c_write(gspca_dev, 0xc8, &data, 1);
3706 data = v;
3707 i2c_write(gspca_dev, 0xc9, &data, 1);
3708 v = 702 - 9 * sd->backlight;
3709 data = v >> 8;
3710 i2c_write(gspca_dev, 0xca, &data, 1);
3711 data = v;
3712 i2c_write(gspca_dev, 0xcb, &data, 1);
3713}
3714
3715static void setwb(struct gspca_dev *gspca_dev)
3716{
3717/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
3718 static const u8 data[2] = {0x00, 0x00};
3719
3720 i2c_write(gspca_dev, 0x16, &data[0], 1);
3721 i2c_write(gspca_dev, 0x18, &data[1], 1);
3722}
3723
3724static int sd_start(struct gspca_dev *gspca_dev)
3725{
3726 struct sd *sd = (struct sd *) gspca_dev;
3727 const u8 (*init)[4];
3728 const u8 *GammaT = NULL;
3729 const u8 *MatrixT = NULL;
3730 int mode;
3731 static const u8 (*mi1320_soc_init[])[4] = {
3732 mi1320_soc_InitSXGA,
3733 mi1320_soc_InitVGA,
3734 mi1320_soc_InitQVGA,
3735 };
3736
3737/*fixme: back sensor only*/
3738 if (sd->flags & FL_SAMSUNG) {
3739 reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
3740 reg_w(gspca_dev, 0xa9, 0x8348, 0x000e);
3741 reg_w(gspca_dev, 0xa9, 0x0000, 0x001a);
3742 }
3743
3744 /* Assume start use the good resolution from gspca_dev->mode */
3745 if (sd->bridge == BRIDGE_VC0321) {
3746 reg_w(gspca_dev, 0xa0, 0xff, 0xbfec);
3747 reg_w(gspca_dev, 0xa0, 0xff, 0xbfed);
3748 reg_w(gspca_dev, 0xa0, 0xff, 0xbfee);
3749 reg_w(gspca_dev, 0xa0, 0xff, 0xbfef);
3750 sd->image_offset = 46;
3751 } else {
3752 if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
3753 == V4L2_PIX_FMT_JPEG)
3754 sd->image_offset = 0;
3755 else
3756 sd->image_offset = 32;
3757 }
3758
3759 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
3760 switch (sd->sensor) {
3761 case SENSOR_HV7131R:
3762 GammaT = hv7131r_gamma;
3763 MatrixT = hv7131r_matrix;
3764 if (mode)
3765 init = hv7131r_initQVGA_data; /* 320x240 */
3766 else
3767 init = hv7131r_initVGA_data; /* 640x480 */
3768 break;
3769 case SENSOR_OV7660:
3770 GammaT = ov7660_gamma;
3771 MatrixT = ov7660_matrix;
3772 if (mode)
3773 init = ov7660_initQVGA_data; /* 320x240 */
3774 else
3775 init = ov7660_initVGA_data; /* 640x480 */
3776 break;
3777 case SENSOR_MI0360:
3778 GammaT = mi1320_gamma;
3779 MatrixT = mi0360_matrix;
3780 if (mode)
3781 init = mi0360_initQVGA_JPG; /* 320x240 */
3782 else
3783 init = mi0360_initVGA_JPG; /* 640x480 */
3784 break;
3785 case SENSOR_MI1310_SOC:
3786 GammaT = mi1320_gamma;
3787 MatrixT = mi1320_matrix;
3788 switch (mode) {
3789 case 1:
3790 init = mi1310_socinitQVGA_JPG; /* 320x240 */
3791 break;
3792 case 0:
3793 init = mi1310_socinitVGA_JPG; /* 640x480 */
3794 break;
3795 default:
3796 init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */
3797 break;
3798 }
3799 break;
3800 case SENSOR_MI1320:
3801 GammaT = mi1320_gamma;
3802 MatrixT = mi1320_matrix;
3803 if (mode)
3804 init = mi1320_initQVGA_data; /* 320x240 */
3805 else
3806 init = mi1320_initVGA_data; /* 640x480 */
3807 break;
3808 case SENSOR_MI1320_SOC:
3809 GammaT = mi1320_gamma;
3810 MatrixT = mi1320_matrix;
3811 init = mi1320_soc_init[mode];
3812 break;
3813 case SENSOR_OV7670:
3814 init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA;
3815 break;
3816 case SENSOR_PO3130NC:
3817 GammaT = po3130_gamma;
3818 MatrixT = po3130_matrix;
3819 if (mode)
3820 init = po3130_initQVGA_data; /* 320x240 */
3821 else
3822 init = po3130_initVGA_data; /* 640x480 */
3823 usb_exchange(gspca_dev, init);
3824 init = po3130_rundata;
3825 break;
3826 case SENSOR_PO1200:
3827 GammaT = po1200_gamma;
3828 MatrixT = po1200_matrix;
3829 init = po1200_initVGA_data;
3830 break;
3831 default:
3832/* case SENSOR_POxxxx: */
3833 usb_exchange(gspca_dev, poxxxx_init_common);
3834 setgamma(gspca_dev);
3835 setbacklight(gspca_dev);
3836 setbrightness(gspca_dev);
3837 setcontrast(gspca_dev);
3838 setcolors(gspca_dev);
3839 setsharpness(gspca_dev);
3840 setautogain(gspca_dev);
3841 setexposure(gspca_dev);
3842 setgain(gspca_dev);
3843 usb_exchange(gspca_dev, poxxxx_init_start_3);
3844 if (mode)
3845 init = poxxxx_initQVGA;
3846 else
3847 init = poxxxx_initVGA;
3848 usb_exchange(gspca_dev, init);
3849 reg_r(gspca_dev, 0x8c, 0x0000, 3);
3850 reg_w(gspca_dev, 0xa0,
3851 gspca_dev->usb_buf[2] & 1 ? 0 : 1,
3852 0xb35c);
3853 msleep(300);
3854/*fixme: i2c read 04 and 05*/
3855 init = poxxxx_init_end_1;
3856 break;
3857 }
3858 usb_exchange(gspca_dev, init);
3859 if (GammaT && MatrixT) {
3860 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
3861 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
3862 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
3863 put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
3864
3865 switch (sd->sensor) {
3866 case SENSOR_PO1200:
3867 case SENSOR_HV7131R:
3868 reg_w(gspca_dev, 0x89, 0x0400, 0x1415);
3869 break;
3870 case SENSOR_MI1310_SOC:
3871 reg_w(gspca_dev, 0x89, 0x058c, 0x0000);
3872 break;
3873 }
3874 msleep(100);
3875 sethvflip(gspca_dev);
3876 setlightfreq(gspca_dev);
3877 }
3878 switch (sd->sensor) {
3879 case SENSOR_OV7670:
3880 reg_w(gspca_dev, 0x87, 0xffff, 0xffff);
3881 reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1);
3882 reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
3883 break;
3884 case SENSOR_POxxxx:
3885 usb_exchange(gspca_dev, poxxxx_init_end_2);
3886 setwb(gspca_dev);
3887 msleep(80); /* led on */
3888 reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
3889 break;
3890 }
3891 return gspca_dev->usb_err;
3892}
3893
3894static void sd_stopN(struct gspca_dev *gspca_dev)
3895{
3896 struct sd *sd = (struct sd *) gspca_dev;
3897
3898 switch (sd->sensor) {
3899 case SENSOR_MI1310_SOC:
3900 reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
3901 break;
3902 case SENSOR_POxxxx:
3903 return;
3904 default:
3905 if (!(sd->flags & FL_SAMSUNG))
3906 reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
3907 break;
3908 }
3909 reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
3910 reg_w(gspca_dev, 0xa0, 0x09, 0xb003);
3911}
3912
3913/* called on streamoff with alt 0 and on disconnect */
3914static void sd_stop0(struct gspca_dev *gspca_dev)
3915{
3916 struct sd *sd = (struct sd *) gspca_dev;
3917
3918 if (!gspca_dev->present)
3919 return;
3920/*fixme: is this useful?*/
3921 if (sd->sensor == SENSOR_MI1310_SOC)
3922 reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
3923 else if (!(sd->flags & FL_SAMSUNG))
3924 reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
3925
3926 if (sd->sensor == SENSOR_POxxxx) {
3927 reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
3928 reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
3929 reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
3930 }
3931}
3932
3933static void sd_pkt_scan(struct gspca_dev *gspca_dev,
3934 u8 *data, /* isoc packet */
3935 int len) /* iso pkt length */
3936{
3937 struct sd *sd = (struct sd *) gspca_dev;
3938
3939 if (data[0] == 0xff && data[1] == 0xd8) {
3940 PDEBUG(D_PACK,
3941 "vc032x header packet found len %d", len);
3942 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
3943 data += sd->image_offset;
3944 len -= sd->image_offset;
3945 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
3946 return;
3947 }
3948
3949 /* The vc0321 sends some additional data after sending the complete
3950 * frame, we ignore this. */
3951 if (sd->bridge == BRIDGE_VC0321) {
3952 int size, l;
3953
3954 l = gspca_dev->image_len;
3955 size = gspca_dev->frsz;
3956 if (len > size - l)
3957 len = size - l;
3958 }
3959 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
3960}
3961
3962static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
3963{
3964 struct sd *sd = (struct sd *) gspca_dev;
3965
3966 sd->brightness = val;
3967 if (gspca_dev->streaming)
3968 setbrightness(gspca_dev);
3969 return gspca_dev->usb_err;
3970}
3971
3972static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
3973{
3974 struct sd *sd = (struct sd *) gspca_dev;
3975
3976 *val = sd->brightness;
3977 return 0;
3978}
3979
3980static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
3981{
3982 struct sd *sd = (struct sd *) gspca_dev;
3983
3984 sd->contrast = val;
3985 if (gspca_dev->streaming)
3986 setcontrast(gspca_dev);
3987 return gspca_dev->usb_err;
3988}
3989
3990static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
3991{
3992 struct sd *sd = (struct sd *) gspca_dev;
3993
3994 *val = sd->contrast;
3995 return 0;
3996}
3997
3998static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
3999{
4000 struct sd *sd = (struct sd *) gspca_dev;
4001
4002 sd->colors = val;
4003 if (gspca_dev->streaming)
4004 setcolors(gspca_dev);
4005 return gspca_dev->usb_err;
4006}
4007
4008static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
4009{
4010 struct sd *sd = (struct sd *) gspca_dev;
4011
4012 *val = sd->colors;
4013 return 0;
4014}
4015
4016static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
4017{
4018 struct sd *sd = (struct sd *) gspca_dev;
4019
4020 sd->hflip = val;
4021 if (gspca_dev->streaming)
4022 sethvflip(gspca_dev);
4023 return gspca_dev->usb_err;
4024}
4025
4026static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
4027{
4028 struct sd *sd = (struct sd *) gspca_dev;
4029
4030 *val = sd->hflip;
4031 return 0;
4032}
4033
4034static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
4035{
4036 struct sd *sd = (struct sd *) gspca_dev;
4037
4038 sd->vflip = val;
4039 if (gspca_dev->streaming)
4040 sethvflip(gspca_dev);
4041 return gspca_dev->usb_err;
4042}
4043
4044static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
4045{
4046 struct sd *sd = (struct sd *) gspca_dev;
4047
4048 *val = sd->vflip;
4049 return 0;
4050}
4051
4052static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
4053{
4054 struct sd *sd = (struct sd *) gspca_dev;
4055
4056 sd->lightfreq = val;
4057 if (gspca_dev->streaming)
4058 setlightfreq(gspca_dev);
4059 return gspca_dev->usb_err;
4060}
4061
4062static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
4063{
4064 struct sd *sd = (struct sd *) gspca_dev;
4065
4066 *val = sd->lightfreq;
4067 return 0;
4068}
4069
4070static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
4071{
4072 struct sd *sd = (struct sd *) gspca_dev;
4073
4074 sd->sharpness = val;
4075 if (gspca_dev->streaming)
4076 setsharpness(gspca_dev);
4077 return gspca_dev->usb_err;
4078}
4079
4080static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
4081{
4082 struct sd *sd = (struct sd *) gspca_dev;
4083
4084 *val = sd->sharpness;
4085 return 0;
4086}
4087
4088static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
4089{
4090 struct sd *sd = (struct sd *) gspca_dev;
4091
4092 sd->gain = val;
4093 if (gspca_dev->streaming)
4094 setgain(gspca_dev);
4095 return gspca_dev->usb_err;
4096}
4097
4098static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
4099{
4100 struct sd *sd = (struct sd *) gspca_dev;
4101
4102 *val = sd->gain;
4103 return 0;
4104}
4105
4106static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
4107{
4108 struct sd *sd = (struct sd *) gspca_dev;
4109
4110 sd->exposure = val;
4111 if (gspca_dev->streaming)
4112 setexposure(gspca_dev);
4113 return gspca_dev->usb_err;
4114}
4115
4116static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
4117{
4118 struct sd *sd = (struct sd *) gspca_dev;
4119
4120 *val = sd->exposure;
4121 return 0;
4122}
4123
4124static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
4125{
4126 struct sd *sd = (struct sd *) gspca_dev;
4127
4128 sd->autogain = val;
4129 if (gspca_dev->streaming)
4130 setautogain(gspca_dev);
4131
4132 return gspca_dev->usb_err;
4133}
4134
4135static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
4136{
4137 struct sd *sd = (struct sd *) gspca_dev;
4138
4139 *val = sd->autogain;
4140 return 0;
4141}
4142
4143static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val)
4144{
4145 struct sd *sd = (struct sd *) gspca_dev;
4146
4147 sd->backlight = val;
4148 if (gspca_dev->streaming)
4149 setbacklight(gspca_dev);
4150
4151 return gspca_dev->usb_err;
4152}
4153
4154static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val)
4155{
4156 struct sd *sd = (struct sd *) gspca_dev;
4157
4158 *val = sd->backlight;
4159 return 0;
4160}
4161
4162static int sd_querymenu(struct gspca_dev *gspca_dev,
4163 struct v4l2_querymenu *menu)
4164{
4165 static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"};
4166
4167 switch (menu->id) {
4168 case V4L2_CID_POWER_LINE_FREQUENCY:
4169 if (menu->index >= ARRAY_SIZE(freq_nm))
4170 break;
4171 strcpy((char *) menu->name, freq_nm[menu->index]);
4172 return 0;
4173 }
4174 return -EINVAL;
4175}
4176
4177/* sub-driver description */
4178static const struct sd_desc sd_desc = {
4179 .name = MODULE_NAME,
4180 .ctrls = sd_ctrls,
4181 .nctrls = ARRAY_SIZE(sd_ctrls),
4182 .config = sd_config,
4183 .init = sd_init,
4184 .start = sd_start,
4185 .stopN = sd_stopN,
4186 .stop0 = sd_stop0,
4187 .pkt_scan = sd_pkt_scan,
4188 .querymenu = sd_querymenu,
4189};
4190
4191/* -- module initialisation -- */
4192#define BF(bridge, flags) \
4193 .driver_info = (BRIDGE_ ## bridge << 8) \
4194 | (flags)
4195static const struct usb_device_id device_table[] = {
4196 {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)},
4197 {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)},
4198 {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)},
4199 {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)},
4200 {USB_DEVICE(0x0ac8, 0x0321), BF(VC0321, 0)},
4201 {USB_DEVICE(0x0ac8, 0x0323), BF(VC0323, 0)},
4202 {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)},
4203 {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)},
4204 {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)},
4205 {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, FL_SAMSUNG)},
4206 {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)},
4207 {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)},
4208 {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)},
4209 {}
4210};
4211MODULE_DEVICE_TABLE(usb, device_table);
4212
4213/* -- device connect -- */
4214static int sd_probe(struct usb_interface *intf,
4215 const struct usb_device_id *id)
4216{
4217 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
4218 THIS_MODULE);
4219}
4220
4221static struct usb_driver sd_driver = {
4222 .name = MODULE_NAME,
4223 .id_table = device_table,
4224 .probe = sd_probe,
4225 .disconnect = gspca_disconnect,
4226#ifdef CONFIG_PM
4227 .suspend = gspca_suspend,
4228 .resume = gspca_resume,
4229#endif
4230};
4231
4232/* -- module insert / remove -- */
4233static int __init sd_mod_init(void)
4234{
4235 return usb_register(&sd_driver);
4236}
4237static void __exit sd_mod_exit(void)
4238{
4239 usb_deregister(&sd_driver);
4240}
4241
4242module_init(sd_mod_init);
4243module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c
new file mode 100644
index 00000000000..84dfbab923b
--- /dev/null
+++ b/drivers/media/video/gspca/vicam.c
@@ -0,0 +1,381 @@
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 MODULE_NAME "vicam"
30#define HEADER_SIZE 64
31
32#include <linux/workqueue.h>
33#include <linux/slab.h>
34#include <linux/firmware.h>
35#include <linux/ihex.h>
36#include "gspca.h"
37
38MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
39MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
40MODULE_LICENSE("GPL");
41
42enum e_ctrl {
43 GAIN,
44 EXPOSURE,
45 NCTRL /* number of controls */
46};
47
48struct sd {
49 struct gspca_dev gspca_dev; /* !! must be the first item */
50 struct work_struct work_struct;
51 struct workqueue_struct *work_thread;
52 struct gspca_ctrl ctrls[NCTRL];
53};
54
55/* The vicam sensor has a resolution of 512 x 244, with I believe square
56 pixels, but this is forced to a 4:3 ratio by optics. So it has
57 non square pixels :( */
58static struct v4l2_pix_format vicam_mode[] = {
59 { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
60 .bytesperline = 256,
61 .sizeimage = 256 * 122,
62 .colorspace = V4L2_COLORSPACE_SRGB,},
63 /* 2 modes with somewhat more square pixels */
64 { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
65 .bytesperline = 256,
66 .sizeimage = 256 * 200,
67 .colorspace = V4L2_COLORSPACE_SRGB,},
68 { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
69 .bytesperline = 256,
70 .sizeimage = 256 * 240,
71 .colorspace = V4L2_COLORSPACE_SRGB,},
72#if 0 /* This mode has extremely non square pixels, testing use only */
73 { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
74 .bytesperline = 512,
75 .sizeimage = 512 * 122,
76 .colorspace = V4L2_COLORSPACE_SRGB,},
77#endif
78 { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
79 .bytesperline = 512,
80 .sizeimage = 512 * 244,
81 .colorspace = V4L2_COLORSPACE_SRGB,},
82};
83
84static const struct ctrl sd_ctrls[] = {
85[GAIN] = {
86 {
87 .id = V4L2_CID_GAIN,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Gain",
90 .minimum = 0,
91 .maximum = 255,
92 .step = 1,
93 .default_value = 200,
94 },
95 },
96[EXPOSURE] = {
97 {
98 .id = V4L2_CID_EXPOSURE,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Exposure",
101 .minimum = 0,
102 .maximum = 2047,
103 .step = 1,
104 .default_value = 256,
105 },
106 },
107};
108
109static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
110 u16 value, u16 index, u8 *data, u16 len)
111{
112 int ret;
113
114 ret = usb_control_msg(gspca_dev->dev,
115 usb_sndctrlpipe(gspca_dev->dev, 0),
116 request,
117 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
118 value, index, data, len, 1000);
119 if (ret < 0)
120 err("control msg req %02X error %d", request, ret);
121
122 return ret;
123}
124
125static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
126{
127 int ret;
128
129 ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
130 if (ret < 0)
131 return ret;
132
133 if (state)
134 ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
135
136 return ret;
137}
138
139/*
140 * request and read a block of data - see warning on vicam_command.
141 */
142static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
143{
144 struct sd *sd = (struct sd *)gspca_dev;
145 int ret, unscaled_height, act_len = 0;
146 u8 *req_data = gspca_dev->usb_buf;
147
148 memset(req_data, 0, 16);
149 req_data[0] = sd->ctrls[GAIN].val;
150 if (gspca_dev->width == 256)
151 req_data[1] |= 0x01; /* low nibble x-scale */
152 if (gspca_dev->height <= 122) {
153 req_data[1] |= 0x10; /* high nibble y-scale */
154 unscaled_height = gspca_dev->height * 2;
155 } else
156 unscaled_height = gspca_dev->height;
157 req_data[2] = 0x90; /* unknown, does not seem to do anything */
158 if (unscaled_height <= 200)
159 req_data[3] = 0x06; /* vend? */
160 else if (unscaled_height <= 242) /* Yes 242 not 240 */
161 req_data[3] = 0x07; /* vend? */
162 else /* Up to 244 lines with req_data[3] == 0x08 */
163 req_data[3] = 0x08; /* vend? */
164
165 if (sd->ctrls[EXPOSURE].val < 256) {
166 /* Frame rate maxed out, use partial frame expo time */
167 req_data[4] = 255 - sd->ctrls[EXPOSURE].val;
168 req_data[5] = 0x00;
169 req_data[6] = 0x00;
170 req_data[7] = 0x01;
171 } else {
172 /* Modify frame rate */
173 req_data[4] = 0x00;
174 req_data[5] = 0x00;
175 req_data[6] = sd->ctrls[EXPOSURE].val & 0xFF;
176 req_data[7] = sd->ctrls[EXPOSURE].val >> 8;
177 }
178 req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */
179 /* bytes 9-15 do not seem to affect exposure or image quality */
180
181 mutex_lock(&gspca_dev->usb_lock);
182 ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
183 mutex_unlock(&gspca_dev->usb_lock);
184 if (ret < 0)
185 return ret;
186
187 ret = usb_bulk_msg(gspca_dev->dev,
188 usb_rcvbulkpipe(gspca_dev->dev, 0x81),
189 data, size, &act_len, 10000);
190 /* successful, it returns 0, otherwise negative */
191 if (ret < 0 || act_len != size) {
192 err("bulk read fail (%d) len %d/%d",
193 ret, act_len, size);
194 return -EIO;
195 }
196 return 0;
197}
198
199/* This function is called as a workqueue function and runs whenever the camera
200 * is streaming data. Because it is a workqueue function it is allowed to sleep
201 * so we can use synchronous USB calls. To avoid possible collisions with other
202 * threads attempting to use the camera's USB interface we take the gspca
203 * usb_lock when performing USB operations. In practice the only thing we need
204 * to protect against is the usb_set_interface call that gspca makes during
205 * stream_off as the camera doesn't provide any controls that the user could try
206 * to change.
207 */
208static void vicam_dostream(struct work_struct *work)
209{
210 struct sd *sd = container_of(work, struct sd, work_struct);
211 struct gspca_dev *gspca_dev = &sd->gspca_dev;
212 int ret, frame_sz;
213 u8 *buffer;
214
215 frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
216 HEADER_SIZE;
217 buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
218 if (!buffer) {
219 err("Couldn't allocate USB buffer");
220 goto exit;
221 }
222
223 while (gspca_dev->present && gspca_dev->streaming) {
224 ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
225 if (ret < 0)
226 break;
227
228 /* Note the frame header contents seem to be completely
229 constant, they do not change with either image, or
230 settings. So we simply discard it. The frames have
231 a very similar 64 byte footer, which we don't even
232 bother reading from the cam */
233 gspca_frame_add(gspca_dev, FIRST_PACKET,
234 buffer + HEADER_SIZE,
235 frame_sz - HEADER_SIZE);
236 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
237 }
238exit:
239 kfree(buffer);
240}
241
242/* This function is called at probe time just before sd_init */
243static int sd_config(struct gspca_dev *gspca_dev,
244 const struct usb_device_id *id)
245{
246 struct cam *cam = &gspca_dev->cam;
247 struct sd *sd = (struct sd *)gspca_dev;
248
249 /* We don't use the buffer gspca allocates so make it small. */
250 cam->bulk = 1;
251 cam->bulk_size = 64;
252 cam->cam_mode = vicam_mode;
253 cam->nmodes = ARRAY_SIZE(vicam_mode);
254 cam->ctrls = sd->ctrls;
255
256 INIT_WORK(&sd->work_struct, vicam_dostream);
257
258 return 0;
259}
260
261/* this function is called at probe and resume time */
262static int sd_init(struct gspca_dev *gspca_dev)
263{
264 int ret;
265 const struct ihex_binrec *rec;
266 const struct firmware *uninitialized_var(fw);
267 u8 *firmware_buf;
268
269 ret = request_ihex_firmware(&fw, "vicam/firmware.fw",
270 &gspca_dev->dev->dev);
271 if (ret) {
272 err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
273 return ret;
274 }
275
276 firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
277 if (!firmware_buf) {
278 ret = -ENOMEM;
279 goto exit;
280 }
281 for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
282 memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
283 ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
284 be16_to_cpu(rec->len));
285 if (ret < 0)
286 break;
287 }
288
289 kfree(firmware_buf);
290exit:
291 release_firmware(fw);
292 return ret;
293}
294
295/* Set up for getting frames. */
296static int sd_start(struct gspca_dev *gspca_dev)
297{
298 struct sd *sd = (struct sd *)gspca_dev;
299 int ret;
300
301 ret = vicam_set_camera_power(gspca_dev, 1);
302 if (ret < 0)
303 return ret;
304
305 /* Start the workqueue function to do the streaming */
306 sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
307 queue_work(sd->work_thread, &sd->work_struct);
308
309 return 0;
310}
311
312/* called on streamoff with alt==0 and on disconnect */
313/* the usb_lock is held at entry - restore on exit */
314static void sd_stop0(struct gspca_dev *gspca_dev)
315{
316 struct sd *dev = (struct sd *)gspca_dev;
317
318 /* wait for the work queue to terminate */
319 mutex_unlock(&gspca_dev->usb_lock);
320 /* This waits for vicam_dostream to finish */
321 destroy_workqueue(dev->work_thread);
322 dev->work_thread = NULL;
323 mutex_lock(&gspca_dev->usb_lock);
324
325 vicam_set_camera_power(gspca_dev, 0);
326}
327
328/* Table of supported USB devices */
329static const struct usb_device_id device_table[] = {
330 {USB_DEVICE(0x04c1, 0x009d)},
331 {USB_DEVICE(0x0602, 0x1001)},
332 {}
333};
334
335MODULE_DEVICE_TABLE(usb, device_table);
336
337/* sub-driver description */
338static const struct sd_desc sd_desc = {
339 .name = MODULE_NAME,
340 .ctrls = sd_ctrls,
341 .nctrls = ARRAY_SIZE(sd_ctrls),
342 .config = sd_config,
343 .init = sd_init,
344 .start = sd_start,
345 .stop0 = sd_stop0,
346};
347
348/* -- device connect -- */
349static int sd_probe(struct usb_interface *intf,
350 const struct usb_device_id *id)
351{
352 return gspca_dev_probe(intf, id,
353 &sd_desc,
354 sizeof(struct sd),
355 THIS_MODULE);
356}
357
358static struct usb_driver sd_driver = {
359 .name = MODULE_NAME,
360 .id_table = device_table,
361 .probe = sd_probe,
362 .disconnect = gspca_disconnect,
363#ifdef CONFIG_PM
364 .suspend = gspca_suspend,
365 .resume = gspca_resume,
366#endif
367};
368
369/* -- module insert / remove -- */
370static int __init sd_mod_init(void)
371{
372 return usb_register(&sd_driver);
373}
374
375static void __exit sd_mod_exit(void)
376{
377 usb_deregister(&sd_driver);
378}
379
380module_init(sd_mod_init);
381module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c
new file mode 100644
index 00000000000..4a9e622e5e1
--- /dev/null
+++ b/drivers/media/video/gspca/w996Xcf.c
@@ -0,0 +1,558 @@
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 W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */
35
36#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
37#define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET])
38
39static const struct v4l2_pix_format w9968cf_vga_mode[] = {
40 {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
41 .bytesperline = 160 * 2,
42 .sizeimage = 160 * 120 * 2,
43 .colorspace = V4L2_COLORSPACE_JPEG},
44 {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
45 .bytesperline = 176 * 2,
46 .sizeimage = 176 * 144 * 2,
47 .colorspace = V4L2_COLORSPACE_JPEG},
48 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
49 .bytesperline = 320 * 2,
50 .sizeimage = 320 * 240 * 2,
51 .colorspace = V4L2_COLORSPACE_JPEG},
52 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
53 .bytesperline = 352 * 2,
54 .sizeimage = 352 * 288 * 2,
55 .colorspace = V4L2_COLORSPACE_JPEG},
56 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
57 .bytesperline = 640 * 2,
58 .sizeimage = 640 * 480 * 2,
59 .colorspace = V4L2_COLORSPACE_JPEG},
60};
61
62static void reg_w(struct sd *sd, u16 index, u16 value);
63
64/*--------------------------------------------------------------------------
65 Write 64-bit data to the fast serial bus registers.
66 Return 0 on success, -1 otherwise.
67 --------------------------------------------------------------------------*/
68static void w9968cf_write_fsb(struct sd *sd, u16* data)
69{
70 struct usb_device *udev = sd->gspca_dev.dev;
71 u16 value;
72 int ret;
73
74 if (sd->gspca_dev.usb_err < 0)
75 return;
76
77 value = *data++;
78 memcpy(sd->gspca_dev.usb_buf, data, 6);
79
80 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
81 USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
82 value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
83 if (ret < 0) {
84 err("Write FSB registers failed (%d)", ret);
85 sd->gspca_dev.usb_err = ret;
86 }
87}
88
89/*--------------------------------------------------------------------------
90 Write data to the serial bus control register.
91 Return 0 on success, a negative number otherwise.
92 --------------------------------------------------------------------------*/
93static void w9968cf_write_sb(struct sd *sd, u16 value)
94{
95 int ret;
96
97 if (sd->gspca_dev.usb_err < 0)
98 return;
99
100 /* We don't use reg_w here, as that would cause all writes when
101 bitbanging i2c to be logged, making the logs impossible to read */
102 ret = usb_control_msg(sd->gspca_dev.dev,
103 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
104 0,
105 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
106 value, 0x01, NULL, 0, 500);
107
108 udelay(W9968CF_I2C_BUS_DELAY);
109
110 if (ret < 0) {
111 err("Write SB reg [01] %04x failed", value);
112 sd->gspca_dev.usb_err = ret;
113 }
114}
115
116/*--------------------------------------------------------------------------
117 Read data from the serial bus control register.
118 Return 0 on success, a negative number otherwise.
119 --------------------------------------------------------------------------*/
120static int w9968cf_read_sb(struct sd *sd)
121{
122 int ret;
123
124 if (sd->gspca_dev.usb_err < 0)
125 return -1;
126
127 /* We don't use reg_r here, as the w9968cf is special and has 16
128 bit registers instead of 8 bit */
129 ret = usb_control_msg(sd->gspca_dev.dev,
130 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
131 1,
132 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
133 0, 0x01, sd->gspca_dev.usb_buf, 2, 500);
134 if (ret >= 0) {
135 ret = sd->gspca_dev.usb_buf[0] |
136 (sd->gspca_dev.usb_buf[1] << 8);
137 } else {
138 err("Read SB reg [01] failed");
139 sd->gspca_dev.usb_err = ret;
140 }
141
142 udelay(W9968CF_I2C_BUS_DELAY);
143
144 return ret;
145}
146
147/*--------------------------------------------------------------------------
148 Upload quantization tables for the JPEG compression.
149 This function is called by w9968cf_start_transfer().
150 Return 0 on success, a negative number otherwise.
151 --------------------------------------------------------------------------*/
152static void w9968cf_upload_quantizationtables(struct sd *sd)
153{
154 u16 a, b;
155 int i, j;
156
157 reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
158
159 for (i = 0, j = 0; i < 32; i++, j += 2) {
160 a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8);
161 b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8);
162 reg_w(sd, 0x40 + i, a);
163 reg_w(sd, 0x60 + i, b);
164 }
165 reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
166}
167
168/****************************************************************************
169 * Low-level I2C I/O functions. *
170 * The adapter supports the following I2C transfer functions: *
171 * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) *
172 * i2c_adap_read_byte_data() *
173 * i2c_adap_read_byte() *
174 ****************************************************************************/
175
176static void w9968cf_smbus_start(struct sd *sd)
177{
178 w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
179 w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
180}
181
182static void w9968cf_smbus_stop(struct sd *sd)
183{
184 w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
185 w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
186 w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
187}
188
189static void w9968cf_smbus_write_byte(struct sd *sd, u8 v)
190{
191 u8 bit;
192 int sda;
193
194 for (bit = 0 ; bit < 8 ; bit++) {
195 sda = (v & 0x80) ? 2 : 0;
196 v <<= 1;
197 /* SDE=1, SDA=sda, SCL=0 */
198 w9968cf_write_sb(sd, 0x10 | sda);
199 /* SDE=1, SDA=sda, SCL=1 */
200 w9968cf_write_sb(sd, 0x11 | sda);
201 /* SDE=1, SDA=sda, SCL=0 */
202 w9968cf_write_sb(sd, 0x10 | sda);
203 }
204}
205
206static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v)
207{
208 u8 bit;
209
210 /* No need to ensure SDA is high as we are always called after
211 read_ack which ends with SDA high */
212 *v = 0;
213 for (bit = 0 ; bit < 8 ; bit++) {
214 *v <<= 1;
215 /* SDE=1, SDA=1, SCL=1 */
216 w9968cf_write_sb(sd, 0x0013);
217 *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0;
218 /* SDE=1, SDA=1, SCL=0 */
219 w9968cf_write_sb(sd, 0x0012);
220 }
221}
222
223static void w9968cf_smbus_write_nack(struct sd *sd)
224{
225 /* No need to ensure SDA is high as we are always called after
226 read_byte which ends with SDA high */
227 w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
228 w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
229}
230
231static void w9968cf_smbus_read_ack(struct sd *sd)
232{
233 int sda;
234
235 /* Ensure SDA is high before raising clock to avoid a spurious stop */
236 w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
237 w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
238 sda = w9968cf_read_sb(sd);
239 w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
240 if (sda >= 0 && (sda & 0x08)) {
241 PDEBUG(D_USBI, "Did not receive i2c ACK");
242 sd->gspca_dev.usb_err = -EIO;
243 }
244}
245
246/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
247static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
248{
249 u16* data = (u16 *)sd->gspca_dev.usb_buf;
250
251 data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
252 data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0;
253 data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0);
254 data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0;
255 data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0;
256 data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0);
257 data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0;
258 data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0;
259 data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0);
260 data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0;
261
262 w9968cf_write_fsb(sd, data);
263
264 data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0);
265 data[0] |= (reg & 0x40) ? 0x0540 : 0x0;
266 data[0] |= (reg & 0x20) ? 0x5000 : 0x0;
267 data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0);
268 data[1] |= (reg & 0x10) ? 0x0054 : 0x0;
269 data[1] |= (reg & 0x08) ? 0x1500 : 0x0;
270 data[1] |= (reg & 0x04) ? 0x4000 : 0x0;
271 data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0);
272 data[2] |= (reg & 0x02) ? 0x0150 : 0x0;
273 data[2] |= (reg & 0x01) ? 0x5400 : 0x0;
274 data[3] = 0x001d;
275
276 w9968cf_write_fsb(sd, data);
277
278 data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
279 data[0] |= (value & 0x40) ? 0x0540 : 0x0;
280 data[0] |= (value & 0x20) ? 0x5000 : 0x0;
281 data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0);
282 data[1] |= (value & 0x10) ? 0x0054 : 0x0;
283 data[1] |= (value & 0x08) ? 0x1500 : 0x0;
284 data[1] |= (value & 0x04) ? 0x4000 : 0x0;
285 data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0);
286 data[2] |= (value & 0x02) ? 0x0150 : 0x0;
287 data[2] |= (value & 0x01) ? 0x5400 : 0x0;
288 data[3] = 0xfe1d;
289
290 w9968cf_write_fsb(sd, data);
291
292 PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
293}
294
295/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
296static int w9968cf_i2c_r(struct sd *sd, u8 reg)
297{
298 int ret = 0;
299 u8 value;
300
301 /* Fast serial bus data control disable */
302 w9968cf_write_sb(sd, 0x0013); /* don't change ! */
303
304 w9968cf_smbus_start(sd);
305 w9968cf_smbus_write_byte(sd, sd->sensor_addr);
306 w9968cf_smbus_read_ack(sd);
307 w9968cf_smbus_write_byte(sd, reg);
308 w9968cf_smbus_read_ack(sd);
309 w9968cf_smbus_stop(sd);
310 w9968cf_smbus_start(sd);
311 w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
312 w9968cf_smbus_read_ack(sd);
313 w9968cf_smbus_read_byte(sd, &value);
314 /* signal we don't want to read anymore, the v4l1 driver used to
315 send an ack here which is very wrong! (and then fixed
316 the issues this gave by retrying reads) */
317 w9968cf_smbus_write_nack(sd);
318 w9968cf_smbus_stop(sd);
319
320 /* Fast serial bus data control re-enable */
321 w9968cf_write_sb(sd, 0x0030);
322
323 if (sd->gspca_dev.usb_err >= 0) {
324 ret = value;
325 PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
326 } else
327 PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg);
328
329 return ret;
330}
331
332/*--------------------------------------------------------------------------
333 Turn on the LED on some webcams. A beep should be heard too.
334 Return 0 on success, a negative number otherwise.
335 --------------------------------------------------------------------------*/
336static void w9968cf_configure(struct sd *sd)
337{
338 reg_w(sd, 0x00, 0xff00); /* power-down */
339 reg_w(sd, 0x00, 0xbf17); /* reset everything */
340 reg_w(sd, 0x00, 0xbf10); /* normal operation */
341 reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
342 reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
343 reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
344 reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
345
346 sd->stopped = 1;
347}
348
349static void w9968cf_init(struct sd *sd)
350{
351 unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2),
352 y0 = 0x0000,
353 u0 = y0 + hw_bufsize / 2,
354 v0 = u0 + hw_bufsize / 4,
355 y1 = v0 + hw_bufsize / 4,
356 u1 = y1 + hw_bufsize / 2,
357 v1 = u1 + hw_bufsize / 4;
358
359 reg_w(sd, 0x00, 0xff00); /* power off */
360 reg_w(sd, 0x00, 0xbf10); /* power on */
361
362 reg_w(sd, 0x03, 0x405d); /* DRAM timings */
363 reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
364
365 reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
366 reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */
367 reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
368 reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */
369 reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
370 reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */
371
372 reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
373 reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */
374 reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
375 reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */
376 reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
377 reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */
378
379 reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
380 reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */
381
382 reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
383 reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */
384
385 reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
386 reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
387 reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
388 reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
389}
390
391static void w9968cf_set_crop_window(struct sd *sd)
392{
393 int start_cropx, start_cropy, x, y, fw, fh, cw, ch,
394 max_width, max_height;
395
396 if (sd->sif) {
397 max_width = 352;
398 max_height = 288;
399 } else {
400 max_width = 640;
401 max_height = 480;
402 }
403
404 if (sd->sensor == SEN_OV7620) {
405 /* Sigh, this is dependend on the clock / framerate changes
406 made by the frequency control, sick. */
407 if (sd->ctrls[FREQ].val == 1) {
408 start_cropx = 277;
409 start_cropy = 37;
410 } else {
411 start_cropx = 105;
412 start_cropy = 37;
413 }
414 } else {
415 start_cropx = 320;
416 start_cropy = 35;
417 }
418
419 /* Work around to avoid FP arithmetics */
420 #define SC(x) ((x) << 10)
421
422 /* Scaling factors */
423 fw = SC(sd->gspca_dev.width) / max_width;
424 fh = SC(sd->gspca_dev.height) / max_height;
425
426 cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
427 ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
428
429 sd->sensor_width = max_width;
430 sd->sensor_height = max_height;
431
432 x = (max_width - cw) / 2;
433 y = (max_height - ch) / 2;
434
435 reg_w(sd, 0x10, start_cropx + x);
436 reg_w(sd, 0x11, start_cropy + y);
437 reg_w(sd, 0x12, start_cropx + x + cw);
438 reg_w(sd, 0x13, start_cropy + y + ch);
439}
440
441static void w9968cf_mode_init_regs(struct sd *sd)
442{
443 int val, vs_polarity, hs_polarity;
444
445 w9968cf_set_crop_window(sd);
446
447 reg_w(sd, 0x14, sd->gspca_dev.width);
448 reg_w(sd, 0x15, sd->gspca_dev.height);
449
450 /* JPEG width & height */
451 reg_w(sd, 0x30, sd->gspca_dev.width);
452 reg_w(sd, 0x31, sd->gspca_dev.height);
453
454 /* Y & UV frame buffer strides (in WORD) */
455 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
456 V4L2_PIX_FMT_JPEG) {
457 reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
458 reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
459 } else
460 reg_w(sd, 0x2c, sd->gspca_dev.width);
461
462 reg_w(sd, 0x00, 0xbf17); /* reset everything */
463 reg_w(sd, 0x00, 0xbf10); /* normal operation */
464
465 /* Transfer size in WORDS (for UYVY format only) */
466 val = sd->gspca_dev.width * sd->gspca_dev.height;
467 reg_w(sd, 0x3d, val & 0xffff); /* low bits */
468 reg_w(sd, 0x3e, val >> 16); /* high bits */
469
470 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
471 V4L2_PIX_FMT_JPEG) {
472 /* We may get called multiple times (usb isoc bw negotiat.) */
473 jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
474 sd->gspca_dev.width, 0x22); /* JPEG 420 */
475 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
476 w9968cf_upload_quantizationtables(sd);
477 }
478
479 /* Video Capture Control Register */
480 if (sd->sensor == SEN_OV7620) {
481 /* Seems to work around a bug in the image sensor */
482 vs_polarity = 1;
483 hs_polarity = 1;
484 } else {
485 vs_polarity = 1;
486 hs_polarity = 0;
487 }
488
489 val = (vs_polarity << 12) | (hs_polarity << 11);
490
491 /* NOTE: We may not have enough memory to do double buffering while
492 doing compression (amount of memory differs per model cam).
493 So we use the second image buffer also as jpeg stream buffer
494 (see w9968cf_init), and disable double buffering. */
495 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
496 V4L2_PIX_FMT_JPEG) {
497 /* val |= 0x0002; YUV422P */
498 val |= 0x0003; /* YUV420P */
499 } else
500 val |= 0x0080; /* Enable HW double buffering */
501
502 /* val |= 0x0020; enable clamping */
503 /* val |= 0x0008; enable (1-2-1) filter */
504 /* val |= 0x000c; enable (2-3-6-3-2) filter */
505
506 val |= 0x8000; /* capt. enable */
507
508 reg_w(sd, 0x16, val);
509
510 sd->gspca_dev.empty_packet = 0;
511}
512
513static void w9968cf_stop0(struct sd *sd)
514{
515 reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
516 reg_w(sd, 0x16, 0x0000); /* stop video capture */
517}
518
519/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF
520 for the next frame). This seems to simply not be true when operating
521 in JPEG mode, in this case there may be empty packets within the
522 frame. So in JPEG mode use the JPEG SOI marker to detect SOF.
523
524 Note to make things even more interesting the w9968cf sends *PLANAR* jpeg,
525 to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS,
526 V-data, EOI. */
527static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev,
528 u8 *data, /* isoc packet */
529 int len) /* iso packet length */
530{
531 struct sd *sd = (struct sd *) gspca_dev;
532
533 if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat ==
534 V4L2_PIX_FMT_JPEG) {
535 if (len >= 2 &&
536 data[0] == 0xff &&
537 data[1] == 0xd8) {
538 gspca_frame_add(gspca_dev, LAST_PACKET,
539 NULL, 0);
540 gspca_frame_add(gspca_dev, FIRST_PACKET,
541 sd->jpeg_hdr, JPEG_HDR_SZ);
542 /* Strip the ff d8, our own header (which adds
543 huffman and quantization tables) already has this */
544 len -= 2;
545 data += 2;
546 }
547 } else {
548 /* In UYVY mode an empty packet signals EOF */
549 if (gspca_dev->empty_packet) {
550 gspca_frame_add(gspca_dev, LAST_PACKET,
551 NULL, 0);
552 gspca_frame_add(gspca_dev, FIRST_PACKET,
553 NULL, 0);
554 gspca_dev->empty_packet = 0;
555 }
556 }
557 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
558}
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
new file mode 100644
index 00000000000..c089a0f6f1d
--- /dev/null
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -0,0 +1,3337 @@
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 MODULE_NAME "xirlink-cit"
31
32#include <linux/input.h>
33#include "gspca.h"
34
35MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
36MODULE_DESCRIPTION("Xirlink C-IT");
37MODULE_LICENSE("GPL");
38
39/* FIXME we should autodetect this */
40static int ibm_netcam_pro;
41module_param(ibm_netcam_pro, int, 0);
42MODULE_PARM_DESC(ibm_netcam_pro,
43 "Use IBM Netcamera Pro init sequences for Model 3 cams");
44
45/* FIXME this should be handled through the V4L2 input selection API */
46static int rca_input;
47module_param(rca_input, int, 0644);
48MODULE_PARM_DESC(rca_input,
49 "Use rca input instead of ccd sensor on Model 3 cams");
50
51/* specific webcam descriptor */
52struct sd {
53 struct gspca_dev gspca_dev; /* !! must be the first item */
54 u8 model;
55#define CIT_MODEL0 0 /* bcd version 0.01 cams ie the xvp-500 */
56#define CIT_MODEL1 1 /* The model 1 - 4 nomenclature comes from the old */
57#define CIT_MODEL2 2 /* ibmcam driver */
58#define CIT_MODEL3 3
59#define CIT_MODEL4 4
60#define CIT_IBM_NETCAM_PRO 5
61 u8 input_index;
62 u8 button_state;
63 u8 stop_on_control_change;
64 u8 sof_read;
65 u8 sof_len;
66 u8 contrast;
67 u8 brightness;
68 u8 hue;
69 u8 sharpness;
70 u8 lighting;
71 u8 hflip;
72};
73
74/* V4L2 controls supported by the driver */
75static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
83static int sd_setlighting(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getlighting(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
87static void sd_stop0(struct gspca_dev *gspca_dev);
88
89static const struct ctrl sd_ctrls[] = {
90#define SD_BRIGHTNESS 0
91 {
92 {
93 .id = V4L2_CID_BRIGHTNESS,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Brightness",
96 .minimum = 0,
97 .maximum = 63,
98 .step = 1,
99#define BRIGHTNESS_DEFAULT 32
100 .default_value = BRIGHTNESS_DEFAULT,
101 .flags = 0,
102 },
103 .set = sd_setbrightness,
104 .get = sd_getbrightness,
105 },
106#define SD_CONTRAST 1
107 {
108 {
109 .id = V4L2_CID_CONTRAST,
110 .type = V4L2_CTRL_TYPE_INTEGER,
111 .name = "contrast",
112 .minimum = 0,
113 .maximum = 20,
114 .step = 1,
115#define CONTRAST_DEFAULT 10
116 .default_value = CONTRAST_DEFAULT,
117 .flags = 0,
118 },
119 .set = sd_setcontrast,
120 .get = sd_getcontrast,
121 },
122#define SD_HUE 2
123 {
124 {
125 .id = V4L2_CID_HUE,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Hue",
128 .minimum = 0,
129 .maximum = 127,
130 .step = 1,
131#define HUE_DEFAULT 63
132 .default_value = HUE_DEFAULT,
133 .flags = 0,
134 },
135 .set = sd_sethue,
136 .get = sd_gethue,
137 },
138#define SD_SHARPNESS 3
139 {
140 {
141 .id = V4L2_CID_SHARPNESS,
142 .type = V4L2_CTRL_TYPE_INTEGER,
143 .name = "Sharpness",
144 .minimum = 0,
145 .maximum = 6,
146 .step = 1,
147#define SHARPNESS_DEFAULT 3
148 .default_value = SHARPNESS_DEFAULT,
149 .flags = 0,
150 },
151 .set = sd_setsharpness,
152 .get = sd_getsharpness,
153 },
154#define SD_LIGHTING 4
155 {
156 {
157 .id = V4L2_CID_BACKLIGHT_COMPENSATION,
158 .type = V4L2_CTRL_TYPE_INTEGER,
159 .name = "Lighting",
160 .minimum = 0,
161 .maximum = 2,
162 .step = 1,
163#define LIGHTING_DEFAULT 1
164 .default_value = LIGHTING_DEFAULT,
165 .flags = 0,
166 },
167 .set = sd_setlighting,
168 .get = sd_getlighting,
169 },
170#define SD_HFLIP 5
171 {
172 {
173 .id = V4L2_CID_HFLIP,
174 .type = V4L2_CTRL_TYPE_BOOLEAN,
175 .name = "Mirror",
176 .minimum = 0,
177 .maximum = 1,
178 .step = 1,
179#define HFLIP_DEFAULT 0
180 .default_value = HFLIP_DEFAULT,
181 },
182 .set = sd_sethflip,
183 .get = sd_gethflip,
184 },
185};
186
187static const struct v4l2_pix_format cif_yuv_mode[] = {
188 {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
189 .bytesperline = 176,
190 .sizeimage = 176 * 144 * 3 / 2 + 4,
191 .colorspace = V4L2_COLORSPACE_SRGB},
192 {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
193 .bytesperline = 352,
194 .sizeimage = 352 * 288 * 3 / 2 + 4,
195 .colorspace = V4L2_COLORSPACE_SRGB},
196};
197
198static const struct v4l2_pix_format vga_yuv_mode[] = {
199 {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
200 .bytesperline = 160,
201 .sizeimage = 160 * 120 * 3 / 2 + 4,
202 .colorspace = V4L2_COLORSPACE_SRGB},
203 {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
204 .bytesperline = 320,
205 .sizeimage = 320 * 240 * 3 / 2 + 4,
206 .colorspace = V4L2_COLORSPACE_SRGB},
207 {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
208 .bytesperline = 640,
209 .sizeimage = 640 * 480 * 3 / 2 + 4,
210 .colorspace = V4L2_COLORSPACE_SRGB},
211};
212
213static const struct v4l2_pix_format model0_mode[] = {
214 {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
215 .bytesperline = 160,
216 .sizeimage = 160 * 120 * 3 / 2 + 4,
217 .colorspace = V4L2_COLORSPACE_SRGB},
218 {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
219 .bytesperline = 176,
220 .sizeimage = 176 * 144 * 3 / 2 + 4,
221 .colorspace = V4L2_COLORSPACE_SRGB},
222 {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
223 .bytesperline = 320,
224 .sizeimage = 320 * 240 * 3 / 2 + 4,
225 .colorspace = V4L2_COLORSPACE_SRGB},
226};
227
228static const struct v4l2_pix_format model2_mode[] = {
229 {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
230 .bytesperline = 160,
231 .sizeimage = 160 * 120 * 3 / 2 + 4,
232 .colorspace = V4L2_COLORSPACE_SRGB},
233 {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
234 .bytesperline = 176,
235 .sizeimage = 176 * 144 * 3 / 2 + 4,
236 .colorspace = V4L2_COLORSPACE_SRGB},
237 {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
238 .bytesperline = 320,
239 .sizeimage = 320 * 240 + 4,
240 .colorspace = V4L2_COLORSPACE_SRGB},
241 {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
242 .bytesperline = 352,
243 .sizeimage = 352 * 288 + 4,
244 .colorspace = V4L2_COLORSPACE_SRGB},
245};
246
247/*
248 * 01.01.08 - Added for RCA video in support -LO
249 * This struct is used to init the Model3 cam to use the RCA video in port
250 * instead of the CCD sensor.
251 */
252static const u16 rca_initdata[][3] = {
253 {0, 0x0000, 0x010c},
254 {0, 0x0006, 0x012c},
255 {0, 0x0078, 0x012d},
256 {0, 0x0046, 0x012f},
257 {0, 0xd141, 0x0124},
258 {0, 0x0000, 0x0127},
259 {0, 0xfea8, 0x0124},
260 {1, 0x0000, 0x0116},
261 {0, 0x0064, 0x0116},
262 {1, 0x0000, 0x0115},
263 {0, 0x0003, 0x0115},
264 {0, 0x0008, 0x0123},
265 {0, 0x0000, 0x0117},
266 {0, 0x0000, 0x0112},
267 {0, 0x0080, 0x0100},
268 {0, 0x0000, 0x0100},
269 {1, 0x0000, 0x0116},
270 {0, 0x0060, 0x0116},
271 {0, 0x0002, 0x0112},
272 {0, 0x0000, 0x0123},
273 {0, 0x0001, 0x0117},
274 {0, 0x0040, 0x0108},
275 {0, 0x0019, 0x012c},
276 {0, 0x0040, 0x0116},
277 {0, 0x000a, 0x0115},
278 {0, 0x000b, 0x0115},
279 {0, 0x0078, 0x012d},
280 {0, 0x0046, 0x012f},
281 {0, 0xd141, 0x0124},
282 {0, 0x0000, 0x0127},
283 {0, 0xfea8, 0x0124},
284 {0, 0x0064, 0x0116},
285 {0, 0x0000, 0x0115},
286 {0, 0x0001, 0x0115},
287 {0, 0xffff, 0x0124},
288 {0, 0xfff9, 0x0124},
289 {0, 0x0086, 0x0127},
290 {0, 0xfff8, 0x0124},
291 {0, 0xfffd, 0x0124},
292 {0, 0x00aa, 0x0127},
293 {0, 0xfff8, 0x0124},
294 {0, 0xfffd, 0x0124},
295 {0, 0x0000, 0x0127},
296 {0, 0xfff8, 0x0124},
297 {0, 0xfffd, 0x0124},
298 {0, 0xfffa, 0x0124},
299 {0, 0xffff, 0x0124},
300 {0, 0xfff9, 0x0124},
301 {0, 0x0086, 0x0127},
302 {0, 0xfff8, 0x0124},
303 {0, 0xfffd, 0x0124},
304 {0, 0x00f2, 0x0127},
305 {0, 0xfff8, 0x0124},
306 {0, 0xfffd, 0x0124},
307 {0, 0x000f, 0x0127},
308 {0, 0xfff8, 0x0124},
309 {0, 0xfffd, 0x0124},
310 {0, 0xfffa, 0x0124},
311 {0, 0xffff, 0x0124},
312 {0, 0xfff9, 0x0124},
313 {0, 0x0086, 0x0127},
314 {0, 0xfff8, 0x0124},
315 {0, 0xfffd, 0x0124},
316 {0, 0x00f8, 0x0127},
317 {0, 0xfff8, 0x0124},
318 {0, 0xfffd, 0x0124},
319 {0, 0x00fc, 0x0127},
320 {0, 0xfff8, 0x0124},
321 {0, 0xfffd, 0x0124},
322 {0, 0xfffa, 0x0124},
323 {0, 0xffff, 0x0124},
324 {0, 0xfff9, 0x0124},
325 {0, 0x0086, 0x0127},
326 {0, 0xfff8, 0x0124},
327 {0, 0xfffd, 0x0124},
328 {0, 0x00f9, 0x0127},
329 {0, 0xfff8, 0x0124},
330 {0, 0xfffd, 0x0124},
331 {0, 0x003c, 0x0127},
332 {0, 0xfff8, 0x0124},
333 {0, 0xfffd, 0x0124},
334 {0, 0xfffa, 0x0124},
335 {0, 0xffff, 0x0124},
336 {0, 0xfff9, 0x0124},
337 {0, 0x0086, 0x0127},
338 {0, 0xfff8, 0x0124},
339 {0, 0xfffd, 0x0124},
340 {0, 0x0027, 0x0127},
341 {0, 0xfff8, 0x0124},
342 {0, 0xfffd, 0x0124},
343 {0, 0x0019, 0x0127},
344 {0, 0xfff8, 0x0124},
345 {0, 0xfffd, 0x0124},
346 {0, 0xfffa, 0x0124},
347 {0, 0xfff9, 0x0124},
348 {0, 0x0086, 0x0127},
349 {0, 0xfff8, 0x0124},
350 {0, 0xfffd, 0x0124},
351 {0, 0x0037, 0x0127},
352 {0, 0xfff8, 0x0124},
353 {0, 0xfffd, 0x0124},
354 {0, 0x0000, 0x0127},
355 {0, 0xfff8, 0x0124},
356 {0, 0xfffd, 0x0124},
357 {0, 0x0021, 0x0127},
358 {0, 0xfff8, 0x0124},
359 {0, 0xfffd, 0x0124},
360 {0, 0xfffa, 0x0124},
361 {0, 0xfff9, 0x0124},
362 {0, 0x0086, 0x0127},
363 {0, 0xfff8, 0x0124},
364 {0, 0xfffd, 0x0124},
365 {0, 0x0038, 0x0127},
366 {0, 0xfff8, 0x0124},
367 {0, 0xfffd, 0x0124},
368 {0, 0x0006, 0x0127},
369 {0, 0xfff8, 0x0124},
370 {0, 0xfffd, 0x0124},
371 {0, 0x0045, 0x0127},
372 {0, 0xfff8, 0x0124},
373 {0, 0xfffd, 0x0124},
374 {0, 0xfffa, 0x0124},
375 {0, 0xfff9, 0x0124},
376 {0, 0x0086, 0x0127},
377 {0, 0xfff8, 0x0124},
378 {0, 0xfffd, 0x0124},
379 {0, 0x0037, 0x0127},
380 {0, 0xfff8, 0x0124},
381 {0, 0xfffd, 0x0124},
382 {0, 0x0001, 0x0127},
383 {0, 0xfff8, 0x0124},
384 {0, 0xfffd, 0x0124},
385 {0, 0x002a, 0x0127},
386 {0, 0xfff8, 0x0124},
387 {0, 0xfffd, 0x0124},
388 {0, 0xfffa, 0x0124},
389 {0, 0xfff9, 0x0124},
390 {0, 0x0086, 0x0127},
391 {0, 0xfff8, 0x0124},
392 {0, 0xfffd, 0x0124},
393 {0, 0x0038, 0x0127},
394 {0, 0xfff8, 0x0124},
395 {0, 0xfffd, 0x0124},
396 {0, 0x0000, 0x0127},
397 {0, 0xfff8, 0x0124},
398 {0, 0xfffd, 0x0124},
399 {0, 0x000e, 0x0127},
400 {0, 0xfff8, 0x0124},
401 {0, 0xfffd, 0x0124},
402 {0, 0xfffa, 0x0124},
403 {0, 0xfff9, 0x0124},
404 {0, 0x0086, 0x0127},
405 {0, 0xfff8, 0x0124},
406 {0, 0xfffd, 0x0124},
407 {0, 0x0037, 0x0127},
408 {0, 0xfff8, 0x0124},
409 {0, 0xfffd, 0x0124},
410 {0, 0x0001, 0x0127},
411 {0, 0xfff8, 0x0124},
412 {0, 0xfffd, 0x0124},
413 {0, 0x002b, 0x0127},
414 {0, 0xfff8, 0x0124},
415 {0, 0xfffd, 0x0124},
416 {0, 0xfffa, 0x0124},
417 {0, 0xfff9, 0x0124},
418 {0, 0x0086, 0x0127},
419 {0, 0xfff8, 0x0124},
420 {0, 0xfffd, 0x0124},
421 {0, 0x0038, 0x0127},
422 {0, 0xfff8, 0x0124},
423 {0, 0xfffd, 0x0124},
424 {0, 0x0001, 0x0127},
425 {0, 0xfff8, 0x0124},
426 {0, 0xfffd, 0x0124},
427 {0, 0x00f4, 0x0127},
428 {0, 0xfff8, 0x0124},
429 {0, 0xfffd, 0x0124},
430 {0, 0xfffa, 0x0124},
431 {0, 0xfff9, 0x0124},
432 {0, 0x0086, 0x0127},
433 {0, 0xfff8, 0x0124},
434 {0, 0xfffd, 0x0124},
435 {0, 0x0037, 0x0127},
436 {0, 0xfff8, 0x0124},
437 {0, 0xfffd, 0x0124},
438 {0, 0x0001, 0x0127},
439 {0, 0xfff8, 0x0124},
440 {0, 0xfffd, 0x0124},
441 {0, 0x002c, 0x0127},
442 {0, 0xfff8, 0x0124},
443 {0, 0xfffd, 0x0124},
444 {0, 0xfffa, 0x0124},
445 {0, 0xfff9, 0x0124},
446 {0, 0x0086, 0x0127},
447 {0, 0xfff8, 0x0124},
448 {0, 0xfffd, 0x0124},
449 {0, 0x0038, 0x0127},
450 {0, 0xfff8, 0x0124},
451 {0, 0xfffd, 0x0124},
452 {0, 0x0001, 0x0127},
453 {0, 0xfff8, 0x0124},
454 {0, 0xfffd, 0x0124},
455 {0, 0x0004, 0x0127},
456 {0, 0xfff8, 0x0124},
457 {0, 0xfffd, 0x0124},
458 {0, 0xfffa, 0x0124},
459 {0, 0xfff9, 0x0124},
460 {0, 0x0086, 0x0127},
461 {0, 0xfff8, 0x0124},
462 {0, 0xfffd, 0x0124},
463 {0, 0x0037, 0x0127},
464 {0, 0xfff8, 0x0124},
465 {0, 0xfffd, 0x0124},
466 {0, 0x0001, 0x0127},
467 {0, 0xfff8, 0x0124},
468 {0, 0xfffd, 0x0124},
469 {0, 0x002d, 0x0127},
470 {0, 0xfff8, 0x0124},
471 {0, 0xfffd, 0x0124},
472 {0, 0xfffa, 0x0124},
473 {0, 0xfff9, 0x0124},
474 {0, 0x0086, 0x0127},
475 {0, 0xfff8, 0x0124},
476 {0, 0xfffd, 0x0124},
477 {0, 0x0038, 0x0127},
478 {0, 0xfff8, 0x0124},
479 {0, 0xfffd, 0x0124},
480 {0, 0x0000, 0x0127},
481 {0, 0xfff8, 0x0124},
482 {0, 0xfffd, 0x0124},
483 {0, 0x0014, 0x0127},
484 {0, 0xfff8, 0x0124},
485 {0, 0xfffd, 0x0124},
486 {0, 0xfffa, 0x0124},
487 {0, 0xfff9, 0x0124},
488 {0, 0x0086, 0x0127},
489 {0, 0xfff8, 0x0124},
490 {0, 0xfffd, 0x0124},
491 {0, 0x0037, 0x0127},
492 {0, 0xfff8, 0x0124},
493 {0, 0xfffd, 0x0124},
494 {0, 0x0001, 0x0127},
495 {0, 0xfff8, 0x0124},
496 {0, 0xfffd, 0x0124},
497 {0, 0x002e, 0x0127},
498 {0, 0xfff8, 0x0124},
499 {0, 0xfffd, 0x0124},
500 {0, 0xfffa, 0x0124},
501 {0, 0xfff9, 0x0124},
502 {0, 0x0086, 0x0127},
503 {0, 0xfff8, 0x0124},
504 {0, 0xfffd, 0x0124},
505 {0, 0x0038, 0x0127},
506 {0, 0xfff8, 0x0124},
507 {0, 0xfffd, 0x0124},
508 {0, 0x0003, 0x0127},
509 {0, 0xfff8, 0x0124},
510 {0, 0xfffd, 0x0124},
511 {0, 0x0000, 0x0127},
512 {0, 0xfff8, 0x0124},
513 {0, 0xfffd, 0x0124},
514 {0, 0xfffa, 0x0124},
515 {0, 0xfff9, 0x0124},
516 {0, 0x0086, 0x0127},
517 {0, 0xfff8, 0x0124},
518 {0, 0xfffd, 0x0124},
519 {0, 0x0037, 0x0127},
520 {0, 0xfff8, 0x0124},
521 {0, 0xfffd, 0x0124},
522 {0, 0x0001, 0x0127},
523 {0, 0xfff8, 0x0124},
524 {0, 0xfffd, 0x0124},
525 {0, 0x002f, 0x0127},
526 {0, 0xfff8, 0x0124},
527 {0, 0xfffd, 0x0124},
528 {0, 0xfffa, 0x0124},
529 {0, 0xfff9, 0x0124},
530 {0, 0x0086, 0x0127},
531 {0, 0xfff8, 0x0124},
532 {0, 0xfffd, 0x0124},
533 {0, 0x0038, 0x0127},
534 {0, 0xfff8, 0x0124},
535 {0, 0xfffd, 0x0124},
536 {0, 0x0003, 0x0127},
537 {0, 0xfff8, 0x0124},
538 {0, 0xfffd, 0x0124},
539 {0, 0x0014, 0x0127},
540 {0, 0xfff8, 0x0124},
541 {0, 0xfffd, 0x0124},
542 {0, 0xfffa, 0x0124},
543 {0, 0xfff9, 0x0124},
544 {0, 0x0086, 0x0127},
545 {0, 0xfff8, 0x0124},
546 {0, 0xfffd, 0x0124},
547 {0, 0x0037, 0x0127},
548 {0, 0xfff8, 0x0124},
549 {0, 0xfffd, 0x0124},
550 {0, 0x0001, 0x0127},
551 {0, 0xfff8, 0x0124},
552 {0, 0xfffd, 0x0124},
553 {0, 0x0040, 0x0127},
554 {0, 0xfff8, 0x0124},
555 {0, 0xfffd, 0x0124},
556 {0, 0xfffa, 0x0124},
557 {0, 0xfff9, 0x0124},
558 {0, 0x0086, 0x0127},
559 {0, 0xfff8, 0x0124},
560 {0, 0xfffd, 0x0124},
561 {0, 0x0038, 0x0127},
562 {0, 0xfff8, 0x0124},
563 {0, 0xfffd, 0x0124},
564 {0, 0x0000, 0x0127},
565 {0, 0xfff8, 0x0124},
566 {0, 0xfffd, 0x0124},
567 {0, 0x0040, 0x0127},
568 {0, 0xfff8, 0x0124},
569 {0, 0xfffd, 0x0124},
570 {0, 0xfffa, 0x0124},
571 {0, 0xfff9, 0x0124},
572 {0, 0x0086, 0x0127},
573 {0, 0xfff8, 0x0124},
574 {0, 0xfffd, 0x0124},
575 {0, 0x0037, 0x0127},
576 {0, 0xfff8, 0x0124},
577 {0, 0xfffd, 0x0124},
578 {0, 0x0001, 0x0127},
579 {0, 0xfff8, 0x0124},
580 {0, 0xfffd, 0x0124},
581 {0, 0x0053, 0x0127},
582 {0, 0xfff8, 0x0124},
583 {0, 0xfffd, 0x0124},
584 {0, 0xfffa, 0x0124},
585 {0, 0xfff9, 0x0124},
586 {0, 0x0086, 0x0127},
587 {0, 0xfff8, 0x0124},
588 {0, 0xfffd, 0x0124},
589 {0, 0x0038, 0x0127},
590 {0, 0xfff8, 0x0124},
591 {0, 0xfffd, 0x0124},
592 {0, 0x0000, 0x0127},
593 {0, 0xfff8, 0x0124},
594 {0, 0xfffd, 0x0124},
595 {0, 0x0038, 0x0127},
596 {0, 0xfff8, 0x0124},
597 {0, 0xfffd, 0x0124},
598 {0, 0xfffa, 0x0124},
599 {0, 0x0000, 0x0101},
600 {0, 0x00a0, 0x0103},
601 {0, 0x0078, 0x0105},
602 {0, 0x0000, 0x010a},
603 {0, 0x0024, 0x010b},
604 {0, 0x0028, 0x0119},
605 {0, 0x0088, 0x011b},
606 {0, 0x0002, 0x011d},
607 {0, 0x0003, 0x011e},
608 {0, 0x0000, 0x0129},
609 {0, 0x00fc, 0x012b},
610 {0, 0x0008, 0x0102},
611 {0, 0x0000, 0x0104},
612 {0, 0x0008, 0x011a},
613 {0, 0x0028, 0x011c},
614 {0, 0x0021, 0x012a},
615 {0, 0x0000, 0x0118},
616 {0, 0x0000, 0x0132},
617 {0, 0x0000, 0x0109},
618 {0, 0xfff9, 0x0124},
619 {0, 0x0086, 0x0127},
620 {0, 0xfff8, 0x0124},
621 {0, 0xfffd, 0x0124},
622 {0, 0x0037, 0x0127},
623 {0, 0xfff8, 0x0124},
624 {0, 0xfffd, 0x0124},
625 {0, 0x0001, 0x0127},
626 {0, 0xfff8, 0x0124},
627 {0, 0xfffd, 0x0124},
628 {0, 0x0031, 0x0127},
629 {0, 0xfff8, 0x0124},
630 {0, 0xfffd, 0x0124},
631 {0, 0xfffa, 0x0124},
632 {0, 0xfff9, 0x0124},
633 {0, 0x0086, 0x0127},
634 {0, 0xfff8, 0x0124},
635 {0, 0xfffd, 0x0124},
636 {0, 0x0038, 0x0127},
637 {0, 0xfff8, 0x0124},
638 {0, 0xfffd, 0x0124},
639 {0, 0x0000, 0x0127},
640 {0, 0xfff8, 0x0124},
641 {0, 0xfffd, 0x0124},
642 {0, 0x0000, 0x0127},
643 {0, 0xfff8, 0x0124},
644 {0, 0xfffd, 0x0124},
645 {0, 0xfffa, 0x0124},
646 {0, 0xfff9, 0x0124},
647 {0, 0x0086, 0x0127},
648 {0, 0xfff8, 0x0124},
649 {0, 0xfffd, 0x0124},
650 {0, 0x0037, 0x0127},
651 {0, 0xfff8, 0x0124},
652 {0, 0xfffd, 0x0124},
653 {0, 0x0001, 0x0127},
654 {0, 0xfff8, 0x0124},
655 {0, 0xfffd, 0x0124},
656 {0, 0x0040, 0x0127},
657 {0, 0xfff8, 0x0124},
658 {0, 0xfffd, 0x0124},
659 {0, 0xfffa, 0x0124},
660 {0, 0xfff9, 0x0124},
661 {0, 0x0086, 0x0127},
662 {0, 0xfff8, 0x0124},
663 {0, 0xfffd, 0x0124},
664 {0, 0x0038, 0x0127},
665 {0, 0xfff8, 0x0124},
666 {0, 0xfffd, 0x0124},
667 {0, 0x0000, 0x0127},
668 {0, 0xfff8, 0x0124},
669 {0, 0xfffd, 0x0124},
670 {0, 0x0040, 0x0127},
671 {0, 0xfff8, 0x0124},
672 {0, 0xfffd, 0x0124},
673 {0, 0xfffa, 0x0124},
674 {0, 0xfff9, 0x0124},
675 {0, 0x0086, 0x0127},
676 {0, 0xfff8, 0x0124},
677 {0, 0xfffd, 0x0124},
678 {0, 0x0037, 0x0127},
679 {0, 0xfff8, 0x0124},
680 {0, 0xfffd, 0x0124},
681 {0, 0x0000, 0x0127},
682 {0, 0xfff8, 0x0124},
683 {0, 0xfffd, 0x0124},
684 {0, 0x00dc, 0x0127},
685 {0, 0xfff8, 0x0124},
686 {0, 0xfffd, 0x0124},
687 {0, 0xfffa, 0x0124},
688 {0, 0xfff9, 0x0124},
689 {0, 0x0086, 0x0127},
690 {0, 0xfff8, 0x0124},
691 {0, 0xfffd, 0x0124},
692 {0, 0x0038, 0x0127},
693 {0, 0xfff8, 0x0124},
694 {0, 0xfffd, 0x0124},
695 {0, 0x0000, 0x0127},
696 {0, 0xfff8, 0x0124},
697 {0, 0xfffd, 0x0124},
698 {0, 0x0000, 0x0127},
699 {0, 0xfff8, 0x0124},
700 {0, 0xfffd, 0x0124},
701 {0, 0xfffa, 0x0124},
702 {0, 0xfff9, 0x0124},
703 {0, 0x0086, 0x0127},
704 {0, 0xfff8, 0x0124},
705 {0, 0xfffd, 0x0124},
706 {0, 0x0037, 0x0127},
707 {0, 0xfff8, 0x0124},
708 {0, 0xfffd, 0x0124},
709 {0, 0x0001, 0x0127},
710 {0, 0xfff8, 0x0124},
711 {0, 0xfffd, 0x0124},
712 {0, 0x0032, 0x0127},
713 {0, 0xfff8, 0x0124},
714 {0, 0xfffd, 0x0124},
715 {0, 0xfffa, 0x0124},
716 {0, 0xfff9, 0x0124},
717 {0, 0x0086, 0x0127},
718 {0, 0xfff8, 0x0124},
719 {0, 0xfffd, 0x0124},
720 {0, 0x0038, 0x0127},
721 {0, 0xfff8, 0x0124},
722 {0, 0xfffd, 0x0124},
723 {0, 0x0001, 0x0127},
724 {0, 0xfff8, 0x0124},
725 {0, 0xfffd, 0x0124},
726 {0, 0x0020, 0x0127},
727 {0, 0xfff8, 0x0124},
728 {0, 0xfffd, 0x0124},
729 {0, 0xfffa, 0x0124},
730 {0, 0xfff9, 0x0124},
731 {0, 0x0086, 0x0127},
732 {0, 0xfff8, 0x0124},
733 {0, 0xfffd, 0x0124},
734 {0, 0x0037, 0x0127},
735 {0, 0xfff8, 0x0124},
736 {0, 0xfffd, 0x0124},
737 {0, 0x0001, 0x0127},
738 {0, 0xfff8, 0x0124},
739 {0, 0xfffd, 0x0124},
740 {0, 0x0040, 0x0127},
741 {0, 0xfff8, 0x0124},
742 {0, 0xfffd, 0x0124},
743 {0, 0xfffa, 0x0124},
744 {0, 0xfff9, 0x0124},
745 {0, 0x0086, 0x0127},
746 {0, 0xfff8, 0x0124},
747 {0, 0xfffd, 0x0124},
748 {0, 0x0038, 0x0127},
749 {0, 0xfff8, 0x0124},
750 {0, 0xfffd, 0x0124},
751 {0, 0x0000, 0x0127},
752 {0, 0xfff8, 0x0124},
753 {0, 0xfffd, 0x0124},
754 {0, 0x0040, 0x0127},
755 {0, 0xfff8, 0x0124},
756 {0, 0xfffd, 0x0124},
757 {0, 0xfffa, 0x0124},
758 {0, 0xfff9, 0x0124},
759 {0, 0x0086, 0x0127},
760 {0, 0xfff8, 0x0124},
761 {0, 0xfffd, 0x0124},
762 {0, 0x0037, 0x0127},
763 {0, 0xfff8, 0x0124},
764 {0, 0xfffd, 0x0124},
765 {0, 0x0000, 0x0127},
766 {0, 0xfff8, 0x0124},
767 {0, 0xfffd, 0x0124},
768 {0, 0x0030, 0x0127},
769 {0, 0xfff8, 0x0124},
770 {0, 0xfffd, 0x0124},
771 {0, 0xfffa, 0x0124},
772 {0, 0xfff9, 0x0124},
773 {0, 0x0086, 0x0127},
774 {0, 0xfff8, 0x0124},
775 {0, 0xfffd, 0x0124},
776 {0, 0x0038, 0x0127},
777 {0, 0xfff8, 0x0124},
778 {0, 0xfffd, 0x0124},
779 {0, 0x0008, 0x0127},
780 {0, 0xfff8, 0x0124},
781 {0, 0xfffd, 0x0124},
782 {0, 0x0000, 0x0127},
783 {0, 0xfff8, 0x0124},
784 {0, 0xfffd, 0x0124},
785 {0, 0xfffa, 0x0124},
786 {0, 0x0003, 0x0111},
787};
788
789/* TESTME the old ibmcam driver repeats certain commands to Model1 cameras, we
790 do the same for now (testing needed to see if this is really necessary) */
791static const int cit_model1_ntries = 5;
792static const int cit_model1_ntries2 = 2;
793
794static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
795{
796 struct usb_device *udev = gspca_dev->dev;
797 int err;
798
799 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
800 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
801 value, index, NULL, 0, 1000);
802 if (err < 0)
803 err("Failed to write a register (index 0x%04X,"
804 " value 0x%02X, error %d)", index, value, err);
805
806 return 0;
807}
808
809static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
810{
811 struct usb_device *udev = gspca_dev->dev;
812 __u8 *buf = gspca_dev->usb_buf;
813 int res;
814
815 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01,
816 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
817 0x00, index, buf, 8, 1000);
818 if (res < 0) {
819 err("Failed to read a register (index 0x%04X, error %d)",
820 index, res);
821 return res;
822 }
823
824 if (verbose)
825 PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]);
826
827 return 0;
828}
829
830/*
831 * cit_send_FF_04_02()
832 *
833 * This procedure sends magic 3-command prefix to the camera.
834 * The purpose of this prefix is not known.
835 *
836 * History:
837 * 1/2/00 Created.
838 */
839static void cit_send_FF_04_02(struct gspca_dev *gspca_dev)
840{
841 cit_write_reg(gspca_dev, 0x00FF, 0x0127);
842 cit_write_reg(gspca_dev, 0x0004, 0x0124);
843 cit_write_reg(gspca_dev, 0x0002, 0x0124);
844}
845
846static void cit_send_00_04_06(struct gspca_dev *gspca_dev)
847{
848 cit_write_reg(gspca_dev, 0x0000, 0x0127);
849 cit_write_reg(gspca_dev, 0x0004, 0x0124);
850 cit_write_reg(gspca_dev, 0x0006, 0x0124);
851}
852
853static void cit_send_x_00(struct gspca_dev *gspca_dev, unsigned short x)
854{
855 cit_write_reg(gspca_dev, x, 0x0127);
856 cit_write_reg(gspca_dev, 0x0000, 0x0124);
857}
858
859static void cit_send_x_00_05(struct gspca_dev *gspca_dev, unsigned short x)
860{
861 cit_send_x_00(gspca_dev, x);
862 cit_write_reg(gspca_dev, 0x0005, 0x0124);
863}
864
865static void cit_send_x_00_05_02(struct gspca_dev *gspca_dev, unsigned short x)
866{
867 cit_write_reg(gspca_dev, x, 0x0127);
868 cit_write_reg(gspca_dev, 0x0000, 0x0124);
869 cit_write_reg(gspca_dev, 0x0005, 0x0124);
870 cit_write_reg(gspca_dev, 0x0002, 0x0124);
871}
872
873static void cit_send_x_01_00_05(struct gspca_dev *gspca_dev, u16 x)
874{
875 cit_write_reg(gspca_dev, x, 0x0127);
876 cit_write_reg(gspca_dev, 0x0001, 0x0124);
877 cit_write_reg(gspca_dev, 0x0000, 0x0124);
878 cit_write_reg(gspca_dev, 0x0005, 0x0124);
879}
880
881static void cit_send_x_00_05_02_01(struct gspca_dev *gspca_dev, u16 x)
882{
883 cit_write_reg(gspca_dev, x, 0x0127);
884 cit_write_reg(gspca_dev, 0x0000, 0x0124);
885 cit_write_reg(gspca_dev, 0x0005, 0x0124);
886 cit_write_reg(gspca_dev, 0x0002, 0x0124);
887 cit_write_reg(gspca_dev, 0x0001, 0x0124);
888}
889
890static void cit_send_x_00_05_02_08_01(struct gspca_dev *gspca_dev, u16 x)
891{
892 cit_write_reg(gspca_dev, x, 0x0127);
893 cit_write_reg(gspca_dev, 0x0000, 0x0124);
894 cit_write_reg(gspca_dev, 0x0005, 0x0124);
895 cit_write_reg(gspca_dev, 0x0002, 0x0124);
896 cit_write_reg(gspca_dev, 0x0008, 0x0124);
897 cit_write_reg(gspca_dev, 0x0001, 0x0124);
898}
899
900static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
901{
902 cit_send_x_01_00_05(gspca_dev, 0x0088);
903 cit_send_x_00_05(gspca_dev, fkey);
904 cit_send_x_00_05_02_08_01(gspca_dev, val);
905 cit_send_x_00_05(gspca_dev, 0x0088);
906 cit_send_x_00_05_02_01(gspca_dev, fkey);
907 cit_send_x_00_05(gspca_dev, 0x0089);
908 cit_send_x_00(gspca_dev, fkey);
909 cit_send_00_04_06(gspca_dev);
910 cit_read_reg(gspca_dev, 0x0126, 0);
911 cit_send_FF_04_02(gspca_dev);
912}
913
914static void cit_PacketFormat2(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
915{
916 cit_send_x_01_00_05(gspca_dev, 0x0088);
917 cit_send_x_00_05(gspca_dev, fkey);
918 cit_send_x_00_05_02(gspca_dev, val);
919}
920
921static void cit_model2_Packet2(struct gspca_dev *gspca_dev)
922{
923 cit_write_reg(gspca_dev, 0x00ff, 0x012d);
924 cit_write_reg(gspca_dev, 0xfea3, 0x0124);
925}
926
927static void cit_model2_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
928{
929 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
930 cit_write_reg(gspca_dev, 0x00ff, 0x012e);
931 cit_write_reg(gspca_dev, v1, 0x012f);
932 cit_write_reg(gspca_dev, 0x00ff, 0x0130);
933 cit_write_reg(gspca_dev, 0xc719, 0x0124);
934 cit_write_reg(gspca_dev, v2, 0x0127);
935
936 cit_model2_Packet2(gspca_dev);
937}
938
939/*
940 * cit_model3_Packet1()
941 *
942 * 00_0078_012d
943 * 00_0097_012f
944 * 00_d141_0124
945 * 00_0096_0127
946 * 00_fea8_0124
947*/
948static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
949{
950 cit_write_reg(gspca_dev, 0x0078, 0x012d);
951 cit_write_reg(gspca_dev, v1, 0x012f);
952 cit_write_reg(gspca_dev, 0xd141, 0x0124);
953 cit_write_reg(gspca_dev, v2, 0x0127);
954 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
955}
956
957static void cit_model4_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
958{
959 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
960 cit_write_reg(gspca_dev, v1, 0x012f);
961 cit_write_reg(gspca_dev, 0xd141, 0x0124);
962 cit_write_reg(gspca_dev, v2, 0x0127);
963 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
964}
965
966static void cit_model4_BrightnessPacket(struct gspca_dev *gspca_dev, u16 val)
967{
968 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
969 cit_write_reg(gspca_dev, 0x0026, 0x012f);
970 cit_write_reg(gspca_dev, 0xd141, 0x0124);
971 cit_write_reg(gspca_dev, val, 0x0127);
972 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
973 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
974 cit_write_reg(gspca_dev, 0x0038, 0x012d);
975 cit_write_reg(gspca_dev, 0x0004, 0x012f);
976 cit_write_reg(gspca_dev, 0xd145, 0x0124);
977 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
978}
979
980/* this function is called at probe time */
981static int sd_config(struct gspca_dev *gspca_dev,
982 const struct usb_device_id *id)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
985 struct cam *cam;
986
987 sd->model = id->driver_info;
988 if (sd->model == CIT_MODEL3 && ibm_netcam_pro)
989 sd->model = CIT_IBM_NETCAM_PRO;
990
991 cam = &gspca_dev->cam;
992 switch (sd->model) {
993 case CIT_MODEL0:
994 cam->cam_mode = model0_mode;
995 cam->nmodes = ARRAY_SIZE(model0_mode);
996 cam->reverse_alts = 1;
997 gspca_dev->ctrl_dis = ~((1 << SD_CONTRAST) | (1 << SD_HFLIP));
998 sd->sof_len = 4;
999 break;
1000 case CIT_MODEL1:
1001 cam->cam_mode = cif_yuv_mode;
1002 cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
1003 cam->reverse_alts = 1;
1004 gspca_dev->ctrl_dis = (1 << SD_HUE) | (1 << SD_HFLIP);
1005 sd->sof_len = 4;
1006 break;
1007 case CIT_MODEL2:
1008 cam->cam_mode = model2_mode + 1; /* no 160x120 */
1009 cam->nmodes = 3;
1010 gspca_dev->ctrl_dis = (1 << SD_CONTRAST) |
1011 (1 << SD_SHARPNESS) |
1012 (1 << SD_HFLIP);
1013 break;
1014 case CIT_MODEL3:
1015 cam->cam_mode = vga_yuv_mode;
1016 cam->nmodes = ARRAY_SIZE(vga_yuv_mode);
1017 gspca_dev->ctrl_dis = (1 << SD_HUE) |
1018 (1 << SD_LIGHTING) |
1019 (1 << SD_HFLIP);
1020 sd->stop_on_control_change = 1;
1021 sd->sof_len = 4;
1022 break;
1023 case CIT_MODEL4:
1024 cam->cam_mode = model2_mode;
1025 cam->nmodes = ARRAY_SIZE(model2_mode);
1026 gspca_dev->ctrl_dis = (1 << SD_CONTRAST) |
1027 (1 << SD_SHARPNESS) |
1028 (1 << SD_LIGHTING) |
1029 (1 << SD_HFLIP);
1030 break;
1031 case CIT_IBM_NETCAM_PRO:
1032 cam->cam_mode = vga_yuv_mode;
1033 cam->nmodes = 2; /* no 640 x 480 */
1034 cam->input_flags = V4L2_IN_ST_VFLIP;
1035 gspca_dev->ctrl_dis = ~(1 << SD_CONTRAST);
1036 sd->stop_on_control_change = 1;
1037 sd->sof_len = 4;
1038 break;
1039 }
1040
1041 sd->brightness = BRIGHTNESS_DEFAULT;
1042 sd->contrast = CONTRAST_DEFAULT;
1043 sd->hue = HUE_DEFAULT;
1044 sd->sharpness = SHARPNESS_DEFAULT;
1045 sd->lighting = LIGHTING_DEFAULT;
1046 sd->hflip = HFLIP_DEFAULT;
1047
1048 return 0;
1049}
1050
1051static int cit_init_model0(struct gspca_dev *gspca_dev)
1052{
1053 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
1054 cit_write_reg(gspca_dev, 0x0001, 0x0112); /* turn on autogain ? */
1055 cit_write_reg(gspca_dev, 0x0000, 0x0400);
1056 cit_write_reg(gspca_dev, 0x0001, 0x0400);
1057 cit_write_reg(gspca_dev, 0x0000, 0x0420);
1058 cit_write_reg(gspca_dev, 0x0001, 0x0420);
1059 cit_write_reg(gspca_dev, 0x000d, 0x0409);
1060 cit_write_reg(gspca_dev, 0x0002, 0x040a);
1061 cit_write_reg(gspca_dev, 0x0018, 0x0405);
1062 cit_write_reg(gspca_dev, 0x0008, 0x0435);
1063 cit_write_reg(gspca_dev, 0x0026, 0x040b);
1064 cit_write_reg(gspca_dev, 0x0007, 0x0437);
1065 cit_write_reg(gspca_dev, 0x0015, 0x042f);
1066 cit_write_reg(gspca_dev, 0x002b, 0x0439);
1067 cit_write_reg(gspca_dev, 0x0026, 0x043a);
1068 cit_write_reg(gspca_dev, 0x0008, 0x0438);
1069 cit_write_reg(gspca_dev, 0x001e, 0x042b);
1070 cit_write_reg(gspca_dev, 0x0041, 0x042c);
1071
1072 return 0;
1073}
1074
1075static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
1076{
1077 cit_read_reg(gspca_dev, 0x128, 1);
1078 cit_write_reg(gspca_dev, 0x0003, 0x0133);
1079 cit_write_reg(gspca_dev, 0x0000, 0x0117);
1080 cit_write_reg(gspca_dev, 0x0008, 0x0123);
1081 cit_write_reg(gspca_dev, 0x0000, 0x0100);
1082 cit_read_reg(gspca_dev, 0x0116, 0);
1083 cit_write_reg(gspca_dev, 0x0060, 0x0116);
1084 cit_write_reg(gspca_dev, 0x0002, 0x0112);
1085 cit_write_reg(gspca_dev, 0x0000, 0x0133);
1086 cit_write_reg(gspca_dev, 0x0000, 0x0123);
1087 cit_write_reg(gspca_dev, 0x0001, 0x0117);
1088 cit_write_reg(gspca_dev, 0x0040, 0x0108);
1089 cit_write_reg(gspca_dev, 0x0019, 0x012c);
1090 cit_write_reg(gspca_dev, 0x0060, 0x0116);
1091 cit_write_reg(gspca_dev, 0x0002, 0x0115);
1092 cit_write_reg(gspca_dev, 0x000b, 0x0115);
1093
1094 cit_write_reg(gspca_dev, 0x0078, 0x012d);
1095 cit_write_reg(gspca_dev, 0x0001, 0x012f);
1096 cit_write_reg(gspca_dev, 0xd141, 0x0124);
1097 cit_write_reg(gspca_dev, 0x0079, 0x012d);
1098 cit_write_reg(gspca_dev, 0x00ff, 0x0130);
1099 cit_write_reg(gspca_dev, 0xcd41, 0x0124);
1100 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
1101 cit_read_reg(gspca_dev, 0x0126, 1);
1102
1103 cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
1104 cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
1105 cit_model3_Packet1(gspca_dev, 0x000b, 0x0000);
1106 cit_model3_Packet1(gspca_dev, 0x000c, 0x0008);
1107 cit_model3_Packet1(gspca_dev, 0x000d, 0x003a);
1108 cit_model3_Packet1(gspca_dev, 0x000e, 0x0060);
1109 cit_model3_Packet1(gspca_dev, 0x000f, 0x0060);
1110 cit_model3_Packet1(gspca_dev, 0x0010, 0x0008);
1111 cit_model3_Packet1(gspca_dev, 0x0011, 0x0004);
1112 cit_model3_Packet1(gspca_dev, 0x0012, 0x0028);
1113 cit_model3_Packet1(gspca_dev, 0x0013, 0x0002);
1114 cit_model3_Packet1(gspca_dev, 0x0014, 0x0000);
1115 cit_model3_Packet1(gspca_dev, 0x0015, 0x00fb);
1116 cit_model3_Packet1(gspca_dev, 0x0016, 0x0002);
1117 cit_model3_Packet1(gspca_dev, 0x0017, 0x0037);
1118 cit_model3_Packet1(gspca_dev, 0x0018, 0x0036);
1119 cit_model3_Packet1(gspca_dev, 0x001e, 0x0000);
1120 cit_model3_Packet1(gspca_dev, 0x001f, 0x0008);
1121 cit_model3_Packet1(gspca_dev, 0x0020, 0x00c1);
1122 cit_model3_Packet1(gspca_dev, 0x0021, 0x0034);
1123 cit_model3_Packet1(gspca_dev, 0x0022, 0x0034);
1124 cit_model3_Packet1(gspca_dev, 0x0025, 0x0002);
1125 cit_model3_Packet1(gspca_dev, 0x0028, 0x0022);
1126 cit_model3_Packet1(gspca_dev, 0x0029, 0x000a);
1127 cit_model3_Packet1(gspca_dev, 0x002b, 0x0000);
1128 cit_model3_Packet1(gspca_dev, 0x002c, 0x0000);
1129 cit_model3_Packet1(gspca_dev, 0x002d, 0x00ff);
1130 cit_model3_Packet1(gspca_dev, 0x002e, 0x00ff);
1131 cit_model3_Packet1(gspca_dev, 0x002f, 0x00ff);
1132 cit_model3_Packet1(gspca_dev, 0x0030, 0x00ff);
1133 cit_model3_Packet1(gspca_dev, 0x0031, 0x00ff);
1134 cit_model3_Packet1(gspca_dev, 0x0032, 0x0007);
1135 cit_model3_Packet1(gspca_dev, 0x0033, 0x0005);
1136 cit_model3_Packet1(gspca_dev, 0x0037, 0x0040);
1137 cit_model3_Packet1(gspca_dev, 0x0039, 0x0000);
1138 cit_model3_Packet1(gspca_dev, 0x003a, 0x0000);
1139 cit_model3_Packet1(gspca_dev, 0x003b, 0x0001);
1140 cit_model3_Packet1(gspca_dev, 0x003c, 0x0000);
1141 cit_model3_Packet1(gspca_dev, 0x0040, 0x000c);
1142 cit_model3_Packet1(gspca_dev, 0x0041, 0x00fb);
1143 cit_model3_Packet1(gspca_dev, 0x0042, 0x0002);
1144 cit_model3_Packet1(gspca_dev, 0x0043, 0x0000);
1145 cit_model3_Packet1(gspca_dev, 0x0045, 0x0000);
1146 cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
1147 cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
1148 cit_model3_Packet1(gspca_dev, 0x0048, 0x0000);
1149 cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
1150 cit_model3_Packet1(gspca_dev, 0x004a, 0x00ff);
1151 cit_model3_Packet1(gspca_dev, 0x004b, 0x00ff);
1152 cit_model3_Packet1(gspca_dev, 0x004c, 0x00ff);
1153 cit_model3_Packet1(gspca_dev, 0x004f, 0x0000);
1154 cit_model3_Packet1(gspca_dev, 0x0050, 0x0000);
1155 cit_model3_Packet1(gspca_dev, 0x0051, 0x0002);
1156 cit_model3_Packet1(gspca_dev, 0x0055, 0x0000);
1157 cit_model3_Packet1(gspca_dev, 0x0056, 0x0000);
1158 cit_model3_Packet1(gspca_dev, 0x0057, 0x0000);
1159 cit_model3_Packet1(gspca_dev, 0x0058, 0x0002);
1160 cit_model3_Packet1(gspca_dev, 0x0059, 0x0000);
1161 cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);
1162 cit_model3_Packet1(gspca_dev, 0x005d, 0x0022);
1163 cit_model3_Packet1(gspca_dev, 0x005e, 0x003c);
1164 cit_model3_Packet1(gspca_dev, 0x005f, 0x0050);
1165 cit_model3_Packet1(gspca_dev, 0x0060, 0x0044);
1166 cit_model3_Packet1(gspca_dev, 0x0061, 0x0005);
1167 cit_model3_Packet1(gspca_dev, 0x006a, 0x007e);
1168 cit_model3_Packet1(gspca_dev, 0x006f, 0x0000);
1169 cit_model3_Packet1(gspca_dev, 0x0072, 0x001b);
1170 cit_model3_Packet1(gspca_dev, 0x0073, 0x0005);
1171 cit_model3_Packet1(gspca_dev, 0x0074, 0x000a);
1172 cit_model3_Packet1(gspca_dev, 0x0075, 0x001b);
1173 cit_model3_Packet1(gspca_dev, 0x0076, 0x002a);
1174 cit_model3_Packet1(gspca_dev, 0x0077, 0x003c);
1175 cit_model3_Packet1(gspca_dev, 0x0078, 0x0050);
1176 cit_model3_Packet1(gspca_dev, 0x007b, 0x0000);
1177 cit_model3_Packet1(gspca_dev, 0x007c, 0x0011);
1178 cit_model3_Packet1(gspca_dev, 0x007d, 0x0024);
1179 cit_model3_Packet1(gspca_dev, 0x007e, 0x0043);
1180 cit_model3_Packet1(gspca_dev, 0x007f, 0x005a);
1181 cit_model3_Packet1(gspca_dev, 0x0084, 0x0020);
1182 cit_model3_Packet1(gspca_dev, 0x0085, 0x0033);
1183 cit_model3_Packet1(gspca_dev, 0x0086, 0x000a);
1184 cit_model3_Packet1(gspca_dev, 0x0087, 0x0030);
1185 cit_model3_Packet1(gspca_dev, 0x0088, 0x0070);
1186 cit_model3_Packet1(gspca_dev, 0x008b, 0x0008);
1187 cit_model3_Packet1(gspca_dev, 0x008f, 0x0000);
1188 cit_model3_Packet1(gspca_dev, 0x0090, 0x0006);
1189 cit_model3_Packet1(gspca_dev, 0x0091, 0x0028);
1190 cit_model3_Packet1(gspca_dev, 0x0092, 0x005a);
1191 cit_model3_Packet1(gspca_dev, 0x0093, 0x0082);
1192 cit_model3_Packet1(gspca_dev, 0x0096, 0x0014);
1193 cit_model3_Packet1(gspca_dev, 0x0097, 0x0020);
1194 cit_model3_Packet1(gspca_dev, 0x0098, 0x0000);
1195 cit_model3_Packet1(gspca_dev, 0x00b0, 0x0046);
1196 cit_model3_Packet1(gspca_dev, 0x00b1, 0x0000);
1197 cit_model3_Packet1(gspca_dev, 0x00b2, 0x0000);
1198 cit_model3_Packet1(gspca_dev, 0x00b3, 0x0004);
1199 cit_model3_Packet1(gspca_dev, 0x00b4, 0x0007);
1200 cit_model3_Packet1(gspca_dev, 0x00b6, 0x0002);
1201 cit_model3_Packet1(gspca_dev, 0x00b7, 0x0004);
1202 cit_model3_Packet1(gspca_dev, 0x00bb, 0x0000);
1203 cit_model3_Packet1(gspca_dev, 0x00bc, 0x0001);
1204 cit_model3_Packet1(gspca_dev, 0x00bd, 0x0000);
1205 cit_model3_Packet1(gspca_dev, 0x00bf, 0x0000);
1206 cit_model3_Packet1(gspca_dev, 0x00c0, 0x00c8);
1207 cit_model3_Packet1(gspca_dev, 0x00c1, 0x0014);
1208 cit_model3_Packet1(gspca_dev, 0x00c2, 0x0001);
1209 cit_model3_Packet1(gspca_dev, 0x00c3, 0x0000);
1210 cit_model3_Packet1(gspca_dev, 0x00c4, 0x0004);
1211 cit_model3_Packet1(gspca_dev, 0x00cb, 0x00bf);
1212 cit_model3_Packet1(gspca_dev, 0x00cc, 0x00bf);
1213 cit_model3_Packet1(gspca_dev, 0x00cd, 0x00bf);
1214 cit_model3_Packet1(gspca_dev, 0x00ce, 0x0000);
1215 cit_model3_Packet1(gspca_dev, 0x00cf, 0x0020);
1216 cit_model3_Packet1(gspca_dev, 0x00d0, 0x0040);
1217 cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
1218 cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
1219 cit_model3_Packet1(gspca_dev, 0x00d2, 0x00bf);
1220 cit_model3_Packet1(gspca_dev, 0x00d3, 0x00bf);
1221 cit_model3_Packet1(gspca_dev, 0x00ea, 0x0008);
1222 cit_model3_Packet1(gspca_dev, 0x00eb, 0x0000);
1223 cit_model3_Packet1(gspca_dev, 0x00ec, 0x00e8);
1224 cit_model3_Packet1(gspca_dev, 0x00ed, 0x0001);
1225 cit_model3_Packet1(gspca_dev, 0x00ef, 0x0022);
1226 cit_model3_Packet1(gspca_dev, 0x00f0, 0x0000);
1227 cit_model3_Packet1(gspca_dev, 0x00f2, 0x0028);
1228 cit_model3_Packet1(gspca_dev, 0x00f4, 0x0002);
1229 cit_model3_Packet1(gspca_dev, 0x00f5, 0x0000);
1230 cit_model3_Packet1(gspca_dev, 0x00fa, 0x0000);
1231 cit_model3_Packet1(gspca_dev, 0x00fb, 0x0001);
1232 cit_model3_Packet1(gspca_dev, 0x00fc, 0x0000);
1233 cit_model3_Packet1(gspca_dev, 0x00fd, 0x0000);
1234 cit_model3_Packet1(gspca_dev, 0x00fe, 0x0000);
1235 cit_model3_Packet1(gspca_dev, 0x00ff, 0x0000);
1236
1237 cit_model3_Packet1(gspca_dev, 0x00be, 0x0003);
1238 cit_model3_Packet1(gspca_dev, 0x00c8, 0x0000);
1239 cit_model3_Packet1(gspca_dev, 0x00c9, 0x0020);
1240 cit_model3_Packet1(gspca_dev, 0x00ca, 0x0040);
1241 cit_model3_Packet1(gspca_dev, 0x0053, 0x0001);
1242 cit_model3_Packet1(gspca_dev, 0x0082, 0x000e);
1243 cit_model3_Packet1(gspca_dev, 0x0083, 0x0020);
1244 cit_model3_Packet1(gspca_dev, 0x0034, 0x003c);
1245 cit_model3_Packet1(gspca_dev, 0x006e, 0x0055);
1246 cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);
1247 cit_model3_Packet1(gspca_dev, 0x0063, 0x0008);
1248 cit_model3_Packet1(gspca_dev, 0x0066, 0x000a);
1249 cit_model3_Packet1(gspca_dev, 0x0067, 0x0006);
1250 cit_model3_Packet1(gspca_dev, 0x006b, 0x0010);
1251 cit_model3_Packet1(gspca_dev, 0x005a, 0x0001);
1252 cit_model3_Packet1(gspca_dev, 0x005b, 0x000a);
1253 cit_model3_Packet1(gspca_dev, 0x0023, 0x0006);
1254 cit_model3_Packet1(gspca_dev, 0x0026, 0x0004);
1255 cit_model3_Packet1(gspca_dev, 0x0036, 0x0069);
1256 cit_model3_Packet1(gspca_dev, 0x0038, 0x0064);
1257 cit_model3_Packet1(gspca_dev, 0x003d, 0x0003);
1258 cit_model3_Packet1(gspca_dev, 0x003e, 0x0001);
1259 cit_model3_Packet1(gspca_dev, 0x00b8, 0x0014);
1260 cit_model3_Packet1(gspca_dev, 0x00b9, 0x0014);
1261 cit_model3_Packet1(gspca_dev, 0x00e6, 0x0004);
1262 cit_model3_Packet1(gspca_dev, 0x00e8, 0x0001);
1263
1264 return 0;
1265}
1266
1267/* this function is called at probe and resume time */
1268static int sd_init(struct gspca_dev *gspca_dev)
1269{
1270 struct sd *sd = (struct sd *) gspca_dev;
1271
1272 switch (sd->model) {
1273 case CIT_MODEL0:
1274 cit_init_model0(gspca_dev);
1275 sd_stop0(gspca_dev);
1276 break;
1277 case CIT_MODEL1:
1278 case CIT_MODEL2:
1279 case CIT_MODEL3:
1280 case CIT_MODEL4:
1281 break; /* All is done in sd_start */
1282 case CIT_IBM_NETCAM_PRO:
1283 cit_init_ibm_netcam_pro(gspca_dev);
1284 sd_stop0(gspca_dev);
1285 break;
1286 }
1287 return 0;
1288}
1289
1290static int cit_set_brightness(struct gspca_dev *gspca_dev)
1291{
1292 struct sd *sd = (struct sd *) gspca_dev;
1293 int i;
1294
1295 switch (sd->model) {
1296 case CIT_MODEL0:
1297 case CIT_IBM_NETCAM_PRO:
1298 /* No (known) brightness control for these */
1299 break;
1300 case CIT_MODEL1:
1301 /* Model 1: Brightness range 0 - 63 */
1302 cit_Packet_Format1(gspca_dev, 0x0031, sd->brightness);
1303 cit_Packet_Format1(gspca_dev, 0x0032, sd->brightness);
1304 cit_Packet_Format1(gspca_dev, 0x0033, sd->brightness);
1305 break;
1306 case CIT_MODEL2:
1307 /* Model 2: Brightness range 0x60 - 0xee */
1308 /* Scale 0 - 63 to 0x60 - 0xee */
1309 i = 0x60 + sd->brightness * 2254 / 1000;
1310 cit_model2_Packet1(gspca_dev, 0x001a, i);
1311 break;
1312 case CIT_MODEL3:
1313 /* Model 3: Brightness range 'i' in [0x0C..0x3F] */
1314 i = sd->brightness;
1315 if (i < 0x0c)
1316 i = 0x0c;
1317 cit_model3_Packet1(gspca_dev, 0x0036, i);
1318 break;
1319 case CIT_MODEL4:
1320 /* Model 4: Brightness range 'i' in [0x04..0xb4] */
1321 /* Scale 0 - 63 to 0x04 - 0xb4 */
1322 i = 0x04 + sd->brightness * 2794 / 1000;
1323 cit_model4_BrightnessPacket(gspca_dev, i);
1324 break;
1325 }
1326
1327 return 0;
1328}
1329
1330static int cit_set_contrast(struct gspca_dev *gspca_dev)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 switch (sd->model) {
1335 case CIT_MODEL0: {
1336 int i;
1337 /* gain 0-15, 0-20 -> 0-15 */
1338 i = sd->contrast * 1000 / 1333;
1339 cit_write_reg(gspca_dev, i, 0x0422);
1340 /* gain 0-31, may not be lower then 0x0422, 0-20 -> 0-31 */
1341 i = sd->contrast * 2000 / 1333;
1342 cit_write_reg(gspca_dev, i, 0x0423);
1343 /* gain 0-127, may not be lower then 0x0423, 0-20 -> 0-63 */
1344 i = sd->contrast * 4000 / 1333;
1345 cit_write_reg(gspca_dev, i, 0x0424);
1346 /* gain 0-127, may not be lower then 0x0424, , 0-20 -> 0-127 */
1347 i = sd->contrast * 8000 / 1333;
1348 cit_write_reg(gspca_dev, i, 0x0425);
1349 break;
1350 }
1351 case CIT_MODEL2:
1352 case CIT_MODEL4:
1353 /* These models do not have this control. */
1354 break;
1355 case CIT_MODEL1:
1356 {
1357 /* Scale 0 - 20 to 15 - 0 */
1358 int i, new_contrast = (20 - sd->contrast) * 1000 / 1333;
1359 for (i = 0; i < cit_model1_ntries; i++) {
1360 cit_Packet_Format1(gspca_dev, 0x0014, new_contrast);
1361 cit_send_FF_04_02(gspca_dev);
1362 }
1363 break;
1364 }
1365 case CIT_MODEL3:
1366 { /* Preset hardware values */
1367 static const struct {
1368 unsigned short cv1;
1369 unsigned short cv2;
1370 unsigned short cv3;
1371 } cv[7] = {
1372 { 0x05, 0x05, 0x0f }, /* Minimum */
1373 { 0x04, 0x04, 0x16 },
1374 { 0x02, 0x03, 0x16 },
1375 { 0x02, 0x08, 0x16 },
1376 { 0x01, 0x0c, 0x16 },
1377 { 0x01, 0x0e, 0x16 },
1378 { 0x01, 0x10, 0x16 } /* Maximum */
1379 };
1380 int i = sd->contrast / 3;
1381 cit_model3_Packet1(gspca_dev, 0x0067, cv[i].cv1);
1382 cit_model3_Packet1(gspca_dev, 0x005b, cv[i].cv2);
1383 cit_model3_Packet1(gspca_dev, 0x005c, cv[i].cv3);
1384 break;
1385 }
1386 case CIT_IBM_NETCAM_PRO:
1387 cit_model3_Packet1(gspca_dev, 0x005b, sd->contrast + 1);
1388 break;
1389 }
1390 return 0;
1391}
1392
1393static int cit_set_hue(struct gspca_dev *gspca_dev)
1394{
1395 struct sd *sd = (struct sd *) gspca_dev;
1396
1397 switch (sd->model) {
1398 case CIT_MODEL0:
1399 case CIT_MODEL1:
1400 case CIT_IBM_NETCAM_PRO:
1401 /* No hue control for these models */
1402 break;
1403 case CIT_MODEL2:
1404 cit_model2_Packet1(gspca_dev, 0x0024, sd->hue);
1405 /* cit_model2_Packet1(gspca_dev, 0x0020, sat); */
1406 break;
1407 case CIT_MODEL3: {
1408 /* Model 3: Brightness range 'i' in [0x05..0x37] */
1409 /* TESTME according to the ibmcam driver this does not work */
1410 if (0) {
1411 /* Scale 0 - 127 to 0x05 - 0x37 */
1412 int i = 0x05 + sd->hue * 1000 / 2540;
1413 cit_model3_Packet1(gspca_dev, 0x007e, i);
1414 }
1415 break;
1416 }
1417 case CIT_MODEL4:
1418 /* HDG: taken from ibmcam, setting the color gains does not
1419 * really belong here.
1420 *
1421 * I am not sure r/g/b_gain variables exactly control gain
1422 * of those channels. Most likely they subtly change some
1423 * very internal image processing settings in the camera.
1424 * In any case, here is what they do, and feel free to tweak:
1425 *
1426 * r_gain: seriously affects red gain
1427 * g_gain: seriously affects green gain
1428 * b_gain: seriously affects blue gain
1429 * hue: changes average color from violet (0) to red (0xFF)
1430 */
1431 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
1432 cit_write_reg(gspca_dev, 0x001e, 0x012f);
1433 cit_write_reg(gspca_dev, 0xd141, 0x0124);
1434 cit_write_reg(gspca_dev, 160, 0x0127); /* Green gain */
1435 cit_write_reg(gspca_dev, 160, 0x012e); /* Red gain */
1436 cit_write_reg(gspca_dev, 160, 0x0130); /* Blue gain */
1437 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
1438 cit_write_reg(gspca_dev, sd->hue, 0x012d); /* Hue */
1439 cit_write_reg(gspca_dev, 0xf545, 0x0124);
1440 break;
1441 }
1442 return 0;
1443}
1444
1445static int cit_set_sharpness(struct gspca_dev *gspca_dev)
1446{
1447 struct sd *sd = (struct sd *) gspca_dev;
1448
1449 switch (sd->model) {
1450 case CIT_MODEL0:
1451 case CIT_MODEL2:
1452 case CIT_MODEL4:
1453 case CIT_IBM_NETCAM_PRO:
1454 /* These models do not have this control */
1455 break;
1456 case CIT_MODEL1: {
1457 int i;
1458 const unsigned short sa[] = {
1459 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
1460
1461 for (i = 0; i < cit_model1_ntries; i++)
1462 cit_PacketFormat2(gspca_dev, 0x0013, sa[sd->sharpness]);
1463 break;
1464 }
1465 case CIT_MODEL3:
1466 { /*
1467 * "Use a table of magic numbers.
1468 * This setting doesn't really change much.
1469 * But that's how Windows does it."
1470 */
1471 static const struct {
1472 unsigned short sv1;
1473 unsigned short sv2;
1474 unsigned short sv3;
1475 unsigned short sv4;
1476 } sv[7] = {
1477 { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */
1478 { 0x01, 0x04, 0x05, 0x14 },
1479 { 0x02, 0x04, 0x05, 0x14 },
1480 { 0x03, 0x04, 0x05, 0x14 },
1481 { 0x03, 0x05, 0x05, 0x14 },
1482 { 0x03, 0x06, 0x05, 0x14 },
1483 { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */
1484 };
1485 cit_model3_Packet1(gspca_dev, 0x0060, sv[sd->sharpness].sv1);
1486 cit_model3_Packet1(gspca_dev, 0x0061, sv[sd->sharpness].sv2);
1487 cit_model3_Packet1(gspca_dev, 0x0062, sv[sd->sharpness].sv3);
1488 cit_model3_Packet1(gspca_dev, 0x0063, sv[sd->sharpness].sv4);
1489 break;
1490 }
1491 }
1492 return 0;
1493}
1494
1495/*
1496 * cit_set_lighting()
1497 *
1498 * Camera model 1:
1499 * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
1500 *
1501 * Camera model 2:
1502 * We have 16 levels of lighting, 0 for bright light and up to 15 for
1503 * low light. But values above 5 or so are useless because camera is
1504 * not really capable to produce anything worth viewing at such light.
1505 * This setting may be altered only in certain camera state.
1506 *
1507 * Low lighting forces slower FPS.
1508 *
1509 * History:
1510 * 1/5/00 Created.
1511 * 2/20/00 Added support for Model 2 cameras.
1512 */
1513static void cit_set_lighting(struct gspca_dev *gspca_dev)
1514{
1515 struct sd *sd = (struct sd *) gspca_dev;
1516
1517 switch (sd->model) {
1518 case CIT_MODEL0:
1519 case CIT_MODEL2:
1520 case CIT_MODEL3:
1521 case CIT_MODEL4:
1522 case CIT_IBM_NETCAM_PRO:
1523 break;
1524 case CIT_MODEL1: {
1525 int i;
1526 for (i = 0; i < cit_model1_ntries; i++)
1527 cit_Packet_Format1(gspca_dev, 0x0027, sd->lighting);
1528 break;
1529 }
1530 }
1531}
1532
1533static void cit_set_hflip(struct gspca_dev *gspca_dev)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536
1537 switch (sd->model) {
1538 case CIT_MODEL0:
1539 if (sd->hflip)
1540 cit_write_reg(gspca_dev, 0x0020, 0x0115);
1541 else
1542 cit_write_reg(gspca_dev, 0x0040, 0x0115);
1543 break;
1544 case CIT_MODEL1:
1545 case CIT_MODEL2:
1546 case CIT_MODEL3:
1547 case CIT_MODEL4:
1548 case CIT_IBM_NETCAM_PRO:
1549 break;
1550 }
1551}
1552
1553static int cit_restart_stream(struct gspca_dev *gspca_dev)
1554{
1555 struct sd *sd = (struct sd *) gspca_dev;
1556
1557 switch (sd->model) {
1558 case CIT_MODEL0:
1559 case CIT_MODEL1:
1560 cit_write_reg(gspca_dev, 0x0001, 0x0114);
1561 /* Fall through */
1562 case CIT_MODEL2:
1563 case CIT_MODEL4:
1564 cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
1565 usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
1566 break;
1567 case CIT_MODEL3:
1568 case CIT_IBM_NETCAM_PRO:
1569 cit_write_reg(gspca_dev, 0x0001, 0x0114);
1570 cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
1571 usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
1572 /* Clear button events from while we were not streaming */
1573 cit_write_reg(gspca_dev, 0x0001, 0x0113);
1574 break;
1575 }
1576
1577 sd->sof_read = 0;
1578
1579 return 0;
1580}
1581
1582static int cit_get_packet_size(struct gspca_dev *gspca_dev)
1583{
1584 struct usb_host_interface *alt;
1585 struct usb_interface *intf;
1586
1587 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
1588 alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
1589 if (!alt) {
1590 err("Couldn't get altsetting");
1591 return -EIO;
1592 }
1593
1594 return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
1595}
1596
1597/* Calculate the clockdiv giving us max fps given the available bandwidth */
1598static int cit_get_clock_div(struct gspca_dev *gspca_dev)
1599{
1600 int clock_div = 7; /* 0=30 1=25 2=20 3=15 4=12 5=7.5 6=6 7=3fps ?? */
1601 int fps[8] = { 30, 25, 20, 15, 12, 8, 6, 3 };
1602 int packet_size;
1603
1604 packet_size = cit_get_packet_size(gspca_dev);
1605 if (packet_size < 0)
1606 return packet_size;
1607
1608 while (clock_div > 3 &&
1609 1000 * packet_size >
1610 gspca_dev->width * gspca_dev->height *
1611 fps[clock_div - 1] * 3 / 2)
1612 clock_div--;
1613
1614 PDEBUG(D_PROBE,
1615 "PacketSize: %d, res: %dx%d -> using clockdiv: %d (%d fps)",
1616 packet_size, gspca_dev->width, gspca_dev->height, clock_div,
1617 fps[clock_div]);
1618
1619 return clock_div;
1620}
1621
1622static int cit_start_model0(struct gspca_dev *gspca_dev)
1623{
1624 const unsigned short compression = 0; /* 0=none, 7=best frame rate */
1625 int clock_div;
1626
1627 clock_div = cit_get_clock_div(gspca_dev);
1628 if (clock_div < 0)
1629 return clock_div;
1630
1631 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
1632 cit_write_reg(gspca_dev, 0x0003, 0x0438);
1633 cit_write_reg(gspca_dev, 0x001e, 0x042b);
1634 cit_write_reg(gspca_dev, 0x0041, 0x042c);
1635 cit_write_reg(gspca_dev, 0x0008, 0x0436);
1636 cit_write_reg(gspca_dev, 0x0024, 0x0403);
1637 cit_write_reg(gspca_dev, 0x002c, 0x0404);
1638 cit_write_reg(gspca_dev, 0x0002, 0x0426);
1639 cit_write_reg(gspca_dev, 0x0014, 0x0427);
1640
1641 switch (gspca_dev->width) {
1642 case 160: /* 160x120 */
1643 cit_write_reg(gspca_dev, 0x0004, 0x010b);
1644 cit_write_reg(gspca_dev, 0x0001, 0x010a);
1645 cit_write_reg(gspca_dev, 0x0010, 0x0102);
1646 cit_write_reg(gspca_dev, 0x00a0, 0x0103);
1647 cit_write_reg(gspca_dev, 0x0000, 0x0104);
1648 cit_write_reg(gspca_dev, 0x0078, 0x0105);
1649 break;
1650
1651 case 176: /* 176x144 */
1652 cit_write_reg(gspca_dev, 0x0006, 0x010b);
1653 cit_write_reg(gspca_dev, 0x0000, 0x010a);
1654 cit_write_reg(gspca_dev, 0x0005, 0x0102);
1655 cit_write_reg(gspca_dev, 0x00b0, 0x0103);
1656 cit_write_reg(gspca_dev, 0x0000, 0x0104);
1657 cit_write_reg(gspca_dev, 0x0090, 0x0105);
1658 break;
1659
1660 case 320: /* 320x240 */
1661 cit_write_reg(gspca_dev, 0x0008, 0x010b);
1662 cit_write_reg(gspca_dev, 0x0004, 0x010a);
1663 cit_write_reg(gspca_dev, 0x0005, 0x0102);
1664 cit_write_reg(gspca_dev, 0x00a0, 0x0103);
1665 cit_write_reg(gspca_dev, 0x0010, 0x0104);
1666 cit_write_reg(gspca_dev, 0x0078, 0x0105);
1667 break;
1668 }
1669
1670 cit_write_reg(gspca_dev, compression, 0x0109);
1671 cit_write_reg(gspca_dev, clock_div, 0x0111);
1672
1673 return 0;
1674}
1675
1676static int cit_start_model1(struct gspca_dev *gspca_dev)
1677{
1678 struct sd *sd = (struct sd *) gspca_dev;
1679 int i, clock_div;
1680
1681 clock_div = cit_get_clock_div(gspca_dev);
1682 if (clock_div < 0)
1683 return clock_div;
1684
1685 cit_read_reg(gspca_dev, 0x0128, 1);
1686 cit_read_reg(gspca_dev, 0x0100, 0);
1687 cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
1688 cit_read_reg(gspca_dev, 0x0100, 0);
1689 cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
1690 cit_read_reg(gspca_dev, 0x0100, 0);
1691 cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
1692 cit_write_reg(gspca_dev, 0x01, 0x0108);
1693
1694 cit_write_reg(gspca_dev, 0x03, 0x0112);
1695 cit_read_reg(gspca_dev, 0x0115, 0);
1696 cit_write_reg(gspca_dev, 0x06, 0x0115);
1697 cit_read_reg(gspca_dev, 0x0116, 0);
1698 cit_write_reg(gspca_dev, 0x44, 0x0116);
1699 cit_read_reg(gspca_dev, 0x0116, 0);
1700 cit_write_reg(gspca_dev, 0x40, 0x0116);
1701 cit_read_reg(gspca_dev, 0x0115, 0);
1702 cit_write_reg(gspca_dev, 0x0e, 0x0115);
1703 cit_write_reg(gspca_dev, 0x19, 0x012c);
1704
1705 cit_Packet_Format1(gspca_dev, 0x00, 0x1e);
1706 cit_Packet_Format1(gspca_dev, 0x39, 0x0d);
1707 cit_Packet_Format1(gspca_dev, 0x39, 0x09);
1708 cit_Packet_Format1(gspca_dev, 0x3b, 0x00);
1709 cit_Packet_Format1(gspca_dev, 0x28, 0x22);
1710 cit_Packet_Format1(gspca_dev, 0x27, 0x00);
1711 cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
1712 cit_Packet_Format1(gspca_dev, 0x39, 0x08);
1713
1714 for (i = 0; i < cit_model1_ntries; i++)
1715 cit_Packet_Format1(gspca_dev, 0x2c, 0x00);
1716
1717 for (i = 0; i < cit_model1_ntries; i++)
1718 cit_Packet_Format1(gspca_dev, 0x30, 0x14);
1719
1720 cit_PacketFormat2(gspca_dev, 0x39, 0x02);
1721 cit_PacketFormat2(gspca_dev, 0x01, 0xe1);
1722 cit_PacketFormat2(gspca_dev, 0x02, 0xcd);
1723 cit_PacketFormat2(gspca_dev, 0x03, 0xcd);
1724 cit_PacketFormat2(gspca_dev, 0x04, 0xfa);
1725 cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
1726 cit_PacketFormat2(gspca_dev, 0x39, 0x00);
1727
1728 cit_PacketFormat2(gspca_dev, 0x39, 0x02);
1729 cit_PacketFormat2(gspca_dev, 0x0a, 0x37);
1730 cit_PacketFormat2(gspca_dev, 0x0b, 0xb8);
1731 cit_PacketFormat2(gspca_dev, 0x0c, 0xf3);
1732 cit_PacketFormat2(gspca_dev, 0x0d, 0xe3);
1733 cit_PacketFormat2(gspca_dev, 0x0e, 0x0d);
1734 cit_PacketFormat2(gspca_dev, 0x0f, 0xf2);
1735 cit_PacketFormat2(gspca_dev, 0x10, 0xd5);
1736 cit_PacketFormat2(gspca_dev, 0x11, 0xba);
1737 cit_PacketFormat2(gspca_dev, 0x12, 0x53);
1738 cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
1739 cit_PacketFormat2(gspca_dev, 0x39, 0x00);
1740
1741 cit_PacketFormat2(gspca_dev, 0x39, 0x02);
1742 cit_PacketFormat2(gspca_dev, 0x16, 0x00);
1743 cit_PacketFormat2(gspca_dev, 0x17, 0x28);
1744 cit_PacketFormat2(gspca_dev, 0x18, 0x7d);
1745 cit_PacketFormat2(gspca_dev, 0x19, 0xbe);
1746 cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
1747 cit_PacketFormat2(gspca_dev, 0x39, 0x00);
1748
1749 for (i = 0; i < cit_model1_ntries; i++)
1750 cit_Packet_Format1(gspca_dev, 0x00, 0x18);
1751 for (i = 0; i < cit_model1_ntries; i++)
1752 cit_Packet_Format1(gspca_dev, 0x13, 0x18);
1753 for (i = 0; i < cit_model1_ntries; i++)
1754 cit_Packet_Format1(gspca_dev, 0x14, 0x06);
1755
1756 /* TESTME These are handled through controls
1757 KEEP until someone can test leaving this out is ok */
1758 if (0) {
1759 /* This is default brightness */
1760 for (i = 0; i < cit_model1_ntries; i++)
1761 cit_Packet_Format1(gspca_dev, 0x31, 0x37);
1762 for (i = 0; i < cit_model1_ntries; i++)
1763 cit_Packet_Format1(gspca_dev, 0x32, 0x46);
1764 for (i = 0; i < cit_model1_ntries; i++)
1765 cit_Packet_Format1(gspca_dev, 0x33, 0x55);
1766 }
1767
1768 cit_Packet_Format1(gspca_dev, 0x2e, 0x04);
1769 for (i = 0; i < cit_model1_ntries; i++)
1770 cit_Packet_Format1(gspca_dev, 0x2d, 0x04);
1771 for (i = 0; i < cit_model1_ntries; i++)
1772 cit_Packet_Format1(gspca_dev, 0x29, 0x80);
1773 cit_Packet_Format1(gspca_dev, 0x2c, 0x01);
1774 cit_Packet_Format1(gspca_dev, 0x30, 0x17);
1775 cit_Packet_Format1(gspca_dev, 0x39, 0x08);
1776 for (i = 0; i < cit_model1_ntries; i++)
1777 cit_Packet_Format1(gspca_dev, 0x34, 0x00);
1778
1779 cit_write_reg(gspca_dev, 0x00, 0x0101);
1780 cit_write_reg(gspca_dev, 0x00, 0x010a);
1781
1782 switch (gspca_dev->width) {
1783 case 128: /* 128x96 */
1784 cit_write_reg(gspca_dev, 0x80, 0x0103);
1785 cit_write_reg(gspca_dev, 0x60, 0x0105);
1786 cit_write_reg(gspca_dev, 0x0c, 0x010b);
1787 cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
1788 cit_write_reg(gspca_dev, 0x0b, 0x011d);
1789 cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
1790 cit_write_reg(gspca_dev, 0x00, 0x0129);
1791 break;
1792 case 176: /* 176x144 */
1793 cit_write_reg(gspca_dev, 0xb0, 0x0103);
1794 cit_write_reg(gspca_dev, 0x8f, 0x0105);
1795 cit_write_reg(gspca_dev, 0x06, 0x010b);
1796 cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
1797 cit_write_reg(gspca_dev, 0x0d, 0x011d);
1798 cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
1799 cit_write_reg(gspca_dev, 0x03, 0x0129);
1800 break;
1801 case 352: /* 352x288 */
1802 cit_write_reg(gspca_dev, 0xb0, 0x0103);
1803 cit_write_reg(gspca_dev, 0x90, 0x0105);
1804 cit_write_reg(gspca_dev, 0x02, 0x010b);
1805 cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
1806 cit_write_reg(gspca_dev, 0x05, 0x011d);
1807 cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
1808 cit_write_reg(gspca_dev, 0x00, 0x0129);
1809 break;
1810 }
1811
1812 cit_write_reg(gspca_dev, 0xff, 0x012b);
1813
1814 /* TESTME These are handled through controls
1815 KEEP until someone can test leaving this out is ok */
1816 if (0) {
1817 /* This is another brightness - don't know why */
1818 for (i = 0; i < cit_model1_ntries; i++)
1819 cit_Packet_Format1(gspca_dev, 0x31, 0xc3);
1820 for (i = 0; i < cit_model1_ntries; i++)
1821 cit_Packet_Format1(gspca_dev, 0x32, 0xd2);
1822 for (i = 0; i < cit_model1_ntries; i++)
1823 cit_Packet_Format1(gspca_dev, 0x33, 0xe1);
1824
1825 /* Default contrast */
1826 for (i = 0; i < cit_model1_ntries; i++)
1827 cit_Packet_Format1(gspca_dev, 0x14, 0x0a);
1828
1829 /* Default sharpness */
1830 for (i = 0; i < cit_model1_ntries2; i++)
1831 cit_PacketFormat2(gspca_dev, 0x13, 0x1a);
1832
1833 /* Default lighting conditions */
1834 cit_Packet_Format1(gspca_dev, 0x0027, sd->lighting);
1835 }
1836
1837 /* Assorted init */
1838 switch (gspca_dev->width) {
1839 case 128: /* 128x96 */
1840 cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
1841 cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
1842 cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
1843 cit_write_reg(gspca_dev, 0x36, 0x0102);
1844 cit_write_reg(gspca_dev, 0x1a, 0x0104);
1845 cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
1846 cit_write_reg(gspca_dev, 0x2b, 0x011c);
1847 cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
1848 break;
1849 case 176: /* 176x144 */
1850 cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
1851 cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
1852 cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
1853 cit_write_reg(gspca_dev, 0x04, 0x0102);
1854 cit_write_reg(gspca_dev, 0x02, 0x0104);
1855 cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
1856 cit_write_reg(gspca_dev, 0x2b, 0x011c);
1857 cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
1858 break;
1859 case 352: /* 352x288 */
1860 cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
1861 cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
1862 cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
1863 cit_write_reg(gspca_dev, 0x08, 0x0102);
1864 cit_write_reg(gspca_dev, 0x01, 0x0104);
1865 cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
1866 cit_write_reg(gspca_dev, 0x2f, 0x011c);
1867 cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
1868 break;
1869 }
1870
1871 cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
1872 cit_write_reg(gspca_dev, clock_div, 0x0111);
1873
1874 return 0;
1875}
1876
1877static int cit_start_model2(struct gspca_dev *gspca_dev)
1878{
1879 struct sd *sd = (struct sd *) gspca_dev;
1880 int clock_div = 0;
1881
1882 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
1883 cit_read_reg(gspca_dev, 0x0116, 0);
1884 cit_write_reg(gspca_dev, 0x0060, 0x0116);
1885 cit_write_reg(gspca_dev, 0x0002, 0x0112);
1886 cit_write_reg(gspca_dev, 0x00bc, 0x012c);
1887 cit_write_reg(gspca_dev, 0x0008, 0x012b);
1888 cit_write_reg(gspca_dev, 0x0000, 0x0108);
1889 cit_write_reg(gspca_dev, 0x0001, 0x0133);
1890 cit_write_reg(gspca_dev, 0x0001, 0x0102);
1891 switch (gspca_dev->width) {
1892 case 176: /* 176x144 */
1893 cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
1894 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1895 cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */
1896 cit_write_reg(gspca_dev, 0x00b9, 0x010a); /* Unique to this mode */
1897 cit_write_reg(gspca_dev, 0x0038, 0x0119); /* Unique to this mode */
1898 /* TESTME HDG: this does not seem right
1899 (it is 2 for all other resolutions) */
1900 sd->sof_len = 10;
1901 break;
1902 case 320: /* 320x240 */
1903 cit_write_reg(gspca_dev, 0x0028, 0x0103); /* Unique to this mode */
1904 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1905 cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
1906 cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
1907 cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
1908 sd->sof_len = 2;
1909 break;
1910 /* case VIDEOSIZE_352x240: */
1911 cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
1912 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1913 cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
1914 cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
1915 cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
1916 sd->sof_len = 2;
1917 break;
1918 case 352: /* 352x288 */
1919 cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
1920 cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
1921 cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */
1922 cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */
1923 cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
1924 sd->sof_len = 2;
1925 break;
1926 }
1927
1928 cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
1929
1930 switch (gspca_dev->width) {
1931 case 176: /* 176x144 */
1932 cit_write_reg(gspca_dev, 0x0050, 0x0111);
1933 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
1934 break;
1935 case 320: /* 320x240 */
1936 case 352: /* 352x288 */
1937 cit_write_reg(gspca_dev, 0x0040, 0x0111);
1938 cit_write_reg(gspca_dev, 0x00c0, 0x0111);
1939 break;
1940 }
1941 cit_write_reg(gspca_dev, 0x009b, 0x010f);
1942 cit_write_reg(gspca_dev, 0x00bb, 0x010f);
1943
1944 /*
1945 * Hardware settings, may affect CMOS sensor; not user controls!
1946 * -------------------------------------------------------------
1947 * 0x0004: no effect
1948 * 0x0006: hardware effect
1949 * 0x0008: no effect
1950 * 0x000a: stops video stream, probably important h/w setting
1951 * 0x000c: changes color in hardware manner (not user setting)
1952 * 0x0012: changes number of colors (does not affect speed)
1953 * 0x002a: no effect
1954 * 0x002c: hardware setting (related to scan lines)
1955 * 0x002e: stops video stream, probably important h/w setting
1956 */
1957 cit_model2_Packet1(gspca_dev, 0x000a, 0x005c);
1958 cit_model2_Packet1(gspca_dev, 0x0004, 0x0000);
1959 cit_model2_Packet1(gspca_dev, 0x0006, 0x00fb);
1960 cit_model2_Packet1(gspca_dev, 0x0008, 0x0000);
1961 cit_model2_Packet1(gspca_dev, 0x000c, 0x0009);
1962 cit_model2_Packet1(gspca_dev, 0x0012, 0x000a);
1963 cit_model2_Packet1(gspca_dev, 0x002a, 0x0000);
1964 cit_model2_Packet1(gspca_dev, 0x002c, 0x0000);
1965 cit_model2_Packet1(gspca_dev, 0x002e, 0x0008);
1966
1967 /*
1968 * Function 0x0030 pops up all over the place. Apparently
1969 * it is a hardware control register, with every bit assigned to
1970 * do something.
1971 */
1972 cit_model2_Packet1(gspca_dev, 0x0030, 0x0000);
1973
1974 /*
1975 * Magic control of CMOS sensor. Only lower values like
1976 * 0-3 work, and picture shifts left or right. Don't change.
1977 */
1978 switch (gspca_dev->width) {
1979 case 176: /* 176x144 */
1980 cit_model2_Packet1(gspca_dev, 0x0014, 0x0002);
1981 cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
1982 cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
1983 clock_div = 6;
1984 break;
1985 case 320: /* 320x240 */
1986 cit_model2_Packet1(gspca_dev, 0x0014, 0x0009);
1987 cit_model2_Packet1(gspca_dev, 0x0016, 0x0005); /* Horizontal shift */
1988 cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */
1989 clock_div = 8;
1990 break;
1991 /* case VIDEOSIZE_352x240: */
1992 /* This mode doesn't work as Windows programs it; changed to work */
1993 cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */
1994 cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */
1995 cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
1996 clock_div = 10;
1997 break;
1998 case 352: /* 352x288 */
1999 cit_model2_Packet1(gspca_dev, 0x0014, 0x0003);
2000 cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
2001 cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
2002 clock_div = 16;
2003 break;
2004 }
2005
2006 /* TESTME These are handled through controls
2007 KEEP until someone can test leaving this out is ok */
2008 if (0)
2009 cit_model2_Packet1(gspca_dev, 0x001a, 0x005a);
2010
2011 /*
2012 * We have our own frame rate setting varying from 0 (slowest) to 6
2013 * (fastest). The camera model 2 allows frame rate in range [0..0x1F]
2014 # where 0 is also the slowest setting. However for all practical
2015 # reasons high settings make no sense because USB is not fast enough
2016 # to support high FPS. Be aware that the picture datastream will be
2017 # severely disrupted if you ask for frame rate faster than allowed
2018 # for the video size - see below:
2019 *
2020 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
2021 * -----------------------------------------------------------------
2022 * 176x144: [6..31]
2023 * 320x240: [8..31]
2024 * 352x240: [10..31]
2025 * 352x288: [16..31] I have to raise lower threshold for stability...
2026 *
2027 * As usual, slower FPS provides better sensitivity.
2028 */
2029 cit_model2_Packet1(gspca_dev, 0x001c, clock_div);
2030
2031 /*
2032 * This setting does not visibly affect pictures; left it here
2033 * because it was present in Windows USB data stream. This function
2034 * does not allow arbitrary values and apparently is a bit mask, to
2035 * be activated only at appropriate time. Don't change it randomly!
2036 */
2037 switch (gspca_dev->width) {
2038 case 176: /* 176x144 */
2039 cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2);
2040 break;
2041 case 320: /* 320x240 */
2042 cit_model2_Packet1(gspca_dev, 0x0026, 0x0044);
2043 break;
2044 /* case VIDEOSIZE_352x240: */
2045 cit_model2_Packet1(gspca_dev, 0x0026, 0x0046);
2046 break;
2047 case 352: /* 352x288 */
2048 cit_model2_Packet1(gspca_dev, 0x0026, 0x0048);
2049 break;
2050 }
2051
2052 /* FIXME this cannot be changed while streaming, so we
2053 should report a grabbed flag for this control. */
2054 cit_model2_Packet1(gspca_dev, 0x0028, sd->lighting);
2055 /* color balance rg2 */
2056 cit_model2_Packet1(gspca_dev, 0x001e, 0x002f);
2057 /* saturation */
2058 cit_model2_Packet1(gspca_dev, 0x0020, 0x0034);
2059 /* color balance yb */
2060 cit_model2_Packet1(gspca_dev, 0x0022, 0x00a0);
2061
2062 /* Hardware control command */
2063 cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
2064
2065 return 0;
2066}
2067
2068static int cit_start_model3(struct gspca_dev *gspca_dev)
2069{
2070 const unsigned short compression = 0; /* 0=none, 7=best frame rate */
2071 int i, clock_div = 0;
2072
2073 /* HDG not in ibmcam driver, added to see if it helps with
2074 auto-detecting between model3 and ibm netcamera pro */
2075 cit_read_reg(gspca_dev, 0x128, 1);
2076
2077 cit_write_reg(gspca_dev, 0x0000, 0x0100);
2078 cit_read_reg(gspca_dev, 0x0116, 0);
2079 cit_write_reg(gspca_dev, 0x0060, 0x0116);
2080 cit_write_reg(gspca_dev, 0x0002, 0x0112);
2081 cit_write_reg(gspca_dev, 0x0000, 0x0123);
2082 cit_write_reg(gspca_dev, 0x0001, 0x0117);
2083 cit_write_reg(gspca_dev, 0x0040, 0x0108);
2084 cit_write_reg(gspca_dev, 0x0019, 0x012c);
2085 cit_write_reg(gspca_dev, 0x0060, 0x0116);
2086 cit_write_reg(gspca_dev, 0x0002, 0x0115);
2087 cit_write_reg(gspca_dev, 0x0003, 0x0115);
2088 cit_read_reg(gspca_dev, 0x0115, 0);
2089 cit_write_reg(gspca_dev, 0x000b, 0x0115);
2090
2091 /* TESTME HDG not in ibmcam driver, added to see if it helps with
2092 auto-detecting between model3 and ibm netcamera pro */
2093 if (0) {
2094 cit_write_reg(gspca_dev, 0x0078, 0x012d);
2095 cit_write_reg(gspca_dev, 0x0001, 0x012f);
2096 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2097 cit_write_reg(gspca_dev, 0x0079, 0x012d);
2098 cit_write_reg(gspca_dev, 0x00ff, 0x0130);
2099 cit_write_reg(gspca_dev, 0xcd41, 0x0124);
2100 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2101 cit_read_reg(gspca_dev, 0x0126, 1);
2102 }
2103
2104 cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
2105 cit_model3_Packet1(gspca_dev, 0x000b, 0x00f6);
2106 cit_model3_Packet1(gspca_dev, 0x000c, 0x0002);
2107 cit_model3_Packet1(gspca_dev, 0x000d, 0x0020);
2108 cit_model3_Packet1(gspca_dev, 0x000e, 0x0033);
2109 cit_model3_Packet1(gspca_dev, 0x000f, 0x0007);
2110 cit_model3_Packet1(gspca_dev, 0x0010, 0x0000);
2111 cit_model3_Packet1(gspca_dev, 0x0011, 0x0070);
2112 cit_model3_Packet1(gspca_dev, 0x0012, 0x0030);
2113 cit_model3_Packet1(gspca_dev, 0x0013, 0x0000);
2114 cit_model3_Packet1(gspca_dev, 0x0014, 0x0001);
2115 cit_model3_Packet1(gspca_dev, 0x0015, 0x0001);
2116 cit_model3_Packet1(gspca_dev, 0x0016, 0x0001);
2117 cit_model3_Packet1(gspca_dev, 0x0017, 0x0001);
2118 cit_model3_Packet1(gspca_dev, 0x0018, 0x0000);
2119 cit_model3_Packet1(gspca_dev, 0x001e, 0x00c3);
2120 cit_model3_Packet1(gspca_dev, 0x0020, 0x0000);
2121 cit_model3_Packet1(gspca_dev, 0x0028, 0x0010);
2122 cit_model3_Packet1(gspca_dev, 0x0029, 0x0054);
2123 cit_model3_Packet1(gspca_dev, 0x002a, 0x0013);
2124 cit_model3_Packet1(gspca_dev, 0x002b, 0x0007);
2125 cit_model3_Packet1(gspca_dev, 0x002d, 0x0028);
2126 cit_model3_Packet1(gspca_dev, 0x002e, 0x0000);
2127 cit_model3_Packet1(gspca_dev, 0x0031, 0x0000);
2128 cit_model3_Packet1(gspca_dev, 0x0032, 0x0000);
2129 cit_model3_Packet1(gspca_dev, 0x0033, 0x0000);
2130 cit_model3_Packet1(gspca_dev, 0x0034, 0x0000);
2131 cit_model3_Packet1(gspca_dev, 0x0035, 0x0038);
2132 cit_model3_Packet1(gspca_dev, 0x003a, 0x0001);
2133 cit_model3_Packet1(gspca_dev, 0x003c, 0x001e);
2134 cit_model3_Packet1(gspca_dev, 0x003f, 0x000a);
2135 cit_model3_Packet1(gspca_dev, 0x0041, 0x0000);
2136 cit_model3_Packet1(gspca_dev, 0x0046, 0x003f);
2137 cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
2138 cit_model3_Packet1(gspca_dev, 0x0050, 0x0005);
2139 cit_model3_Packet1(gspca_dev, 0x0052, 0x001a);
2140 cit_model3_Packet1(gspca_dev, 0x0053, 0x0003);
2141 cit_model3_Packet1(gspca_dev, 0x005a, 0x006b);
2142 cit_model3_Packet1(gspca_dev, 0x005d, 0x001e);
2143 cit_model3_Packet1(gspca_dev, 0x005e, 0x0030);
2144 cit_model3_Packet1(gspca_dev, 0x005f, 0x0041);
2145 cit_model3_Packet1(gspca_dev, 0x0064, 0x0008);
2146 cit_model3_Packet1(gspca_dev, 0x0065, 0x0015);
2147 cit_model3_Packet1(gspca_dev, 0x0068, 0x000f);
2148 cit_model3_Packet1(gspca_dev, 0x0079, 0x0000);
2149 cit_model3_Packet1(gspca_dev, 0x007a, 0x0000);
2150 cit_model3_Packet1(gspca_dev, 0x007c, 0x003f);
2151 cit_model3_Packet1(gspca_dev, 0x0082, 0x000f);
2152 cit_model3_Packet1(gspca_dev, 0x0085, 0x0000);
2153 cit_model3_Packet1(gspca_dev, 0x0099, 0x0000);
2154 cit_model3_Packet1(gspca_dev, 0x009b, 0x0023);
2155 cit_model3_Packet1(gspca_dev, 0x009c, 0x0022);
2156 cit_model3_Packet1(gspca_dev, 0x009d, 0x0096);
2157 cit_model3_Packet1(gspca_dev, 0x009e, 0x0096);
2158 cit_model3_Packet1(gspca_dev, 0x009f, 0x000a);
2159
2160 switch (gspca_dev->width) {
2161 case 160:
2162 cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
2163 cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
2164 cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
2165 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2166 cit_write_reg(gspca_dev, 0x0024, 0x010b); /* Differs everywhere */
2167 cit_write_reg(gspca_dev, 0x00a9, 0x0119);
2168 cit_write_reg(gspca_dev, 0x0016, 0x011b);
2169 cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
2170 cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
2171 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2172 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2173 cit_write_reg(gspca_dev, 0x0018, 0x0102);
2174 cit_write_reg(gspca_dev, 0x0004, 0x0104);
2175 cit_write_reg(gspca_dev, 0x0004, 0x011a);
2176 cit_write_reg(gspca_dev, 0x0028, 0x011c);
2177 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2178 cit_write_reg(gspca_dev, 0x0000, 0x0118);
2179 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2180 cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
2181 cit_write_reg(gspca_dev, compression, 0x0109);
2182 clock_div = 3;
2183 break;
2184 case 320:
2185 cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
2186 cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
2187 cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
2188 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2189 cit_write_reg(gspca_dev, 0x0028, 0x010b); /* Differs everywhere */
2190 cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same */
2191 cit_write_reg(gspca_dev, 0x0000, 0x011e);
2192 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2193 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2194 /* 4 commands from 160x120 skipped */
2195 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2196 cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
2197 cit_write_reg(gspca_dev, compression, 0x0109);
2198 cit_write_reg(gspca_dev, 0x00d9, 0x0119);
2199 cit_write_reg(gspca_dev, 0x0006, 0x011b);
2200 cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
2201 cit_write_reg(gspca_dev, 0x0010, 0x0104);
2202 cit_write_reg(gspca_dev, 0x0004, 0x011a);
2203 cit_write_reg(gspca_dev, 0x003f, 0x011c);
2204 cit_write_reg(gspca_dev, 0x001c, 0x0118);
2205 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2206 clock_div = 5;
2207 break;
2208 case 640:
2209 cit_write_reg(gspca_dev, 0x00f0, 0x0105);
2210 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2211 cit_write_reg(gspca_dev, 0x0038, 0x010b); /* Differs everywhere */
2212 cit_write_reg(gspca_dev, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
2213 cit_write_reg(gspca_dev, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
2214 cit_write_reg(gspca_dev, 0x0004, 0x011d); /* NC */
2215 cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
2216 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2217 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2218 cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
2219 cit_write_reg(gspca_dev, 0x0016, 0x0104); /* NC */
2220 cit_write_reg(gspca_dev, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
2221 cit_write_reg(gspca_dev, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
2222 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2223 cit_write_reg(gspca_dev, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
2224 cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
2225 cit_write_reg(gspca_dev, compression, 0x0109);
2226 cit_write_reg(gspca_dev, 0x0040, 0x0101);
2227 cit_write_reg(gspca_dev, 0x0040, 0x0103);
2228 cit_write_reg(gspca_dev, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
2229 clock_div = 7;
2230 break;
2231 }
2232
2233 cit_model3_Packet1(gspca_dev, 0x007e, 0x000e); /* Hue */
2234 cit_model3_Packet1(gspca_dev, 0x0036, 0x0011); /* Brightness */
2235 cit_model3_Packet1(gspca_dev, 0x0060, 0x0002); /* Sharpness */
2236 cit_model3_Packet1(gspca_dev, 0x0061, 0x0004); /* Sharpness */
2237 cit_model3_Packet1(gspca_dev, 0x0062, 0x0005); /* Sharpness */
2238 cit_model3_Packet1(gspca_dev, 0x0063, 0x0014); /* Sharpness */
2239 cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */
2240 cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */
2241 cit_model3_Packet1(gspca_dev, 0x0067, 0x0001); /* Contrast */
2242 cit_model3_Packet1(gspca_dev, 0x005b, 0x000c); /* Contrast */
2243 cit_model3_Packet1(gspca_dev, 0x005c, 0x0016); /* Contrast */
2244 cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
2245 cit_model3_Packet1(gspca_dev, 0x002c, 0x0003); /* Was 1, broke 640x480 */
2246 cit_model3_Packet1(gspca_dev, 0x002f, 0x002a);
2247 cit_model3_Packet1(gspca_dev, 0x0030, 0x0029);
2248 cit_model3_Packet1(gspca_dev, 0x0037, 0x0002);
2249 cit_model3_Packet1(gspca_dev, 0x0038, 0x0059);
2250 cit_model3_Packet1(gspca_dev, 0x003d, 0x002e);
2251 cit_model3_Packet1(gspca_dev, 0x003e, 0x0028);
2252 cit_model3_Packet1(gspca_dev, 0x0078, 0x0005);
2253 cit_model3_Packet1(gspca_dev, 0x007b, 0x0011);
2254 cit_model3_Packet1(gspca_dev, 0x007d, 0x004b);
2255 cit_model3_Packet1(gspca_dev, 0x007f, 0x0022);
2256 cit_model3_Packet1(gspca_dev, 0x0080, 0x000c);
2257 cit_model3_Packet1(gspca_dev, 0x0081, 0x000b);
2258 cit_model3_Packet1(gspca_dev, 0x0083, 0x00fd);
2259 cit_model3_Packet1(gspca_dev, 0x0086, 0x000b);
2260 cit_model3_Packet1(gspca_dev, 0x0087, 0x000b);
2261 cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);
2262 cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */
2263 cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */
2264 cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
2265
2266 /* FIXME we should probably use cit_get_clock_div() here (in
2267 combination with isoc negotiation using the programmable isoc size)
2268 like with the IBM netcam pro). */
2269 cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */
2270
2271 switch (gspca_dev->width) {
2272 case 160:
2273 cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
2274 cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
2275 cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
2276 cit_model3_Packet1(gspca_dev, 0x0040, 0x000a);
2277 cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
2278 break;
2279 case 320:
2280 cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
2281 cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
2282 cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
2283 cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
2284 cit_model3_Packet1(gspca_dev, 0x0051, 0x000b);
2285 break;
2286 case 640:
2287 cit_model3_Packet1(gspca_dev, 0x001f, 0x0002); /* !Same */
2288 cit_model3_Packet1(gspca_dev, 0x0039, 0x003e); /* !Same */
2289 cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
2290 cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
2291 break;
2292 }
2293
2294/* if (sd->input_index) { */
2295 if (rca_input) {
2296 for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
2297 if (rca_initdata[i][0])
2298 cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
2299 else
2300 cit_write_reg(gspca_dev, rca_initdata[i][1],
2301 rca_initdata[i][2]);
2302 }
2303 }
2304
2305 return 0;
2306}
2307
2308static int cit_start_model4(struct gspca_dev *gspca_dev)
2309{
2310 struct sd *sd = (struct sd *) gspca_dev;
2311
2312 cit_write_reg(gspca_dev, 0x0000, 0x0100);
2313 cit_write_reg(gspca_dev, 0x00c0, 0x0111);
2314 cit_write_reg(gspca_dev, 0x00bc, 0x012c);
2315 cit_write_reg(gspca_dev, 0x0080, 0x012b);
2316 cit_write_reg(gspca_dev, 0x0000, 0x0108);
2317 cit_write_reg(gspca_dev, 0x0001, 0x0133);
2318 cit_write_reg(gspca_dev, 0x009b, 0x010f);
2319 cit_write_reg(gspca_dev, 0x00bb, 0x010f);
2320 cit_model4_Packet1(gspca_dev, 0x0038, 0x0000);
2321 cit_model4_Packet1(gspca_dev, 0x000a, 0x005c);
2322
2323 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2324 cit_write_reg(gspca_dev, 0x0004, 0x012f);
2325 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2326 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2327 cit_write_reg(gspca_dev, 0x00fb, 0x012e);
2328 cit_write_reg(gspca_dev, 0x0000, 0x0130);
2329 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2330 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2331 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2332 cit_write_reg(gspca_dev, 0x000c, 0x0127);
2333 cit_write_reg(gspca_dev, 0x0009, 0x012e);
2334 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2335
2336 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2337 cit_write_reg(gspca_dev, 0x0012, 0x012f);
2338 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2339 cit_write_reg(gspca_dev, 0x0008, 0x0127);
2340 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2341 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2342 cit_write_reg(gspca_dev, 0x002a, 0x012d);
2343 cit_write_reg(gspca_dev, 0x0000, 0x012f);
2344 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2345 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2346 cit_model4_Packet1(gspca_dev, 0x0034, 0x0000);
2347
2348 switch (gspca_dev->width) {
2349 case 128: /* 128x96 */
2350 cit_write_reg(gspca_dev, 0x0070, 0x0119);
2351 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2352 cit_write_reg(gspca_dev, 0x0039, 0x010a);
2353 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2354 cit_write_reg(gspca_dev, 0x0028, 0x0103);
2355 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2356 cit_write_reg(gspca_dev, 0x001e, 0x0105);
2357 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2358 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2359 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2360 cit_write_reg(gspca_dev, 0x000a, 0x0127);
2361 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2362 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2363 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2364 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2365 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2366 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2367 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2368 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2369 cit_write_reg(gspca_dev, 0x005a, 0x012d);
2370 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2371 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2372 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2373 cit_write_reg(gspca_dev, 0x0043, 0x0130);
2374 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2375 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2376 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2377 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2378 cit_write_reg(gspca_dev, 0x00eb, 0x012e);
2379 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2380 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2381 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2382 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2383 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2384 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2385 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2386 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2387 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2388 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2389 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2390 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2391 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2392 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2393 cit_write_reg(gspca_dev, 0x0017, 0x0127);
2394 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2395 cit_write_reg(gspca_dev, 0x0031, 0x0130);
2396 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2397 cit_write_reg(gspca_dev, 0x0017, 0x012d);
2398 cit_write_reg(gspca_dev, 0x0078, 0x012f);
2399 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2400 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2401 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2402 sd->sof_len = 2;
2403 break;
2404 case 160: /* 160x120 */
2405 cit_write_reg(gspca_dev, 0x0038, 0x0119);
2406 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2407 cit_write_reg(gspca_dev, 0x00b9, 0x010a);
2408 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2409 cit_write_reg(gspca_dev, 0x0028, 0x0103);
2410 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2411 cit_write_reg(gspca_dev, 0x001e, 0x0105);
2412 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2413 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2414 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2415 cit_write_reg(gspca_dev, 0x000b, 0x0127);
2416 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2417 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2418 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2419 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2420 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2421 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2422 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2423 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2424 cit_write_reg(gspca_dev, 0x005a, 0x012d);
2425 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2426 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2427 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2428 cit_write_reg(gspca_dev, 0x0043, 0x0130);
2429 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2430 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2431 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2432 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2433 cit_write_reg(gspca_dev, 0x00c7, 0x012e);
2434 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2435 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2436 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2437 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2438 cit_write_reg(gspca_dev, 0x0025, 0x0127);
2439 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2440 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2441 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2442 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2443 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2444 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2445 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2446 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2447 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2448 cit_write_reg(gspca_dev, 0x0048, 0x0127);
2449 cit_write_reg(gspca_dev, 0x0035, 0x012e);
2450 cit_write_reg(gspca_dev, 0x00d0, 0x0130);
2451 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2452 cit_write_reg(gspca_dev, 0x0048, 0x012d);
2453 cit_write_reg(gspca_dev, 0x0090, 0x012f);
2454 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2455 cit_write_reg(gspca_dev, 0x0001, 0x0127);
2456 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2457 sd->sof_len = 2;
2458 break;
2459 case 176: /* 176x144 */
2460 cit_write_reg(gspca_dev, 0x0038, 0x0119);
2461 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2462 cit_write_reg(gspca_dev, 0x00b9, 0x010a);
2463 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2464 cit_write_reg(gspca_dev, 0x002c, 0x0103);
2465 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2466 cit_write_reg(gspca_dev, 0x0024, 0x0105);
2467 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2468 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2469 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2470 cit_write_reg(gspca_dev, 0x0007, 0x0127);
2471 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2472 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2473 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2474 cit_write_reg(gspca_dev, 0x0001, 0x012f);
2475 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2476 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2477 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2478 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2479 cit_write_reg(gspca_dev, 0x005e, 0x012d);
2480 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2481 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2482 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2483 cit_write_reg(gspca_dev, 0x0049, 0x0130);
2484 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2485 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2486 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2487 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2488 cit_write_reg(gspca_dev, 0x00c7, 0x012e);
2489 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2490 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2491 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2492 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2493 cit_write_reg(gspca_dev, 0x0028, 0x0127);
2494 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2495 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2496 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2497 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2498 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2499 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2500 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2501 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2502 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2503 cit_write_reg(gspca_dev, 0x0010, 0x0127);
2504 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2505 cit_write_reg(gspca_dev, 0x002a, 0x0130);
2506 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2507 cit_write_reg(gspca_dev, 0x0010, 0x012d);
2508 cit_write_reg(gspca_dev, 0x006d, 0x012f);
2509 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2510 cit_write_reg(gspca_dev, 0x0001, 0x0127);
2511 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2512 /* TESTME HDG: this does not seem right
2513 (it is 2 for all other resolutions) */
2514 sd->sof_len = 10;
2515 break;
2516 case 320: /* 320x240 */
2517 cit_write_reg(gspca_dev, 0x0070, 0x0119);
2518 cit_write_reg(gspca_dev, 0x00d0, 0x0111);
2519 cit_write_reg(gspca_dev, 0x0039, 0x010a);
2520 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2521 cit_write_reg(gspca_dev, 0x0028, 0x0103);
2522 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2523 cit_write_reg(gspca_dev, 0x001e, 0x0105);
2524 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2525 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2526 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2527 cit_write_reg(gspca_dev, 0x000a, 0x0127);
2528 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2529 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2530 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2531 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2532 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2533 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2534 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2535 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2536 cit_write_reg(gspca_dev, 0x005a, 0x012d);
2537 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2538 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2539 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2540 cit_write_reg(gspca_dev, 0x0043, 0x0130);
2541 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2542 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2543 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2544 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2545 cit_write_reg(gspca_dev, 0x00eb, 0x012e);
2546 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2547 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2548 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2549 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2550 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2551 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2552 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2553 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2554 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2555 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2556 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2557 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2558 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2559 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2560 cit_write_reg(gspca_dev, 0x0017, 0x0127);
2561 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2562 cit_write_reg(gspca_dev, 0x0031, 0x0130);
2563 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2564 cit_write_reg(gspca_dev, 0x0017, 0x012d);
2565 cit_write_reg(gspca_dev, 0x0078, 0x012f);
2566 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2567 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2568 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2569 sd->sof_len = 2;
2570 break;
2571 case 352: /* 352x288 */
2572 cit_write_reg(gspca_dev, 0x0070, 0x0119);
2573 cit_write_reg(gspca_dev, 0x00c0, 0x0111);
2574 cit_write_reg(gspca_dev, 0x0039, 0x010a);
2575 cit_write_reg(gspca_dev, 0x0001, 0x0102);
2576 cit_write_reg(gspca_dev, 0x002c, 0x0103);
2577 cit_write_reg(gspca_dev, 0x0000, 0x0104);
2578 cit_write_reg(gspca_dev, 0x0024, 0x0105);
2579 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2580 cit_write_reg(gspca_dev, 0x0016, 0x012f);
2581 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2582 cit_write_reg(gspca_dev, 0x0006, 0x0127);
2583 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2584 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2585 cit_write_reg(gspca_dev, 0x0014, 0x012d);
2586 cit_write_reg(gspca_dev, 0x0002, 0x012f);
2587 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2588 cit_write_reg(gspca_dev, 0x00aa, 0x012e);
2589 cit_write_reg(gspca_dev, 0x001a, 0x0130);
2590 cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
2591 cit_write_reg(gspca_dev, 0x005e, 0x012d);
2592 cit_write_reg(gspca_dev, 0x9545, 0x0124);
2593 cit_write_reg(gspca_dev, 0x00aa, 0x0127);
2594 cit_write_reg(gspca_dev, 0x0018, 0x012e);
2595 cit_write_reg(gspca_dev, 0x0049, 0x0130);
2596 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2597 cit_write_reg(gspca_dev, 0x00aa, 0x012f);
2598 cit_write_reg(gspca_dev, 0xd055, 0x0124);
2599 cit_write_reg(gspca_dev, 0x001c, 0x0127);
2600 cit_write_reg(gspca_dev, 0x00cf, 0x012e);
2601 cit_write_reg(gspca_dev, 0xaa28, 0x0124);
2602 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2603 cit_write_reg(gspca_dev, 0x0032, 0x012f);
2604 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2605 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2606 cit_write_reg(gspca_dev, 0x00aa, 0x0130);
2607 cit_write_reg(gspca_dev, 0x82a8, 0x0124);
2608 cit_write_reg(gspca_dev, 0x0036, 0x012d);
2609 cit_write_reg(gspca_dev, 0x0008, 0x012f);
2610 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2611 cit_write_reg(gspca_dev, 0xfffa, 0x0124);
2612 cit_write_reg(gspca_dev, 0x00aa, 0x012d);
2613 cit_write_reg(gspca_dev, 0x001e, 0x012f);
2614 cit_write_reg(gspca_dev, 0xd141, 0x0124);
2615 cit_write_reg(gspca_dev, 0x0010, 0x0127);
2616 cit_write_reg(gspca_dev, 0x0013, 0x012e);
2617 cit_write_reg(gspca_dev, 0x0025, 0x0130);
2618 cit_write_reg(gspca_dev, 0x8a28, 0x0124);
2619 cit_write_reg(gspca_dev, 0x0010, 0x012d);
2620 cit_write_reg(gspca_dev, 0x0048, 0x012f);
2621 cit_write_reg(gspca_dev, 0xd145, 0x0124);
2622 cit_write_reg(gspca_dev, 0x0000, 0x0127);
2623 cit_write_reg(gspca_dev, 0xfea8, 0x0124);
2624 sd->sof_len = 2;
2625 break;
2626 }
2627
2628 cit_model4_Packet1(gspca_dev, 0x0038, 0x0004);
2629
2630 return 0;
2631}
2632
2633static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
2634{
2635 const unsigned short compression = 0; /* 0=none, 7=best frame rate */
2636 int i, clock_div;
2637
2638 clock_div = cit_get_clock_div(gspca_dev);
2639 if (clock_div < 0)
2640 return clock_div;
2641
2642 cit_write_reg(gspca_dev, 0x0003, 0x0133);
2643 cit_write_reg(gspca_dev, 0x0000, 0x0117);
2644 cit_write_reg(gspca_dev, 0x0008, 0x0123);
2645 cit_write_reg(gspca_dev, 0x0000, 0x0100);
2646 cit_write_reg(gspca_dev, 0x0060, 0x0116);
2647 /* cit_write_reg(gspca_dev, 0x0002, 0x0112); see sd_stop0 */
2648 cit_write_reg(gspca_dev, 0x0000, 0x0133);
2649 cit_write_reg(gspca_dev, 0x0000, 0x0123);
2650 cit_write_reg(gspca_dev, 0x0001, 0x0117);
2651 cit_write_reg(gspca_dev, 0x0040, 0x0108);
2652 cit_write_reg(gspca_dev, 0x0019, 0x012c);
2653 cit_write_reg(gspca_dev, 0x0060, 0x0116);
2654 /* cit_write_reg(gspca_dev, 0x000b, 0x0115); see sd_stop0 */
2655
2656 cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
2657
2658 cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
2659 cit_write_reg(gspca_dev, 0x003a, 0x0102); /* Hstart */
2660 cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
2661 cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
2662 cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
2663 cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
2664 cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
2665 cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
2666 cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
2667
2668 switch (gspca_dev->width) {
2669 case 160: /* 160x120 */
2670 cit_write_reg(gspca_dev, 0x0024, 0x010b);
2671 cit_write_reg(gspca_dev, 0x0089, 0x0119);
2672 cit_write_reg(gspca_dev, 0x000a, 0x011b);
2673 cit_write_reg(gspca_dev, 0x0003, 0x011e);
2674 cit_write_reg(gspca_dev, 0x0007, 0x0104);
2675 cit_write_reg(gspca_dev, 0x0009, 0x011a);
2676 cit_write_reg(gspca_dev, 0x008b, 0x011c);
2677 cit_write_reg(gspca_dev, 0x0008, 0x0118);
2678 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2679 break;
2680 case 320: /* 320x240 */
2681 cit_write_reg(gspca_dev, 0x0028, 0x010b);
2682 cit_write_reg(gspca_dev, 0x00d9, 0x0119);
2683 cit_write_reg(gspca_dev, 0x0006, 0x011b);
2684 cit_write_reg(gspca_dev, 0x0000, 0x011e);
2685 cit_write_reg(gspca_dev, 0x000e, 0x0104);
2686 cit_write_reg(gspca_dev, 0x0004, 0x011a);
2687 cit_write_reg(gspca_dev, 0x003f, 0x011c);
2688 cit_write_reg(gspca_dev, 0x000c, 0x0118);
2689 cit_write_reg(gspca_dev, 0x0000, 0x0132);
2690 break;
2691 }
2692
2693 cit_model3_Packet1(gspca_dev, 0x0019, 0x0031);
2694 cit_model3_Packet1(gspca_dev, 0x001a, 0x0003);
2695 cit_model3_Packet1(gspca_dev, 0x001b, 0x0038);
2696 cit_model3_Packet1(gspca_dev, 0x001c, 0x0000);
2697 cit_model3_Packet1(gspca_dev, 0x0024, 0x0001);
2698 cit_model3_Packet1(gspca_dev, 0x0027, 0x0001);
2699 cit_model3_Packet1(gspca_dev, 0x002a, 0x0004);
2700 cit_model3_Packet1(gspca_dev, 0x0035, 0x000b);
2701 cit_model3_Packet1(gspca_dev, 0x003f, 0x0001);
2702 cit_model3_Packet1(gspca_dev, 0x0044, 0x0000);
2703 cit_model3_Packet1(gspca_dev, 0x0054, 0x0000);
2704 cit_model3_Packet1(gspca_dev, 0x00c4, 0x0000);
2705 cit_model3_Packet1(gspca_dev, 0x00e7, 0x0001);
2706 cit_model3_Packet1(gspca_dev, 0x00e9, 0x0001);
2707 cit_model3_Packet1(gspca_dev, 0x00ee, 0x0000);
2708 cit_model3_Packet1(gspca_dev, 0x00f3, 0x00c0);
2709
2710 cit_write_reg(gspca_dev, compression, 0x0109);
2711 cit_write_reg(gspca_dev, clock_div, 0x0111);
2712
2713/* if (sd->input_index) { */
2714 if (rca_input) {
2715 for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
2716 if (rca_initdata[i][0])
2717 cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
2718 else
2719 cit_write_reg(gspca_dev, rca_initdata[i][1],
2720 rca_initdata[i][2]);
2721 }
2722 }
2723
2724 return 0;
2725}
2726
2727/* -- start the camera -- */
2728static int sd_start(struct gspca_dev *gspca_dev)
2729{
2730 struct sd *sd = (struct sd *) gspca_dev;
2731 int packet_size;
2732
2733 packet_size = cit_get_packet_size(gspca_dev);
2734 if (packet_size < 0)
2735 return packet_size;
2736
2737 switch (sd->model) {
2738 case CIT_MODEL0:
2739 cit_start_model0(gspca_dev);
2740 break;
2741 case CIT_MODEL1:
2742 cit_start_model1(gspca_dev);
2743 break;
2744 case CIT_MODEL2:
2745 cit_start_model2(gspca_dev);
2746 break;
2747 case CIT_MODEL3:
2748 cit_start_model3(gspca_dev);
2749 break;
2750 case CIT_MODEL4:
2751 cit_start_model4(gspca_dev);
2752 break;
2753 case CIT_IBM_NETCAM_PRO:
2754 cit_start_ibm_netcam_pro(gspca_dev);
2755 break;
2756 }
2757
2758 cit_set_brightness(gspca_dev);
2759 cit_set_contrast(gspca_dev);
2760 cit_set_hue(gspca_dev);
2761 cit_set_sharpness(gspca_dev);
2762 cit_set_lighting(gspca_dev);
2763 cit_set_hflip(gspca_dev);
2764
2765 /* Program max isoc packet size */
2766 cit_write_reg(gspca_dev, packet_size >> 8, 0x0106);
2767 cit_write_reg(gspca_dev, packet_size & 0xff, 0x0107);
2768
2769 cit_restart_stream(gspca_dev);
2770
2771 return 0;
2772}
2773
2774static int sd_isoc_init(struct gspca_dev *gspca_dev)
2775{
2776 struct usb_host_interface *alt;
2777 int max_packet_size;
2778
2779 switch (gspca_dev->width) {
2780 case 160:
2781 max_packet_size = 450;
2782 break;
2783 case 176:
2784 max_packet_size = 600;
2785 break;
2786 default:
2787 max_packet_size = 1022;
2788 break;
2789 }
2790
2791 /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
2792 alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
2793 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
2794
2795 return 0;
2796}
2797
2798static int sd_isoc_nego(struct gspca_dev *gspca_dev)
2799{
2800 int ret, packet_size, min_packet_size;
2801 struct usb_host_interface *alt;
2802
2803 switch (gspca_dev->width) {
2804 case 160:
2805 min_packet_size = 200;
2806 break;
2807 case 176:
2808 min_packet_size = 266;
2809 break;
2810 default:
2811 min_packet_size = 400;
2812 break;
2813 }
2814
2815 alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
2816 packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
2817 if (packet_size <= min_packet_size)
2818 return -EIO;
2819
2820 packet_size -= 100;
2821 if (packet_size < min_packet_size)
2822 packet_size = min_packet_size;
2823 alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
2824
2825 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
2826 if (ret < 0)
2827 err("set alt 1 err %d", ret);
2828
2829 return ret;
2830}
2831
2832static void sd_stopN(struct gspca_dev *gspca_dev)
2833{
2834 cit_write_reg(gspca_dev, 0x0000, 0x010c);
2835}
2836
2837static void sd_stop0(struct gspca_dev *gspca_dev)
2838{
2839 struct sd *sd = (struct sd *) gspca_dev;
2840
2841 /* We cannot use gspca_dev->present here as that is not set when
2842 sd_init gets called and we get called from sd_init */
2843 if (!gspca_dev->dev)
2844 return;
2845
2846 switch (sd->model) {
2847 case CIT_MODEL0:
2848 /* HDG windows does this, but it causes the cams autogain to
2849 restart from a gain of 0, which does not look good when
2850 changing resolutions. */
2851 /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
2852 cit_write_reg(gspca_dev, 0x00c0, 0x0100); /* LED Off */
2853 break;
2854 case CIT_MODEL1:
2855 cit_send_FF_04_02(gspca_dev);
2856 cit_read_reg(gspca_dev, 0x0100, 0);
2857 cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
2858 break;
2859 case CIT_MODEL2:
2860 case CIT_MODEL4:
2861 cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
2862
2863 cit_write_reg(gspca_dev, 0x0080, 0x0100); /* LED Off */
2864 cit_write_reg(gspca_dev, 0x0020, 0x0111);
2865 cit_write_reg(gspca_dev, 0x00a0, 0x0111);
2866
2867 cit_model2_Packet1(gspca_dev, 0x0030, 0x0002);
2868
2869 cit_write_reg(gspca_dev, 0x0020, 0x0111);
2870 cit_write_reg(gspca_dev, 0x0000, 0x0112);
2871 break;
2872 case CIT_MODEL3:
2873 cit_write_reg(gspca_dev, 0x0006, 0x012c);
2874 cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
2875 cit_read_reg(gspca_dev, 0x0116, 0);
2876 cit_write_reg(gspca_dev, 0x0064, 0x0116);
2877 cit_read_reg(gspca_dev, 0x0115, 0);
2878 cit_write_reg(gspca_dev, 0x0003, 0x0115);
2879 cit_write_reg(gspca_dev, 0x0008, 0x0123);
2880 cit_write_reg(gspca_dev, 0x0000, 0x0117);
2881 cit_write_reg(gspca_dev, 0x0000, 0x0112);
2882 cit_write_reg(gspca_dev, 0x0080, 0x0100);
2883 break;
2884 case CIT_IBM_NETCAM_PRO:
2885 cit_model3_Packet1(gspca_dev, 0x0049, 0x00ff);
2886 cit_write_reg(gspca_dev, 0x0006, 0x012c);
2887 cit_write_reg(gspca_dev, 0x0000, 0x0116);
2888 /* HDG windows does this, but I cannot get the camera
2889 to restart with this without redoing the entire init
2890 sequence which makes switching modes really slow */
2891 /* cit_write_reg(gspca_dev, 0x0006, 0x0115); */
2892 cit_write_reg(gspca_dev, 0x0008, 0x0123);
2893 cit_write_reg(gspca_dev, 0x0000, 0x0117);
2894 cit_write_reg(gspca_dev, 0x0003, 0x0133);
2895 cit_write_reg(gspca_dev, 0x0000, 0x0111);
2896 /* HDG windows does this, but I get a green picture when
2897 restarting the stream after this */
2898 /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
2899 cit_write_reg(gspca_dev, 0x00c0, 0x0100);
2900 break;
2901 }
2902
2903#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
2904 /* If the last button state is pressed, release it now! */
2905 if (sd->button_state) {
2906 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
2907 input_sync(gspca_dev->input_dev);
2908 sd->button_state = 0;
2909 }
2910#endif
2911}
2912
2913static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
2914{
2915 struct sd *sd = (struct sd *) gspca_dev;
2916 u8 byte3 = 0, byte4 = 0;
2917 int i;
2918
2919 switch (sd->model) {
2920 case CIT_MODEL0:
2921 case CIT_MODEL1:
2922 case CIT_MODEL3:
2923 case CIT_IBM_NETCAM_PRO:
2924 switch (gspca_dev->width) {
2925 case 160: /* 160x120 */
2926 byte3 = 0x02;
2927 byte4 = 0x0a;
2928 break;
2929 case 176: /* 176x144 */
2930 byte3 = 0x02;
2931 byte4 = 0x0e;
2932 break;
2933 case 320: /* 320x240 */
2934 byte3 = 0x02;
2935 byte4 = 0x08;
2936 break;
2937 case 352: /* 352x288 */
2938 byte3 = 0x02;
2939 byte4 = 0x00;
2940 break;
2941 case 640:
2942 byte3 = 0x03;
2943 byte4 = 0x08;
2944 break;
2945 }
2946
2947 /* These have a different byte3 */
2948 if (sd->model <= CIT_MODEL1)
2949 byte3 = 0x00;
2950
2951 for (i = 0; i < len; i++) {
2952 /* For this model the SOF always starts at offset 0
2953 so no need to search the entire frame */
2954 if (sd->model == CIT_MODEL0 && sd->sof_read != i)
2955 break;
2956
2957 switch (sd->sof_read) {
2958 case 0:
2959 if (data[i] == 0x00)
2960 sd->sof_read++;
2961 break;
2962 case 1:
2963 if (data[i] == 0xff)
2964 sd->sof_read++;
2965 else if (data[i] == 0x00)
2966 sd->sof_read = 1;
2967 else
2968 sd->sof_read = 0;
2969 break;
2970 case 2:
2971 if (data[i] == byte3)
2972 sd->sof_read++;
2973 else if (data[i] == 0x00)
2974 sd->sof_read = 1;
2975 else
2976 sd->sof_read = 0;
2977 break;
2978 case 3:
2979 if (data[i] == byte4) {
2980 sd->sof_read = 0;
2981 return data + i + (sd->sof_len - 3);
2982 }
2983 if (byte3 == 0x00 && data[i] == 0xff)
2984 sd->sof_read = 2;
2985 else if (data[i] == 0x00)
2986 sd->sof_read = 1;
2987 else
2988 sd->sof_read = 0;
2989 break;
2990 }
2991 }
2992 break;
2993 case CIT_MODEL2:
2994 case CIT_MODEL4:
2995 /* TESTME we need to find a longer sof signature to avoid
2996 false positives */
2997 for (i = 0; i < len; i++) {
2998 switch (sd->sof_read) {
2999 case 0:
3000 if (data[i] == 0x00)
3001 sd->sof_read++;
3002 break;
3003 case 1:
3004 sd->sof_read = 0;
3005 if (data[i] == 0xff) {
3006 if (i >= 4)
3007 PDEBUG(D_FRAM,
3008 "header found at offset: %d: %02x %02x 00 %02x %02x %02x\n",
3009 i - 1,
3010 data[i - 4],
3011 data[i - 3],
3012 data[i],
3013 data[i + 1],
3014 data[i + 2]);
3015 else
3016 PDEBUG(D_FRAM,
3017 "header found at offset: %d: 00 %02x %02x %02x\n",
3018 i - 1,
3019 data[i],
3020 data[i + 1],
3021 data[i + 2]);
3022 return data + i + (sd->sof_len - 1);
3023 }
3024 break;
3025 }
3026 }
3027 break;
3028 }
3029 return NULL;
3030}
3031
3032static void sd_pkt_scan(struct gspca_dev *gspca_dev,
3033 u8 *data, int len)
3034{
3035 struct sd *sd = (struct sd *) gspca_dev;
3036 unsigned char *sof;
3037
3038 sof = cit_find_sof(gspca_dev, data, len);
3039 if (sof) {
3040 int n;
3041
3042 /* finish decoding current frame */
3043 n = sof - data;
3044 if (n > sd->sof_len)
3045 n -= sd->sof_len;
3046 else
3047 n = 0;
3048 gspca_frame_add(gspca_dev, LAST_PACKET,
3049 data, n);
3050 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
3051 len -= sof - data;
3052 data = sof;
3053 }
3054
3055 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
3056}
3057
3058static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
3059{
3060 struct sd *sd = (struct sd *) gspca_dev;
3061
3062 sd->brightness = val;
3063 if (gspca_dev->streaming) {
3064 if (sd->stop_on_control_change)
3065 sd_stopN(gspca_dev);
3066 cit_set_brightness(gspca_dev);
3067 if (sd->stop_on_control_change)
3068 cit_restart_stream(gspca_dev);
3069 }
3070
3071 return 0;
3072}
3073
3074static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
3075{
3076 struct sd *sd = (struct sd *) gspca_dev;
3077
3078 *val = sd->brightness;
3079
3080 return 0;
3081}
3082
3083static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
3084{
3085 struct sd *sd = (struct sd *) gspca_dev;
3086
3087 sd->contrast = val;
3088 if (gspca_dev->streaming) {
3089 if (sd->stop_on_control_change)
3090 sd_stopN(gspca_dev);
3091 cit_set_contrast(gspca_dev);
3092 if (sd->stop_on_control_change)
3093 cit_restart_stream(gspca_dev);
3094 }
3095
3096 return 0;
3097}
3098
3099static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
3100{
3101 struct sd *sd = (struct sd *) gspca_dev;
3102
3103 *val = sd->contrast;
3104
3105 return 0;
3106}
3107
3108static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
3109{
3110 struct sd *sd = (struct sd *) gspca_dev;
3111
3112 sd->hue = val;
3113 if (gspca_dev->streaming) {
3114 if (sd->stop_on_control_change)
3115 sd_stopN(gspca_dev);
3116 cit_set_hue(gspca_dev);
3117 if (sd->stop_on_control_change)
3118 cit_restart_stream(gspca_dev);
3119 }
3120 return 0;
3121}
3122
3123static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
3124{
3125 struct sd *sd = (struct sd *) gspca_dev;
3126
3127 *val = sd->hue;
3128
3129 return 0;
3130}
3131
3132static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
3133{
3134 struct sd *sd = (struct sd *) gspca_dev;
3135
3136 sd->sharpness = val;
3137 if (gspca_dev->streaming) {
3138 if (sd->stop_on_control_change)
3139 sd_stopN(gspca_dev);
3140 cit_set_sharpness(gspca_dev);
3141 if (sd->stop_on_control_change)
3142 cit_restart_stream(gspca_dev);
3143 }
3144 return 0;
3145}
3146
3147static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
3148{
3149 struct sd *sd = (struct sd *) gspca_dev;
3150
3151 *val = sd->sharpness;
3152
3153 return 0;
3154}
3155
3156static int sd_setlighting(struct gspca_dev *gspca_dev, __s32 val)
3157{
3158 struct sd *sd = (struct sd *) gspca_dev;
3159
3160 sd->lighting = val;
3161 if (gspca_dev->streaming) {
3162 if (sd->stop_on_control_change)
3163 sd_stopN(gspca_dev);
3164 cit_set_lighting(gspca_dev);
3165 if (sd->stop_on_control_change)
3166 cit_restart_stream(gspca_dev);
3167 }
3168 return 0;
3169}
3170
3171static int sd_getlighting(struct gspca_dev *gspca_dev, __s32 *val)
3172{
3173 struct sd *sd = (struct sd *) gspca_dev;
3174
3175 *val = sd->lighting;
3176
3177 return 0;
3178}
3179
3180static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
3181{
3182 struct sd *sd = (struct sd *) gspca_dev;
3183
3184 sd->hflip = val;
3185 if (gspca_dev->streaming) {
3186 if (sd->stop_on_control_change)
3187 sd_stopN(gspca_dev);
3188 cit_set_hflip(gspca_dev);
3189 if (sd->stop_on_control_change)
3190 cit_restart_stream(gspca_dev);
3191 }
3192 return 0;
3193}
3194
3195static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
3196{
3197 struct sd *sd = (struct sd *) gspca_dev;
3198
3199 *val = sd->hflip;
3200
3201 return 0;
3202}
3203
3204#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3205static void cit_check_button(struct gspca_dev *gspca_dev)
3206{
3207 int new_button_state;
3208 struct sd *sd = (struct sd *)gspca_dev;
3209
3210 switch (sd->model) {
3211 case CIT_MODEL3:
3212 case CIT_IBM_NETCAM_PRO:
3213 break;
3214 default: /* TEST ME unknown if this works on other models too */
3215 return;
3216 }
3217
3218 /* Read the button state */
3219 cit_read_reg(gspca_dev, 0x0113, 0);
3220 new_button_state = !gspca_dev->usb_buf[0];
3221
3222 /* Tell the cam we've seen the button press, notice that this
3223 is a nop (iow the cam keeps reporting pressed) until the
3224 button is actually released. */
3225 if (new_button_state)
3226 cit_write_reg(gspca_dev, 0x01, 0x0113);
3227
3228 if (sd->button_state != new_button_state) {
3229 input_report_key(gspca_dev->input_dev, KEY_CAMERA,
3230 new_button_state);
3231 input_sync(gspca_dev->input_dev);
3232 sd->button_state = new_button_state;
3233 }
3234}
3235#endif
3236
3237/* sub-driver description */
3238static const struct sd_desc sd_desc = {
3239 .name = MODULE_NAME,
3240 .ctrls = sd_ctrls,
3241 .nctrls = ARRAY_SIZE(sd_ctrls),
3242 .config = sd_config,
3243 .init = sd_init,
3244 .start = sd_start,
3245 .stopN = sd_stopN,
3246 .stop0 = sd_stop0,
3247 .pkt_scan = sd_pkt_scan,
3248#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3249 .dq_callback = cit_check_button,
3250 .other_input = 1,
3251#endif
3252};
3253
3254static const struct sd_desc sd_desc_isoc_nego = {
3255 .name = MODULE_NAME,
3256 .ctrls = sd_ctrls,
3257 .nctrls = ARRAY_SIZE(sd_ctrls),
3258 .config = sd_config,
3259 .init = sd_init,
3260 .start = sd_start,
3261 .isoc_init = sd_isoc_init,
3262 .isoc_nego = sd_isoc_nego,
3263 .stopN = sd_stopN,
3264 .stop0 = sd_stop0,
3265 .pkt_scan = sd_pkt_scan,
3266#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3267 .dq_callback = cit_check_button,
3268 .other_input = 1,
3269#endif
3270};
3271
3272/* -- module initialisation -- */
3273static const struct usb_device_id device_table[] = {
3274 { USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 },
3275 { USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 },
3276 { USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
3277 { USB_DEVICE_VER(0x0545, 0x8080, 0x0301, 0x0301), .driver_info = CIT_MODEL3 },
3278 { USB_DEVICE_VER(0x0545, 0x8002, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
3279 { USB_DEVICE_VER(0x0545, 0x800c, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
3280 { USB_DEVICE_VER(0x0545, 0x800d, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
3281 {}
3282};
3283MODULE_DEVICE_TABLE(usb, device_table);
3284
3285/* -- device connect -- */
3286static int sd_probe(struct usb_interface *intf,
3287 const struct usb_device_id *id)
3288{
3289 const struct sd_desc *desc = &sd_desc;
3290
3291 switch (id->driver_info) {
3292 case CIT_MODEL0:
3293 case CIT_MODEL1:
3294 if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
3295 return -ENODEV;
3296 break;
3297 case CIT_MODEL2:
3298 case CIT_MODEL4:
3299 if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
3300 return -ENODEV;
3301 break;
3302 case CIT_MODEL3:
3303 if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
3304 return -ENODEV;
3305 /* FIXME this likely applies to all model3 cams and probably
3306 to other models too. */
3307 if (ibm_netcam_pro)
3308 desc = &sd_desc_isoc_nego;
3309 break;
3310 }
3311
3312 return gspca_dev_probe2(intf, id, desc, sizeof(struct sd), THIS_MODULE);
3313}
3314
3315static struct usb_driver sd_driver = {
3316 .name = MODULE_NAME,
3317 .id_table = device_table,
3318 .probe = sd_probe,
3319 .disconnect = gspca_disconnect,
3320#ifdef CONFIG_PM
3321 .suspend = gspca_suspend,
3322 .resume = gspca_resume,
3323#endif
3324};
3325
3326/* -- module insert / remove -- */
3327static int __init sd_mod_init(void)
3328{
3329 return usb_register(&sd_driver);
3330}
3331static void __exit sd_mod_exit(void)
3332{
3333 usb_deregister(&sd_driver);
3334}
3335
3336module_init(sd_mod_init);
3337module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/zc3xx-reg.h b/drivers/media/video/gspca/zc3xx-reg.h
new file mode 100644
index 00000000000..a1bd94e8ce5
--- /dev/null
+++ b/drivers/media/video/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/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
new file mode 100644
index 00000000000..61cdd56a74a
--- /dev/null
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -0,0 +1,7065 @@
1/*
2 * Z-Star/Vimicro zc301/zc302p/vc30x library
3 *
4 * Copyright (C) 2009-2011 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 MODULE_NAME "zc3xx"
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 QUANT_VAL 1 /* quantization table */
36#include "zc3xx-reg.h"
37
38/* controls */
39enum e_ctrl {
40 BRIGHTNESS,
41 CONTRAST,
42 EXPOSURE,
43 GAMMA,
44 AUTOGAIN,
45 LIGHTFREQ,
46 SHARPNESS,
47 NCTRLS /* number of controls */
48};
49
50#define AUTOGAIN_DEF 1
51
52/* specific webcam descriptor */
53struct sd {
54 struct gspca_dev gspca_dev; /* !! must be the first item */
55
56 struct gspca_ctrl ctrls[NCTRLS];
57
58 u8 quality; /* image quality */
59#define QUALITY_MIN 50
60#define QUALITY_MAX 80
61#define QUALITY_DEF 70
62
63 u8 bridge;
64 u8 sensor; /* Type of image sensor chip */
65 u16 chip_revision;
66
67 u8 jpeg_hdr[JPEG_HDR_SZ];
68};
69enum bridges {
70 BRIDGE_ZC301,
71 BRIDGE_ZC303,
72};
73enum sensors {
74 SENSOR_ADCM2700,
75 SENSOR_CS2102,
76 SENSOR_CS2102K,
77 SENSOR_GC0303,
78 SENSOR_GC0305,
79 SENSOR_HDCS2020,
80 SENSOR_HV7131B,
81 SENSOR_HV7131R,
82 SENSOR_ICM105A,
83 SENSOR_MC501CB,
84 SENSOR_MT9V111_1, /* (mi360soc) zc301 */
85 SENSOR_MT9V111_3, /* (mi360soc) zc303 */
86 SENSOR_OV7620, /* OV7648 - same values */
87 SENSOR_OV7630C,
88 SENSOR_PAS106,
89 SENSOR_PAS202B,
90 SENSOR_PB0330,
91 SENSOR_PO2030,
92 SENSOR_TAS5130C,
93 SENSOR_MAX
94};
95
96/* V4L2 controls supported by the driver */
97static void setcontrast(struct gspca_dev *gspca_dev);
98static void setexposure(struct gspca_dev *gspca_dev);
99static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
100static void setlightfreq(struct gspca_dev *gspca_dev);
101static void setsharpness(struct gspca_dev *gspca_dev);
102
103static const struct ctrl sd_ctrls[NCTRLS] = {
104[BRIGHTNESS] = {
105 {
106 .id = V4L2_CID_BRIGHTNESS,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Brightness",
109 .minimum = 0,
110 .maximum = 255,
111 .step = 1,
112 .default_value = 128,
113 },
114 .set_control = setcontrast
115 },
116[CONTRAST] = {
117 {
118 .id = V4L2_CID_CONTRAST,
119 .type = V4L2_CTRL_TYPE_INTEGER,
120 .name = "Contrast",
121 .minimum = 0,
122 .maximum = 255,
123 .step = 1,
124 .default_value = 128,
125 },
126 .set_control = setcontrast
127 },
128[EXPOSURE] = {
129 {
130 .id = V4L2_CID_EXPOSURE,
131 .type = V4L2_CTRL_TYPE_INTEGER,
132 .name = "Exposure",
133 .minimum = 0x30d,
134 .maximum = 0x493e,
135 .step = 1,
136 .default_value = 0x927
137 },
138 .set_control = setexposure
139 },
140[GAMMA] = {
141 {
142 .id = V4L2_CID_GAMMA,
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Gamma",
145 .minimum = 1,
146 .maximum = 6,
147 .step = 1,
148 .default_value = 4,
149 },
150 .set_control = setcontrast
151 },
152[AUTOGAIN] = {
153 {
154 .id = V4L2_CID_AUTOGAIN,
155 .type = V4L2_CTRL_TYPE_BOOLEAN,
156 .name = "Auto Gain",
157 .minimum = 0,
158 .maximum = 1,
159 .step = 1,
160 .default_value = AUTOGAIN_DEF,
161 .flags = V4L2_CTRL_FLAG_UPDATE
162 },
163 .set = sd_setautogain
164 },
165[LIGHTFREQ] = {
166 {
167 .id = V4L2_CID_POWER_LINE_FREQUENCY,
168 .type = V4L2_CTRL_TYPE_MENU,
169 .name = "Light frequency filter",
170 .minimum = 0,
171 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
172 .step = 1,
173 .default_value = 0,
174 },
175 .set_control = setlightfreq
176 },
177[SHARPNESS] = {
178 {
179 .id = V4L2_CID_SHARPNESS,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "Sharpness",
182 .minimum = 0,
183 .maximum = 3,
184 .step = 1,
185 .default_value = 2,
186 },
187 .set_control = setsharpness
188 },
189};
190
191static const struct v4l2_pix_format vga_mode[] = {
192 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
193 .bytesperline = 320,
194 .sizeimage = 320 * 240 * 3 / 8 + 590,
195 .colorspace = V4L2_COLORSPACE_JPEG,
196 .priv = 1},
197 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
198 .bytesperline = 640,
199 .sizeimage = 640 * 480 * 3 / 8 + 590,
200 .colorspace = V4L2_COLORSPACE_JPEG,
201 .priv = 0},
202};
203
204static const struct v4l2_pix_format broken_vga_mode[] = {
205 {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
206 .bytesperline = 320,
207 .sizeimage = 320 * 232 * 4 / 8 + 590,
208 .colorspace = V4L2_COLORSPACE_JPEG,
209 .priv = 1},
210 {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
211 .bytesperline = 640,
212 .sizeimage = 640 * 472 * 3 / 8 + 590,
213 .colorspace = V4L2_COLORSPACE_JPEG,
214 .priv = 0},
215};
216
217static const struct v4l2_pix_format sif_mode[] = {
218 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
219 .bytesperline = 176,
220 .sizeimage = 176 * 144 * 3 / 8 + 590,
221 .colorspace = V4L2_COLORSPACE_JPEG,
222 .priv = 1},
223 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
224 .bytesperline = 352,
225 .sizeimage = 352 * 288 * 3 / 8 + 590,
226 .colorspace = V4L2_COLORSPACE_JPEG,
227 .priv = 0},
228};
229
230/* usb exchanges */
231struct usb_action {
232 u8 req;
233 u8 val;
234 u16 idx;
235};
236
237static const struct usb_action adcm2700_Initial[] = {
238 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
239 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
240 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
241 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
242 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
243 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
244 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
245 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
246 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
247 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
248 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
249 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
250 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
251 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
252 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
253 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
254 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
255 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
256 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
257 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
258 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
259 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
260 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
261 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
262 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
263 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
264 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
265 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
266 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
267 {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */
268 {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */
269 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
270 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
271 {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */
272 {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */
273 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
274 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
275 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
276 {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */
277 {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */
278 {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */
279 {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */
280 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
281 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
282 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
283 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
284 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
285 {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */
286 {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */
287 {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */
288 {0xbb, 0x86, 0x0002}, /* 00,86,02,bb */
289 {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */
290 {0xbb, 0x86, 0x0802}, /* 08,86,02,bb */
291 {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */
292 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
293 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
294 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
295 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
296 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
297 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
298 {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */
299/*mswin+*/
300 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
301 {0xaa, 0xfe, 0x0002},
302 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
303 {0xaa, 0xb4, 0xcd37},
304 {0xaa, 0xa4, 0x0004},
305 {0xaa, 0xa8, 0x0007},
306 {0xaa, 0xac, 0x0004},
307/*mswin-*/
308 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
309 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
310 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
311 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
312 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
313 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
314 {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */
315 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
316 {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */
317 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
318 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
319 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
320 {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */
321 {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */
322 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
323 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
324 {}
325};
326static const struct usb_action adcm2700_InitialScale[] = {
327 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
328 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
329 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
330 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
331 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
332 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
333 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
334 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
335 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
336 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
337 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
338 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
339 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
340 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
341 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
342 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
343 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
344 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
345 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
346 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
347 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
348 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
349 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
350 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
351 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
352 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
353 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
354 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
355 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
356 {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */
357 {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */
358 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
359 {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */
360 {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */
361 {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */
362 {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */
363 {0xdd, 0x00, 0x0050}, /* 00,00,50,dd */
364 {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */
365 {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */
366 {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */
367 {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */
368 {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */
369 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
370 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
371 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
372 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
373 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
374 {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */
375 {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */
376 {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */
377 {0xbb, 0x86, 0x0002}, /* 00,88,02,bb */
378 {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */
379 {0xbb, 0x86, 0x0802}, /* 08,88,02,bb */
380 {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */
381 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
382 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
383 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
384 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
385 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
386 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
387 {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */
388 /*******/
389 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
390 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
391 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
392 {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */
393 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
394 {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */
395 {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */
396 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
397 {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */
398 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
399 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
400 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
401 {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */
402 {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */
403 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
404 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
405 {}
406};
407static const struct usb_action adcm2700_50HZ[] = {
408 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
409 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
410 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
411 {0xbb, 0x05, 0x8400}, /* 84,05,00,bb */
412 {0xbb, 0xd0, 0xb007}, /* b0,d0,07,bb */
413 {0xbb, 0xa0, 0xb80f}, /* b8,a0,0f,bb */
414 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
415 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
416 {0xaa, 0x26, 0x00d0}, /* 00,26,d0,aa */
417 {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
418 {}
419};
420static const struct usb_action adcm2700_60HZ[] = {
421 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
422 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
423 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
424 {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */
425 {0xbb, 0x82, 0xb006}, /* b0,82,06,bb */
426 {0xbb, 0x04, 0xb80d}, /* b8,04,0d,bb */
427 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
428 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
429 {0xaa, 0x26, 0x0057}, /* 00,26,57,aa */
430 {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
431 {}
432};
433static const struct usb_action adcm2700_NoFliker[] = {
434 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
435 {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
436 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
437 {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */
438 {0xbb, 0x05, 0xb000}, /* b0,05,00,bb */
439 {0xbb, 0xa0, 0xb801}, /* b8,a0,01,bb */
440 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
441 {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */
442 {}
443};
444static const struct usb_action cs2102_InitialScale[] = { /* 320x240 */
445 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
446 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
447 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
448 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
449 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
450 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
451 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
452 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
453 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
454 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
455 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
456 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
457 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
458 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
459 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
460 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
461 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
462 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
463 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
464 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
465 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
466 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
467 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
468 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
469 {0xaa, 0x02, 0x0008},
470 {0xaa, 0x03, 0x0000},
471 {0xaa, 0x11, 0x0000},
472 {0xaa, 0x12, 0x0089},
473 {0xaa, 0x13, 0x0000},
474 {0xaa, 0x14, 0x00e9},
475 {0xaa, 0x20, 0x0000},
476 {0xaa, 0x22, 0x0000},
477 {0xaa, 0x0b, 0x0004},
478 {0xaa, 0x30, 0x0030},
479 {0xaa, 0x31, 0x0030},
480 {0xaa, 0x32, 0x0030},
481 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
482 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
483 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
484 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
485 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
486 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
487 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
488 {0xa0, 0x10, 0x01ae},
489 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
490 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
491 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
492 {0xa0, 0x00, 0x01ad},
493 {}
494};
495
496static const struct usb_action cs2102_Initial[] = { /* 640x480 */
497 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
498 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
499 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
500 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
501 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
502 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
503 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
504 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
505 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
506 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
507 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
508 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
509 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
510 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
511 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
512 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
513 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
514 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
515 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
516 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
517 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
518 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
519 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
520 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
521 {0xaa, 0x02, 0x0008},
522 {0xaa, 0x03, 0x0000},
523 {0xaa, 0x11, 0x0001},
524 {0xaa, 0x12, 0x0087},
525 {0xaa, 0x13, 0x0001},
526 {0xaa, 0x14, 0x00e7},
527 {0xaa, 0x20, 0x0000},
528 {0xaa, 0x22, 0x0000},
529 {0xaa, 0x0b, 0x0004},
530 {0xaa, 0x30, 0x0030},
531 {0xaa, 0x31, 0x0030},
532 {0xaa, 0x32, 0x0030},
533 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
534 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
535 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
536 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
537 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
538 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
539 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
540 {0xa0, 0x15, 0x01ae},
541 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
542 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
543 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
544 {0xa0, 0x00, 0x01ad},
545 {}
546};
547static const struct usb_action cs2102_50HZScale[] = {
548 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
549 {0xaa, 0x23, 0x0001},
550 {0xaa, 0x24, 0x005f},
551 {0xaa, 0x25, 0x0090},
552 {0xaa, 0x21, 0x00dd},
553 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
554 {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
555 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
556 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
557 {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID},
558 {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW},
559 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
560 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
561 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
562 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
563 {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0},
564 {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1},
565 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
566 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
567 {}
568};
569static const struct usb_action cs2102_50HZ[] = {
570 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
571 {0xaa, 0x23, 0x0000},
572 {0xaa, 0x24, 0x00af},
573 {0xaa, 0x25, 0x00c8},
574 {0xaa, 0x21, 0x0068},
575 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
576 {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
577 {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW},
578 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
579 {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID},
580 {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW},
581 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
582 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
583 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
584 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
585 {0xa0, 0x68, ZC3XX_R01D_HSYNC_0},
586 {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1},
587 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
588 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
589 {}
590};
591static const struct usb_action cs2102_60HZScale[] = {
592 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
593 {0xaa, 0x23, 0x0001},
594 {0xaa, 0x24, 0x0055},
595 {0xaa, 0x25, 0x00cc},
596 {0xaa, 0x21, 0x003f},
597 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
598 {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID},
599 {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW},
600 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
601 {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID},
602 {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW},
603 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
604 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
605 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
606 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
607 {0xa0, 0x39, ZC3XX_R01D_HSYNC_0},
608 {0xa0, 0x70, ZC3XX_R01E_HSYNC_1},
609 {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2},
610 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
611 {}
612};
613static const struct usb_action cs2102_60HZ[] = {
614 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
615 {0xaa, 0x23, 0x0000},
616 {0xaa, 0x24, 0x00aa},
617 {0xaa, 0x25, 0x00e6},
618 {0xaa, 0x21, 0x003f},
619 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
620 {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID},
621 {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW},
622 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
623 {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID},
624 {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW},
625 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
626 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
627 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
628 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
629 {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0},
630 {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1},
631 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
632 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
633 {}
634};
635static const struct usb_action cs2102_NoFlikerScale[] = {
636 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
637 {0xaa, 0x23, 0x0001},
638 {0xaa, 0x24, 0x005f},
639 {0xaa, 0x25, 0x0000},
640 {0xaa, 0x21, 0x0001},
641 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
642 {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
643 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
644 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
645 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
646 {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
647 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
648 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
649 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
650 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
651 {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
652 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
653 {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
654 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
655 {}
656};
657static const struct usb_action cs2102_NoFliker[] = {
658 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
659 {0xaa, 0x23, 0x0000},
660 {0xaa, 0x24, 0x00af},
661 {0xaa, 0x25, 0x0080},
662 {0xaa, 0x21, 0x0001},
663 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
664 {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
665 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
666 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
667 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
668 {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
669 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
670 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
671 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
672 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
673 {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
674 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
675 {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
676 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
677 {}
678};
679
680/* CS2102_KOCOM */
681static const struct usb_action cs2102K_InitialScale[] = {
682 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
683 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
684 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
685 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
686 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
687 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
688 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
689 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
690 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
691 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
692 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
693 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
694 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
695 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
696 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
697 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
698 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
699 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
700 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
701 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
702 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
703 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
704 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
705 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
706 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
707 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
708 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
709 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
710 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
711 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
712 {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE},
713 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
714 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
715 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
716 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
717 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
718 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
719 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
720 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
721 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
722 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
723 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
724 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
725 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
726 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
727 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
728 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
729 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
730 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
731 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
732 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
733 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
734 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
735 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
736 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
737 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
738 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
739 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
740 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
741 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
742 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
743 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
744 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
745 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
746 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
747 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
748 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
749 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
750 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
751 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
752 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
753 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
754 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
755 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
756 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
757 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
758 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
759 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
760 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
761 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
762 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
763 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
764 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
765 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
766 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
767 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
768 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
769 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
770 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
771 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
772 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
773 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
774 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
775 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
776 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
777 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
778 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
779 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
780 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
781 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
782 {0xa0, 0x00, 0x01ad},
783 {0xa0, 0x01, 0x01b1},
784 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
785 {0xa0, 0x60, ZC3XX_R116_RGAIN},
786 {0xa0, 0x40, ZC3XX_R117_GGAIN},
787 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
788 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
789 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
790 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
791 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
792 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
793 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
794 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
795 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
796 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
797 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
798 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
799 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
800 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
801 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
802 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
803 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
804 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
805 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
806 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
807 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
808 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
809 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
810 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
811 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
812 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
813 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
814 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
815 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
816 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
817 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
818 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
819 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
820 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
821 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
822 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
823 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
824 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
825 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
826 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
827 {0xa0, 0x58, ZC3XX_R10E_RGB11},
828 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
829 {0xa0, 0xf4, ZC3XX_R110_RGB20},
830 {0xa0, 0xf4, ZC3XX_R111_RGB21},
831 {0xa0, 0x58, ZC3XX_R112_RGB22},
832 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
833 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
834 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
835 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
836 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
837 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
838 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
839 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
840 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
841 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
842 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
843 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
844 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
845 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
846 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
847 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
848 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
849 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
850 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
851 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
852 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
853 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
854 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
855 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
856 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
857 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
858 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
859 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
860 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
861 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
862 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
863 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
864 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
865 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
866 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
867 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
868 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
869 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
870 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
871 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
872 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
873 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
874 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
875 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
876 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
877 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
878 {0xa0, 0x60, ZC3XX_R116_RGAIN},
879 {0xa0, 0x40, ZC3XX_R117_GGAIN},
880 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
881 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
882 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
883 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
884 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
885 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
886 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
887 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
888 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
889 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
890 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
891 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
892 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
893 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
894 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
895 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
896 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
897 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
898 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
899 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
900 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
901 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
902 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
903 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
904 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
905 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
906 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
907 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
908 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
909 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
910 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
911 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
912 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
913 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
914 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
915 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
916 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
917 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
918 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
919 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
920 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
921 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
922 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
923 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
924 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
925 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
926 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
927 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
928 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
929 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
930 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
931 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
932 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
933 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
934 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
935 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
936 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
937 {}
938};
939
940static const struct usb_action cs2102K_Initial[] = {
941 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
942 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
943 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
944 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
945 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
946 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
947 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
948 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
949 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
950 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
951 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
952 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
953 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
954 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
955 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
956 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
957 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
958/*fixme: next sequence = i2c exchanges*/
959 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
960 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
961 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
962 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
963 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
964 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
965 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
966 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
967 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
968 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
969 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
970 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
971 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
972 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
973 {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
974 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
975 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
976 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
977 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
978 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
979 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
980 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
981 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
982 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
983 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
984 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
985 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
986 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
987 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
988 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
989 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
990 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
991 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
992 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
993 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
994 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
995 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
996 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
997 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
998 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
999 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1000 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
1001 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1002 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1003 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1004 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
1005 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1006 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1007 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1008 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
1009 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1010 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1011 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1012 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
1013 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1014 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1015 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1016 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
1017 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1018 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1019 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1020 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
1021 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
1022 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1023 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1024 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
1025 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
1026 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1027 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1028 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1029 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1030 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1031 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1032 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
1033 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1034 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
1035 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1036 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1037 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1038 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1039 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1040 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1041 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1042 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1043 {0xa0, 0x00, 0x01ad},
1044 {0xa0, 0x01, 0x01b1},
1045 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1046 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1047 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1048 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1049 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1050 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1051 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1052 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1053 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1054 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1055 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1056 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1057 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1058 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1059 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1060 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1061 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1062 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1063 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1064 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1065 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1066 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1067 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1068 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1069 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1070 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1071 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1072 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1073 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1074 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1075 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1076 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1077 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1078 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1079 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1080 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1081 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1082 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1083 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1084 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
1085 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
1086 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
1087 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
1088 {0xa0, 0x58, ZC3XX_R10E_RGB11},
1089 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
1090 {0xa0, 0xf4, ZC3XX_R110_RGB20},
1091 {0xa0, 0xf4, ZC3XX_R111_RGB21},
1092 {0xa0, 0x58, ZC3XX_R112_RGB22},
1093 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1094 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1095 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1096 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1097 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1098 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1099 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1100 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1101 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1102 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1103 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1104 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1105 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1106 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1107 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1108 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1109 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1110 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1111 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1112 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1113 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1114 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1115 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1116 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1117 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1118 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1119 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
1120 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
1121 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1122 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
1123 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
1124 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1125 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1126 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
1127 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1128 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1129 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1130 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1131 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1132 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
1133 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
1134 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
1135 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1136 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1137 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1138 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1139 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1140 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1141 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1142 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1143 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1144 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1145 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1146 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1147 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1148 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1149 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1150 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1151 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1152 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1153 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1154 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1155 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1156 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1157 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1158 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1159 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1160 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1161 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1162 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1163 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1164 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1165 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1166 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1167 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1168 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1169 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1170 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1171 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1172 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1173 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1174 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1175 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1176 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1177 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1178 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1179 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1180 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1181 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1182 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1183 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1184 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1185 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1186 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1187 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1188 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1189 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1190 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1191 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1192 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1193 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1194 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1195 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1196 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1197 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1198/*fixme:what does the next sequence?*/
1199 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1200 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1201 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1202 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1203 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1204 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1205 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1206 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1207 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1208 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1209 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1210 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1211 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1212 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1213 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1214 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1215 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1216 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1217 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1218 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1219 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1220 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1221 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1222 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1223 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1224 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1225 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1226 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1227 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
1228 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1229 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1230 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1231 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1232 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1233 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1234 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1235 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1236 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1237 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1238 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1239 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1240 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1241 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1242 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1243 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1244 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1245 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1246 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1247 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1248 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1249 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1250 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1251 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1252 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1253 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1254 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1255 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1256 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1257 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1258 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1259 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1260 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1261 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1262 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1263 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1264 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1265 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1266 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1267 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1268 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1269 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1270 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1271 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1272 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1273 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1274 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1275 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1276 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1277 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1278 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1279 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1280 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1281 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1282 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1283 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1284 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1285 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1286 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1287 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1288 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1289 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1290 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1291 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1292 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1293 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1294 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1295 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1296 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1297 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1298 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1299 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1300 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1301 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1302 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1303 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1304 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1305 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1306 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1307 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1308 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1309 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1310 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1311 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1312 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1313 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1314 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1315 {}
1316};
1317
1318static const struct usb_action gc0305_Initial[] = { /* 640x480 */
1319 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1320 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1321 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1322 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
1323 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1324 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1325 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1326 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1327 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1328 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1329 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1330 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1331 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1332 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1333 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1334 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
1335 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
1336 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1337 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa */
1338 {0xaa, 0x15, 0x0003}, /* 00,15,03,aa */
1339 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1340 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1341 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1342 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1343 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1344 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1345 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1346 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1347 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1348 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1349 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1350 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1351 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1352 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1353 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1354 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1355 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1356 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1357 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1358 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1359 {0xaa, 0x17, 0x00e6}, /* 00,17,e6,aa */
1360 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1361 {0xaa, 0x19, 0x0086}, /* 00,19,86,aa */
1362 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1363 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1364 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1365 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1366 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1367 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1368 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1369 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1370 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1371 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1372 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1373 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1374 {0xa0, 0x85, ZC3XX_R18D_YTARGET}, /* 01,8d,85,cc */
1375 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1376 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1377 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1378 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1379 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1380 {}
1381};
1382static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */
1383 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1384 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1385 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1386 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
1387 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1388 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1389 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1390 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1391 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1392 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1393 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1394 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1395 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1396 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1397 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1398 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
1399 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
1400 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1401 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
1402 {0xaa, 0x15, 0x0001}, /* 00,15,01,aa */
1403 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1404 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1405 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1406 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1407 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1408 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1409 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1410 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1411 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1412 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1413 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1414 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1415 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1416 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1417 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1418 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1419 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1420 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1421 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1422 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1423 {0xaa, 0x17, 0x00e8}, /* 00,17,e8,aa */
1424 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1425 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa */
1426 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1427 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1428 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1429 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1430 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1431 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1432 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1433 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1434 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1435 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1436 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1437 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1438 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1439 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1440 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1441 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1442 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1443 {}
1444};
1445static const struct usb_action gc0305_50HZ[] = {
1446 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1447 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
1448 {0xaa, 0x84, 0x0038}, /* 00,84,38,aa */ /* win: 00,84,ec */
1449 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1450 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1451 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
1452 /* win: 01,92,10 */
1453 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1454 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1455 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc */
1456 /* win: 01,97,ec */
1457 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1458 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1459 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1460 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1461 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1462 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1463 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1464 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1465 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1466 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1467/* {0xa0, 0x85, ZC3XX_R18D_YTARGET}, * 01,8d,85,cc *
1468 * if 640x480 */
1469 {}
1470};
1471static const struct usb_action gc0305_60HZ[] = {
1472 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1473 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1474 {0xaa, 0x84, 0x00ec}, /* 00,84,ec,aa */
1475 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1476 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1477 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
1478 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1479 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1480 {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,ec,cc */
1481 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1482 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1483 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1484 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1485 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1486 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1487 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1488 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1489 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1490 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1491 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1492 {}
1493};
1494
1495static const struct usb_action gc0305_NoFliker[] = {
1496 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
1497 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1498 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1499 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
1500 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1501 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,00,cc */
1502 {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,48,cc */
1503 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1504 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1505 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
1506 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1507 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1508 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1509 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1510 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1511 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1512 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1513 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
1514 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1515 {}
1516};
1517
1518static const struct usb_action hdcs2020_InitialScale[] = {
1519 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1520 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
1521 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */
1522 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1523 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1524 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1525 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1526 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1527 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1528 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1529 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1530 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1531 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1532 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1533 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1534 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1535 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1536 {0xaa, 0x1c, 0x0000},
1537 {0xaa, 0x0a, 0x0001},
1538 {0xaa, 0x0b, 0x0006},
1539 {0xaa, 0x0c, 0x007b},
1540 {0xaa, 0x0d, 0x00a7},
1541 {0xaa, 0x03, 0x00fb},
1542 {0xaa, 0x05, 0x0000},
1543 {0xaa, 0x06, 0x0003},
1544 {0xaa, 0x09, 0x0008},
1545
1546 {0xaa, 0x0f, 0x0018}, /* set sensor gain */
1547 {0xaa, 0x10, 0x0018},
1548 {0xaa, 0x11, 0x0018},
1549 {0xaa, 0x12, 0x0018},
1550
1551 {0xaa, 0x15, 0x004e},
1552 {0xaa, 0x1c, 0x0004},
1553 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
1554 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1555 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1556 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1557 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1558 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1559 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1560 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1561 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1562 {0xa1, 0x01, 0x0002},
1563 {0xa1, 0x01, 0x0008},
1564 {0xa1, 0x01, 0x0180},
1565 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1566 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1567 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1568 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1569 {0xa1, 0x01, 0x0008},
1570 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1571 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1572 {0xa1, 0x01, 0x01c8},
1573 {0xa1, 0x01, 0x01c9},
1574 {0xa1, 0x01, 0x01ca},
1575 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1576 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1577 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1578 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1579 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1580 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1581 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1582 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1583 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1584 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1585 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1586 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1587 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1588 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1589 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1590 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1591 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1592 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1593 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1594 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1595 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1596 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1597 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1598 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1599 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1600 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1601 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1602 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1603 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1604 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1605 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1606 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1607 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1608
1609 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
1610 {0xa0, 0xed, ZC3XX_R10B_RGB01},
1611 {0xa0, 0xed, ZC3XX_R10C_RGB02},
1612 {0xa0, 0xed, ZC3XX_R10D_RGB10},
1613 {0xa0, 0x66, ZC3XX_R10E_RGB11},
1614 {0xa0, 0xed, ZC3XX_R10F_RGB12},
1615 {0xa0, 0xed, ZC3XX_R110_RGB20},
1616 {0xa0, 0xed, ZC3XX_R111_RGB21},
1617 {0xa0, 0x66, ZC3XX_R112_RGB22},
1618
1619 {0xa1, 0x01, 0x0180},
1620 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1621 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1622 {0xaa, 0x13, 0x0031},
1623 {0xaa, 0x14, 0x0001},
1624 {0xaa, 0x0e, 0x0004},
1625 {0xaa, 0x19, 0x00cd},
1626 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1627 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1628 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
1629 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1630 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1631 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
1632 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1633 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1634
1635 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 0x14 */
1636 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1637 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1638 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
1639 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
1640 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
1641 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1642 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1643 {0xa1, 0x01, 0x0180},
1644 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1645 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1646 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1647 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1648 {}
1649};
1650static const struct usb_action hdcs2020_Initial[] = {
1651 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1652 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1653 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1654 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1655 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1656 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1657 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1658 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1659 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1660 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1661 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1662 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1663 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1664 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1665 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1666 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1667 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1668 {0xaa, 0x1c, 0x0000},
1669 {0xaa, 0x0a, 0x0001},
1670 {0xaa, 0x0b, 0x0006},
1671 {0xaa, 0x0c, 0x007a},
1672 {0xaa, 0x0d, 0x00a7},
1673 {0xaa, 0x03, 0x00fb},
1674 {0xaa, 0x05, 0x0000},
1675 {0xaa, 0x06, 0x0003},
1676 {0xaa, 0x09, 0x0008},
1677 {0xaa, 0x0f, 0x0018}, /* original setting */
1678 {0xaa, 0x10, 0x0018},
1679 {0xaa, 0x11, 0x0018},
1680 {0xaa, 0x12, 0x0018},
1681 {0xaa, 0x15, 0x004e},
1682 {0xaa, 0x1c, 0x0004},
1683 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
1684 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1685 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1686 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1687 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1688 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1689 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1690 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1691 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1692 {0xa1, 0x01, 0x0002},
1693 {0xa1, 0x01, 0x0008},
1694 {0xa1, 0x01, 0x0180},
1695 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1696 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1697 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1698 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1699 {0xa1, 0x01, 0x0008},
1700 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1701 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1702 {0xa1, 0x01, 0x01c8},
1703 {0xa1, 0x01, 0x01c9},
1704 {0xa1, 0x01, 0x01ca},
1705 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1706 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1707 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1708 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1709 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1710 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1711 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1712 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1713 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1714 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1715 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1716 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1717 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1718 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1719 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1720 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1721 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1722 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1723 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1724 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1725 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1726 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1727 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1728 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1729 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1730 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1731 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1732 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1733 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1734 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1735 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1736 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1737 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1738 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
1739 {0xa0, 0xed, ZC3XX_R10B_RGB01},
1740 {0xa0, 0xed, ZC3XX_R10C_RGB02},
1741 {0xa0, 0xed, ZC3XX_R10D_RGB10},
1742 {0xa0, 0x66, ZC3XX_R10E_RGB11},
1743 {0xa0, 0xed, ZC3XX_R10F_RGB12},
1744 {0xa0, 0xed, ZC3XX_R110_RGB20},
1745 {0xa0, 0xed, ZC3XX_R111_RGB21},
1746 {0xa0, 0x66, ZC3XX_R112_RGB22},
1747 {0xa1, 0x01, 0x0180},
1748 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1749 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1750 /**** set exposure ***/
1751 {0xaa, 0x13, 0x0031},
1752 {0xaa, 0x14, 0x0001},
1753 {0xaa, 0x0e, 0x0004},
1754 {0xaa, 0x19, 0x00cd},
1755 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1756 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1757 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
1758 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1759 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1760 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
1761 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1762 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1763 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1764 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1765 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1766 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
1767 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
1768 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
1769 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1770 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1771 {0xa1, 0x01, 0x0180},
1772 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1773 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1774 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1775 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1776 {}
1777};
1778static const struct usb_action hdcs2020_50HZ[] = {
1779 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1780 {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */
1781 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
1782 {0xaa, 0x0e, 0x0005}, /* 00,0e,05,aa */
1783 {0xaa, 0x19, 0x001f}, /* 00,19,1f,aa */
1784 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1785 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
1786 {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
1787 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1788 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1789 {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
1790 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1791 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1792 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
1793 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
1794 {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */
1795 {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */
1796 {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
1797 {}
1798};
1799static const struct usb_action hdcs2020_60HZ[] = {
1800 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1801 {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */
1802 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
1803 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
1804 {0xaa, 0x19, 0x00cd}, /* 00,19,cd,aa */
1805 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1806 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
1807 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
1808 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1809 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1810 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
1811 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1812 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1813 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
1814 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
1815 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
1816 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */
1817 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
1818 {}
1819};
1820static const struct usb_action hdcs2020_NoFliker[] = {
1821 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1822 {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
1823 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
1824 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
1825 {0xaa, 0x19, 0x0000}, /* 00,19,00,aa */
1826 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1827 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
1828 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
1829 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1830 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1831 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
1832 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
1833 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
1834 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
1835 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
1836 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
1837 {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */
1838 {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */
1839 {}
1840};
1841
1842static const struct usb_action hv7131b_InitialScale[] = { /* 320x240 */
1843 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1844 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
1845 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
1846 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1847 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
1848 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
1849 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1850 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1851 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1852 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1853 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1854 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1855 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1856 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1857 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1858 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1859 {0xaa, 0x30, 0x002d},
1860 {0xaa, 0x01, 0x0005},
1861 {0xaa, 0x11, 0x0000},
1862 {0xaa, 0x13, 0x0001}, /* {0xaa, 0x13, 0x0000}, */
1863 {0xaa, 0x14, 0x0001},
1864 {0xaa, 0x15, 0x00e8},
1865 {0xaa, 0x16, 0x0002},
1866 {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */
1867 {0xaa, 0x31, 0x0038},
1868 {0xaa, 0x32, 0x0038},
1869 {0xaa, 0x33, 0x0038},
1870 {0xaa, 0x5b, 0x0001},
1871 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1872 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1873 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1874 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
1875 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
1876 {0xa0, 0x00, 0x01ad},
1877 {0xa0, 0xc0, 0x019b},
1878 {0xa0, 0xa0, 0x019c},
1879 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
1880 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1881 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1882 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1883 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1884 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1885 {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */
1886 {}
1887};
1888
1889static const struct usb_action hv7131b_Initial[] = { /* 640x480*/
1890 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1891 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1892 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
1893 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1894 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
1895 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
1896 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1897 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1898 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1899 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1900 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1901 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1902 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1903 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1904 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1905 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1906 {0xaa, 0x30, 0x002d},
1907 {0xaa, 0x01, 0x0005},
1908 {0xaa, 0x11, 0x0001},
1909 {0xaa, 0x13, 0x0000}, /* {0xaa, 0x13, 0x0001}; */
1910 {0xaa, 0x14, 0x0001},
1911 {0xaa, 0x15, 0x00e6},
1912 {0xaa, 0x16, 0x0002},
1913 {0xaa, 0x17, 0x0086},
1914 {0xaa, 0x31, 0x0038},
1915 {0xaa, 0x32, 0x0038},
1916 {0xaa, 0x33, 0x0038},
1917 {0xaa, 0x5b, 0x0001},
1918 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1919 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1920 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1921 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1922 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
1923 {0xa0, 0x00, 0x01ad},
1924 {0xa0, 0xc0, 0x019b},
1925 {0xa0, 0xa0, 0x019c},
1926 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
1927 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1928 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1929 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1930 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1931 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1932 {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}, */
1933 {}
1934};
1935static const struct usb_action hv7131b_50HZ[] = { /* 640x480*/
1936 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1937 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1938 {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */
1939 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
1940 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1941 {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */
1942 {0xaa, 0x22, 0x001b}, /* 00,22,1b,aa */
1943 {0xaa, 0x23, 0x00fc}, /* 00,23,fc,aa */
1944 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1945 {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */
1946 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
1947 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1948 {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,ea,cc */
1949 {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,60,cc */
1950 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
1951 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
1952 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
1953 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1954 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1955 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
1956 {0xa0, 0x1b, ZC3XX_R01F_HSYNC_2}, /* 00,1f,1b,cc */
1957 {0xa0, 0xfc, ZC3XX_R020_HSYNC_3}, /* 00,20,fc,cc */
1958 {}
1959};
1960static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */
1961 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1962 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1963 {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */
1964 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
1965 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1966 {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */
1967 {0xaa, 0x22, 0x0012}, /* 00,22,12,aa */
1968 {0xaa, 0x23, 0x0080}, /* 00,23,80,aa */
1969 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1970 {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */
1971 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
1972 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */
1973 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,d4,cc */
1974 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,c0,cc */
1975 {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */
1976 {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */
1977 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
1978 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1979 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
1980 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
1981 {0xa0, 0x12, ZC3XX_R01F_HSYNC_2}, /* 00,1f,12,cc */
1982 {0xa0, 0x80, ZC3XX_R020_HSYNC_3}, /* 00,20,80,cc */
1983 {}
1984};
1985static const struct usb_action hv7131b_60HZ[] = { /* 640x480*/
1986 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
1987 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
1988 {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */
1989 {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */
1990 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1991 {0xaa, 0x21, 0x0040}, /* 00,21,40,aa */
1992 {0xaa, 0x22, 0x0013}, /* 00,22,13,aa */
1993 {0xaa, 0x23, 0x004c}, /* 00,23,4c,aa */
1994 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
1995 {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */
1996 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */
1997 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1998 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,c3,cc */
1999 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,50,cc */
2000 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
2001 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
2002 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
2003 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
2004 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
2005 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
2006 {0xa0, 0x13, ZC3XX_R01F_HSYNC_2}, /* 00,1f,13,cc */
2007 {0xa0, 0x4c, ZC3XX_R020_HSYNC_3}, /* 00,20,4c,cc */
2008 {}
2009};
2010static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
2011 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2012 {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */
2013 {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */
2014 {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */
2015 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
2016 {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */
2017 {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */
2018 {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */
2019 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
2020 {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */
2021 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */
2022 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */
2023 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,86,cc */
2024 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,a0,cc */
2025 {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */
2026 {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */
2027 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */
2028 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
2029 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
2030 {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */
2031 {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */
2032 {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
2033 {}
2034};
2035static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
2036 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2037 {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
2038 {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
2039 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
2040 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
2041 {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */
2042 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
2043 {0xaa, 0x23, 0x0003}, /* 00,23,03,aa */
2044 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
2045 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */
2046 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */
2047 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2048 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */
2049 {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */
2050 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2051 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2052 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2053 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2054 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
2055 {0xa0, 0x10, ZC3XX_R01E_HSYNC_1}, /* 00,1e,10,cc */
2056 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, /* 00,1f,00,cc */
2057 {0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */
2058 {}
2059};
2060static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
2061 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2062 {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
2063 {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
2064 {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */
2065 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
2066 {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */
2067 {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */
2068 {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */
2069 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */
2070 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */
2071 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */
2072 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2073 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */
2074 {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */
2075 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2076 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2077 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2078 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2079 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */
2080 {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */
2081 {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */
2082 {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
2083 {}
2084};
2085
2086/* from lPEPI264v.inf (hv7131b!) */
2087static const struct usb_action hv7131r_InitialScale[] = {
2088 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2089 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2090 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2091 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2092 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2093 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2094 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2095 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2096 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2097 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2098 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2099 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2100 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2101 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2102 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2103 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2104 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2105 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2106 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2107 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2108 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2109 {0xdd, 0x00, 0x0200},
2110 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2111 {0xaa, 0x01, 0x000c},
2112 {0xaa, 0x11, 0x0000},
2113 {0xaa, 0x13, 0x0000},
2114 {0xaa, 0x14, 0x0001},
2115 {0xaa, 0x15, 0x00e8},
2116 {0xaa, 0x16, 0x0002},
2117 {0xaa, 0x17, 0x0088},
2118 {0xaa, 0x30, 0x000b},
2119 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2120 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2121 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2122 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2123 {0xa0, 0x00, 0x01ad},
2124 {0xa0, 0xc0, 0x019b},
2125 {0xa0, 0xa0, 0x019c},
2126 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2127 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2128 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2129 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2130 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2131 {}
2132};
2133static const struct usb_action hv7131r_Initial[] = {
2134 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2135 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2136 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2137 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2138 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2139 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2140 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2141 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2142 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2143 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2144 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2145 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2146 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2147 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2148 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2149 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2150 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2151 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2152 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2153 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2154 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2155 {0xdd, 0x00, 0x0200},
2156 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2157 {0xaa, 0x01, 0x000c},
2158 {0xaa, 0x11, 0x0000},
2159 {0xaa, 0x13, 0x0000},
2160 {0xaa, 0x14, 0x0001},
2161 {0xaa, 0x15, 0x00e6},
2162 {0xaa, 0x16, 0x0002},
2163 {0xaa, 0x17, 0x0086},
2164 {0xaa, 0x30, 0x000b},
2165 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2166 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2167 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2168 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2169 {0xa0, 0x00, 0x01ad},
2170 {0xa0, 0xc0, 0x019b},
2171 {0xa0, 0xa0, 0x019c},
2172 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2173 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2174 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2175 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2176 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2177 {}
2178};
2179static const struct usb_action hv7131r_50HZ[] = {
2180 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2181 {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
2182 {0xa0, 0x68, ZC3XX_R191_EXPOSURELIMITMID},
2183 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
2184 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2185 {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},
2186 {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},
2187 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2188 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2189 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2190 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2191 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2192 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2193 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2194 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2195 {}
2196};
2197static const struct usb_action hv7131r_50HZScale[] = {
2198 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2199 {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
2200 {0xa0, 0xd1, ZC3XX_R191_EXPOSURELIMITMID},
2201 {0xa0, 0x40, ZC3XX_R192_EXPOSURELIMITLOW},
2202 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2203 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2204 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2205 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2206 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2207 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2208 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2209 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2210 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2211 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2212 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2213 {}
2214};
2215static const struct usb_action hv7131r_60HZ[] = {
2216 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2217 {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
2218 {0xa0, 0x1a, ZC3XX_R191_EXPOSURELIMITMID},
2219 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
2220 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2221 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
2222 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
2223 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2224 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2225 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2226 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2227 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2228 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2229 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2230 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2231 {}
2232};
2233static const struct usb_action hv7131r_60HZScale[] = {
2234 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2235 {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
2236 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID},
2237 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2238 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2239 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
2240 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
2241 {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
2242 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2243 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2244 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
2245 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2246 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2247 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2248 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2249 {}
2250};
2251static const struct usb_action hv7131r_NoFliker[] = {
2252 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2253 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
2254 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
2255 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2256 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2257 {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},
2258 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW},
2259 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2260 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2261 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
2262 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
2263 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2264 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2265 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2266 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2267 {}
2268};
2269static const struct usb_action hv7131r_NoFlikerScale[] = {
2270 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2271 {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
2272 {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
2273 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
2274 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2275 {0xa0, 0x04, ZC3XX_R196_ANTIFLICKERMID},
2276 {0xa0, 0xb0, ZC3XX_R197_ANTIFLICKERLOW},
2277 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2278 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2279 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
2280 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
2281 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2282 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
2283 {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
2284 {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
2285 {}
2286};
2287
2288static const struct usb_action icm105a_InitialScale[] = {
2289 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2290 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2291 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2292 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2293 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2294 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2295 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2296 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2297 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2298 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2299 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2300 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2301 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2302 {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW},
2303 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2304 {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW},
2305 {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW},
2306 {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW},
2307 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2308 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2309 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2310 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2311 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
2312 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2313 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2314 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2315 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2316 {0xaa, 0x01, 0x0010},
2317 {0xaa, 0x03, 0x0000},
2318 {0xaa, 0x04, 0x0001},
2319 {0xaa, 0x05, 0x0020},
2320 {0xaa, 0x06, 0x0001},
2321 {0xaa, 0x08, 0x0000},
2322 {0xaa, 0x03, 0x0001},
2323 {0xaa, 0x04, 0x0011},
2324 {0xaa, 0x05, 0x00a0},
2325 {0xaa, 0x06, 0x0001},
2326 {0xaa, 0x08, 0x0000},
2327 {0xaa, 0x03, 0x0002},
2328 {0xaa, 0x04, 0x0013},
2329 {0xaa, 0x05, 0x0020},
2330 {0xaa, 0x06, 0x0001},
2331 {0xaa, 0x08, 0x0000},
2332 {0xaa, 0x03, 0x0003},
2333 {0xaa, 0x04, 0x0015},
2334 {0xaa, 0x05, 0x0020},
2335 {0xaa, 0x06, 0x0005},
2336 {0xaa, 0x08, 0x0000},
2337 {0xaa, 0x03, 0x0004},
2338 {0xaa, 0x04, 0x0017},
2339 {0xaa, 0x05, 0x0020},
2340 {0xaa, 0x06, 0x000d},
2341 {0xaa, 0x08, 0x0000},
2342 {0xaa, 0x03, 0x0005},
2343 {0xaa, 0x04, 0x0019},
2344 {0xaa, 0x05, 0x0020},
2345 {0xaa, 0x06, 0x0005},
2346 {0xaa, 0x08, 0x0000},
2347 {0xaa, 0x03, 0x0006},
2348 {0xaa, 0x04, 0x0017},
2349 {0xaa, 0x05, 0x0026},
2350 {0xaa, 0x06, 0x0005},
2351 {0xaa, 0x08, 0x0000},
2352 {0xaa, 0x03, 0x0007},
2353 {0xaa, 0x04, 0x0019},
2354 {0xaa, 0x05, 0x0022},
2355 {0xaa, 0x06, 0x0005},
2356 {0xaa, 0x08, 0x0000},
2357 {0xaa, 0x03, 0x0008},
2358 {0xaa, 0x04, 0x0021},
2359 {0xaa, 0x05, 0x00aa},
2360 {0xaa, 0x06, 0x0005},
2361 {0xaa, 0x08, 0x0000},
2362 {0xaa, 0x03, 0x0009},
2363 {0xaa, 0x04, 0x0023},
2364 {0xaa, 0x05, 0x00aa},
2365 {0xaa, 0x06, 0x000d},
2366 {0xaa, 0x08, 0x0000},
2367 {0xaa, 0x03, 0x000a},
2368 {0xaa, 0x04, 0x0025},
2369 {0xaa, 0x05, 0x00aa},
2370 {0xaa, 0x06, 0x0005},
2371 {0xaa, 0x08, 0x0000},
2372 {0xaa, 0x03, 0x000b},
2373 {0xaa, 0x04, 0x00ec},
2374 {0xaa, 0x05, 0x002e},
2375 {0xaa, 0x06, 0x0005},
2376 {0xaa, 0x08, 0x0000},
2377 {0xaa, 0x03, 0x000c},
2378 {0xaa, 0x04, 0x00fa},
2379 {0xaa, 0x05, 0x002a},
2380 {0xaa, 0x06, 0x0005},
2381 {0xaa, 0x08, 0x0000},
2382 {0xaa, 0x07, 0x000d},
2383 {0xaa, 0x01, 0x0005},
2384 {0xaa, 0x94, 0x0002},
2385 {0xaa, 0x90, 0x0000},
2386 {0xaa, 0x91, 0x001f},
2387 {0xaa, 0x10, 0x0064},
2388 {0xaa, 0x9b, 0x00f0},
2389 {0xaa, 0x9c, 0x0002},
2390 {0xaa, 0x14, 0x001a},
2391 {0xaa, 0x20, 0x0080},
2392 {0xaa, 0x22, 0x0080},
2393 {0xaa, 0x24, 0x0080},
2394 {0xaa, 0x26, 0x0080},
2395 {0xaa, 0x00, 0x0084},
2396 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2397 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2398 {0xaa, 0xa8, 0x00c0},
2399 {0xa1, 0x01, 0x0002},
2400 {0xa1, 0x01, 0x0008},
2401 {0xa1, 0x01, 0x0180},
2402 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2403 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2404 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2405 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2406 {0xa1, 0x01, 0x0008},
2407
2408 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2409 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2410 {0xa1, 0x01, 0x01c8},
2411 {0xa1, 0x01, 0x01c9},
2412 {0xa1, 0x01, 0x01ca},
2413 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2414 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2415 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2416 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2417 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2418 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2419 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2420 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2421 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2422 {0xa0, 0x52, ZC3XX_R112_RGB22},
2423 {0xa1, 0x01, 0x0180},
2424 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2425 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2426 {0xaa, 0x0d, 0x0003},
2427 {0xaa, 0x0c, 0x008c},
2428 {0xaa, 0x0e, 0x0095},
2429 {0xaa, 0x0f, 0x0002},
2430 {0xaa, 0x1c, 0x0094},
2431 {0xaa, 0x1d, 0x0002},
2432 {0xaa, 0x20, 0x0080},
2433 {0xaa, 0x22, 0x0080},
2434 {0xaa, 0x24, 0x0080},
2435 {0xaa, 0x26, 0x0080},
2436 {0xaa, 0x00, 0x0084},
2437 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
2438 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW},
2439 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2440 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
2441 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
2442 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2443 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2444 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW},
2445 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2446 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2447 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2448 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
2449 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0},
2450 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1},
2451 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2},
2452 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
2453 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
2454 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN},
2455 {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN},
2456 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2457 {0xa1, 0x01, 0x0180},
2458 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2459 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2460 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2461 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2462 {}
2463};
2464
2465static const struct usb_action icm105a_Initial[] = {
2466 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2467 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2468 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2469 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2470 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2471 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2472 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2473 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2474 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2475 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2476 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2477 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2478 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2479 {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW},
2480 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2481 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
2482 {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW},
2483 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
2484 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2485 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2486 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2487 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2488 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2489 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2490 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2491 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2492 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2493 {0xaa, 0x01, 0x0010},
2494 {0xaa, 0x03, 0x0000},
2495 {0xaa, 0x04, 0x0001},
2496 {0xaa, 0x05, 0x0020},
2497 {0xaa, 0x06, 0x0001},
2498 {0xaa, 0x08, 0x0000},
2499 {0xaa, 0x03, 0x0001},
2500 {0xaa, 0x04, 0x0011},
2501 {0xaa, 0x05, 0x00a0},
2502 {0xaa, 0x06, 0x0001},
2503 {0xaa, 0x08, 0x0000},
2504 {0xaa, 0x03, 0x0002},
2505 {0xaa, 0x04, 0x0013},
2506 {0xaa, 0x05, 0x0020},
2507 {0xaa, 0x06, 0x0001},
2508 {0xaa, 0x08, 0x0000},
2509 {0xaa, 0x03, 0x0003},
2510 {0xaa, 0x04, 0x0015},
2511 {0xaa, 0x05, 0x0020},
2512 {0xaa, 0x06, 0x0005},
2513 {0xaa, 0x08, 0x0000},
2514 {0xaa, 0x03, 0x0004},
2515 {0xaa, 0x04, 0x0017},
2516 {0xaa, 0x05, 0x0020},
2517 {0xaa, 0x06, 0x000d},
2518 {0xaa, 0x08, 0x0000},
2519 {0xaa, 0x03, 0x0005},
2520 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
2521 {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE},
2522 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
2523 {0xa1, 0x01, 0x0091},
2524 {0xaa, 0x05, 0x0020},
2525 {0xaa, 0x06, 0x0005},
2526 {0xaa, 0x08, 0x0000},
2527 {0xaa, 0x03, 0x0006},
2528 {0xaa, 0x04, 0x0017},
2529 {0xaa, 0x05, 0x0026},
2530 {0xaa, 0x06, 0x0005},
2531 {0xaa, 0x08, 0x0000},
2532 {0xaa, 0x03, 0x0007},
2533 {0xaa, 0x04, 0x0019},
2534 {0xaa, 0x05, 0x0022},
2535 {0xaa, 0x06, 0x0005},
2536 {0xaa, 0x08, 0x0000},
2537 {0xaa, 0x03, 0x0008},
2538 {0xaa, 0x04, 0x0021},
2539 {0xaa, 0x05, 0x00aa},
2540 {0xaa, 0x06, 0x0005},
2541 {0xaa, 0x08, 0x0000},
2542 {0xaa, 0x03, 0x0009},
2543 {0xaa, 0x04, 0x0023},
2544 {0xaa, 0x05, 0x00aa},
2545 {0xaa, 0x06, 0x000d},
2546 {0xaa, 0x08, 0x0000},
2547 {0xaa, 0x03, 0x000a},
2548 {0xaa, 0x04, 0x0025},
2549 {0xaa, 0x05, 0x00aa},
2550 {0xaa, 0x06, 0x0005},
2551 {0xaa, 0x08, 0x0000},
2552 {0xaa, 0x03, 0x000b},
2553 {0xaa, 0x04, 0x00ec},
2554 {0xaa, 0x05, 0x002e},
2555 {0xaa, 0x06, 0x0005},
2556 {0xaa, 0x08, 0x0000},
2557 {0xaa, 0x03, 0x000c},
2558 {0xaa, 0x04, 0x00fa},
2559 {0xaa, 0x05, 0x002a},
2560 {0xaa, 0x06, 0x0005},
2561 {0xaa, 0x08, 0x0000},
2562 {0xaa, 0x07, 0x000d},
2563 {0xaa, 0x01, 0x0005},
2564 {0xaa, 0x94, 0x0002},
2565 {0xaa, 0x90, 0x0000},
2566 {0xaa, 0x91, 0x0010},
2567 {0xaa, 0x10, 0x0064},
2568 {0xaa, 0x9b, 0x00f0},
2569 {0xaa, 0x9c, 0x0002},
2570 {0xaa, 0x14, 0x001a},
2571 {0xaa, 0x20, 0x0080},
2572 {0xaa, 0x22, 0x0080},
2573 {0xaa, 0x24, 0x0080},
2574 {0xaa, 0x26, 0x0080},
2575 {0xaa, 0x00, 0x0084},
2576 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2577 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2578 {0xaa, 0xa8, 0x0080},
2579 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2580 {0xa1, 0x01, 0x0002},
2581 {0xa1, 0x01, 0x0008},
2582 {0xa1, 0x01, 0x0180},
2583 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2584 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2585 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2586 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2587 {0xa1, 0x01, 0x0008},
2588
2589 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2590 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2591 {0xa1, 0x01, 0x01c8},
2592 {0xa1, 0x01, 0x01c9},
2593 {0xa1, 0x01, 0x01ca},
2594 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2595
2596 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2597 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2598 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2599 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2600 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2601 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2602 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2603 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2604 {0xa0, 0x52, ZC3XX_R112_RGB22},
2605 {0xa1, 0x01, 0x0180},
2606 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2607 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2608 {0xaa, 0x0d, 0x0003},
2609 {0xaa, 0x0c, 0x0020},
2610 {0xaa, 0x0e, 0x000e},
2611 {0xaa, 0x0f, 0x0002},
2612 {0xaa, 0x1c, 0x000d},
2613 {0xaa, 0x1d, 0x0002},
2614 {0xaa, 0x20, 0x0080},
2615 {0xaa, 0x22, 0x0080},
2616 {0xaa, 0x24, 0x0080},
2617 {0xaa, 0x26, 0x0080},
2618 {0xaa, 0x00, 0x0084},
2619 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
2620 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW},
2621 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2622 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
2623 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW},
2624 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2625 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2626 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW},
2627 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2628 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2629 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2630 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
2631 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0},
2632 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1},
2633 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
2634 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
2635 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
2636 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2637 {0xa1, 0x01, 0x0180},
2638 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2639 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2640 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2641 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2642 {}
2643};
2644static const struct usb_action icm105a_50HZScale[] = {
2645 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2646 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2647 {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
2648 {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */
2649 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2650 {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */
2651 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2652 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2653 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2654 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2655 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2656 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2657 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2658 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */
2659 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2660 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2661 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */
2662 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2663 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2664 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */
2665 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2666 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2667 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2668 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2669 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
2670 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */
2671 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
2672 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2673 {}
2674};
2675static const struct usb_action icm105a_50HZ[] = {
2676 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2677 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2678 {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
2679 {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */
2680 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2681 {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */
2682 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2683 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2684 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2685 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2686 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2687 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2688 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2689 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */
2690 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2691 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2692 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
2693 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2694 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2695 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */
2696 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2697 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2698 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2699 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2700 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */
2701 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */
2702 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */
2703 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2704 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
2705 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
2706 {}
2707};
2708static const struct usb_action icm105a_60HZScale[] = {
2709 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2710 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2711 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
2712 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
2713 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2714 {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */
2715 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2716 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2717 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2718 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2719 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2720 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2721 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2722 {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */
2723 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2724 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2725 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
2726 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2727 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2728 {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */
2729 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2730 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2731 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2732 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2733 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
2734 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
2735 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
2736 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2737 {}
2738};
2739static const struct usb_action icm105a_60HZ[] = {
2740 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2741 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2742 {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
2743 {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */
2744 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2745 {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */
2746 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2747 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2748 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2749 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2750 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2751 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2752 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2753 {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */
2754 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2755 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2756 {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */
2757 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2758 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2759 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
2760 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2761 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2762 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
2763 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
2764 {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */
2765 {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */
2766 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
2767 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2768 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
2769 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
2770 {}
2771};
2772static const struct usb_action icm105a_NoFlikerScale[] = {
2773 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2774 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2775 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
2776 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
2777 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2778 {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */
2779 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2780 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2781 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2782 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2783 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2784 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2785 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2786 {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */
2787 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2788 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2789 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
2790 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2791 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2792 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
2793 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2794 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2795 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2796 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2797 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
2798 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
2799 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
2800 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2801 {}
2802};
2803static const struct usb_action icm105a_NoFliker[] = {
2804 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2805 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
2806 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
2807 {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */
2808 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
2809 {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */
2810 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
2811 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
2812 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
2813 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
2814 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
2815 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
2816 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
2817 {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */
2818 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2819 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
2820 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
2821 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2822 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2823 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
2824 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2825 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2826 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2827 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2828 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
2829 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
2830 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
2831 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
2832 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
2833 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
2834 {}
2835};
2836
2837static const struct usb_action mc501cb_Initial[] = {
2838 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
2839 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
2840 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
2841 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
2842 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
2843 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
2844 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2845 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
2846 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
2847 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
2848 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
2849 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
2850 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
2851 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
2852 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
2853 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
2854 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
2855 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
2856 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
2857 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
2858 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
2859 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
2860 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
2861 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2862 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2863 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
2864 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2865 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
2866 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2867 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
2868 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
2869 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
2870 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
2871 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
2872 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
2873 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
2874 {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */
2875 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
2876 {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */
2877 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
2878 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
2879 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
2880 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
2881 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
2882 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
2883 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
2884 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
2885 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
2886 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
2887 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
2888 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
2889 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
2890 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
2891 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
2892 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
2893 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
2894 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
2895 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
2896 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
2897 {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
2898 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
2899 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
2900 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
2901 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
2902 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
2903 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
2904 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
2905 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
2906 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
2907 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
2908 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
2909 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
2910 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
2911 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
2912 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
2913 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
2914 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
2915 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
2916 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2917 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
2918 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
2919 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
2920 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2921 {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */
2922 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
2923 {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */
2924 {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */
2925 {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */
2926 {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */
2927 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
2928 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
2929 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2930 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
2931 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
2932 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
2933 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
2934 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
2935 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
2936 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
2937 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
2938 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
2939 {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */
2940 {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */
2941 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2942 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
2943 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
2944 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
2945 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
2946 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
2947 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
2948
2949 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
2950 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
2951 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
2952 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
2953 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
2954 {}
2955};
2956
2957static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */
2958 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
2959 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
2960 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
2961 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
2962 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
2963 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
2964 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2965 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
2966 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
2967 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
2968 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
2969 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
2970 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
2971 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
2972 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
2973 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
2974 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
2975 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
2976 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
2977 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
2978 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
2979 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
2980 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
2981 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
2982 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2983 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
2984 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
2985 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
2986 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
2987 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
2988 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
2989 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
2990 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
2991 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
2992 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
2993 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
2994 {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */
2995 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
2996 {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */
2997 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
2998 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
2999 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
3000 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
3001 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
3002 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
3003 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
3004 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
3005 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
3006 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
3007 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
3008 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
3009 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
3010 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
3011 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
3012 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
3013 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
3014 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
3015 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
3016 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
3017 {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
3018 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
3019 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
3020 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
3021 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
3022 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
3023 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
3024 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
3025 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
3026 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
3027 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
3028 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
3029 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
3030 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
3031 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
3032 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
3033 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
3034 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
3035 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
3036 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3037 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
3038 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
3039 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
3040 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3041 {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */
3042 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
3043 {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */
3044 {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */
3045 {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */
3046 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3047 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
3048 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
3049 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3050 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3051 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
3052 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3053 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3054 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3055 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3056 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3057 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3058 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
3059 {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */
3060 {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */
3061 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3062 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
3063 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
3064 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
3065 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
3066 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
3067 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
3068 {}
3069};
3070
3071static const struct usb_action mc501cb_50HZ[] = {
3072 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3073 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3074 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3075 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3076 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3077 {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */
3078 {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */
3079 {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */
3080 {}
3081};
3082
3083static const struct usb_action mc501cb_50HZScale[] = {
3084 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3085 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3086 {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
3087 {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
3088 {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
3089 {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */
3090 {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */
3091 {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */
3092 {}
3093};
3094
3095static const struct usb_action mc501cb_60HZ[] = {
3096 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3097 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3098 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3099 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3100 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3101 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3102 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3103 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3104 {}
3105};
3106
3107static const struct usb_action mc501cb_60HZScale[] = {
3108 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3109 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3110 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3111 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3112 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3113 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3114 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3115 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3116 {}
3117};
3118
3119static const struct usb_action mc501cb_NoFliker[] = {
3120 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3121 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3122 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3123 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3124 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3125 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3126 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3127 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3128 {}
3129};
3130
3131static const struct usb_action mc501cb_NoFlikerScale[] = {
3132 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3133 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3134 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3135 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3136 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3137 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3138 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3139 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3140 {}
3141};
3142
3143/* from zs211.inf */
3144static const struct usb_action ov7620_Initial[] = { /* 640x480 */
3145 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3146 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
3147 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3148 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3149 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3150 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3151 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3152 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3153 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3154 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3155 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3156 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3157 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3158 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3159 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3160 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
3161 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3162 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3163 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3164 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3165 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3166 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3167 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
3168 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3169 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3170 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3171 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3172 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3173 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3174 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3175 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3176 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3177 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3178 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3179 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3180 {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */
3181 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3182 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3183 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3184 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3185 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3186 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3187 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3188 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3189 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3190 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3191 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3192 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3193 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3194 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3195 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3196 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3197 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3198 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3199 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3200 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3201 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3202 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3203 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3204 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3205 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3206 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3207 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3208 {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */
3209 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3210 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3211 {}
3212};
3213static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */
3214 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3215 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */
3216 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3217 /* mx change? */
3218 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3219 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3220 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3221 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3222 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3223 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3224 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3225 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3226 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3227 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3228 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3229 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3230 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
3231 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3232 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3233 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3234 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3235 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3236 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3237 {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d6,cc */
3238 /* OV7648 00,9c,d8,cc */
3239 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3240 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3241 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3242 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3243 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3244 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3245 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3246 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3247 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3248 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3249 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3250 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3251 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3252 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3253 {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */
3254 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3255 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3256 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3257 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3258 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3259 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3260 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3261 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3262 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3263 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3264 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3265 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3266 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3267 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3268 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3269 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3270 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3271 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3272 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3273 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3274 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3275 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3276 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3277 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3278 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3279 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,50,cc */
3280 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3281 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3282 {}
3283};
3284static const struct usb_action ov7620_50HZ[] = {
3285 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3286 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3287 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3288 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3289 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3290 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3291 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3292 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3293 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3294 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3295 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3296 {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */
3297 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3298/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3299 * if mode0 (640x480) */
3300 {}
3301};
3302static const struct usb_action ov7620_60HZ[] = {
3303 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3304 /* (bug in zs211.inf) */
3305 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3306 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3307 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3308 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3309 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3310 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3311 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3312 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3313 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3314 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3315 {0xaa, 0x10, 0x0020}, /* 00,10,20,aa */
3316 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3317/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3318 * if mode0 (640x480) */
3319/* ?? in gspca v1, it was
3320 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3321 {0xa1, 0x01, 0x0037}, */
3322 {}
3323};
3324static const struct usb_action ov7620_NoFliker[] = {
3325 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3326 /* (bug in zs211.inf) */
3327 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3328 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3329 {0xaa, 0x75, 0x008e}, /* 00,75,8e,aa */
3330 {0xaa, 0x2d, 0x0001}, /* 00,2d,01,aa */
3331 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3332 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3333 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3334 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3335 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3336 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
3337/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc
3338 * if mode1 (320x240) */
3339/* ?? was
3340 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3341 {0xa1, 0x01, 0x0037}, */
3342 {}
3343};
3344
3345static const struct usb_action ov7630c_InitialScale[] = {
3346 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3347 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3348 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3349 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3350 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3351 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3352 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3353 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3354 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3355 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3356 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3357 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3358 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3359 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3360 {0xaa, 0x12, 0x0080},
3361 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3362 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3363 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3364 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3365 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3366 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3367 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3368 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3369 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3370 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
3371 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
3372 {0xaa, 0x12, 0x0069},
3373 {0xaa, 0x04, 0x0020},
3374 {0xaa, 0x06, 0x0050},
3375 {0xaa, 0x13, 0x0083},
3376 {0xaa, 0x14, 0x0000},
3377 {0xaa, 0x15, 0x0024},
3378 {0xaa, 0x17, 0x0018},
3379 {0xaa, 0x18, 0x00ba},
3380 {0xaa, 0x19, 0x0002},
3381 {0xaa, 0x1a, 0x00f6},
3382 {0xaa, 0x1b, 0x0002},
3383 {0xaa, 0x20, 0x00c2},
3384 {0xaa, 0x24, 0x0060},
3385 {0xaa, 0x25, 0x0040},
3386 {0xaa, 0x26, 0x0030},
3387 {0xaa, 0x27, 0x00ea},
3388 {0xaa, 0x28, 0x00a0},
3389 {0xaa, 0x21, 0x0000},
3390 {0xaa, 0x2a, 0x0081},
3391 {0xaa, 0x2b, 0x0096},
3392 {0xaa, 0x2d, 0x0094},
3393 {0xaa, 0x2f, 0x003d},
3394 {0xaa, 0x30, 0x0024},
3395 {0xaa, 0x60, 0x0000},
3396 {0xaa, 0x61, 0x0040},
3397 {0xaa, 0x68, 0x007c},
3398 {0xaa, 0x6f, 0x0015},
3399 {0xaa, 0x75, 0x0088},
3400 {0xaa, 0x77, 0x00b5},
3401 {0xaa, 0x01, 0x0060},
3402 {0xaa, 0x02, 0x0060},
3403 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3404 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3405 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3406 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3407 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3408 {0xa0, 0x00, 0x01ad},
3409 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3410 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3411 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3412 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3413 {0xa0, 0x60, ZC3XX_R116_RGAIN},
3414 {0xa0, 0x46, ZC3XX_R118_BGAIN},
3415 {0xa0, 0x04, ZC3XX_R113_RGB03},
3416/* 0x10, */
3417 {0xa1, 0x01, 0x0002},
3418 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3419 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3420 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3421 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3422 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3423 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3424 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3425 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3426 {0xa0, 0x50, ZC3XX_R112_RGB22},
3427 {0xa1, 0x01, 0x0008},
3428 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3429 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
3430 {0xa1, 0x01, 0x01c8},
3431 {0xa1, 0x01, 0x01c9},
3432 {0xa1, 0x01, 0x01ca},
3433 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
3434 {0xa0, 0x01, ZC3XX_R120_GAMMA00}, /* gamma 2 ?*/
3435 {0xa0, 0x0c, ZC3XX_R121_GAMMA01},
3436 {0xa0, 0x1f, ZC3XX_R122_GAMMA02},
3437 {0xa0, 0x3a, ZC3XX_R123_GAMMA03},
3438 {0xa0, 0x53, ZC3XX_R124_GAMMA04},
3439 {0xa0, 0x6d, ZC3XX_R125_GAMMA05},
3440 {0xa0, 0x85, ZC3XX_R126_GAMMA06},
3441 {0xa0, 0x9c, ZC3XX_R127_GAMMA07},
3442 {0xa0, 0xb0, ZC3XX_R128_GAMMA08},
3443 {0xa0, 0xc2, ZC3XX_R129_GAMMA09},
3444 {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A},
3445 {0xa0, 0xde, ZC3XX_R12B_GAMMA0B},
3446 {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C},
3447 {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D},
3448 {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E},
3449 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
3450 {0xa0, 0x05, ZC3XX_R130_GAMMA10},
3451 {0xa0, 0x0f, ZC3XX_R131_GAMMA11},
3452 {0xa0, 0x16, ZC3XX_R132_GAMMA12},
3453 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
3454 {0xa0, 0x19, ZC3XX_R134_GAMMA14},
3455 {0xa0, 0x19, ZC3XX_R135_GAMMA15},
3456 {0xa0, 0x17, ZC3XX_R136_GAMMA16},
3457 {0xa0, 0x15, ZC3XX_R137_GAMMA17},
3458 {0xa0, 0x12, ZC3XX_R138_GAMMA18},
3459 {0xa0, 0x10, ZC3XX_R139_GAMMA19},
3460 {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A},
3461 {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B},
3462 {0xa0, 0x09, ZC3XX_R13C_GAMMA1C},
3463 {0xa0, 0x08, ZC3XX_R13D_GAMMA1D},
3464 {0xa0, 0x06, ZC3XX_R13E_GAMMA1E},
3465 {0xa0, 0x03, ZC3XX_R13F_GAMMA1F},
3466 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3467 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3468 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3469 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3470 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3471 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3472 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3473 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3474 {0xa0, 0x50, ZC3XX_R112_RGB22},
3475
3476 {0xa1, 0x01, 0x0180},
3477 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3478 {0xaa, 0x10, 0x001b},
3479 {0xaa, 0x76, 0x0002},
3480 {0xaa, 0x2a, 0x0081},
3481 {0xaa, 0x2b, 0x0000},
3482 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3483 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID},
3484 {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW},
3485 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3486 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3487 {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW},
3488 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3489 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3490 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3491 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3492 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
3493 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
3494 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3495 {0xaa, 0x13, 0x0083}, /* 40 */
3496 {0xa1, 0x01, 0x0180},
3497 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3498 {}
3499};
3500
3501static const struct usb_action ov7630c_Initial[] = {
3502 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3503 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
3504 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3505 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3506 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3507 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3508 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3509 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3510 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3511 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3512 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3513 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3514
3515 {0xaa, 0x12, 0x0080},
3516 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3517 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3518 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3519 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3520 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3521 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3522 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3523 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3524 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3525 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
3526 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
3527 {0xaa, 0x12, 0x0069}, /* i2c */
3528 {0xaa, 0x04, 0x0020},
3529 {0xaa, 0x06, 0x0050},
3530 {0xaa, 0x13, 0x00c3},
3531 {0xaa, 0x14, 0x0000},
3532 {0xaa, 0x15, 0x0024},
3533 {0xaa, 0x19, 0x0003},
3534 {0xaa, 0x1a, 0x00f6},
3535 {0xaa, 0x1b, 0x0002},
3536 {0xaa, 0x20, 0x00c2},
3537 {0xaa, 0x24, 0x0060},
3538 {0xaa, 0x25, 0x0040},
3539 {0xaa, 0x26, 0x0030},
3540 {0xaa, 0x27, 0x00ea},
3541 {0xaa, 0x28, 0x00a0},
3542 {0xaa, 0x21, 0x0000},
3543 {0xaa, 0x2a, 0x0081},
3544 {0xaa, 0x2b, 0x0096},
3545 {0xaa, 0x2d, 0x0084},
3546 {0xaa, 0x2f, 0x003d},
3547 {0xaa, 0x30, 0x0024},
3548 {0xaa, 0x60, 0x0000},
3549 {0xaa, 0x61, 0x0040},
3550 {0xaa, 0x68, 0x007c},
3551 {0xaa, 0x6f, 0x0015},
3552 {0xaa, 0x75, 0x0088},
3553 {0xaa, 0x77, 0x00b5},
3554 {0xaa, 0x01, 0x0060},
3555 {0xaa, 0x02, 0x0060},
3556 {0xaa, 0x17, 0x0018},
3557 {0xaa, 0x18, 0x00ba},
3558 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3559 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3560 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3561 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3562 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3563 {0xa0, 0x00, 0x01ad},
3564 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3565 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3566 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3567 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3568 {0xa0, 0x60, ZC3XX_R116_RGAIN},
3569 {0xa0, 0x46, ZC3XX_R118_BGAIN},
3570 {0xa0, 0x04, ZC3XX_R113_RGB03},
3571
3572 {0xa1, 0x01, 0x0002},
3573 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
3574 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
3575 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3576 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
3577 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
3578 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
3579 {0xa0, 0x00, ZC3XX_R110_RGB20},
3580 {0xa0, 0xf6, ZC3XX_R111_RGB21},
3581 {0xa0, 0x4a, ZC3XX_R112_RGB22},
3582
3583 {0xa1, 0x01, 0x0008},
3584 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3585 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
3586 {0xa1, 0x01, 0x01c8},
3587 {0xa1, 0x01, 0x01c9},
3588 {0xa1, 0x01, 0x01ca},
3589 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
3590 {0xa0, 0x16, ZC3XX_R120_GAMMA00}, /* gamma ~4 */
3591 {0xa0, 0x3a, ZC3XX_R121_GAMMA01},
3592 {0xa0, 0x5b, ZC3XX_R122_GAMMA02},
3593 {0xa0, 0x7c, ZC3XX_R123_GAMMA03},
3594 {0xa0, 0x94, ZC3XX_R124_GAMMA04},
3595 {0xa0, 0xa9, ZC3XX_R125_GAMMA05},
3596 {0xa0, 0xbb, ZC3XX_R126_GAMMA06},
3597 {0xa0, 0xca, ZC3XX_R127_GAMMA07},
3598 {0xa0, 0xd7, ZC3XX_R128_GAMMA08},
3599 {0xa0, 0xe1, ZC3XX_R129_GAMMA09},
3600 {0xa0, 0xea, ZC3XX_R12A_GAMMA0A},
3601 {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B},
3602 {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C},
3603 {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D},
3604 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
3605 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
3606 {0xa0, 0x20, ZC3XX_R130_GAMMA10},
3607 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
3608 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
3609 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
3610 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
3611 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
3612 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
3613 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
3614 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
3615 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
3616 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
3617 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
3618 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
3619 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
3620 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
3621 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
3622 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
3623 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
3624 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3625 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
3626 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
3627 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
3628 {0xa0, 0x00, ZC3XX_R110_RGB20},
3629 {0xa0, 0xf6, ZC3XX_R111_RGB21},
3630 {0xa0, 0x4a, ZC3XX_R112_RGB22},
3631
3632 {0xa1, 0x01, 0x0180},
3633 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3634 {0xaa, 0x10, 0x000d},
3635 {0xaa, 0x76, 0x0002},
3636 {0xaa, 0x2a, 0x0081},
3637 {0xaa, 0x2b, 0x0000},
3638 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3639 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
3640 {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW},
3641 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3642 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3643 {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW},
3644 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3645 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3646 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3647 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3648 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
3649 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
3650 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3651 {0xaa, 0x13, 0x00c3},
3652
3653 {0xa1, 0x01, 0x0180},
3654 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3655 {}
3656};
3657
3658static const struct usb_action pas106b_Initial_com[] = {
3659/* Sream and Sensor specific */
3660 {0xa1, 0x01, 0x0010}, /* CMOSSensorSelect */
3661/* System */
3662 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
3663 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
3664/* Picture size */
3665 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* ClockSelect */
3666 {0xa0, 0x03, 0x003a},
3667 {0xa0, 0x0c, 0x003b},
3668 {0xa0, 0x04, 0x0038},
3669 {}
3670};
3671
3672static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */
3673/* JPEG control */
3674 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3675/* Sream and Sensor specific */
3676 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
3677/* Picture size */
3678 {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH},
3679 {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW},
3680 {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH},
3681 {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW},
3682/* System */
3683 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3684/* Sream and Sensor specific */
3685 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
3686 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3687/* Sensor Interface */
3688 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3689/* Window inside sensor array */
3690 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
3691 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3692 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
3693 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
3694 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
3695/* Init the sensor */
3696 {0xaa, 0x02, 0x0004},
3697 {0xaa, 0x08, 0x0000},
3698 {0xaa, 0x09, 0x0005},
3699 {0xaa, 0x0a, 0x0002},
3700 {0xaa, 0x0b, 0x0002},
3701 {0xaa, 0x0c, 0x0005},
3702 {0xaa, 0x0d, 0x0000},
3703 {0xaa, 0x0e, 0x0002},
3704 {0xaa, 0x14, 0x0081},
3705/* Other registers */
3706 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
3707/* Frame retreiving */
3708 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
3709/* Gains */
3710 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
3711/* Unknown */
3712 {0xa0, 0x00, 0x01ad},
3713/* Sharpness */
3714 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3715 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3716/* Other registers */
3717 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3718/* Auto exposure and white balance */
3719 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3720/*Dead pixels */
3721 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3722/* EEPROM */
3723 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3724/* JPEG control */
3725 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3726 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3727 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3728/* Other registers */
3729 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3730/* Auto exposure and white balance */
3731 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3732/*Dead pixels */
3733 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3734/* EEPROM */
3735 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3736/* JPEG control */
3737 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3738 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3739 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3740
3741 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
3742 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
3743 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3744 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
3745 {0xa0, 0x58, ZC3XX_R10E_RGB11},
3746 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
3747 {0xa0, 0xf4, ZC3XX_R110_RGB20},
3748 {0xa0, 0xf4, ZC3XX_R111_RGB21},
3749 {0xa0, 0x58, ZC3XX_R112_RGB22},
3750/* Auto correction */
3751 {0xa0, 0x03, ZC3XX_R181_WINXSTART},
3752 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
3753 {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
3754 {0xa0, 0x03, ZC3XX_R184_WINYSTART},
3755 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
3756 {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
3757 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3758/* Auto exposure and white balance */
3759 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3760 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
3761 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
3762 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3763 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3764 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
3765 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
3766 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
3767/* sensor on */
3768 {0xaa, 0x07, 0x00b1},
3769 {0xaa, 0x05, 0x0003},
3770 {0xaa, 0x04, 0x0001},
3771 {0xaa, 0x03, 0x003b},
3772/* Gains */
3773 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
3774 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3775 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
3776 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
3777/* Auto correction */
3778 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3779 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
3780 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3781/* Gains */
3782 {0xa0, 0x40, ZC3XX_R116_RGAIN},
3783 {0xa0, 0x40, ZC3XX_R117_GGAIN},
3784 {0xa0, 0x40, ZC3XX_R118_BGAIN},
3785 {}
3786};
3787
3788static const struct usb_action pas106b_Initial[] = { /* 352x288 */
3789/* JPEG control */
3790 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3791/* Sream and Sensor specific */
3792 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
3793/* Picture size */
3794 {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH},
3795 {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW},
3796 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3797 {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW},
3798/* System */
3799 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3800/* Sream and Sensor specific */
3801 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
3802 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3803/* Sensor Interface */
3804 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3805/* Window inside sensor array */
3806 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
3807 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3808 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
3809 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
3810 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
3811/* Init the sensor */
3812 {0xaa, 0x02, 0x0004},
3813 {0xaa, 0x08, 0x0000},
3814 {0xaa, 0x09, 0x0005},
3815 {0xaa, 0x0a, 0x0002},
3816 {0xaa, 0x0b, 0x0002},
3817 {0xaa, 0x0c, 0x0005},
3818 {0xaa, 0x0d, 0x0000},
3819 {0xaa, 0x0e, 0x0002},
3820 {0xaa, 0x14, 0x0081},
3821/* Other registers */
3822 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
3823/* Frame retreiving */
3824 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
3825/* Gains */
3826 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
3827/* Unknown */
3828 {0xa0, 0x00, 0x01ad},
3829/* Sharpness */
3830 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3831 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3832/* Other registers */
3833 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3834/* Auto exposure and white balance */
3835 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3836 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
3837/*Dead pixels */
3838 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3839/* EEPROM */
3840 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3841/* JPEG control */
3842 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3843 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3844 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3845/* Other registers */
3846 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3847/* Auto exposure and white balance */
3848 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3849/*Dead pixels */
3850 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3851/* EEPROM */
3852 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3853/* JPEG control */
3854 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3855 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
3856 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
3857
3858 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
3859 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
3860 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
3861 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
3862 {0xa0, 0x58, ZC3XX_R10E_RGB11},
3863 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
3864 {0xa0, 0xf4, ZC3XX_R110_RGB20},
3865 {0xa0, 0xf4, ZC3XX_R111_RGB21},
3866 {0xa0, 0x58, ZC3XX_R112_RGB22},
3867/* Auto correction */
3868 {0xa0, 0x03, ZC3XX_R181_WINXSTART},
3869 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
3870 {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
3871 {0xa0, 0x03, ZC3XX_R184_WINYSTART},
3872 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
3873 {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
3874 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3875
3876/* Auto exposure and white balance */
3877 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3878 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
3879 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
3880
3881 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3882 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3883 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
3884
3885 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3886 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3887/* sensor on */
3888 {0xaa, 0x07, 0x00b1},
3889 {0xaa, 0x05, 0x0003},
3890 {0xaa, 0x04, 0x0001},
3891 {0xaa, 0x03, 0x003b},
3892/* Gains */
3893 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
3894 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3895 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
3896 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
3897/* Auto correction */
3898 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3899 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
3900 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3901/* Gains */
3902 {0xa0, 0x40, ZC3XX_R116_RGAIN},
3903 {0xa0, 0x40, ZC3XX_R117_GGAIN},
3904 {0xa0, 0x40, ZC3XX_R118_BGAIN},
3905
3906 {0xa0, 0x00, 0x0007}, /* AutoCorrectEnable */
3907 {0xa0, 0xff, ZC3XX_R018_FRAMELOST}, /* Frame adjust */
3908 {}
3909};
3910static const struct usb_action pas106b_50HZ[] = {
3911 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3912 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
3913 {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */
3914 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3915 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3916 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */
3917 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3918 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
3919 {0xaa, 0x03, 0x0021}, /* 00,03,21,aa */
3920 {0xaa, 0x04, 0x000c}, /* 00,04,0c,aa */
3921 {0xaa, 0x05, 0x0002}, /* 00,05,02,aa */
3922 {0xaa, 0x07, 0x001c}, /* 00,07,1c,aa */
3923 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
3924 {}
3925};
3926static const struct usb_action pas106b_60HZ[] = {
3927 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3928 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
3929 {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */
3930 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3931 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3932 {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */
3933 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3934 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
3935 {0xaa, 0x03, 0x001c}, /* 00,03,1c,aa */
3936 {0xaa, 0x04, 0x0004}, /* 00,04,04,aa */
3937 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
3938 {0xaa, 0x07, 0x00c4}, /* 00,07,c4,aa */
3939 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
3940 {}
3941};
3942static const struct usb_action pas106b_NoFliker[] = {
3943 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3944 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
3945 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
3946 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3947 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3948 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
3949 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3950 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3951 {0xaa, 0x03, 0x0013}, /* 00,03,13,aa */
3952 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3953 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
3954 {0xaa, 0x07, 0x0030}, /* 00,07,30,aa */
3955 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
3956 {}
3957};
3958
3959/* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */
3960static const struct usb_action pas202b_Initial[] = { /* 640x480 */
3961 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3962 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3963 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */
3964 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
3965 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3966 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3967 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3968 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
3969 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3970 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3971 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3972 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3973 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3974 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,03,cc */
3975 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3976 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,03,cc */
3977 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3978 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
3979 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3980 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3981 {0xaa, 0x02, 0x0002}, /* 00,02,04,aa --> 02 */
3982 {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */
3983 {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */
3984 {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */
3985 {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */
3986 {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */
3987 {0xaa, 0x0c, 0x0006},
3988 {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */
3989 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3990 {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */
3991 {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */
3992 {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */
3993 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
3994 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3995 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3996 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3997 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3998 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3999 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
4000 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
4001 {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */
4002 {}
4003};
4004static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */
4005 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
4006 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4007 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */
4008 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
4009 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
4010 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
4011 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
4012 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4013 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
4014 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
4015 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
4016 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
4017 {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,08,cc */
4018 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,02,cc */
4019 {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */
4020 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */
4021 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
4022 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
4023 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
4024 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
4025 {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */
4026 {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */
4027 {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */
4028 {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */
4029 {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */
4030 {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */
4031 {0xaa, 0x0c, 0x0006},
4032 {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */
4033 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
4034 {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */
4035 {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */
4036 {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */
4037 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
4038 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
4039 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
4040 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
4041 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
4042 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
4043 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
4044 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
4045 {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */
4046 {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH},
4047 {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW},
4048 {}
4049};
4050static const struct usb_action pas202b_50HZ[] = {
4051 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4052 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4053 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4054 {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
4055 {0xaa, 0x21, 0x001b},
4056 {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */
4057 {0xaa, 0x04, 0x0008},
4058 {0xaa, 0x05, 0x001b},
4059 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4060 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4061 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
4062 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
4063 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4064 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
4065 {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
4066 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4067 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4068 {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */
4069 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4070 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4071 {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */
4072 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
4073 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */
4074 {0xa0, 0xeb, ZC3XX_R020_HSYNC_3}, /* 00,20,eb,cc */
4075 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4076 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4077 {}
4078};
4079static const struct usb_action pas202b_50HZScale[] = {
4080 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4081 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4082 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4083 {0xaa, 0x20, 0x0004},
4084 {0xaa, 0x21, 0x003d},
4085 {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */
4086 {0xaa, 0x04, 0x0010},
4087 {0xaa, 0x05, 0x003d},
4088 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4089 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4090 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
4091 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
4092 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4093 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
4094 {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
4095 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4096 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4097 {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */
4098 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4099 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4100 {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */
4101 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
4102 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */
4103 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4104 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4105 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4106 {}
4107};
4108static const struct usb_action pas202b_60HZ[] = {
4109 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4110 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4111 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4112 {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
4113 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
4114 {0xaa, 0x03, 0x0045}, /* 00,03,45,aa */
4115 {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
4116 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
4117 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4118 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4119 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
4120 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
4121 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4122 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
4123 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
4124 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4125 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4126 {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */
4127 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4128 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4129 {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */
4130 {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */
4131 {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */
4132 {0xa0, 0xf5, ZC3XX_R020_HSYNC_3}, /* 00,20,f5,cc */
4133 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4134 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4135 {}
4136};
4137static const struct usb_action pas202b_60HZScale[] = {
4138 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4139 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4140 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4141 {0xaa, 0x20, 0x0004},
4142 {0xaa, 0x21, 0x0008},
4143 {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */
4144 {0xaa, 0x04, 0x0010},
4145 {0xaa, 0x05, 0x0008},
4146 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4147 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4148 {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
4149 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
4150 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4151 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
4152 {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW},
4153 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4154 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4155 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
4156 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4157 {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
4158 {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */
4159 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */
4160 {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */
4161 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4162 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4163 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4164 {}
4165};
4166static const struct usb_action pas202b_NoFliker[] = {
4167 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4168 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4169 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4170 {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */
4171 {0xaa, 0x21, 0x0006},
4172 {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */
4173 {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */
4174 {0xaa, 0x05, 0x0006},
4175 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4176 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4177 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4178 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
4179 {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW},
4180 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4181 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4182 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
4183 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4184 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4185 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4186 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4187 {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */
4188 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */
4189 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4190 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4191 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4192 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4193 {}
4194};
4195static const struct usb_action pas202b_NoFlikerScale[] = {
4196 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4197 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
4198 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
4199 {0xaa, 0x20, 0x0004},
4200 {0xaa, 0x21, 0x000c},
4201 {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */
4202 {0xaa, 0x04, 0x0010},
4203 {0xaa, 0x05, 0x000c},
4204 {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */
4205 {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */
4206 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4207 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
4208 {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW},
4209 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4210 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4211 {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */
4212 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4213 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4214 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4215 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4216 {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */
4217 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */
4218 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4219 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
4220 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */
4221 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
4222 {}
4223};
4224
4225/* mt9v111 (mi0360soc) and pb0330 from vm30x.inf 0ac8:301b 07/02/13 */
4226static const struct usb_action mt9v111_1_Initial[] = { /* 640x480 */
4227 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4228 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4229 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4230 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4231 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4232 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4233 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4234 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4235 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4236 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4237 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4238 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4239 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4240 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4241 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4242 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4243 {0xdd, 0x00, 0x0200},
4244 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4245 {0xaa, 0x01, 0x0001},
4246 {0xaa, 0x06, 0x0000},
4247 {0xaa, 0x08, 0x0483},
4248 {0xaa, 0x01, 0x0004},
4249 {0xaa, 0x08, 0x0006},
4250 {0xaa, 0x02, 0x0011},
4251 {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/
4252 {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/
4253 {0xaa, 0x07, 0x3002},
4254 {0xaa, 0x20, 0x5100},
4255 {0xaa, 0x35, 0x507f},
4256 {0xaa, 0x30, 0x0005},
4257 {0xaa, 0x31, 0x0000},
4258 {0xaa, 0x58, 0x0078},
4259 {0xaa, 0x62, 0x0411},
4260 {0xaa, 0x2b, 0x007f},
4261 {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/
4262 {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/
4263 {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/
4264 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4265 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
4266 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4267 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4268 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4269 {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/
4270 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4271 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4272 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4273 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4274 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4275 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4276 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4277 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4278 {}
4279};
4280static const struct usb_action mt9v111_1_InitialScale[] = { /* 320x240 */
4281 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4282 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4283 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4284 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4285 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4286 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4287 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4288 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4289 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4290 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4291 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4292 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4293 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4294 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4295 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4296 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4297 {0xdd, 0x00, 0x0200},
4298 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4299 {0xaa, 0x01, 0x0001},
4300 {0xaa, 0x06, 0x0000},
4301 {0xaa, 0x08, 0x0483},
4302 {0xaa, 0x01, 0x0004},
4303 {0xaa, 0x08, 0x0006},
4304 {0xaa, 0x02, 0x0011},
4305 {0xaa, 0x03, 0x01e7},
4306 {0xaa, 0x04, 0x0287},
4307 {0xaa, 0x07, 0x3002},
4308 {0xaa, 0x20, 0x5100},
4309 {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/
4310 {0xaa, 0x30, 0x0005},
4311 {0xaa, 0x31, 0x0000},
4312 {0xaa, 0x58, 0x0078},
4313 {0xaa, 0x62, 0x0411},
4314 {0xaa, 0x2b, 0x007f}, /*jfm: was 28*/
4315 {0xaa, 0x2c, 0x007f}, /*jfm: was 30*/
4316 {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/
4317 {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/
4318 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4319 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
4320 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4321 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4322 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4323 {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/
4324 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4325 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4326 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4327 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4328 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4329 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4330 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4331 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4332 {}
4333};
4334static const struct usb_action mt9v111_1_AE50HZ[] = {
4335 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4336 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4337 {0xbb, 0x00, 0x0562},
4338 {0xbb, 0x01, 0x09aa},
4339 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4340 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
4341 {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
4342 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4343 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4344 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
4345 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4346 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4347 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4348 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4349 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
4350 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
4351 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
4352 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4353 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4354 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4355 {}
4356};
4357static const struct usb_action mt9v111_1_AE50HZScale[] = {
4358 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4359 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4360 {0xbb, 0x00, 0x0509},
4361 {0xbb, 0x01, 0x0934},
4362 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4363 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4364 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4365 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4366 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4367 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4368 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4369 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4370 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4371 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4372 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4373 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4374 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4375 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4376 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4377 {}
4378};
4379static const struct usb_action mt9v111_1_AE60HZ[] = {
4380 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4381 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4382 {0xaa, 0x05, 0x003d},
4383 {0xaa, 0x09, 0x016e},
4384 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4385 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4386 {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW},
4387 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4388 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4389 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
4390 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4391 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4392 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4393 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4394 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
4395 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
4396 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
4397 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4398 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4399 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4400 {}
4401};
4402static const struct usb_action mt9v111_1_AE60HZScale[] = {
4403 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4404 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4405 {0xbb, 0x00, 0x0509},
4406 {0xbb, 0x01, 0x0983},
4407 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4408 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4409 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4410 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4411 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4412 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4413 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4414 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4415 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4416 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4417 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4418 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4419 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4420 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4421 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4422 {}
4423};
4424static const struct usb_action mt9v111_1_AENoFliker[] = {
4425 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4426 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4427 {0xbb, 0x00, 0x0509},
4428 {0xbb, 0x01, 0x0960},
4429 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4430 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4431 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4432 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4433 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4434 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4435 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4436 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4437 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4438 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4439 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
4440 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
4441 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4442 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4443 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4444 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4445 {}
4446};
4447static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
4448 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4449 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4450 {0xbb, 0x00, 0x0534},
4451 {0xbb, 0x02, 0x0960},
4452 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4453 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4454 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4455 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4456 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4457 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4458 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4459 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4460 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4461 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4462 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4463 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4464 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4465 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4466 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4467 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4468 {}
4469};
4470/* from usbvm303.inf 0ac8:303b 07/03/25 (3 - tas5130c) */
4471static const struct usb_action mt9v111_3_Initial[] = {
4472 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4473 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4474 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4475 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4476 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4477 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4478 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4479 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4480 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4481 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4482 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4483 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4484 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4485 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4486 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4487 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4488 {0xdd, 0x00, 0x0200},
4489 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4490 {0xaa, 0x01, 0x0001}, /* select IFP/SOC registers */
4491 {0xaa, 0x06, 0x0000}, /* operating mode control */
4492 {0xaa, 0x08, 0x0483}, /* output format control */
4493 /* H red first, V red or blue first,
4494 * raw Bayer, auto flicker */
4495 {0xaa, 0x01, 0x0004}, /* select sensor core registers */
4496 {0xaa, 0x08, 0x0006}, /* row start */
4497 {0xaa, 0x02, 0x0011}, /* column start */
4498 {0xaa, 0x03, 0x01e5}, /* window height - 1 */
4499 {0xaa, 0x04, 0x0285}, /* window width - 1 */
4500 {0xaa, 0x07, 0x3002}, /* output control */
4501 {0xaa, 0x20, 0x1100}, /* read mode: bits 8 & 12 (?) */
4502 {0xaa, 0x35, 0x007f}, /* global gain */
4503 {0xaa, 0x30, 0x0005},
4504 {0xaa, 0x31, 0x0000},
4505 {0xaa, 0x58, 0x0078},
4506 {0xaa, 0x62, 0x0411},
4507 {0xaa, 0x2b, 0x007f}, /* green1 gain */
4508 {0xaa, 0x2c, 0x007f}, /* blue gain */
4509 {0xaa, 0x2d, 0x007f}, /* red gain */
4510 {0xaa, 0x2e, 0x007f}, /* green2 gain */
4511 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4512 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4513 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4514 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4515 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4516 {0xa0, 0x00, 0x01ad},
4517 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4518 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4519 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4520 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4521 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4522 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
4523 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4524 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4525 {}
4526};
4527static const struct usb_action mt9v111_3_InitialScale[] = {
4528 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4529 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4530 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4531 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4532 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4533 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4534 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4535 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4536 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4537 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4538 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4539 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4540 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4541 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4542 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4543 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4544 {0xdd, 0x00, 0x0200},
4545 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4546 {0xaa, 0x01, 0x0001},
4547 {0xaa, 0x06, 0x0000},
4548 {0xaa, 0x08, 0x0483},
4549 {0xaa, 0x01, 0x0004},
4550 {0xaa, 0x08, 0x0006},
4551 {0xaa, 0x02, 0x0011},
4552 {0xaa, 0x03, 0x01e7},
4553 {0xaa, 0x04, 0x0287},
4554 {0xaa, 0x07, 0x3002},
4555 {0xaa, 0x20, 0x1100},
4556 {0xaa, 0x35, 0x007f},
4557 {0xaa, 0x30, 0x0005},
4558 {0xaa, 0x31, 0x0000},
4559 {0xaa, 0x58, 0x0078},
4560 {0xaa, 0x62, 0x0411},
4561 {0xaa, 0x2b, 0x007f},
4562 {0xaa, 0x2c, 0x007f},
4563 {0xaa, 0x2d, 0x007f},
4564 {0xaa, 0x2e, 0x007f},
4565 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4566 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4567 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4568 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4569 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4570 {0xa0, 0x00, 0x01ad},
4571 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4572 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4573 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4574 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4575 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4576 {0xa0, 0x80, ZC3XX_R18D_YTARGET},
4577 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4578 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4579 {}
4580};
4581static const struct usb_action mt9v111_3_AE50HZ[] = {
4582 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4583 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4584 {0xaa, 0x05, 0x0009}, /* horizontal blanking */
4585 {0xaa, 0x09, 0x01ce}, /* shutter width */
4586 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4587 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4588 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4589 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4590 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4591 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4592 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4593 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4594 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4595 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4596 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4597 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4598 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4599 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4600 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4601 {}
4602};
4603static const struct usb_action mt9v111_3_AE50HZScale[] = {
4604 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4605 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4606 {0xaa, 0x05, 0x0009},
4607 {0xaa, 0x09, 0x01ce},
4608 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4609 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4610 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
4611 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4612 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4613 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
4614 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4615 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4616 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4617 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4618 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4619 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4620 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4621 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4622 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4623 {}
4624};
4625static const struct usb_action mt9v111_3_AE60HZ[] = {
4626 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4627 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4628 {0xaa, 0x05, 0x0009},
4629 {0xaa, 0x09, 0x0083},
4630 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4631 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4632 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4633 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4634 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4635 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4636 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4637 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4638 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4639 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4640 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4641 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4642 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4643 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4644 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4645 {}
4646};
4647static const struct usb_action mt9v111_3_AE60HZScale[] = {
4648 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4649 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4650 {0xaa, 0x05, 0x0009},
4651 {0xaa, 0x09, 0x0083},
4652 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4653 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4654 {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
4655 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4656 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4657 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
4658 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4659 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4660 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4661 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4662 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4663 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4664 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4665 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4666 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4667 {}
4668};
4669static const struct usb_action mt9v111_3_AENoFliker[] = {
4670 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4671 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4672 {0xaa, 0x05, 0x0034},
4673 {0xaa, 0x09, 0x0260},
4674 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4675 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4676 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4677 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4678 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4679 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4680 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4681 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4682 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4683 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4684 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4685 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4686 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4687 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4688 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4689 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4690 {}
4691};
4692static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
4693 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4694 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4695 {0xaa, 0x05, 0x0034},
4696 {0xaa, 0x09, 0x0260},
4697 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4698 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4699 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4700 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4701 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4702 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
4703 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4704 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4705 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4706 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4707 {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
4708 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4709 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4710 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4711 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4712 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4713 {}
4714};
4715
4716static const struct usb_action pb0330_Initial[] = { /* 640x480 */
4717 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4718 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4719 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4720 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4721 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4722 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4723 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4724 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4725 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4726 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4727 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4728 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4729 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4730 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4731 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4732 {0xdd, 0x00, 0x0200},
4733 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4734 {0xaa, 0x01, 0x0006},
4735 {0xaa, 0x02, 0x0011},
4736 {0xaa, 0x03, 0x01e5}, /*jfm: was 1e7*/
4737 {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/
4738 {0xaa, 0x06, 0x0003},
4739 {0xaa, 0x07, 0x3002},
4740 {0xaa, 0x20, 0x1100},
4741 {0xaa, 0x2f, 0xf7b0},
4742 {0xaa, 0x30, 0x0005},
4743 {0xaa, 0x31, 0x0000},
4744 {0xaa, 0x34, 0x0100},
4745 {0xaa, 0x35, 0x0060},
4746 {0xaa, 0x3d, 0x068f},
4747 {0xaa, 0x40, 0x01e0},
4748 {0xaa, 0x58, 0x0078},
4749 {0xaa, 0x62, 0x0411},
4750 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4751 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4752 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4753 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4754 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4755 {0xa0, 0x09, 0x01ad}, /*jfm: was 00 */
4756 {0xa0, 0x15, 0x01ae},
4757 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4758 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4759 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4760 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4761 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4762 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/
4763 {}
4764};
4765static const struct usb_action pb0330_InitialScale[] = { /* 320x240 */
4766 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4767 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4768 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4769 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4770 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4771 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4772 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4773 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4774 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4775 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4776 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4777 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4778 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4779 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4780 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4781 {0xdd, 0x00, 0x0200},
4782 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4783 {0xaa, 0x01, 0x0006},
4784 {0xaa, 0x02, 0x0011},
4785 {0xaa, 0x03, 0x01e7},
4786 {0xaa, 0x04, 0x0287},
4787 {0xaa, 0x06, 0x0003},
4788 {0xaa, 0x07, 0x3002},
4789 {0xaa, 0x20, 0x1100},
4790 {0xaa, 0x2f, 0xf7b0},
4791 {0xaa, 0x30, 0x0005},
4792 {0xaa, 0x31, 0x0000},
4793 {0xaa, 0x34, 0x0100},
4794 {0xaa, 0x35, 0x0060},
4795 {0xaa, 0x3d, 0x068f},
4796 {0xaa, 0x40, 0x01e0},
4797 {0xaa, 0x58, 0x0078},
4798 {0xaa, 0x62, 0x0411},
4799 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4800 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4801 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4802 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4803 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4804 {0xa0, 0x09, 0x01ad},
4805 {0xa0, 0x15, 0x01ae},
4806 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4807 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4808 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4809 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4810 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4811 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/
4812 {}
4813};
4814static const struct usb_action pb0330_50HZ[] = {
4815 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4816 {0xbb, 0x00, 0x055c},
4817 {0xbb, 0x01, 0x09aa},
4818 {0xbb, 0x00, 0x1001},
4819 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4820 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4821 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4822 {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW},
4823 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4824 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4825 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
4826 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4827 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4828 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4829 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4830 {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0},
4831 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
4832 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
4833 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4834 {}
4835};
4836static const struct usb_action pb0330_50HZScale[] = {
4837 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4838 {0xbb, 0x00, 0x0566},
4839 {0xbb, 0x02, 0x09b2},
4840 {0xbb, 0x00, 0x1002},
4841 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4842 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4843 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4844 {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
4845 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4846 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4847 {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
4848 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4849 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4850 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4851 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4852 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4853 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
4854 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
4855 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4856 {}
4857};
4858static const struct usb_action pb0330_60HZ[] = {
4859 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4860 {0xbb, 0x00, 0x0535},
4861 {0xbb, 0x01, 0x0974},
4862 {0xbb, 0x00, 0x1001},
4863 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4864 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4865 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4866 {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
4867 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4868 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4869 {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW},
4870 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4871 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4872 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4873 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4874 {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
4875 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
4876 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4877 {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
4878 {}
4879};
4880static const struct usb_action pb0330_60HZScale[] = {
4881 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4882 {0xbb, 0x00, 0x0535},
4883 {0xbb, 0x02, 0x096c},
4884 {0xbb, 0x00, 0x1002},
4885 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4886 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4887 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4888 {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW},
4889 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4890 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4891 {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW},
4892 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4893 {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
4894 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4895 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
4896 {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
4897 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
4898 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4899 {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
4900 {}
4901};
4902static const struct usb_action pb0330_NoFliker[] = {
4903 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4904 {0xbb, 0x00, 0x0509},
4905 {0xbb, 0x02, 0x0940},
4906 {0xbb, 0x00, 0x1002},
4907 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4908 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4909 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4910 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4911 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4912 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4913 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
4914 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4915 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4916 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4917 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4918 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
4919 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
4920 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4921 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4922 {}
4923};
4924static const struct usb_action pb0330_NoFlikerScale[] = {
4925 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4926 {0xbb, 0x00, 0x0535},
4927 {0xbb, 0x01, 0x0980},
4928 {0xbb, 0x00, 0x1001},
4929 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4930 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4931 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4932 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
4933 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4934 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4935 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
4936 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4937 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4938 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
4939 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
4940 {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
4941 {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
4942 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
4943 {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
4944 {}
4945};
4946
4947/* from oem9.inf */
4948static const struct usb_action po2030_Initial[] = { /* 640x480 */
4949 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
4950 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
4951 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
4952 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
4953 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
4954 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
4955 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
4956 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
4957 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
4958 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
4959 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
4960 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
4961 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
4962 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
4963 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
4964 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
4965 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
4966 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
4967 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
4968 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
4969 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
4970 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
4971 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
4972 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
4973 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
4974 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
4975 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
4976 {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */
4977 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
4978 {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */
4979 {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */
4980 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
4981 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
4982 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
4983 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
4984 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
4985 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
4986 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
4987 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
4988 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
4989 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
4990 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
4991 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
4992 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
4993 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
4994 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
4995 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
4996 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
4997 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
4998 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
4999 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
5000 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
5001 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
5002 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
5003 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
5004 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
5005 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
5006 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
5007 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
5008 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
5009 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
5010 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
5011 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
5012 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
5013 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
5014 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
5015 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5016 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5017 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5018 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5019 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5020 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5021 {}
5022};
5023
5024/* from oem9.inf */
5025static const struct usb_action po2030_InitialScale[] = { /* 320x240 */
5026 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
5027 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
5028 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
5029 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
5030 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
5031 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
5032 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
5033 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
5034 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
5035 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
5036 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
5037 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
5038 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
5039 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
5040 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
5041 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
5042 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
5043 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
5044 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
5045 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5046 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5047 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
5048 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
5049 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
5050 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
5051 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
5052 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
5053 {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */
5054 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
5055 {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */
5056 {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */
5057 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
5058 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
5059 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
5060 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
5061 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
5062 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
5063 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
5064 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
5065 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
5066 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
5067 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
5068 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
5069 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
5070 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
5071 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
5072 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
5073 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
5074 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
5075 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
5076 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
5077 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
5078 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
5079 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
5080 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
5081 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
5082 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
5083 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
5084 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
5085 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
5086 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
5087 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
5088 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
5089 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
5090 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
5091 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
5092 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5093 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5094 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5095 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5096 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5097 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5098 {}
5099};
5100
5101static const struct usb_action po2030_50HZ[] = {
5102 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5103 {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
5104 {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
5105 {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */
5106 {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */
5107 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */
5108 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
5109 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5110 {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */
5111 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */
5112 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5113 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5114 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5115 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5116 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5117 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5118 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5119 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5120 {}
5121};
5122
5123static const struct usb_action po2030_60HZ[] = {
5124 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5125 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5126 {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
5127 {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */
5128 {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */
5129 {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */
5130 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
5131 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5132 {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */
5133 {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */
5134 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5135 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5136 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5137 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5138 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5139 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5140 /* win: 01,8d,80 */
5141 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5142 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5143 {}
5144};
5145
5146static const struct usb_action po2030_NoFliker[] = {
5147 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
5148 {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
5149 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5150 {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */
5151 {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */
5152 {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */
5153 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
5154 {}
5155};
5156
5157static const struct usb_action tas5130c_InitialScale[] = { /* 320x240 */
5158 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5159 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
5160 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5161 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5162 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5163 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5164 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5165 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5166 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5167 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5168 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5169 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5170 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5171
5172 {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW},
5173 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5174 {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW},
5175 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5176 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
5177 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5178 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
5179 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5180 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
5181 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5182 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5183 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
5184 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
5185 {0xa0, 0x00, 0x01ad},
5186 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5187 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5188 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5189 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5190 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5191 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5192 {}
5193};
5194static const struct usb_action tas5130c_Initial[] = { /* 640x480 */
5195 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5196 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
5197 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},
5198 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5199 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5200 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5201 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5202 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5203 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5204 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5205 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5206 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5207 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5208 {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW},
5209 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5210 {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW},
5211 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5212 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
5213 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5214 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
5215 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5216 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
5217 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5218 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5219 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
5220 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
5221 {0xa0, 0x00, 0x01ad},
5222 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5223 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5224 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5225 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5226 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5227 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5228 {}
5229};
5230static const struct usb_action tas5130c_50HZ[] = {
5231 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5232 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5233 {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
5234 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5235 {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */
5236 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5237 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
5238 {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
5239 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5240 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5241 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */
5242 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5243 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5244 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5245 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5246 {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */
5247 {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */
5248 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
5249 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5250 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5251 {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW},
5252 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5253 {}
5254};
5255static const struct usb_action tas5130c_50HZScale[] = {
5256 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5257 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5258 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5259 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5260 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5261 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5262 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
5263 {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW},
5264 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5265 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5266 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5267 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5268 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5269 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5270 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5271 {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */
5272 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */
5273 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
5274 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5275 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5276 {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW},
5277 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5278 {}
5279};
5280static const struct usb_action tas5130c_60HZ[] = {
5281 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5282 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5283 {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
5284 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5285 {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */
5286 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5287 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
5288 {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW},
5289 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5290 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5291 {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */
5292 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5293 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5294 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5295 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5296 {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */
5297 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5298 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5299 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5300 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5301 {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW},
5302 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5303 {}
5304};
5305static const struct usb_action tas5130c_60HZScale[] = {
5306 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5307 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5308 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5309 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5310 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5311 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5312 {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID},
5313 {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW},
5314 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5315 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5316 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5317 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5318 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5319 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5320 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5321 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
5322 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5323 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5324 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5325 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5326 {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW},
5327 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5328 {}
5329};
5330static const struct usb_action tas5130c_NoFliker[] = {
5331 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5332 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5333 {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
5334 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5335 {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */
5336 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5337 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
5338 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
5339 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5340 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5341 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
5342 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5343 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5344 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5345 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5346 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5347 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5348 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5349 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5350 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5351 {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
5352 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5353 {}
5354};
5355
5356static const struct usb_action tas5130c_NoFlikerScale[] = {
5357 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5358 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5359 {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
5360 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5361 {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */
5362 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5363 {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID},
5364 {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
5365 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5366 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5367 {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
5368 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5369 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5370 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5371 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5372 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5373 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5374 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5375 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5376 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5377 {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
5378 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5379 {}
5380};
5381
5382static const struct usb_action gc0303_InitialScale[] = {
5383 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
5384 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
5385 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
5386 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc,
5387 * 0<->10 */
5388 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
5389 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
5390 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
5391 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
5392 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5393 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
5394 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
5395 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
5396 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
5397 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
5398 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
5399 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
5400 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc,
5401 * 6<->8 */
5402 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc,
5403 * 6<->8 */
5404 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
5405 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5406 {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
5407 {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
5408 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
5409 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
5410 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
5411/*?? {0xaa, 0x01, 0x0000}, */
5412 {0xaa, 0x01, 0x0000},
5413 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
5414 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
5415 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
5416 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
5417 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
5418 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
5419 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
5420 {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
5421 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
5422 {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
5423 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
5424 {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
5425 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
5426 {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
5427/*?? {0xa0, 0x00, 0x0039},
5428 {0xa1, 0x01, 0x0037}, */
5429 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
5430 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */
5431 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
5432 {0xaa, 0x19, 0x0088}, /* 00,19,86,aa, */
5433 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
5434 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
5435 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
5436 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
5437 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
5438 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
5439 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
5440 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
5441 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
5442 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
5443 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
5444 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
5445 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
5446 {}
5447};
5448
5449static const struct usb_action gc0303_Initial[] = {
5450 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
5451 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
5452 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
5453 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc, */
5454 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
5455 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
5456 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
5457 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
5458 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5459 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
5460 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
5461 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
5462 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
5463 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
5464 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
5465 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
5466 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc,
5467 * 8<->6 */
5468 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc,
5469 * 8<->6 */
5470 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
5471 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5472 {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
5473 {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
5474 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
5475 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
5476 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
5477/*?? {0xaa, 0x01, 0x0000}, */
5478 {0xaa, 0x01, 0x0000},
5479 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
5480 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
5481 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
5482 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
5483 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
5484 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
5485 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
5486 {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
5487 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
5488 {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
5489 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
5490 {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
5491 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
5492 {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
5493/*?? {0xa0, 0x00, 0x0039},
5494 {0xa1, 0x01, 0x0037}, */
5495 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
5496 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */
5497 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
5498 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */
5499 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
5500 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
5501 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
5502 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
5503 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
5504 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
5505 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
5506 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
5507 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
5508 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
5509 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
5510 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
5511 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
5512 {}
5513};
5514static const struct usb_action gc0303_50HZScale[] = {
5515 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5516 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
5517 {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */
5518 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5519 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
5520 {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
5521 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5522 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5523 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */
5524 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5525 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5526 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
5527 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
5528 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5529 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5530 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5531 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5532 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5533 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5534 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
5535 {}
5536};
5537
5538static const struct usb_action gc0303_50HZ[] = {
5539 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5540 {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */
5541 {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */
5542 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5543 {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
5544 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
5545 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5546 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5547 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc, */
5548 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5549 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5550 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
5551 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
5552 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5553 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5554 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5555 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5556 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5557 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5558 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
5559 {}
5560};
5561
5562static const struct usb_action gc0303_60HZScale[] = {
5563 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5564 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
5565 {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */
5566 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5567 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
5568 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
5569 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5570 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5571 {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3b,cc, */
5572 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5573 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5574 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
5575 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
5576 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5577 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5578 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5579 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5580 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5581 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5582 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
5583 {}
5584};
5585
5586static const struct usb_action gc0303_60HZ[] = {
5587 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5588 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
5589 {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */
5590 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5591 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */
5592 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */
5593 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,5,00,cc, */
5594 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,6,00,cc, */
5595 {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,7,76,cc, */
5596 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,c,0e,cc, */
5597 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,f,15,cc, */
5598 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,9,10,cc, */
5599 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,a,24,cc, */
5600 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,d,62,cc, */
5601 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,e,90,cc, */
5602 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,f,c8,cc, */
5603 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */
5604 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */
5605 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
5606 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,d,78,cc */
5607 {}
5608};
5609
5610static const struct usb_action gc0303_NoFlikerScale[] = {
5611 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
5612 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5613 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
5614 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
5615 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */
5616 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
5617 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
5618 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5619 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5620 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
5621 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5622 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5623 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5624 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5625 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5626 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5627 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5628 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
5629 {}
5630};
5631
5632static const struct usb_action gc0303_NoFliker[] = {
5633 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
5634 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
5635 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
5636 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
5637 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
5638 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc, */
5639 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc, */
5640 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
5641 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
5642 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
5643 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
5644 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
5645 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
5646 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
5647 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
5648 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
5649 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
5650 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
5651 {}
5652};
5653
5654static u8 reg_r_i(struct gspca_dev *gspca_dev,
5655 u16 index)
5656{
5657 int ret;
5658
5659 if (gspca_dev->usb_err < 0)
5660 return 0;
5661 ret = usb_control_msg(gspca_dev->dev,
5662 usb_rcvctrlpipe(gspca_dev->dev, 0),
5663 0xa1,
5664 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5665 0x01, /* value */
5666 index, gspca_dev->usb_buf, 1,
5667 500);
5668 if (ret < 0) {
5669 err("reg_r_i err %d", ret);
5670 gspca_dev->usb_err = ret;
5671 return 0;
5672 }
5673 return gspca_dev->usb_buf[0];
5674}
5675
5676static u8 reg_r(struct gspca_dev *gspca_dev,
5677 u16 index)
5678{
5679 u8 ret;
5680
5681 ret = reg_r_i(gspca_dev, index);
5682 PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret);
5683 return ret;
5684}
5685
5686static void reg_w_i(struct gspca_dev *gspca_dev,
5687 u8 value,
5688 u16 index)
5689{
5690 int ret;
5691
5692 if (gspca_dev->usb_err < 0)
5693 return;
5694 ret = usb_control_msg(gspca_dev->dev,
5695 usb_sndctrlpipe(gspca_dev->dev, 0),
5696 0xa0,
5697 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5698 value, index, NULL, 0,
5699 500);
5700 if (ret < 0) {
5701 err("reg_w_i err %d", ret);
5702 gspca_dev->usb_err = ret;
5703 }
5704}
5705
5706static void reg_w(struct gspca_dev *gspca_dev,
5707 u8 value,
5708 u16 index)
5709{
5710 PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value);
5711 reg_w_i(gspca_dev, value, index);
5712}
5713
5714static u16 i2c_read(struct gspca_dev *gspca_dev,
5715 u8 reg)
5716{
5717 u8 retbyte;
5718 u16 retval;
5719
5720 if (gspca_dev->usb_err < 0)
5721 return 0;
5722 reg_w_i(gspca_dev, reg, 0x0092);
5723 reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */
5724 msleep(20);
5725 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
5726 if (retbyte != 0x00)
5727 err("i2c_r status error %02x", retbyte);
5728 retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */
5729 retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */
5730 PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)",
5731 reg, retval, retbyte);
5732 return retval;
5733}
5734
5735static u8 i2c_write(struct gspca_dev *gspca_dev,
5736 u8 reg,
5737 u8 valL,
5738 u8 valH)
5739{
5740 u8 retbyte;
5741
5742 if (gspca_dev->usb_err < 0)
5743 return 0;
5744 reg_w_i(gspca_dev, reg, 0x92);
5745 reg_w_i(gspca_dev, valL, 0x93);
5746 reg_w_i(gspca_dev, valH, 0x94);
5747 reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */
5748 msleep(1);
5749 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
5750 if (retbyte != 0x00)
5751 err("i2c_w status error %02x", retbyte);
5752 PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)",
5753 reg, valH, valL, retbyte);
5754 return retbyte;
5755}
5756
5757static void usb_exchange(struct gspca_dev *gspca_dev,
5758 const struct usb_action *action)
5759{
5760 while (action->req) {
5761 switch (action->req) {
5762 case 0xa0: /* write register */
5763 reg_w(gspca_dev, action->val, action->idx);
5764 break;
5765 case 0xa1: /* read status */
5766 reg_r(gspca_dev, action->idx);
5767 break;
5768 case 0xaa:
5769 i2c_write(gspca_dev,
5770 action->val, /* reg */
5771 action->idx & 0xff, /* valL */
5772 action->idx >> 8); /* valH */
5773 break;
5774 case 0xbb:
5775 i2c_write(gspca_dev,
5776 action->idx >> 8, /* reg */
5777 action->idx & 0xff, /* valL */
5778 action->val); /* valH */
5779 break;
5780 default:
5781/* case 0xdd: * delay */
5782 msleep(action->idx);
5783 break;
5784 }
5785 action++;
5786 msleep(1);
5787 }
5788}
5789
5790static void setmatrix(struct gspca_dev *gspca_dev)
5791{
5792 struct sd *sd = (struct sd *) gspca_dev;
5793 int i;
5794 const u8 *matrix;
5795 static const u8 adcm2700_matrix[9] =
5796/* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */
5797/*ms-win*/
5798 {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74};
5799 static const u8 gc0305_matrix[9] =
5800 {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
5801 static const u8 ov7620_matrix[9] =
5802 {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
5803 static const u8 pas202b_matrix[9] =
5804 {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f};
5805 static const u8 po2030_matrix[9] =
5806 {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
5807 static const u8 tas5130c_matrix[9] =
5808 {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
5809 static const u8 gc0303_matrix[9] =
5810 {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
5811 static const u8 *matrix_tb[SENSOR_MAX] = {
5812 [SENSOR_ADCM2700] = adcm2700_matrix,
5813 [SENSOR_CS2102] = ov7620_matrix,
5814 [SENSOR_CS2102K] = NULL,
5815 [SENSOR_GC0303] = gc0303_matrix,
5816 [SENSOR_GC0305] = gc0305_matrix,
5817 [SENSOR_HDCS2020] = NULL,
5818 [SENSOR_HV7131B] = NULL,
5819 [SENSOR_HV7131R] = po2030_matrix,
5820 [SENSOR_ICM105A] = po2030_matrix,
5821 [SENSOR_MC501CB] = NULL,
5822 [SENSOR_MT9V111_1] = gc0305_matrix,
5823 [SENSOR_MT9V111_3] = gc0305_matrix,
5824 [SENSOR_OV7620] = ov7620_matrix,
5825 [SENSOR_OV7630C] = NULL,
5826 [SENSOR_PAS106] = NULL,
5827 [SENSOR_PAS202B] = pas202b_matrix,
5828 [SENSOR_PB0330] = gc0305_matrix,
5829 [SENSOR_PO2030] = po2030_matrix,
5830 [SENSOR_TAS5130C] = tas5130c_matrix,
5831 };
5832
5833 matrix = matrix_tb[sd->sensor];
5834 if (matrix == NULL)
5835 return; /* matrix already loaded */
5836 for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
5837 reg_w(gspca_dev, matrix[i], 0x010a + i);
5838}
5839
5840static void setsharpness(struct gspca_dev *gspca_dev)
5841{
5842 struct sd *sd = (struct sd *) gspca_dev;
5843 int sharpness;
5844 static const u8 sharpness_tb[][2] = {
5845 {0x02, 0x03},
5846 {0x04, 0x07},
5847 {0x08, 0x0f},
5848 {0x10, 0x1e}
5849 };
5850
5851 sharpness = sd->ctrls[SHARPNESS].val;
5852 reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6);
5853 reg_r(gspca_dev, 0x01c8);
5854 reg_r(gspca_dev, 0x01c9);
5855 reg_r(gspca_dev, 0x01ca);
5856 reg_w(gspca_dev, sharpness_tb[sharpness][1], 0x01cb);
5857}
5858
5859static void setcontrast(struct gspca_dev *gspca_dev)
5860{
5861 struct sd *sd = (struct sd *) gspca_dev;
5862 const u8 *Tgamma;
5863 int g, i, brightness, contrast, adj, gp1, gp2;
5864 u8 gr[16];
5865 static const u8 delta_b[16] = /* delta for brightness */
5866 {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
5867 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18};
5868 static const u8 delta_c[16] = /* delta for contrast */
5869 {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06,
5870 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02};
5871 static const u8 gamma_tb[6][16] = {
5872 {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
5873 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff},
5874 {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
5875 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff},
5876 {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
5877 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff},
5878 {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
5879 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff},
5880 {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
5881 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff},
5882 {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
5883 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
5884 };
5885
5886 Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1];
5887
5888 contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */
5889 brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */
5890 adj = 0;
5891 gp1 = gp2 = 0;
5892 for (i = 0; i < 16; i++) {
5893 g = Tgamma[i] + delta_b[i] * brightness / 256
5894 - delta_c[i] * contrast / 256 - adj / 2;
5895 if (g > 0xff)
5896 g = 0xff;
5897 else if (g < 0)
5898 g = 0;
5899 reg_w(gspca_dev, g, 0x0120 + i); /* gamma */
5900 if (contrast > 0)
5901 adj--;
5902 else if (contrast < 0)
5903 adj++;
5904 if (i > 1)
5905 gr[i - 1] = (g - gp2) / 2;
5906 else if (i != 0)
5907 gr[0] = gp1 == 0 ? 0 : (g - gp1);
5908 gp2 = gp1;
5909 gp1 = g;
5910 }
5911 gr[15] = (0xff - gp2) / 2;
5912 for (i = 0; i < 16; i++)
5913 reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */
5914}
5915
5916static void getexposure(struct gspca_dev *gspca_dev)
5917{
5918 struct sd *sd = (struct sd *) gspca_dev;
5919
5920 sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9)
5921 | (i2c_read(gspca_dev, 0x26) << 1)
5922 | (i2c_read(gspca_dev, 0x27) >> 7);
5923}
5924
5925static void setexposure(struct gspca_dev *gspca_dev)
5926{
5927 struct sd *sd = (struct sd *) gspca_dev;
5928 int val;
5929
5930 val = sd->ctrls[EXPOSURE].val;
5931 i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
5932 i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
5933 i2c_write(gspca_dev, 0x27, val << 7, 0x00);
5934}
5935
5936static void setquality(struct gspca_dev *gspca_dev)
5937{
5938 struct sd *sd = (struct sd *) gspca_dev;
5939 u8 frxt;
5940
5941 switch (sd->sensor) {
5942 case SENSOR_ADCM2700:
5943 case SENSOR_GC0305:
5944 case SENSOR_HV7131B:
5945 case SENSOR_HV7131R:
5946 case SENSOR_OV7620:
5947 case SENSOR_PAS202B:
5948 case SENSOR_PO2030:
5949 return;
5950 }
5951/*fixme: is it really 0008 0007 0018 for all other sensors? */
5952 reg_w(gspca_dev, QUANT_VAL, 0x0008);
5953 frxt = 0x30;
5954 reg_w(gspca_dev, frxt, 0x0007);
5955#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2
5956 frxt = 0xff;
5957#elif QUANT_VAL == 3
5958 frxt = 0xf0;
5959#elif QUANT_VAL == 4
5960 frxt = 0xe0;
5961#else
5962 frxt = 0x20;
5963#endif
5964 reg_w(gspca_dev, frxt, 0x0018);
5965}
5966
5967/* Matches the sensor's internal frame rate to the lighting frequency.
5968 * Valid frequencies are:
5969 * 50Hz, for European and Asian lighting (default)
5970 * 60Hz, for American lighting
5971 * 0 = No Fliker (for outdoore usage)
5972 */
5973static void setlightfreq(struct gspca_dev *gspca_dev)
5974{
5975 struct sd *sd = (struct sd *) gspca_dev;
5976 int i, mode;
5977 const struct usb_action *zc3_freq;
5978 static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
5979 [SENSOR_ADCM2700] =
5980 {adcm2700_NoFliker, adcm2700_NoFliker,
5981 adcm2700_50HZ, adcm2700_50HZ,
5982 adcm2700_60HZ, adcm2700_60HZ},
5983 [SENSOR_CS2102] =
5984 {cs2102_NoFliker, cs2102_NoFlikerScale,
5985 cs2102_50HZ, cs2102_50HZScale,
5986 cs2102_60HZ, cs2102_60HZScale},
5987 [SENSOR_CS2102K] =
5988 {cs2102_NoFliker, cs2102_NoFlikerScale,
5989 NULL, NULL, /* currently disabled */
5990 NULL, NULL},
5991 [SENSOR_GC0303] =
5992 {gc0303_NoFliker, gc0303_NoFlikerScale,
5993 gc0303_50HZ, gc0303_50HZScale,
5994 gc0303_60HZ, gc0303_60HZScale},
5995 [SENSOR_GC0305] =
5996 {gc0305_NoFliker, gc0305_NoFliker,
5997 gc0305_50HZ, gc0305_50HZ,
5998 gc0305_60HZ, gc0305_60HZ},
5999 [SENSOR_HDCS2020] =
6000 {hdcs2020_NoFliker, hdcs2020_NoFliker,
6001 hdcs2020_50HZ, hdcs2020_50HZ,
6002 hdcs2020_60HZ, hdcs2020_60HZ},
6003 [SENSOR_HV7131B] =
6004 {hv7131b_NoFliker, hv7131b_NoFlikerScale,
6005 hv7131b_50HZ, hv7131b_50HZScale,
6006 hv7131b_60HZ, hv7131b_60HZScale},
6007 [SENSOR_HV7131R] =
6008 {hv7131r_NoFliker, hv7131r_NoFlikerScale,
6009 hv7131r_50HZ, hv7131r_50HZScale,
6010 hv7131r_60HZ, hv7131r_60HZScale},
6011 [SENSOR_ICM105A] =
6012 {icm105a_NoFliker, icm105a_NoFlikerScale,
6013 icm105a_50HZ, icm105a_50HZScale,
6014 icm105a_60HZ, icm105a_60HZScale},
6015 [SENSOR_MC501CB] =
6016 {mc501cb_NoFliker, mc501cb_NoFlikerScale,
6017 mc501cb_50HZ, mc501cb_50HZScale,
6018 mc501cb_60HZ, mc501cb_60HZScale},
6019 [SENSOR_MT9V111_1] =
6020 {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
6021 mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
6022 mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
6023 [SENSOR_MT9V111_3] =
6024 {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
6025 mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
6026 mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
6027 [SENSOR_OV7620] =
6028 {ov7620_NoFliker, ov7620_NoFliker,
6029 ov7620_50HZ, ov7620_50HZ,
6030 ov7620_60HZ, ov7620_60HZ},
6031 [SENSOR_OV7630C] =
6032 {NULL, NULL,
6033 NULL, NULL,
6034 NULL, NULL},
6035 [SENSOR_PAS106] =
6036 {pas106b_NoFliker, pas106b_NoFliker,
6037 pas106b_50HZ, pas106b_50HZ,
6038 pas106b_60HZ, pas106b_60HZ},
6039 [SENSOR_PAS202B] =
6040 {pas202b_NoFliker, pas202b_NoFlikerScale,
6041 pas202b_50HZ, pas202b_50HZScale,
6042 pas202b_60HZ, pas202b_60HZScale},
6043 [SENSOR_PB0330] =
6044 {pb0330_NoFliker, pb0330_NoFlikerScale,
6045 pb0330_50HZ, pb0330_50HZScale,
6046 pb0330_60HZ, pb0330_60HZScale},
6047 [SENSOR_PO2030] =
6048 {po2030_NoFliker, po2030_NoFliker,
6049 po2030_50HZ, po2030_50HZ,
6050 po2030_60HZ, po2030_60HZ},
6051 [SENSOR_TAS5130C] =
6052 {tas5130c_NoFliker, tas5130c_NoFlikerScale,
6053 tas5130c_50HZ, tas5130c_50HZScale,
6054 tas5130c_60HZ, tas5130c_60HZScale},
6055 };
6056
6057 i = sd->ctrls[LIGHTFREQ].val * 2;
6058 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
6059 if (mode)
6060 i++; /* 320x240 */
6061 zc3_freq = freq_tb[sd->sensor][i];
6062 if (zc3_freq == NULL)
6063 return;
6064 usb_exchange(gspca_dev, zc3_freq);
6065 switch (sd->sensor) {
6066 case SENSOR_GC0305:
6067 if (mode /* if 320x240 */
6068 && sd->ctrls[LIGHTFREQ].val == 1) /* and 50Hz */
6069 reg_w(gspca_dev, 0x85, 0x018d);
6070 /* win: 0x80, 0x018d */
6071 break;
6072 case SENSOR_OV7620:
6073 if (!mode) { /* if 640x480 */
6074 if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */
6075 reg_w(gspca_dev, 0x40, 0x0002);
6076 else
6077 reg_w(gspca_dev, 0x44, 0x0002);
6078 }
6079 break;
6080 case SENSOR_PAS202B:
6081 reg_w(gspca_dev, 0x00, 0x01a7);
6082 break;
6083 }
6084}
6085
6086static void setautogain(struct gspca_dev *gspca_dev)
6087{
6088 struct sd *sd = (struct sd *) gspca_dev;
6089 u8 autoval;
6090
6091 if (sd->ctrls[AUTOGAIN].val)
6092 autoval = 0x42;
6093 else
6094 autoval = 0x02;
6095 reg_w(gspca_dev, autoval, 0x0180);
6096}
6097
6098static void send_unknown(struct gspca_dev *gspca_dev, int sensor)
6099{
6100 reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */
6101 switch (sensor) {
6102 case SENSOR_PAS106:
6103 reg_w(gspca_dev, 0x03, 0x003a);
6104 reg_w(gspca_dev, 0x0c, 0x003b);
6105 reg_w(gspca_dev, 0x08, 0x0038);
6106 break;
6107 case SENSOR_ADCM2700:
6108 case SENSOR_GC0305:
6109 case SENSOR_OV7620:
6110 case SENSOR_MT9V111_1:
6111 case SENSOR_MT9V111_3:
6112 case SENSOR_PB0330:
6113 case SENSOR_PO2030:
6114 reg_w(gspca_dev, 0x0d, 0x003a);
6115 reg_w(gspca_dev, 0x02, 0x003b);
6116 reg_w(gspca_dev, 0x00, 0x0038);
6117 break;
6118 case SENSOR_HV7131R:
6119 case SENSOR_PAS202B:
6120 reg_w(gspca_dev, 0x03, 0x003b);
6121 reg_w(gspca_dev, 0x0c, 0x003a);
6122 reg_w(gspca_dev, 0x0b, 0x0039);
6123 if (sensor == SENSOR_PAS202B)
6124 reg_w(gspca_dev, 0x0b, 0x0038);
6125 break;
6126 }
6127}
6128
6129/* start probe 2 wires */
6130static void start_2wr_probe(struct gspca_dev *gspca_dev, int sensor)
6131{
6132 reg_w(gspca_dev, 0x01, 0x0000);
6133 reg_w(gspca_dev, sensor, 0x0010);
6134 reg_w(gspca_dev, 0x01, 0x0001);
6135 reg_w(gspca_dev, 0x03, 0x0012);
6136 reg_w(gspca_dev, 0x01, 0x0012);
6137/* msleep(2); */
6138}
6139
6140static int sif_probe(struct gspca_dev *gspca_dev)
6141{
6142 u16 checkword;
6143
6144 start_2wr_probe(gspca_dev, 0x0f); /* PAS106 */
6145 reg_w(gspca_dev, 0x08, 0x008d);
6146 msleep(150);
6147 checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
6148 | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
6149 PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
6150 if (checkword == 0x0007) {
6151 send_unknown(gspca_dev, SENSOR_PAS106);
6152 return 0x0f; /* PAS106 */
6153 }
6154 return -1;
6155}
6156
6157static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6158{
6159 u16 retword;
6160
6161 start_2wr_probe(gspca_dev, 0x00); /* HV7131B */
6162 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6163 retword = i2c_read(gspca_dev, 0x01);
6164 if (retword != 0)
6165 return 0x00; /* HV7131B */
6166
6167 start_2wr_probe(gspca_dev, 0x04); /* CS2102 */
6168 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6169 retword = i2c_read(gspca_dev, 0x01);
6170 if (retword != 0)
6171 return 0x04; /* CS2102 */
6172
6173 start_2wr_probe(gspca_dev, 0x06); /* OmniVision */
6174 reg_w(gspca_dev, 0x08, 0x008d);
6175 i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
6176 retword = i2c_read(gspca_dev, 0x11);
6177 if (retword != 0) {
6178 /* (should have returned 0xaa) --> Omnivision? */
6179 /* reg_r 0x10 -> 0x06 --> */
6180 goto ov_check;
6181 }
6182
6183 start_2wr_probe(gspca_dev, 0x08); /* HDCS2020 */
6184 i2c_write(gspca_dev, 0x1c, 0x00, 0x00);
6185 i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
6186 retword = i2c_read(gspca_dev, 0x15);
6187 if (retword != 0)
6188 return 0x08; /* HDCS2020 */
6189
6190 start_2wr_probe(gspca_dev, 0x0a); /* PB0330 */
6191 i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
6192 retword = i2c_read(gspca_dev, 0x07);
6193 if (retword != 0)
6194 return 0x0a; /* PB0330 */
6195 retword = i2c_read(gspca_dev, 0x03);
6196 if (retword != 0)
6197 return 0x0a; /* PB0330 ?? */
6198 retword = i2c_read(gspca_dev, 0x04);
6199 if (retword != 0)
6200 return 0x0a; /* PB0330 ?? */
6201
6202 start_2wr_probe(gspca_dev, 0x0c); /* ICM105A */
6203 i2c_write(gspca_dev, 0x01, 0x11, 0x00);
6204 retword = i2c_read(gspca_dev, 0x01);
6205 if (retword != 0)
6206 return 0x0c; /* ICM105A */
6207
6208 start_2wr_probe(gspca_dev, 0x0e); /* PAS202BCB */
6209 reg_w(gspca_dev, 0x08, 0x008d);
6210 i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
6211 msleep(50);
6212 retword = i2c_read(gspca_dev, 0x03);
6213 if (retword != 0) {
6214 send_unknown(gspca_dev, SENSOR_PAS202B);
6215 return 0x0e; /* PAS202BCB */
6216 }
6217
6218 start_2wr_probe(gspca_dev, 0x02); /* TAS5130C */
6219 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6220 retword = i2c_read(gspca_dev, 0x01);
6221 if (retword != 0)
6222 return 0x02; /* TAS5130C */
6223ov_check:
6224 reg_r(gspca_dev, 0x0010); /* ?? */
6225 reg_r(gspca_dev, 0x0010);
6226
6227 reg_w(gspca_dev, 0x01, 0x0000);
6228 reg_w(gspca_dev, 0x01, 0x0001);
6229 reg_w(gspca_dev, 0x06, 0x0010); /* OmniVision */
6230 reg_w(gspca_dev, 0xa1, 0x008b);
6231 reg_w(gspca_dev, 0x08, 0x008d);
6232 msleep(500);
6233 reg_w(gspca_dev, 0x01, 0x0012);
6234 i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
6235 retword = i2c_read(gspca_dev, 0x0a) << 8;
6236 retword |= i2c_read(gspca_dev, 0x0b);
6237 PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword);
6238 switch (retword) {
6239 case 0x7631: /* OV7630C */
6240 reg_w(gspca_dev, 0x06, 0x0010);
6241 break;
6242 case 0x7620: /* OV7620 */
6243 case 0x7648: /* OV7648 */
6244 break;
6245 default:
6246 return -1; /* not OmniVision */
6247 }
6248 return retword;
6249}
6250
6251struct sensor_by_chipset_revision {
6252 u16 revision;
6253 u8 internal_sensor_id;
6254};
6255static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
6256 {0xc000, 0x12}, /* TAS5130C */
6257 {0xc001, 0x13}, /* MT9V111 */
6258 {0xe001, 0x13},
6259 {0x8001, 0x13},
6260 {0x8000, 0x14}, /* CS2102K */
6261 {0x8400, 0x15}, /* MT9V111 */
6262 {0xe400, 0x15},
6263};
6264
6265static int vga_3wr_probe(struct gspca_dev *gspca_dev)
6266{
6267 struct sd *sd = (struct sd *) gspca_dev;
6268 int i;
6269 u16 retword;
6270
6271/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
6272 reg_w(gspca_dev, 0x02, 0x0010);
6273 reg_r(gspca_dev, 0x0010);
6274 reg_w(gspca_dev, 0x01, 0x0000);
6275 reg_w(gspca_dev, 0x00, 0x0010);
6276 reg_w(gspca_dev, 0x01, 0x0001);
6277 reg_w(gspca_dev, 0x91, 0x008b);
6278 reg_w(gspca_dev, 0x03, 0x0012);
6279 reg_w(gspca_dev, 0x01, 0x0012);
6280 reg_w(gspca_dev, 0x05, 0x0012);
6281 retword = i2c_read(gspca_dev, 0x14);
6282 if (retword != 0)
6283 return 0x11; /* HV7131R */
6284 retword = i2c_read(gspca_dev, 0x15);
6285 if (retword != 0)
6286 return 0x11; /* HV7131R */
6287 retword = i2c_read(gspca_dev, 0x16);
6288 if (retword != 0)
6289 return 0x11; /* HV7131R */
6290
6291 reg_w(gspca_dev, 0x02, 0x0010);
6292 retword = reg_r(gspca_dev, 0x000b) << 8;
6293 retword |= reg_r(gspca_dev, 0x000a);
6294 PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
6295 reg_r(gspca_dev, 0x0010);
6296 if ((retword & 0xff00) == 0x6400)
6297 return 0x02; /* TAS5130C */
6298 for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
6299 if (chipset_revision_sensor[i].revision == retword) {
6300 sd->chip_revision = retword;
6301 send_unknown(gspca_dev, SENSOR_PB0330);
6302 return chipset_revision_sensor[i].internal_sensor_id;
6303 }
6304 }
6305
6306 reg_w(gspca_dev, 0x01, 0x0000); /* check PB0330 */
6307 reg_w(gspca_dev, 0x01, 0x0001);
6308 reg_w(gspca_dev, 0xdd, 0x008b);
6309 reg_w(gspca_dev, 0x0a, 0x0010);
6310 reg_w(gspca_dev, 0x03, 0x0012);
6311 reg_w(gspca_dev, 0x01, 0x0012);
6312 retword = i2c_read(gspca_dev, 0x00);
6313 if (retword != 0) {
6314 PDEBUG(D_PROBE, "probe 3wr vga type 0a");
6315 return 0x0a; /* PB0330 */
6316 }
6317
6318 /* probe gc0303 / gc0305 */
6319 reg_w(gspca_dev, 0x01, 0x0000);
6320 reg_w(gspca_dev, 0x01, 0x0001);
6321 reg_w(gspca_dev, 0x98, 0x008b);
6322 reg_w(gspca_dev, 0x01, 0x0010);
6323 reg_w(gspca_dev, 0x03, 0x0012);
6324 msleep(2);
6325 reg_w(gspca_dev, 0x01, 0x0012);
6326 retword = i2c_read(gspca_dev, 0x00);
6327 if (retword != 0) {
6328 PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
6329 if (retword == 0x0011) /* gc0303 */
6330 return 0x0303;
6331 if (retword == 0x0029) /* gc0305 */
6332 send_unknown(gspca_dev, SENSOR_GC0305);
6333 return retword;
6334 }
6335
6336 reg_w(gspca_dev, 0x01, 0x0000); /* check OmniVision */
6337 reg_w(gspca_dev, 0x01, 0x0001);
6338 reg_w(gspca_dev, 0xa1, 0x008b);
6339 reg_w(gspca_dev, 0x08, 0x008d);
6340 reg_w(gspca_dev, 0x06, 0x0010);
6341 reg_w(gspca_dev, 0x01, 0x0012);
6342 reg_w(gspca_dev, 0x05, 0x0012);
6343 if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */
6344 && i2c_read(gspca_dev, 0x1d) == 0x00a2) {
6345 send_unknown(gspca_dev, SENSOR_OV7620);
6346 return 0x06; /* OmniVision confirm ? */
6347 }
6348
6349 reg_w(gspca_dev, 0x01, 0x0000);
6350 reg_w(gspca_dev, 0x00, 0x0002);
6351 reg_w(gspca_dev, 0x01, 0x0010);
6352 reg_w(gspca_dev, 0x01, 0x0001);
6353 reg_w(gspca_dev, 0xee, 0x008b);
6354 reg_w(gspca_dev, 0x03, 0x0012);
6355 reg_w(gspca_dev, 0x01, 0x0012);
6356 reg_w(gspca_dev, 0x05, 0x0012);
6357 retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */
6358 retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */
6359 PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
6360 if (retword == 0x2030) {
6361#ifdef GSPCA_DEBUG
6362 u8 retbyte;
6363
6364 retbyte = i2c_read(gspca_dev, 0x02); /* revision number */
6365 PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
6366#endif
6367 send_unknown(gspca_dev, SENSOR_PO2030);
6368 return retword;
6369 }
6370
6371 reg_w(gspca_dev, 0x01, 0x0000);
6372 reg_w(gspca_dev, 0x0a, 0x0010);
6373 reg_w(gspca_dev, 0xd3, 0x008b);
6374 reg_w(gspca_dev, 0x01, 0x0001);
6375 reg_w(gspca_dev, 0x03, 0x0012);
6376 reg_w(gspca_dev, 0x01, 0x0012);
6377 reg_w(gspca_dev, 0x05, 0x0012);
6378 reg_w(gspca_dev, 0xd3, 0x008b);
6379 retword = i2c_read(gspca_dev, 0x01);
6380 if (retword != 0) {
6381 PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
6382 return 0x16; /* adcm2700 (6100/6200) */
6383 }
6384 return -1;
6385}
6386
6387static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
6388{
6389 struct sd *sd = (struct sd *) gspca_dev;
6390 int sensor;
6391
6392 switch (sd->sensor) {
6393 case SENSOR_MC501CB:
6394 return -1; /* don't probe */
6395 case SENSOR_GC0303:
6396 /* may probe but with no write in reg 0x0010 */
6397 return -1; /* don't probe */
6398 case SENSOR_PAS106:
6399 sensor = sif_probe(gspca_dev);
6400 if (sensor >= 0)
6401 return sensor;
6402 break;
6403 }
6404 sensor = vga_2wr_probe(gspca_dev);
6405 if (sensor >= 0)
6406 return sensor;
6407 return vga_3wr_probe(gspca_dev);
6408}
6409
6410/* this function is called at probe time */
6411static int sd_config(struct gspca_dev *gspca_dev,
6412 const struct usb_device_id *id)
6413{
6414 struct sd *sd = (struct sd *) gspca_dev;
6415
6416 if (id->idProduct == 0x301b)
6417 sd->bridge = BRIDGE_ZC301;
6418 else
6419 sd->bridge = BRIDGE_ZC303;
6420
6421 /* define some sensors from the vendor/product */
6422 sd->sensor = id->driver_info;
6423
6424 gspca_dev->cam.ctrls = sd->ctrls;
6425 sd->quality = QUALITY_DEF;
6426
6427 /* if USB 1.1, let some bandwidth for the audio device */
6428 if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
6429 gspca_dev->nbalt--;
6430
6431 return 0;
6432}
6433
6434/* this function is called at probe and resume time */
6435static int sd_init(struct gspca_dev *gspca_dev)
6436{
6437 struct sd *sd = (struct sd *) gspca_dev;
6438 struct cam *cam;
6439 int sensor;
6440 static const u8 gamma[SENSOR_MAX] = {
6441 [SENSOR_ADCM2700] = 4,
6442 [SENSOR_CS2102] = 4,
6443 [SENSOR_CS2102K] = 5,
6444 [SENSOR_GC0303] = 3,
6445 [SENSOR_GC0305] = 4,
6446 [SENSOR_HDCS2020] = 4,
6447 [SENSOR_HV7131B] = 4,
6448 [SENSOR_HV7131R] = 4,
6449 [SENSOR_ICM105A] = 4,
6450 [SENSOR_MC501CB] = 4,
6451 [SENSOR_MT9V111_1] = 4,
6452 [SENSOR_MT9V111_3] = 4,
6453 [SENSOR_OV7620] = 3,
6454 [SENSOR_OV7630C] = 4,
6455 [SENSOR_PAS106] = 4,
6456 [SENSOR_PAS202B] = 4,
6457 [SENSOR_PB0330] = 4,
6458 [SENSOR_PO2030] = 4,
6459 [SENSOR_TAS5130C] = 3,
6460 };
6461 static const u8 mode_tb[SENSOR_MAX] = {
6462 [SENSOR_ADCM2700] = 2,
6463 [SENSOR_CS2102] = 1,
6464 [SENSOR_CS2102K] = 1,
6465 [SENSOR_GC0303] = 1,
6466 [SENSOR_GC0305] = 1,
6467 [SENSOR_HDCS2020] = 1,
6468 [SENSOR_HV7131B] = 1,
6469 [SENSOR_HV7131R] = 1,
6470 [SENSOR_ICM105A] = 1,
6471 [SENSOR_MC501CB] = 2,
6472 [SENSOR_MT9V111_1] = 1,
6473 [SENSOR_MT9V111_3] = 1,
6474 [SENSOR_OV7620] = 2,
6475 [SENSOR_OV7630C] = 1,
6476 [SENSOR_PAS106] = 0,
6477 [SENSOR_PAS202B] = 1,
6478 [SENSOR_PB0330] = 1,
6479 [SENSOR_PO2030] = 1,
6480 [SENSOR_TAS5130C] = 1,
6481 };
6482
6483 sensor = zcxx_probeSensor(gspca_dev);
6484 if (sensor >= 0)
6485 PDEBUG(D_PROBE, "probe sensor -> %04x", sensor);
6486 if ((unsigned) force_sensor < SENSOR_MAX) {
6487 sd->sensor = force_sensor;
6488 PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
6489 } else {
6490 switch (sensor) {
6491 case -1:
6492 switch (sd->sensor) {
6493 case SENSOR_MC501CB:
6494 PDEBUG(D_PROBE, "Sensor MC501CB");
6495 break;
6496 case SENSOR_GC0303:
6497 PDEBUG(D_PROBE, "Sensor GC0303");
6498 break;
6499 default:
6500 warn("Unknown sensor - set to TAS5130C");
6501 sd->sensor = SENSOR_TAS5130C;
6502 }
6503 break;
6504 case 0:
6505 /* check the sensor type */
6506 sensor = i2c_read(gspca_dev, 0x00);
6507 PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor);
6508 switch (sensor) {
6509 case 0: /* hv7131b */
6510 case 1: /* hv7131e */
6511 PDEBUG(D_PROBE, "Find Sensor HV7131B");
6512 sd->sensor = SENSOR_HV7131B;
6513 break;
6514 default:
6515/* case 2: * hv7131r */
6516 PDEBUG(D_PROBE, "Find Sensor HV7131R");
6517 sd->sensor = SENSOR_HV7131R;
6518 break;
6519 }
6520 break;
6521 case 0x02:
6522 PDEBUG(D_PROBE, "Sensor TAS5130C");
6523 sd->sensor = SENSOR_TAS5130C;
6524 break;
6525 case 0x04:
6526 PDEBUG(D_PROBE, "Find Sensor CS2102");
6527 sd->sensor = SENSOR_CS2102;
6528 break;
6529 case 0x08:
6530 PDEBUG(D_PROBE, "Find Sensor HDCS2020");
6531 sd->sensor = SENSOR_HDCS2020;
6532 break;
6533 case 0x0a:
6534 PDEBUG(D_PROBE,
6535 "Find Sensor PB0330. Chip revision %x",
6536 sd->chip_revision);
6537 sd->sensor = SENSOR_PB0330;
6538 break;
6539 case 0x0c:
6540 PDEBUG(D_PROBE, "Find Sensor ICM105A");
6541 sd->sensor = SENSOR_ICM105A;
6542 break;
6543 case 0x0e:
6544 PDEBUG(D_PROBE, "Find Sensor PAS202B");
6545 sd->sensor = SENSOR_PAS202B;
6546/* sd->sharpness = 1; */
6547 break;
6548 case 0x0f:
6549 PDEBUG(D_PROBE, "Find Sensor PAS106");
6550 sd->sensor = SENSOR_PAS106;
6551 break;
6552 case 0x10:
6553 case 0x12:
6554 PDEBUG(D_PROBE, "Find Sensor TAS5130C");
6555 sd->sensor = SENSOR_TAS5130C;
6556 break;
6557 case 0x11:
6558 PDEBUG(D_PROBE, "Find Sensor HV7131R");
6559 sd->sensor = SENSOR_HV7131R;
6560 break;
6561 case 0x13:
6562 case 0x15:
6563 PDEBUG(D_PROBE,
6564 "Sensor MT9V111. Chip revision %04x",
6565 sd->chip_revision);
6566 sd->sensor = sd->bridge == BRIDGE_ZC301
6567 ? SENSOR_MT9V111_1
6568 : SENSOR_MT9V111_3;
6569 break;
6570 case 0x14:
6571 PDEBUG(D_PROBE,
6572 "Find Sensor CS2102K?. Chip revision %x",
6573 sd->chip_revision);
6574 sd->sensor = SENSOR_CS2102K;
6575 break;
6576 case 0x16:
6577 PDEBUG(D_PROBE, "Find Sensor ADCM2700");
6578 sd->sensor = SENSOR_ADCM2700;
6579 break;
6580 case 0x29:
6581 PDEBUG(D_PROBE, "Find Sensor GC0305");
6582 sd->sensor = SENSOR_GC0305;
6583 break;
6584 case 0x0303:
6585 PDEBUG(D_PROBE, "Sensor GC0303");
6586 sd->sensor = SENSOR_GC0303;
6587 break;
6588 case 0x2030:
6589 PDEBUG(D_PROBE, "Find Sensor PO2030");
6590 sd->sensor = SENSOR_PO2030;
6591 sd->ctrls[SHARPNESS].def = 0; /* from win traces */
6592 break;
6593 case 0x7620:
6594 PDEBUG(D_PROBE, "Find Sensor OV7620");
6595 sd->sensor = SENSOR_OV7620;
6596 break;
6597 case 0x7631:
6598 PDEBUG(D_PROBE, "Find Sensor OV7630C");
6599 sd->sensor = SENSOR_OV7630C;
6600 break;
6601 case 0x7648:
6602 PDEBUG(D_PROBE, "Find Sensor OV7648");
6603 sd->sensor = SENSOR_OV7620; /* same sensor (?) */
6604 break;
6605 default:
6606 err("Unknown sensor %04x", sensor);
6607 return -EINVAL;
6608 }
6609 }
6610 if (sensor < 0x20) {
6611 if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
6612 reg_w(gspca_dev, 0x02, 0x0010);
6613 reg_r(gspca_dev, 0x0010);
6614 }
6615
6616 cam = &gspca_dev->cam;
6617 switch (mode_tb[sd->sensor]) {
6618 case 0:
6619 cam->cam_mode = sif_mode;
6620 cam->nmodes = ARRAY_SIZE(sif_mode);
6621 break;
6622 case 1:
6623 cam->cam_mode = vga_mode;
6624 cam->nmodes = ARRAY_SIZE(vga_mode);
6625 break;
6626 default:
6627/* case 2: */
6628 cam->cam_mode = broken_vga_mode;
6629 cam->nmodes = ARRAY_SIZE(broken_vga_mode);
6630 break;
6631 }
6632
6633 sd->ctrls[GAMMA].def = gamma[sd->sensor];
6634
6635 switch (sd->sensor) {
6636 case SENSOR_HV7131R:
6637 break;
6638 case SENSOR_OV7630C:
6639 gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE);
6640 break;
6641 default:
6642 gspca_dev->ctrl_dis = (1 << EXPOSURE);
6643 break;
6644 }
6645#if AUTOGAIN_DEF
6646 if (sd->ctrls[AUTOGAIN].val)
6647 gspca_dev->ctrl_inac = (1 << EXPOSURE);
6648#endif
6649
6650 /* switch off the led */
6651 reg_w(gspca_dev, 0x01, 0x0000);
6652 return gspca_dev->usb_err;
6653}
6654
6655static int sd_start(struct gspca_dev *gspca_dev)
6656{
6657 struct sd *sd = (struct sd *) gspca_dev;
6658 int mode;
6659 static const struct usb_action *init_tb[SENSOR_MAX][2] = {
6660 [SENSOR_ADCM2700] =
6661 {adcm2700_Initial, adcm2700_InitialScale},
6662 [SENSOR_CS2102] =
6663 {cs2102_Initial, cs2102_InitialScale},
6664 [SENSOR_CS2102K] =
6665 {cs2102K_Initial, cs2102K_InitialScale},
6666 [SENSOR_GC0303] =
6667 {gc0303_Initial, gc0303_InitialScale},
6668 [SENSOR_GC0305] =
6669 {gc0305_Initial, gc0305_InitialScale},
6670 [SENSOR_HDCS2020] =
6671 {hdcs2020_Initial, hdcs2020_InitialScale},
6672 [SENSOR_HV7131B] =
6673 {hv7131b_Initial, hv7131b_InitialScale},
6674 [SENSOR_HV7131R] =
6675 {hv7131r_Initial, hv7131r_InitialScale},
6676 [SENSOR_ICM105A] =
6677 {icm105a_Initial, icm105a_InitialScale},
6678 [SENSOR_MC501CB] =
6679 {mc501cb_Initial, mc501cb_InitialScale},
6680 [SENSOR_MT9V111_1] =
6681 {mt9v111_1_Initial, mt9v111_1_InitialScale},
6682 [SENSOR_MT9V111_3] =
6683 {mt9v111_3_Initial, mt9v111_3_InitialScale},
6684 [SENSOR_OV7620] =
6685 {ov7620_Initial, ov7620_InitialScale},
6686 [SENSOR_OV7630C] =
6687 {ov7630c_Initial, ov7630c_InitialScale},
6688 [SENSOR_PAS106] =
6689 {pas106b_Initial, pas106b_InitialScale},
6690 [SENSOR_PAS202B] =
6691 {pas202b_Initial, pas202b_InitialScale},
6692 [SENSOR_PB0330] =
6693 {pb0330_Initial, pb0330_InitialScale},
6694 [SENSOR_PO2030] =
6695 {po2030_Initial, po2030_InitialScale},
6696 [SENSOR_TAS5130C] =
6697 {tas5130c_Initial, tas5130c_InitialScale},
6698 };
6699
6700 /* create the JPEG header */
6701 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
6702 0x21); /* JPEG 422 */
6703 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
6704
6705 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
6706 switch (sd->sensor) {
6707 case SENSOR_HV7131R:
6708 zcxx_probeSensor(gspca_dev);
6709 break;
6710 case SENSOR_PAS106:
6711 usb_exchange(gspca_dev, pas106b_Initial_com);
6712 break;
6713 }
6714 usb_exchange(gspca_dev, init_tb[sd->sensor][mode]);
6715
6716 switch (sd->sensor) {
6717 case SENSOR_ADCM2700:
6718 case SENSOR_GC0305:
6719 case SENSOR_OV7620:
6720 case SENSOR_PO2030:
6721 case SENSOR_TAS5130C:
6722 case SENSOR_GC0303:
6723/* msleep(100); * ?? */
6724 reg_r(gspca_dev, 0x0002); /* --> 0x40 */
6725 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6726 reg_w(gspca_dev, 0x15, 0x01ae);
6727 if (sd->sensor == SENSOR_TAS5130C)
6728 break;
6729 reg_w(gspca_dev, 0x0d, 0x003a);
6730 reg_w(gspca_dev, 0x02, 0x003b);
6731 reg_w(gspca_dev, 0x00, 0x0038);
6732 break;
6733 case SENSOR_HV7131R:
6734 case SENSOR_PAS202B:
6735 reg_w(gspca_dev, 0x03, 0x003b);
6736 reg_w(gspca_dev, 0x0c, 0x003a);
6737 reg_w(gspca_dev, 0x0b, 0x0039);
6738 if (sd->sensor == SENSOR_HV7131R)
6739 reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN);
6740 break;
6741 }
6742
6743 setmatrix(gspca_dev);
6744 switch (sd->sensor) {
6745 case SENSOR_ADCM2700:
6746 case SENSOR_OV7620:
6747 reg_r(gspca_dev, 0x0008);
6748 reg_w(gspca_dev, 0x00, 0x0008);
6749 break;
6750 case SENSOR_PAS202B:
6751 case SENSOR_GC0305:
6752 case SENSOR_HV7131R:
6753 case SENSOR_TAS5130C:
6754 reg_r(gspca_dev, 0x0008);
6755 /* fall thru */
6756 case SENSOR_PO2030:
6757 reg_w(gspca_dev, 0x03, 0x0008);
6758 break;
6759 }
6760 setsharpness(gspca_dev);
6761
6762 /* set the gamma tables when not set */
6763 switch (sd->sensor) {
6764 case SENSOR_CS2102K: /* gamma set in xxx_Initial */
6765 case SENSOR_HDCS2020:
6766 case SENSOR_OV7630C:
6767 break;
6768 default:
6769 setcontrast(gspca_dev);
6770 break;
6771 }
6772 setmatrix(gspca_dev); /* one more time? */
6773 switch (sd->sensor) {
6774 case SENSOR_OV7620:
6775 case SENSOR_PAS202B:
6776 reg_r(gspca_dev, 0x0180); /* from win */
6777 reg_w(gspca_dev, 0x00, 0x0180);
6778 break;
6779 default:
6780 setquality(gspca_dev);
6781 break;
6782 }
6783 setlightfreq(gspca_dev);
6784
6785 switch (sd->sensor) {
6786 case SENSOR_ADCM2700:
6787 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6788 reg_w(gspca_dev, 0x15, 0x01ae);
6789 reg_w(gspca_dev, 0x02, 0x0180);
6790 /* ms-win + */
6791 reg_w(gspca_dev, 0x40, 0x0117);
6792 break;
6793 case SENSOR_HV7131R:
6794 if (!sd->ctrls[AUTOGAIN].val)
6795 setexposure(gspca_dev);
6796 reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
6797 break;
6798 case SENSOR_GC0305:
6799 case SENSOR_TAS5130C:
6800 reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
6801 reg_w(gspca_dev, 0x15, 0x01ae);
6802 /* fall thru */
6803 case SENSOR_PAS202B:
6804 case SENSOR_PO2030:
6805/* reg_w(gspca_dev, 0x40, ZC3XX_R117_GGAIN); in win traces */
6806 reg_r(gspca_dev, 0x0180);
6807 break;
6808 case SENSOR_OV7620:
6809 reg_w(gspca_dev, 0x09, 0x01ad);
6810 reg_w(gspca_dev, 0x15, 0x01ae);
6811 i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */
6812 i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
6813 /*fixme: returned value to send? */
6814 reg_w(gspca_dev, 0x40, 0x0117);
6815 reg_r(gspca_dev, 0x0180);
6816 break;
6817 }
6818
6819 setautogain(gspca_dev);
6820 switch (sd->sensor) {
6821 case SENSOR_PO2030:
6822 msleep(50);
6823 reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */
6824 reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING);
6825 break;
6826 }
6827 return gspca_dev->usb_err;
6828}
6829
6830/* called on streamoff with alt 0 and on disconnect */
6831static void sd_stop0(struct gspca_dev *gspca_dev)
6832{
6833 struct sd *sd = (struct sd *) gspca_dev;
6834
6835 if (!gspca_dev->present)
6836 return;
6837 send_unknown(gspca_dev, sd->sensor);
6838}
6839
6840static void sd_pkt_scan(struct gspca_dev *gspca_dev,
6841 u8 *data,
6842 int len)
6843{
6844 struct sd *sd = (struct sd *) gspca_dev;
6845
6846 /* check the JPEG end of frame */
6847 if (len >= 3
6848 && data[len - 3] == 0xff && data[len - 2] == 0xd9) {
6849/*fixme: what does the last byte mean?*/
6850 gspca_frame_add(gspca_dev, LAST_PACKET,
6851 data, len - 1);
6852 return;
6853 }
6854
6855 /* check the JPEG start of a frame */
6856 if (data[0] == 0xff && data[1] == 0xd8) {
6857 /* put the JPEG header in the new frame */
6858 gspca_frame_add(gspca_dev, FIRST_PACKET,
6859 sd->jpeg_hdr, JPEG_HDR_SZ);
6860
6861 /* remove the webcam's header:
6862 * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
6863 * - 'ss ss' is the frame sequence number (BE)
6864 * - 'ww ww' and 'hh hh' are the window dimensions (BE)
6865 * - 'pp pp' is the packet sequence number (BE)
6866 */
6867 data += 18;
6868 len -= 18;
6869 }
6870 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6871}
6872
6873static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
6874{
6875 struct sd *sd = (struct sd *) gspca_dev;
6876
6877 sd->ctrls[AUTOGAIN].val = val;
6878 if (val) {
6879 gspca_dev->ctrl_inac |= (1 << EXPOSURE);
6880 } else {
6881 gspca_dev->ctrl_inac &= ~(1 << EXPOSURE);
6882 if (gspca_dev->streaming)
6883 getexposure(gspca_dev);
6884 }
6885 if (gspca_dev->streaming)
6886 setautogain(gspca_dev);
6887 return gspca_dev->usb_err;
6888}
6889
6890static int sd_querymenu(struct gspca_dev *gspca_dev,
6891 struct v4l2_querymenu *menu)
6892{
6893 switch (menu->id) {
6894 case V4L2_CID_POWER_LINE_FREQUENCY:
6895 switch (menu->index) {
6896 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
6897 strcpy((char *) menu->name, "NoFliker");
6898 return 0;
6899 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
6900 strcpy((char *) menu->name, "50 Hz");
6901 return 0;
6902 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
6903 strcpy((char *) menu->name, "60 Hz");
6904 return 0;
6905 }
6906 break;
6907 }
6908 return -EINVAL;
6909}
6910
6911static int sd_set_jcomp(struct gspca_dev *gspca_dev,
6912 struct v4l2_jpegcompression *jcomp)
6913{
6914 struct sd *sd = (struct sd *) gspca_dev;
6915
6916 if (jcomp->quality < QUALITY_MIN)
6917 sd->quality = QUALITY_MIN;
6918 else if (jcomp->quality > QUALITY_MAX)
6919 sd->quality = QUALITY_MAX;
6920 else
6921 sd->quality = jcomp->quality;
6922 if (gspca_dev->streaming)
6923 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
6924 return gspca_dev->usb_err;
6925}
6926
6927static int sd_get_jcomp(struct gspca_dev *gspca_dev,
6928 struct v4l2_jpegcompression *jcomp)
6929{
6930 struct sd *sd = (struct sd *) gspca_dev;
6931
6932 memset(jcomp, 0, sizeof *jcomp);
6933 jcomp->quality = sd->quality;
6934 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
6935 | V4L2_JPEG_MARKER_DQT;
6936 return 0;
6937}
6938
6939#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
6940static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
6941 u8 *data, /* interrupt packet data */
6942 int len) /* interrput packet length */
6943{
6944 if (len == 8 && data[4] == 1) {
6945 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
6946 input_sync(gspca_dev->input_dev);
6947 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
6948 input_sync(gspca_dev->input_dev);
6949 }
6950
6951 return 0;
6952}
6953#endif
6954
6955static const struct sd_desc sd_desc = {
6956 .name = MODULE_NAME,
6957 .ctrls = sd_ctrls,
6958 .nctrls = ARRAY_SIZE(sd_ctrls),
6959 .config = sd_config,
6960 .init = sd_init,
6961 .start = sd_start,
6962 .stop0 = sd_stop0,
6963 .pkt_scan = sd_pkt_scan,
6964 .querymenu = sd_querymenu,
6965 .get_jcomp = sd_get_jcomp,
6966 .set_jcomp = sd_set_jcomp,
6967#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
6968 .int_pkt_scan = sd_int_pkt_scan,
6969#endif
6970};
6971
6972static const struct usb_device_id device_table[] = {
6973 {USB_DEVICE(0x041e, 0x041e)},
6974 {USB_DEVICE(0x041e, 0x4017)},
6975 {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
6976 {USB_DEVICE(0x041e, 0x401e)},
6977 {USB_DEVICE(0x041e, 0x401f)},
6978 {USB_DEVICE(0x041e, 0x4022)},
6979 {USB_DEVICE(0x041e, 0x4029)},
6980 {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
6981 {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
6982 {USB_DEVICE(0x041e, 0x4036)},
6983 {USB_DEVICE(0x041e, 0x403a)},
6984 {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303},
6985 {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303},
6986 {USB_DEVICE(0x0458, 0x7007)},
6987 {USB_DEVICE(0x0458, 0x700c)},
6988 {USB_DEVICE(0x0458, 0x700f)},
6989 {USB_DEVICE(0x0461, 0x0a00)},
6990 {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB},
6991 {USB_DEVICE(0x046d, 0x08a0)},
6992 {USB_DEVICE(0x046d, 0x08a1)},
6993 {USB_DEVICE(0x046d, 0x08a2)},
6994 {USB_DEVICE(0x046d, 0x08a3)},
6995 {USB_DEVICE(0x046d, 0x08a6)},
6996 {USB_DEVICE(0x046d, 0x08a7)},
6997 {USB_DEVICE(0x046d, 0x08a9)},
6998 {USB_DEVICE(0x046d, 0x08aa)},
6999 {USB_DEVICE(0x046d, 0x08ac)},
7000 {USB_DEVICE(0x046d, 0x08ad)},
7001 {USB_DEVICE(0x046d, 0x08ae)},
7002 {USB_DEVICE(0x046d, 0x08af)},
7003 {USB_DEVICE(0x046d, 0x08b9)},
7004 {USB_DEVICE(0x046d, 0x08d7)},
7005 {USB_DEVICE(0x046d, 0x08d8)},
7006 {USB_DEVICE(0x046d, 0x08d9)},
7007 {USB_DEVICE(0x046d, 0x08da)},
7008 {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
7009 {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
7010 {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
7011 {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
7012 {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
7013 {USB_DEVICE(0x055f, 0xc005)},
7014 {USB_DEVICE(0x055f, 0xd003)},
7015 {USB_DEVICE(0x055f, 0xd004)},
7016 {USB_DEVICE(0x0698, 0x2003)},
7017 {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
7018 {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106},
7019 {USB_DEVICE(0x0ac8, 0x301b)},
7020 {USB_DEVICE(0x0ac8, 0x303b)},
7021 {USB_DEVICE(0x0ac8, 0x305b)},
7022 {USB_DEVICE(0x0ac8, 0x307b)},
7023 {USB_DEVICE(0x10fd, 0x0128)},
7024 {USB_DEVICE(0x10fd, 0x804d)},
7025 {USB_DEVICE(0x10fd, 0x8050)},
7026 {} /* end of entry */
7027};
7028MODULE_DEVICE_TABLE(usb, device_table);
7029
7030/* -- device connect -- */
7031static int sd_probe(struct usb_interface *intf,
7032 const struct usb_device_id *id)
7033{
7034 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
7035 THIS_MODULE);
7036}
7037
7038/* USB driver */
7039static struct usb_driver sd_driver = {
7040 .name = MODULE_NAME,
7041 .id_table = device_table,
7042 .probe = sd_probe,
7043 .disconnect = gspca_disconnect,
7044#ifdef CONFIG_PM
7045 .suspend = gspca_suspend,
7046 .resume = gspca_resume,
7047#endif
7048};
7049
7050static int __init sd_mod_init(void)
7051{
7052 return usb_register(&sd_driver);
7053}
7054
7055static void __exit sd_mod_exit(void)
7056{
7057 usb_deregister(&sd_driver);
7058}
7059
7060module_init(sd_mod_init);
7061module_exit(sd_mod_exit);
7062
7063module_param(force_sensor, int, 0644);
7064MODULE_PARM_DESC(force_sensor,
7065 "Force sensor. Only for experts!!!");