diff options
Diffstat (limited to 'drivers/media/video/gspca')
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 @@ | |||
1 | menuconfig 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 | |||
18 | if USB_GSPCA && VIDEO_V4L2 | ||
19 | |||
20 | source "drivers/media/video/gspca/m5602/Kconfig" | ||
21 | source "drivers/media/video/gspca/stv06xx/Kconfig" | ||
22 | source "drivers/media/video/gspca/gl860/Kconfig" | ||
23 | |||
24 | config 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 | |||
33 | config 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 | |||
42 | config 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 | |||
53 | config 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 | |||
62 | config 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 | |||
71 | config 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 | |||
80 | config 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 | |||
89 | config 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 | |||
98 | config 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 | |||
107 | config 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 | |||
116 | config 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 | |||
125 | config 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 | |||
135 | config 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 | |||
145 | config 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 | |||
155 | config 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 | |||
164 | config 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 | |||
173 | config 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 | |||
182 | config 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 | |||
192 | config 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 | |||
202 | config 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 | |||
212 | config 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 | |||
222 | config 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 | |||
232 | config 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 | |||
241 | config 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 | |||
250 | config 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 | |||
259 | config 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 | |||
268 | config 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 | |||
277 | config 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 | |||
286 | config 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 | |||
295 | config 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 | |||
304 | config 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 | |||
313 | config 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 | |||
322 | config 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 | |||
331 | config 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 | |||
340 | config 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 | |||
350 | config 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 | |||
359 | config 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 | |||
368 | config 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 | |||
377 | config 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 | |||
387 | config 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 | |||
396 | config 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 | |||
405 | endif | ||
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 @@ | |||
1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o | ||
2 | obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o | ||
3 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o | ||
4 | obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o | ||
5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o | ||
6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o | ||
7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o | ||
8 | obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o | ||
9 | obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o | ||
10 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | ||
11 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o | ||
12 | obj-$(CONFIG_USB_GSPCA_NW80X) += gspca_nw80x.o | ||
13 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o | ||
14 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o | ||
15 | obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o | ||
16 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o | ||
17 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o | ||
18 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | ||
19 | obj-$(CONFIG_USB_GSPCA_SE401) += gspca_se401.o | ||
20 | obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o | ||
21 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o | ||
22 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | ||
23 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o | ||
24 | obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o | ||
25 | obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o | ||
26 | obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o | ||
27 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o | ||
28 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o | ||
29 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o | ||
30 | obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o | ||
31 | obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o | ||
32 | obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o | ||
33 | obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o | ||
34 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | ||
35 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | ||
36 | obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o | ||
37 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | ||
38 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o | ||
39 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | ||
40 | obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o | ||
41 | obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o | ||
42 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | ||
43 | |||
44 | gspca_main-objs := gspca.o | ||
45 | gspca_benq-objs := benq.o | ||
46 | gspca_conex-objs := conex.o | ||
47 | gspca_cpia1-objs := cpia1.o | ||
48 | gspca_etoms-objs := etoms.o | ||
49 | gspca_finepix-objs := finepix.o | ||
50 | gspca_jeilinj-objs := jeilinj.o | ||
51 | gspca_kinect-objs := kinect.o | ||
52 | gspca_konica-objs := konica.o | ||
53 | gspca_mars-objs := mars.o | ||
54 | gspca_mr97310a-objs := mr97310a.o | ||
55 | gspca_nw80x-objs := nw80x.o | ||
56 | gspca_ov519-objs := ov519.o | ||
57 | gspca_ov534-objs := ov534.o | ||
58 | gspca_ov534_9-objs := ov534_9.o | ||
59 | gspca_pac207-objs := pac207.o | ||
60 | gspca_pac7302-objs := pac7302.o | ||
61 | gspca_pac7311-objs := pac7311.o | ||
62 | gspca_se401-objs := se401.o | ||
63 | gspca_sn9c2028-objs := sn9c2028.o | ||
64 | gspca_sn9c20x-objs := sn9c20x.o | ||
65 | gspca_sonixb-objs := sonixb.o | ||
66 | gspca_sonixj-objs := sonixj.o | ||
67 | gspca_spca500-objs := spca500.o | ||
68 | gspca_spca501-objs := spca501.o | ||
69 | gspca_spca505-objs := spca505.o | ||
70 | gspca_spca506-objs := spca506.o | ||
71 | gspca_spca508-objs := spca508.o | ||
72 | gspca_spca561-objs := spca561.o | ||
73 | gspca_spca1528-objs := spca1528.o | ||
74 | gspca_sq905-objs := sq905.o | ||
75 | gspca_sq905c-objs := sq905c.o | ||
76 | gspca_sq930x-objs := sq930x.o | ||
77 | gspca_stk014-objs := stk014.o | ||
78 | gspca_stv0680-objs := stv0680.o | ||
79 | gspca_sunplus-objs := sunplus.o | ||
80 | gspca_t613-objs := t613.o | ||
81 | gspca_tv8532-objs := tv8532.o | ||
82 | gspca_vc032x-objs := vc032x.o | ||
83 | gspca_vicam-objs := vicam.o | ||
84 | gspca_xirlink_cit-objs := xirlink_cit.o | ||
85 | gspca_zc3xx-objs := zc3xx.o | ||
86 | |||
87 | obj-$(CONFIG_USB_M5602) += m5602/ | ||
88 | obj-$(CONFIG_USB_STV06XX) += stv06xx/ | ||
89 | obj-$(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. */ | ||
26 | static 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. */ | ||
110 | static 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 | |||
25 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
26 | MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | }; | ||
33 | |||
34 | /* V4L2 controls supported by the driver */ | ||
35 | static const struct ctrl sd_ctrls[] = { | ||
36 | }; | ||
37 | |||
38 | static 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 | |||
45 | static void sd_isoc_irq(struct urb *urb); | ||
46 | |||
47 | /* -- write a register -- */ | ||
48 | static 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 */ | ||
71 | static 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 */ | ||
82 | static int sd_init(struct gspca_dev *gspca_dev) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static 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 -- */ | ||
102 | static 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 | |||
148 | static 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 | |||
159 | static 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 */ | ||
167 | static 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 */ | ||
266 | static 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 -- */ | ||
279 | static const struct usb_device_id device_table[] = { | ||
280 | {USB_DEVICE(0x04a5, 0x3035)}, | ||
281 | {} | ||
282 | }; | ||
283 | MODULE_DEVICE_TABLE(usb, device_table); | ||
284 | |||
285 | /* -- device connect -- */ | ||
286 | static 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 | |||
293 | static 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 -- */ | ||
305 | static int __init sd_mod_init(void) | ||
306 | { | ||
307 | return usb_register(&sd_driver); | ||
308 | } | ||
309 | static void __exit sd_mod_exit(void) | ||
310 | { | ||
311 | usb_deregister(&sd_driver); | ||
312 | } | ||
313 | |||
314 | module_init(sd_mod_init); | ||
315 | module_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 | |||
28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
29 | MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | /* specific webcam descriptor */ | ||
33 | struct 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 */ | ||
48 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
50 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
51 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
52 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
53 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
54 | |||
55 | static 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 | |||
100 | static 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 */ | ||
124 | static 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 */ | ||
148 | static 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 | |||
163 | static 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 | |||
186 | static 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 | |||
194 | static 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 | }; | ||
261 | static 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 | |||
273 | static 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 | |||
288 | static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff }; | ||
289 | static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff }; | ||
290 | static const __u8 reg10[] = { 0xb1, 0xb1 }; | ||
291 | static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */ | ||
292 | static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f }; | ||
293 | /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */ | ||
294 | static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 }; | ||
295 | /* 320{0x04,0x0c,0x05,0x0f}; //320 */ | ||
296 | static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */ | ||
297 | static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }; | ||
298 | |||
299 | static 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 | |||
344 | static 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 | }; | ||
353 | static 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 | }; | ||
362 | static 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 | }; | ||
371 | static 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 | |||
381 | static 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 | |||
428 | static 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 | |||
511 | static 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 | }; | ||
540 | static 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 | }; | ||
569 | static 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 | }; | ||
598 | static 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 */ | ||
628 | static 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 | |||
650 | static 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 | |||
669 | static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 }; | ||
670 | static const __u8 regE5_8[] = | ||
671 | { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 }; | ||
672 | static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 }; | ||
673 | static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 }; | ||
674 | static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 }; | ||
675 | static const __u8 reg51[] = { 0x77, 0x03 }; | ||
676 | #define reg70 0x03 | ||
677 | |||
678 | static 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 | |||
782 | static 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 */ | ||
815 | static 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 */ | ||
833 | static 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 | |||
843 | static 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 */ | ||
860 | static 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 | |||
884 | static 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 | |||
904 | static 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 | |||
927 | static 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 | |||
944 | static 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 | |||
954 | static 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 | |||
962 | static 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 | |||
972 | static 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 | |||
980 | static 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 | |||
992 | static 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 | |||
1000 | static 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 | |||
1016 | static 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 */ | ||
1029 | static 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 -- */ | ||
1043 | static const struct usb_device_id device_table[] = { | ||
1044 | {USB_DEVICE(0x0572, 0x0041)}, | ||
1045 | {} | ||
1046 | }; | ||
1047 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1048 | |||
1049 | /* -- device connect -- */ | ||
1050 | static 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 | |||
1057 | static 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 -- */ | ||
1069 | static int __init sd_mod_init(void) | ||
1070 | { | ||
1071 | return usb_register(&sd_driver); | ||
1072 | } | ||
1073 | static void __exit sd_mod_exit(void) | ||
1074 | { | ||
1075 | usb_deregister(&sd_driver); | ||
1076 | } | ||
1077 | |||
1078 | module_init(sd_mod_init); | ||
1079 | module_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 | |||
34 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
35 | MODULE_DESCRIPTION("Vision CPiA"); | ||
36 | MODULE_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]*/ | ||
228 | static 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 | |||
233 | struct 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 */ | ||
353 | struct 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 */ | ||
367 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
368 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
369 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
370 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
371 | static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val); | ||
372 | static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val); | ||
373 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
374 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
375 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); | ||
376 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); | ||
377 | static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val); | ||
378 | static int sd_getilluminator1(struct gspca_dev *gspca_dev, __s32 *val); | ||
379 | static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val); | ||
380 | static int sd_getilluminator2(struct gspca_dev *gspca_dev, __s32 *val); | ||
381 | |||
382 | static 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 | |||
492 | static 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 | |||
524 | static 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 | |||
544 | retry: | ||
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 */ | ||
565 | static 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 */ | ||
683 | static 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 | ||
722 | static 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 */ | ||
741 | static 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 | |||
820 | static 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 | |||
829 | static 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 | |||
856 | static 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 | |||
885 | static 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 | |||
898 | static 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 | |||
909 | static 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 | |||
926 | static 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 | |||
935 | static 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 | |||
945 | static 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 | |||
955 | static 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 | |||
991 | static 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 | |||
1021 | static 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 | |||
1031 | static 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 | |||
1040 | static 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 | |||
1057 | static 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 | |||
1066 | static 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 | |||
1075 | static 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 | |||
1086 | static 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 | |||
1094 | static int command_pause(struct gspca_dev *gspca_dev) | ||
1095 | { | ||
1096 | return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); | ||
1097 | } | ||
1098 | |||
1099 | static 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 | |||
1107 | static 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 | |||
1127 | static 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 */ | ||
1262 | static 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 | */ | ||
1513 | static 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 */ | ||
1550 | static 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 -- */ | ||
1570 | static 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 | |||
1743 | static 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 */ | ||
1771 | static 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 | |||
1809 | static 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 | |||
1848 | static 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 | |||
1873 | static 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 | |||
1890 | static 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 | |||
1898 | static 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 | |||
1909 | static 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 | |||
1917 | static 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 | |||
1928 | static 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 | |||
1936 | static 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 | |||
1966 | static 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 | |||
1974 | static 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 | |||
1985 | static 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 | |||
1993 | static 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 | |||
2019 | static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val) | ||
2020 | { | ||
2021 | return sd_setilluminator(gspca_dev, val, 1); | ||
2022 | } | ||
2023 | |||
2024 | static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val) | ||
2025 | { | ||
2026 | return sd_setilluminator(gspca_dev, val, 2); | ||
2027 | } | ||
2028 | |||
2029 | static 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 | |||
2049 | static int sd_getilluminator1(struct gspca_dev *gspca_dev, __s32 *val) | ||
2050 | { | ||
2051 | return sd_getilluminator(gspca_dev, val, 1); | ||
2052 | } | ||
2053 | |||
2054 | static int sd_getilluminator2(struct gspca_dev *gspca_dev, __s32 *val) | ||
2055 | { | ||
2056 | return sd_getilluminator(gspca_dev, val, 2); | ||
2057 | } | ||
2058 | |||
2059 | static 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 */ | ||
2091 | static 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 -- */ | ||
2108 | static const struct usb_device_id device_table[] = { | ||
2109 | {USB_DEVICE(0x0553, 0x0002)}, | ||
2110 | {USB_DEVICE(0x0813, 0x0001)}, | ||
2111 | {} | ||
2112 | }; | ||
2113 | MODULE_DEVICE_TABLE(usb, device_table); | ||
2114 | |||
2115 | /* -- device connect -- */ | ||
2116 | static 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 | |||
2123 | static 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 -- */ | ||
2135 | static int __init sd_mod_init(void) | ||
2136 | { | ||
2137 | return usb_register(&sd_driver); | ||
2138 | } | ||
2139 | static void __exit sd_mod_exit(void) | ||
2140 | { | ||
2141 | usb_deregister(&sd_driver); | ||
2142 | } | ||
2143 | |||
2144 | module_init(sd_mod_init); | ||
2145 | module_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 | |||
25 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
26 | MODULE_DESCRIPTION("Etoms USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct 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 */ | ||
46 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
47 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
48 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
50 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
51 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
54 | |||
55 | static 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 | |||
115 | static 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 | |||
128 | static 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 | |||
222 | static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; | ||
223 | |||
224 | static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d }; | ||
225 | |||
226 | static const __u8 I2c3[] = { 0x12, 0x05 }; | ||
227 | |||
228 | static const __u8 I2c4[] = { 0x41, 0x08 }; | ||
229 | |||
230 | /* read 'len' bytes to gspca_dev->usb_buf */ | ||
231 | static 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 | |||
253 | static 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 | |||
268 | static 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 | |||
290 | static 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 | |||
311 | static 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 | |||
326 | static 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 | |||
338 | static 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 | |||
352 | static 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 | |||
465 | static 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 | |||
475 | static 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 | |||
485 | static 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 | |||
505 | static 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 | |||
516 | static 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 | |||
526 | static 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 */ | ||
628 | static 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 */ | ||
653 | static 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 -- */ | ||
667 | static 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 | |||
683 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
684 | { | ||
685 | et_video(gspca_dev, 0); /* video off */ | ||
686 | } | ||
687 | |||
688 | static __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 | |||
700 | static 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 | |||
717 | static 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 | |||
754 | static 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 | |||
781 | static 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 | |||
791 | static 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 | |||
799 | static 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 | |||
809 | static 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 | |||
817 | static 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 | |||
827 | static 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 | |||
835 | static 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 | |||
845 | static 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 */ | ||
854 | static 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 -- */ | ||
867 | static 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 | |||
875 | MODULE_DEVICE_TABLE(usb, device_table); | ||
876 | |||
877 | /* -- device connect -- */ | ||
878 | static 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 | |||
885 | static 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 -- */ | ||
897 | static int __init sd_mod_init(void) | ||
898 | { | ||
899 | return usb_register(&sd_driver); | ||
900 | } | ||
901 | |||
902 | static void __exit sd_mod_exit(void) | ||
903 | { | ||
904 | usb_deregister(&sd_driver); | ||
905 | } | ||
906 | |||
907 | module_init(sd_mod_init); | ||
908 | module_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 | |||
25 | MODULE_AUTHOR("Frank Zago <frank@zago.net>"); | ||
26 | MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); | ||
27 | MODULE_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 */ | ||
38 | struct 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. */ | ||
52 | static 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 */ | ||
61 | static 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 */ | ||
79 | static 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 */ | ||
94 | again: | ||
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 | |||
149 | out: | ||
150 | PDEBUG(D_STREAM, "dostream stopped"); | ||
151 | } | ||
152 | |||
153 | /* this function is called at probe time */ | ||
154 | static 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 */ | ||
171 | static int sd_init(struct gspca_dev *gspca_dev) | ||
172 | { | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /* start the camera */ | ||
177 | static 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 */ | ||
220 | static 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 */ | ||
232 | static 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 | |||
259 | MODULE_DEVICE_TABLE(usb, device_table); | ||
260 | |||
261 | /* sub-driver description */ | ||
262 | static 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 -- */ | ||
271 | static 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 | |||
280 | static 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 -- */ | ||
292 | static int __init sd_mod_init(void) | ||
293 | { | ||
294 | return usb_register(&sd_driver); | ||
295 | } | ||
296 | |||
297 | static void __exit sd_mod_exit(void) | ||
298 | { | ||
299 | usb_deregister(&sd_driver); | ||
300 | } | ||
301 | |||
302 | module_init(sd_mod_init); | ||
303 | module_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 @@ | |||
1 | config 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 @@ | |||
1 | obj-$(CONFIG_USB_GL860) += gspca_gl860.o | ||
2 | |||
3 | gspca_gl860-objs := gl860.o \ | ||
4 | gl860-mi1320.o \ | ||
5 | gl860-ov2640.o \ | ||
6 | gl860-ov9655.o \ | ||
7 | gl860-mi2020.o | ||
8 | |||
9 | EXTRA_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 | |||
22 | static 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 | |||
35 | static 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 | |||
42 | static struct validx tbl_sensor_settings_common[] = { | ||
43 | {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000}, | ||
44 | {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006}, | ||
45 | }; | ||
46 | static 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 | }; | ||
50 | static 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 | }; | ||
54 | static 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 | }; | ||
59 | static struct validx tbl_post_unset_alt[] = { | ||
60 | {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1}, | ||
61 | {0x0061, 0x0000}, {0x0068, 0x000d}, | ||
62 | }; | ||
63 | |||
64 | static 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 | |||
77 | static 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 | |||
90 | static 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 | |||
103 | static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d}; | ||
104 | static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70}; | ||
105 | static s32 tbl_backlight[] = {0x0e, 0x06, 0x02}; | ||
106 | |||
107 | static s32 tbl_cntr1[] = { | ||
108 | 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0}; | ||
109 | static s32 tbl_cntr2[] = { | ||
110 | 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10}; | ||
111 | |||
112 | static 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 | |||
117 | static 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 | |||
122 | static 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 | |||
127 | static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00}; | ||
128 | |||
129 | static 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"; | ||
132 | static 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"; | ||
135 | static 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"; | ||
139 | static 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"; | ||
143 | static u8 dat_common04[] = | ||
144 | "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43"; | ||
145 | static 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"; | ||
149 | static 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"; | ||
153 | static 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"; | ||
158 | static 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"; | ||
162 | static 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"; | ||
166 | static 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"; | ||
171 | static 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 | |||
176 | static int mi1320_init_at_startup(struct gspca_dev *gspca_dev); | ||
177 | static int mi1320_configure_alt(struct gspca_dev *gspca_dev); | ||
178 | static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev); | ||
179 | static int mi1320_init_post_alt(struct gspca_dev *gspca_dev); | ||
180 | static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev); | ||
181 | static int mi1320_sensor_settings(struct gspca_dev *gspca_dev); | ||
182 | static int mi1320_camera_settings(struct gspca_dev *gspca_dev); | ||
183 | /*==========================================================================*/ | ||
184 | |||
185 | void 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 | |||
222 | static 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 | |||
248 | static 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 | |||
260 | static 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 | |||
287 | static int mi1320_init_post_alt(struct gspca_dev *gspca_dev) | ||
288 | { | ||
289 | mi1320_camera_settings(gspca_dev); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static 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 | |||
331 | static 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 | |||
348 | static 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 | |||
530 | static 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 | |||
24 | static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c}; | ||
25 | |||
26 | static u8 dat_bright1[] = {0x8c, 0xa2, 0x06}; | ||
27 | static u8 dat_bright3[] = {0x8c, 0xa1, 0x02}; | ||
28 | static u8 dat_bright4[] = {0x90, 0x00, 0x0f}; | ||
29 | static u8 dat_bright5[] = {0x8c, 0xa1, 0x03}; | ||
30 | static u8 dat_bright6[] = {0x90, 0x00, 0x05}; | ||
31 | |||
32 | static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19}; | ||
33 | static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b}; | ||
34 | static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03}; | ||
35 | static u8 dat_hvflip6[] = {0x90, 0x00, 0x06}; | ||
36 | |||
37 | static 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 | |||
48 | static 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 | |||
56 | static 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 | |||
66 | static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 }; | ||
67 | |||
68 | static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; | ||
69 | static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; | ||
70 | |||
71 | static 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 | |||
78 | static 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 | |||
84 | static 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 | |||
179 | static 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 | |||
188 | static 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 | |||
196 | static 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 | |||
219 | static 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 | |||
249 | static 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 | |||
278 | static u8 *dat_640 = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81"; | ||
279 | static u8 *dat_800 = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21"; | ||
280 | static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01"; | ||
281 | static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41"; | ||
282 | |||
283 | static int mi2020_init_at_startup(struct gspca_dev *gspca_dev); | ||
284 | static int mi2020_configure_alt(struct gspca_dev *gspca_dev); | ||
285 | static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev); | ||
286 | static int mi2020_init_post_alt(struct gspca_dev *gspca_dev); | ||
287 | static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev); | ||
288 | static int mi2020_camera_settings(struct gspca_dev *gspca_dev); | ||
289 | /*==========================================================================*/ | ||
290 | |||
291 | void 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 | |||
328 | static 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 | |||
335 | static 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 | |||
358 | static 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 | |||
379 | static 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 | |||
543 | static 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 | |||
561 | static 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 | |||
728 | static 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 | |||
22 | static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; | ||
23 | |||
24 | static u8 c61[] = {0x61}; /* expected */ | ||
25 | static u8 c51[] = {0x51}; /* expected */ | ||
26 | static u8 c50[] = {0x50}; /* expected */ | ||
27 | static u8 c28[] = {0x28}; /* expected */ | ||
28 | static u8 ca8[] = {0xa8}; /* expected */ | ||
29 | |||
30 | static u8 dat_post[] = | ||
31 | "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; | ||
32 | |||
33 | static u8 dat_640[] = "\xd0\x01\xd1\x08\xd2\xe0\xd3\x02\xd4\x10\xd5\x81"; | ||
34 | static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21"; | ||
35 | static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; | ||
36 | static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; | ||
37 | |||
38 | static 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 | |||
47 | static 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 | |||
94 | static 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 | |||
106 | static struct validx tbl_sensor_settings_common2[] = { | ||
107 | {0x6001, 0x00ff}, {0x6038, 0x000c}, | ||
108 | {10, 0xffff}, | ||
109 | {0x6000, 0x0011}, | ||
110 | }; | ||
111 | |||
112 | static 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 | |||
126 | static 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 | |||
138 | static 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 | |||
148 | static 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 | |||
155 | static 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 | |||
168 | static 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 | |||
175 | static int ov2640_init_at_startup(struct gspca_dev *gspca_dev); | ||
176 | static int ov2640_configure_alt(struct gspca_dev *gspca_dev); | ||
177 | static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev); | ||
178 | static int ov2640_init_post_alt(struct gspca_dev *gspca_dev); | ||
179 | static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev); | ||
180 | static int ov2640_camera_settings(struct gspca_dev *gspca_dev); | ||
181 | /*==========================================================================*/ | ||
182 | |||
183 | void 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 | |||
219 | static void common(struct gspca_dev *gspca_dev) | ||
220 | { | ||
221 | fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); | ||
222 | } | ||
223 | |||
224 | static 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 | |||
245 | static 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 | |||
267 | static 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 | |||
329 | static 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 | |||
347 | static 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 | |||
483 | static 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 | |||
23 | static 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 | |||
30 | static 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 | |||
37 | static s32 tbl_length[] = {12, 56, 52, 54, 56, 42, 32, 12}; | ||
38 | |||
39 | static 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 | |||
72 | static 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 | |||
105 | static u8 c04[] = {0x04}; | ||
106 | static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02"; | ||
107 | static u8 dat_post2[] = "\x10\x10\xc1\x02"; | ||
108 | static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04"; | ||
109 | static u8 dat_post4[] = "\x10\x02\xc1\x06"; | ||
110 | static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08"; | ||
111 | static u8 dat_post6[] = "\x10\x10\xc1\x05"; | ||
112 | static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08"; | ||
113 | static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09"; | ||
114 | |||
115 | static 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 | |||
145 | static int ov9655_init_at_startup(struct gspca_dev *gspca_dev); | ||
146 | static int ov9655_configure_alt(struct gspca_dev *gspca_dev); | ||
147 | static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev); | ||
148 | static int ov9655_init_post_alt(struct gspca_dev *gspca_dev); | ||
149 | static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev); | ||
150 | static int ov9655_camera_settings(struct gspca_dev *gspca_dev); | ||
151 | /*==========================================================================*/ | ||
152 | |||
153 | void 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 | |||
187 | static 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 | |||
197 | static 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 | |||
211 | static 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 | |||
290 | static 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 | |||
306 | static 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 | |||
332 | static 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 | |||
24 | MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>"); | ||
25 | MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver"); | ||
26 | MODULE_LICENSE("GPL"); | ||
27 | |||
28 | /*======================== static function declarations ====================*/ | ||
29 | |||
30 | static void (*dev_init_settings)(struct gspca_dev *gspca_dev); | ||
31 | |||
32 | static int sd_config(struct gspca_dev *gspca_dev, | ||
33 | const struct usb_device_id *id); | ||
34 | static int sd_init(struct gspca_dev *gspca_dev); | ||
35 | static int sd_isoc_init(struct gspca_dev *gspca_dev); | ||
36 | static int sd_start(struct gspca_dev *gspca_dev); | ||
37 | static void sd_stop0(struct gspca_dev *gspca_dev); | ||
38 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
39 | u8 *data, int len); | ||
40 | static void sd_callback(struct gspca_dev *gspca_dev); | ||
41 | |||
42 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | ||
43 | u16 vendor_id, u16 product_id); | ||
44 | |||
45 | /*============================ driver options ==============================*/ | ||
46 | |||
47 | static s32 AC50Hz = 0xff; | ||
48 | module_param(AC50Hz, int, 0644); | ||
49 | MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)"); | ||
50 | |||
51 | static char sensor[7]; | ||
52 | module_param_string(sensor, sensor, sizeof(sensor), 0644); | ||
53 | MODULE_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) \ | ||
60 | static 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 | } \ | ||
69 | static 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 | |||
77 | SD_SETGET(mirror) | ||
78 | SD_SETGET(flip) | ||
79 | SD_SETGET(AC50Hz) | ||
80 | SD_SETGET(backlight) | ||
81 | SD_SETGET(brightness) | ||
82 | SD_SETGET(gamma) | ||
83 | SD_SETGET(hue) | ||
84 | SD_SETGET(saturation) | ||
85 | SD_SETGET(sharpness) | ||
86 | SD_SETGET(whitebal) | ||
87 | SD_SETGET(contrast) | ||
88 | |||
89 | #define GL860_NCTRLS 11 | ||
90 | |||
91 | /* control table */ | ||
92 | static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; | ||
93 | static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; | ||
94 | static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; | ||
95 | static 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 | |||
113 | static 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 | |||
161 | static 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 | |||
174 | static 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 | |||
187 | static 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 | |||
200 | static 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 | |||
215 | static 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 | |||
242 | static 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 | |||
269 | static 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 | |||
290 | static 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 */ | ||
308 | static 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 */ | ||
378 | static 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 */ | ||
386 | static 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 */ | ||
394 | static 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 */ | ||
402 | static 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 */ | ||
410 | static 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 */ | ||
450 | static 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 | |||
491 | static const struct usb_device_id device_table[] = { | ||
492 | {USB_DEVICE(0x05e3, 0x0503)}, | ||
493 | {USB_DEVICE(0x05e3, 0xf191)}, | ||
494 | {} | ||
495 | }; | ||
496 | |||
497 | MODULE_DEVICE_TABLE(usb, device_table); | ||
498 | |||
499 | static 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 | |||
506 | static void sd_disconnect(struct usb_interface *intf) | ||
507 | { | ||
508 | gspca_disconnect(intf); | ||
509 | } | ||
510 | |||
511 | static 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 | |||
524 | static 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 | |||
533 | static void __exit sd_mod_exit(void) | ||
534 | { | ||
535 | usb_deregister(&sd_driver); | ||
536 | } | ||
537 | |||
538 | module_init(sd_mod_init); | ||
539 | module_exit(sd_mod_exit); | ||
540 | |||
541 | /*==========================================================================*/ | ||
542 | |||
543 | int 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 | |||
586 | int 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 | |||
602 | int 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 | |||
617 | void 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 | |||
630 | static 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 | |||
45 | struct 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 */ | ||
60 | struct 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 | |||
81 | struct validx { | ||
82 | u16 val; | ||
83 | u16 idx; | ||
84 | }; | ||
85 | |||
86 | struct idxdata { | ||
87 | u8 idx; | ||
88 | u8 data[3]; | ||
89 | }; | ||
90 | |||
91 | int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len); | ||
92 | int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl, | ||
93 | int len, int n); | ||
94 | void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len); | ||
95 | |||
96 | int gl860_RTx(struct gspca_dev *gspca_dev, | ||
97 | unsigned char pref, u32 req, u16 val, u16 index, | ||
98 | s32 len, void *pdata); | ||
99 | |||
100 | void mi1320_init_settings(struct gspca_dev *); | ||
101 | void ov2640_init_settings(struct gspca_dev *); | ||
102 | void ov9655_init_settings(struct gspca_dev *); | ||
103 | void 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 | |||
55 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); | ||
56 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | ||
57 | MODULE_LICENSE("GPL"); | ||
58 | MODULE_VERSION(DRIVER_VERSION_NUMBER); | ||
59 | |||
60 | #ifdef GSPCA_DEBUG | ||
61 | int gspca_debug = D_ERR | D_PROBE; | ||
62 | EXPORT_SYMBOL(gspca_debug); | ||
63 | |||
64 | static 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 | */ | ||
94 | static 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 | |||
102 | static 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 | |||
110 | static 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) | ||
119 | static 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 | |||
155 | static 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 | |||
192 | static 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 | |||
235 | error_submit: | ||
236 | usb_free_coherent(dev, | ||
237 | urb->transfer_buffer_length, | ||
238 | urb->transfer_buffer, | ||
239 | urb->transfer_dma); | ||
240 | error_buffer: | ||
241 | usb_free_urb(urb); | ||
242 | error: | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | static 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 | |||
268 | static 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 | ||
284 | static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) | ||
285 | { | ||
286 | } | ||
287 | |||
288 | static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev) | ||
289 | { | ||
290 | } | ||
291 | |||
292 | static 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 | */ | ||
301 | static 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 | |||
345 | resubmit: | ||
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 | */ | ||
357 | static 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 | */ | ||
370 | static 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 | |||
398 | resubmit: | ||
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 | */ | ||
418 | void 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 | } | ||
498 | EXPORT_SYMBOL(gspca_frame_add); | ||
499 | |||
500 | static 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 | |||
513 | static 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 | |||
553 | static 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 | |||
570 | static 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 | |||
592 | static 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 */ | ||
605 | static 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 | */ | ||
626 | static 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 | */ | ||
651 | static 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 | */ | ||
695 | static 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 | */ | ||
775 | static 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 | } | ||
879 | out: | ||
880 | gspca_input_create_urb(gspca_dev); | ||
881 | unlock: | ||
882 | mutex_unlock(&gspca_dev->usb_lock); | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | static 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 | |||
908 | static 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 | */ | ||
924 | static 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 | ||
947 | static 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 | |||
971 | static 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 | |||
996 | static 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 | |||
1017 | static 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 | |||
1057 | static 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 | |||
1069 | static 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 | |||
1101 | static 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 | |||
1114 | static 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; | ||
1148 | out: | ||
1149 | mutex_unlock(&gspca_dev->queue_lock); | ||
1150 | return ret; | ||
1151 | } | ||
1152 | |||
1153 | static 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 | |||
1179 | static 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 | |||
1207 | static 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 | |||
1218 | static 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 | |||
1244 | static 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 | |||
1271 | static 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; | ||
1301 | out: | ||
1302 | mutex_unlock(&gspca_dev->usb_lock); | ||
1303 | return ret; | ||
1304 | } | ||
1305 | |||
1306 | static 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 | |||
1323 | static 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 | |||
1366 | static 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; | ||
1410 | out: | ||
1411 | mutex_unlock(&gspca_dev->usb_lock); | ||
1412 | return ret; | ||
1413 | } | ||
1414 | |||
1415 | static 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; | ||
1441 | out: | ||
1442 | mutex_unlock(&gspca_dev->usb_lock); | ||
1443 | return ret; | ||
1444 | } | ||
1445 | |||
1446 | static 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 | |||
1456 | static 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 | |||
1470 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
1471 | { | ||
1472 | *i = 0; | ||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | static 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 | |||
1483 | static 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 | } | ||
1548 | out: | ||
1549 | mutex_unlock(&gspca_dev->queue_lock); | ||
1550 | PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count); | ||
1551 | return ret; | ||
1552 | } | ||
1553 | |||
1554 | static 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 | |||
1569 | static 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; | ||
1605 | out: | ||
1606 | mutex_unlock(&gspca_dev->queue_lock); | ||
1607 | return ret; | ||
1608 | } | ||
1609 | |||
1610 | static 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; | ||
1649 | out: | ||
1650 | mutex_unlock(&gspca_dev->queue_lock); | ||
1651 | return ret; | ||
1652 | } | ||
1653 | |||
1654 | static 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 | |||
1673 | static 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 | |||
1692 | static 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 | |||
1718 | static 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 | |||
1749 | static 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; | ||
1816 | out: | ||
1817 | mutex_unlock(&gspca_dev->queue_lock); | ||
1818 | return ret; | ||
1819 | } | ||
1820 | |||
1821 | static 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 | |||
1834 | static 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 | */ | ||
1851 | static 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 | } | ||
1916 | out: | ||
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 | */ | ||
1927 | static 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; | ||
1974 | out: | ||
1975 | mutex_unlock(&gspca_dev->queue_lock); | ||
1976 | return ret; | ||
1977 | } | ||
1978 | |||
1979 | /* | ||
1980 | * allocate the resources for read() | ||
1981 | */ | ||
1982 | static 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 | |||
2022 | static 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 | |||
2052 | static 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; | ||
2109 | out: | ||
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 | |||
2117 | static 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 | |||
2127 | static 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 | |||
2159 | static 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 */ | ||
2167 | static 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 | */ | ||
2188 | int 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; | ||
2277 | out: | ||
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 | } | ||
2286 | EXPORT_SYMBOL(gspca_dev_probe2); | ||
2287 | |||
2288 | /* same function as the previous one, but check the interface */ | ||
2289 | int 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 | } | ||
2311 | EXPORT_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 | */ | ||
2319 | void 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 | } | ||
2356 | EXPORT_SYMBOL(gspca_disconnect); | ||
2357 | |||
2358 | #ifdef CONFIG_PM | ||
2359 | int 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 | } | ||
2375 | EXPORT_SYMBOL(gspca_suspend); | ||
2376 | |||
2377 | int 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 | } | ||
2388 | EXPORT_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. */ | ||
2397 | int 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 | } | ||
2478 | EXPORT_SYMBOL(gspca_auto_gain_n_exposure); | ||
2479 | |||
2480 | /* -- module insert / remove -- */ | ||
2481 | static int __init gspca_init(void) | ||
2482 | { | ||
2483 | info("v" DRIVER_VERSION_NUMBER " registered"); | ||
2484 | return 0; | ||
2485 | } | ||
2486 | static void __exit gspca_exit(void) | ||
2487 | { | ||
2488 | } | ||
2489 | |||
2490 | module_init(gspca_init); | ||
2491 | module_exit(gspca_exit); | ||
2492 | |||
2493 | #ifdef GSPCA_DEBUG | ||
2494 | module_param_named(debug, gspca_debug, int, 0644); | ||
2495 | MODULE_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 */ | ||
16 | extern 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) */ | ||
50 | struct framerates { | ||
51 | const u8 *rates; | ||
52 | int nrates; | ||
53 | }; | ||
54 | |||
55 | /* control definition */ | ||
56 | struct 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 */ | ||
63 | struct 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 | |||
83 | struct gspca_dev; | ||
84 | struct gspca_frame; | ||
85 | |||
86 | /* subdriver operations */ | ||
87 | typedef int (*cam_op) (struct gspca_dev *); | ||
88 | typedef void (*cam_v_op) (struct gspca_dev *); | ||
89 | typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *); | ||
90 | typedef int (*cam_jpg_op) (struct gspca_dev *, | ||
91 | struct v4l2_jpegcompression *); | ||
92 | typedef int (*cam_reg_op) (struct gspca_dev *, | ||
93 | struct v4l2_dbg_register *); | ||
94 | typedef int (*cam_ident_op) (struct gspca_dev *, | ||
95 | struct v4l2_dbg_chip_ident *); | ||
96 | typedef void (*cam_streamparm_op) (struct gspca_dev *, | ||
97 | struct v4l2_streamparm *); | ||
98 | typedef int (*cam_qmnu_op) (struct gspca_dev *, | ||
99 | struct v4l2_querymenu *); | ||
100 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, | ||
101 | u8 *data, | ||
102 | int len); | ||
103 | typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev, | ||
104 | u8 *data, | ||
105 | int len); | ||
106 | |||
107 | struct 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 */ | ||
115 | struct 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 */ | ||
151 | enum gspca_packet_type { | ||
152 | DISCARD_PACKET, | ||
153 | FIRST_PACKET, | ||
154 | INTER_PACKET, | ||
155 | LAST_PACKET | ||
156 | }; | ||
157 | |||
158 | struct gspca_frame { | ||
159 | __u8 *data; /* frame buffer */ | ||
160 | int vma_use_count; | ||
161 | struct v4l2_buffer v4l2_buf; | ||
162 | }; | ||
163 | |||
164 | struct 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 | |||
223 | int 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); | ||
228 | int 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); | ||
233 | void gspca_disconnect(struct usb_interface *intf); | ||
234 | void 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 | ||
239 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); | ||
240 | int gspca_resume(struct usb_interface *intf); | ||
241 | #endif | ||
242 | int 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 | |||
33 | MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); | ||
34 | MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver"); | ||
35 | MODULE_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 | |||
47 | enum { | ||
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 | |||
55 | enum 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 */ | ||
65 | struct 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 | |||
79 | struct 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. */ | ||
86 | static 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 */ | ||
105 | static 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 */ | ||
123 | static 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 | |||
140 | static 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 | |||
154 | static 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 | |||
172 | static 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 | |||
186 | static 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 | |||
200 | static 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 | |||
214 | static 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 | |||
228 | static 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 | |||
296 | static 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 | |||
353 | static 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; | ||
391 | discard: | ||
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 */ | ||
397 | static 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 | |||
421 | static 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 */ | ||
457 | static int sd_init(struct gspca_dev *gspca_dev) | ||
458 | { | ||
459 | return gspca_dev->usb_err; | ||
460 | } | ||
461 | |||
462 | /* Set up for getting frames. */ | ||
463 | static 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 */ | ||
478 | static 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 | |||
484 | MODULE_DEVICE_TABLE(usb, device_table); | ||
485 | |||
486 | static 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 | |||
507 | static 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 | |||
525 | static 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 */ | ||
539 | static 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 */ | ||
549 | static 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 | |||
563 | static const struct sd_desc *sd_desc[2] = { | ||
564 | &sd_desc_sakar_57379, | ||
565 | &sd_desc_sportscam_dv15 | ||
566 | }; | ||
567 | |||
568 | /* -- device connect -- */ | ||
569 | static 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 | |||
578 | static 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 -- */ | ||
590 | static int __init sd_mod_init(void) | ||
591 | { | ||
592 | return usb_register(&sd_driver); | ||
593 | } | ||
594 | |||
595 | static void __exit sd_mod_exit(void) | ||
596 | { | ||
597 | usb_deregister(&sd_driver); | ||
598 | } | ||
599 | |||
600 | module_init(sd_mod_init); | ||
601 | module_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 */ | ||
33 | static const u8 jpeg_head[] = { | ||
34 | 0xff, 0xd8, /* jpeg */ | ||
35 | |||
36 | /* quantization table quality 50% */ | ||
37 | 0xff, 0xdb, 0x00, 0x84, /* DQT */ | ||
38 | 0, | ||
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, | ||
48 | 1, | ||
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 */ | ||
136 | static 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 */ | ||
152 | static 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 | |||
33 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
34 | MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | #ifdef GSPCA_DEBUG | ||
38 | int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK | | ||
39 | D_USBI | D_USBO | D_V4L2; | ||
40 | #endif | ||
41 | |||
42 | struct 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 | |||
53 | struct 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 */ | ||
61 | struct 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 | |||
72 | static 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 | |||
85 | static 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 | |||
113 | static 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 | |||
123 | static 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 | |||
132 | static 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 | |||
206 | static 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 */ | ||
228 | static 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 */ | ||
255 | static int sd_init(struct gspca_dev *gspca_dev) | ||
256 | { | ||
257 | PDEBUG(D_PROBE, "Kinect Camera device."); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static 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 | |||
334 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
335 | { | ||
336 | /* reset video stream */ | ||
337 | write_register(gspca_dev, 0x05, 0x00); | ||
338 | } | ||
339 | |||
340 | static 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 */ | ||
375 | static 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 -- */ | ||
392 | static const struct usb_device_id device_table[] = { | ||
393 | {USB_DEVICE(0x045e, 0x02ae)}, | ||
394 | {} | ||
395 | }; | ||
396 | |||
397 | MODULE_DEVICE_TABLE(usb, device_table); | ||
398 | |||
399 | /* -- device connect -- */ | ||
400 | static 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 | |||
406 | static 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 -- */ | ||
418 | static int __init sd_mod_init(void) | ||
419 | { | ||
420 | return usb_register(&sd_driver); | ||
421 | } | ||
422 | |||
423 | static void __exit sd_mod_exit(void) | ||
424 | { | ||
425 | usb_deregister(&sd_driver); | ||
426 | } | ||
427 | |||
428 | module_init(sd_mod_init); | ||
429 | module_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 | |||
36 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
37 | MODULE_DESCRIPTION("Konica chipset USB Camera Driver"); | ||
38 | MODULE_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 */ | ||
47 | struct 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 */ | ||
59 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
60 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
61 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
62 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
63 | static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val); | ||
64 | static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val); | ||
65 | static int sd_setwhitebal(struct gspca_dev *gspca_dev, __s32 val); | ||
66 | static int sd_getwhitebal(struct gspca_dev *gspca_dev, __s32 *val); | ||
67 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
68 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
69 | |||
70 | static 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 | */ | ||
167 | static 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 | |||
185 | static void sd_isoc_irq(struct urb *urb); | ||
186 | |||
187 | static 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 | |||
208 | static 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 | |||
229 | static void konica_stream_on(struct gspca_dev *gspca_dev) | ||
230 | { | ||
231 | reg_w(gspca_dev, 1, 0x0b); | ||
232 | } | ||
233 | |||
234 | static 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 */ | ||
240 | static 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 */ | ||
262 | static 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 | |||
276 | static 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 | |||
350 | static 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 */ | ||
367 | static 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 | |||
471 | resubmit: | ||
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 | |||
483 | static 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 | |||
497 | static 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 | |||
506 | static 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 | |||
520 | static 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 | |||
529 | static 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 | |||
542 | static 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 | |||
551 | static 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 | |||
564 | static 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 | |||
573 | static 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 | |||
586 | static 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 */ | ||
596 | static 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 -- */ | ||
610 | static const struct usb_device_id device_table[] = { | ||
611 | {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */ | ||
612 | {} | ||
613 | }; | ||
614 | MODULE_DEVICE_TABLE(usb, device_table); | ||
615 | |||
616 | /* -- device connect -- */ | ||
617 | static 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 | |||
624 | static 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 -- */ | ||
636 | static int __init sd_mod_init(void) | ||
637 | { | ||
638 | return usb_register(&sd_driver); | ||
639 | } | ||
640 | static void __exit sd_mod_exit(void) | ||
641 | { | ||
642 | usb_deregister(&sd_driver); | ||
643 | } | ||
644 | |||
645 | module_init(sd_mod_init); | ||
646 | module_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 @@ | |||
1 | config 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 @@ | |||
1 | obj-$(CONFIG_USB_M5602) += gspca_m5602.o | ||
2 | |||
3 | gspca_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 | |||
11 | EXTRA_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 */ | ||
119 | static const unsigned char bridge_urb_skeleton[] = { | ||
120 | 0x13, 0x00, 0x81, 0x00 | ||
121 | }; | ||
122 | |||
123 | /* A skeleton used for sending messages to the sensor */ | ||
124 | static 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 | |||
133 | struct 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 | |||
151 | int m5602_read_bridge( | ||
152 | struct sd *sd, const u8 address, u8 *i2c_data); | ||
153 | |||
154 | int m5602_write_bridge( | ||
155 | struct sd *sd, const u8 address, const u8 i2c_data); | ||
156 | |||
157 | int m5602_write_sensor(struct sd *sd, const u8 address, | ||
158 | u8 *i2c_data, const u8 len); | ||
159 | |||
160 | int 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 */ | ||
27 | int force_sensor; | ||
28 | static int dump_bridge; | ||
29 | int dump_sensor; | ||
30 | |||
31 | static const struct usb_device_id m5602_table[] = { | ||
32 | {USB_DEVICE(0x0402, 0x5602)}, | ||
33 | {} | ||
34 | }; | ||
35 | |||
36 | MODULE_DEVICE_TABLE(usb, m5602_table); | ||
37 | |||
38 | /* Reads a byte from the m5602 */ | ||
39 | int 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 */ | ||
60 | int 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 | |||
84 | static 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 | |||
95 | int 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 | |||
143 | int 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 */ | ||
189 | static 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 | |||
201 | static 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 | |||
239 | static int m5602_configure(struct gspca_dev *gspca_dev, | ||
240 | const struct usb_device_id *id); | ||
241 | |||
242 | static 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 | |||
254 | static 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 | |||
276 | static 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 | |||
329 | static 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 */ | ||
339 | static 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 */ | ||
349 | static 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 | |||
369 | fail: | ||
370 | PDEBUG(D_ERR, "ALi m5602 webcam failed"); | ||
371 | cam->cam_mode = NULL; | ||
372 | cam->nmodes = 0; | ||
373 | |||
374 | return err; | ||
375 | } | ||
376 | |||
377 | static 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 | |||
384 | static 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 | |||
395 | static 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 -- */ | ||
407 | static int __init mod_m5602_init(void) | ||
408 | { | ||
409 | return usb_register(&sd_driver); | ||
410 | } | ||
411 | |||
412 | static void __exit mod_m5602_exit(void) | ||
413 | { | ||
414 | usb_deregister(&sd_driver); | ||
415 | } | ||
416 | |||
417 | module_init(mod_m5602_init); | ||
418 | module_exit(mod_m5602_exit); | ||
419 | |||
420 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
421 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
422 | MODULE_LICENSE("GPL"); | ||
423 | module_param(force_sensor, int, S_IRUGO | S_IWUSR); | ||
424 | MODULE_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 | |||
429 | module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); | ||
430 | MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); | ||
431 | |||
432 | module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); | ||
433 | MODULE_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 | |||
21 | static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
22 | static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
23 | static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
24 | static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
25 | static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
28 | __s32 val); | ||
29 | static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
30 | __s32 *val); | ||
31 | static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
36 | static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
37 | |||
38 | static 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 | |||
51 | static 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 | |||
156 | static void mt9m111_dump_registers(struct sd *sd); | ||
157 | |||
158 | int 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 | |||
200 | sensor_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 | |||
218 | int 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 | |||
268 | int 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 | |||
359 | void mt9m111_disconnect(struct sd *sd) | ||
360 | { | ||
361 | sd->sensor = NULL; | ||
362 | kfree(sd->sensor_priv); | ||
363 | } | ||
364 | |||
365 | static 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 | |||
376 | static 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 | |||
405 | static 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 | |||
416 | static 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 | |||
445 | static 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 | |||
456 | static 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 | |||
477 | static 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 | |||
487 | static 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 | |||
528 | static 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 | |||
549 | static 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 | |||
559 | static 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 | |||
575 | static 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 | |||
585 | static 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 | |||
601 | static 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 | |||
611 | static 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 */ | ||
108 | extern int force_sensor; | ||
109 | extern int dump_sensor; | ||
110 | |||
111 | int mt9m111_probe(struct sd *sd); | ||
112 | int mt9m111_init(struct sd *sd); | ||
113 | int mt9m111_start(struct sd *sd); | ||
114 | void mt9m111_disconnect(struct sd *sd); | ||
115 | |||
116 | static 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 | |||
128 | static 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 | |||
167 | static 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 | |||
258 | static 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 | |||
21 | static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
22 | static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
23 | static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
24 | __s32 *val); | ||
25 | static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
26 | __s32 val); | ||
27 | static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | |||
36 | static 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 | |||
127 | static 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 | |||
141 | static void ov7660_dump_registers(struct sd *sd); | ||
142 | |||
143 | int 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 | |||
191 | sensor_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 | |||
209 | int 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 | |||
261 | int ov7660_start(struct sd *sd) | ||
262 | { | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | int ov7660_stop(struct sd *sd) | ||
267 | { | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | void ov7660_disconnect(struct sd *sd) | ||
272 | { | ||
273 | ov7660_stop(sd); | ||
274 | |||
275 | sd->sensor = NULL; | ||
276 | kfree(sd->sensor_priv); | ||
277 | } | ||
278 | |||
279 | static 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 | |||
289 | static 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 | |||
305 | static 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 | |||
315 | static 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 | |||
336 | static 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 | |||
346 | static 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 | |||
365 | static 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 | |||
375 | static 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 | |||
395 | static 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 | |||
405 | static 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 | |||
424 | static 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 | |||
435 | static 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 | |||
457 | static 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 */ | ||
88 | extern int force_sensor; | ||
89 | extern int dump_sensor; | ||
90 | |||
91 | int ov7660_probe(struct sd *sd); | ||
92 | int ov7660_init(struct sd *sd); | ||
93 | int ov7660_start(struct sd *sd); | ||
94 | int ov7660_stop(struct sd *sd); | ||
95 | void ov7660_disconnect(struct sd *sd); | ||
96 | |||
97 | static 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 | |||
108 | static 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 | |||
142 | static 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 | |||
21 | static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
22 | static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
23 | static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
24 | static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
25 | static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
34 | __s32 *val); | ||
35 | static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
36 | __s32 val); | ||
37 | static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
38 | static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
39 | static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
40 | static 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 */ | ||
44 | static | ||
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 | |||
114 | static 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 | |||
248 | static 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 | |||
292 | static void ov9650_dump_registers(struct sd *sd); | ||
293 | |||
294 | int 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 | |||
338 | sensor_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 | |||
355 | int 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 | |||
415 | int 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 | |||
543 | int 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 | |||
549 | void ov9650_disconnect(struct sd *sd) | ||
550 | { | ||
551 | ov9650_stop(sd); | ||
552 | |||
553 | sd->sensor = NULL; | ||
554 | kfree(sd->sensor_priv); | ||
555 | } | ||
556 | |||
557 | static 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 | |||
567 | static 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 | |||
597 | static 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 | |||
607 | static 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 | |||
638 | static 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 | |||
648 | static 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 | |||
664 | static 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 | |||
675 | static 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 | |||
691 | static 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 | |||
701 | static 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 | |||
724 | static 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 | |||
735 | static 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 | |||
760 | static 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 | |||
770 | static 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 | |||
790 | static 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 | |||
800 | static 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 | |||
821 | static 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 | |||
831 | static 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 | |||
850 | static 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 */ | ||
137 | extern int force_sensor; | ||
138 | extern int dump_sensor; | ||
139 | |||
140 | int ov9650_probe(struct sd *sd); | ||
141 | int ov9650_init(struct sd *sd); | ||
142 | int ov9650_start(struct sd *sd); | ||
143 | int ov9650_stop(struct sd *sd); | ||
144 | void ov9650_disconnect(struct sd *sd); | ||
145 | |||
146 | static 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 | |||
157 | static 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 | |||
182 | static 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 | |||
298 | static 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 | |||
21 | static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
22 | static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
23 | static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
24 | static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
25 | static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
36 | __s32 val); | ||
37 | static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
38 | __s32 *val); | ||
39 | static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, | ||
40 | __s32 val); | ||
41 | static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, | ||
42 | __s32 *val); | ||
43 | |||
44 | static 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 | |||
57 | static 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 | |||
191 | static void po1030_dump_registers(struct sd *sd); | ||
192 | |||
193 | int 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 | |||
229 | sensor_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 | |||
247 | int 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 | |||
322 | int 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 | |||
449 | static 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 | |||
459 | static 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 | |||
487 | static 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 | |||
497 | static 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 | |||
513 | static 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 | |||
524 | static 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 | |||
546 | static 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 | |||
557 | static 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 | |||
579 | static 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 | |||
589 | static 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 | |||
605 | static 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 | |||
616 | static 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 | |||
633 | static 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 | |||
644 | static 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 | |||
664 | static 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 | |||
676 | static 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 | |||
696 | static 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 | |||
707 | static 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 | |||
725 | void po1030_disconnect(struct sd *sd) | ||
726 | { | ||
727 | sd->sensor = NULL; | ||
728 | kfree(sd->sensor_priv); | ||
729 | } | ||
730 | |||
731 | static 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 */ | ||
149 | extern int force_sensor; | ||
150 | extern int dump_sensor; | ||
151 | |||
152 | int po1030_probe(struct sd *sd); | ||
153 | int po1030_init(struct sd *sd); | ||
154 | int po1030_start(struct sd *sd); | ||
155 | void po1030_disconnect(struct sd *sd); | ||
156 | |||
157 | static 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 | |||
169 | static 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 | |||
195 | static 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 | |||
21 | static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
22 | static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
23 | static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
24 | static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
25 | static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | |||
34 | static | ||
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 | |||
117 | static 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 | |||
142 | static 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 | |||
232 | static void s5k4aa_dump_registers(struct sd *sd); | ||
233 | |||
234 | int 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 | |||
297 | sensor_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 | |||
315 | int 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 | |||
423 | int 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 | |||
461 | static 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 | |||
472 | static 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 | |||
494 | static 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 | |||
505 | static 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 | |||
542 | static 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 | |||
553 | static 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 | |||
590 | static 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 | |||
600 | static 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 | |||
620 | static 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 | |||
630 | static 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 | |||
648 | static 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 | |||
658 | static 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 | |||
676 | void s5k4aa_disconnect(struct sd *sd) | ||
677 | { | ||
678 | sd->sensor = NULL; | ||
679 | kfree(sd->sensor_priv); | ||
680 | } | ||
681 | |||
682 | static 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 */ | ||
67 | extern int force_sensor; | ||
68 | extern int dump_sensor; | ||
69 | |||
70 | int s5k4aa_probe(struct sd *sd); | ||
71 | int s5k4aa_init(struct sd *sd); | ||
72 | int s5k4aa_start(struct sd *sd); | ||
73 | void s5k4aa_disconnect(struct sd *sd); | ||
74 | |||
75 | static 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 | |||
86 | static 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 | |||
129 | static 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 | |||
180 | static 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 | |||
235 | static 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 | |||
22 | static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
23 | static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
24 | static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
25 | static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
29 | static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
30 | static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
31 | static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
32 | |||
33 | static 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 | |||
47 | static 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 | |||
124 | static void s5k83a_dump_registers(struct sd *sd); | ||
125 | static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); | ||
126 | static int s5k83a_set_led_indication(struct sd *sd, u8 val); | ||
127 | static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, | ||
128 | __s32 vflip, __s32 hflip); | ||
129 | |||
130 | int 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 | |||
173 | sensor_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 | |||
201 | int 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 | |||
261 | static 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, ®); | ||
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 | |||
304 | int 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 | |||
332 | int 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 | |||
342 | void 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 | |||
353 | static 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 | |||
362 | static 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 | |||
392 | static 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 | |||
401 | static 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 | |||
414 | static 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 | |||
423 | static 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 | |||
437 | static 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 | |||
446 | static 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 | |||
477 | static 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, ®); | ||
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 | |||
501 | static 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 | |||
510 | static 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, ®); | ||
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 | |||
534 | static 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 */ | ||
554 | static 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 | |||
561 | static 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 */ | ||
43 | extern int force_sensor; | ||
44 | extern int dump_sensor; | ||
45 | |||
46 | int s5k83a_probe(struct sd *sd); | ||
47 | int s5k83a_init(struct sd *sd); | ||
48 | int s5k83a_start(struct sd *sd); | ||
49 | int s5k83a_stop(struct sd *sd); | ||
50 | void s5k83a_disconnect(struct sd *sd); | ||
51 | |||
52 | static 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 | |||
63 | struct 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 | |||
70 | static 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 | */ | ||
110 | static 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 | |||
167 | static 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 */ | ||
28 | enum 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 */ | ||
38 | enum instruction { | ||
39 | BRIDGE, | ||
40 | SENSOR, | ||
41 | SENSOR_LONG | ||
42 | }; | ||
43 | |||
44 | struct 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 | |||
27 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
28 | MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); | ||
29 | MODULE_LICENSE("GPL"); | ||
30 | |||
31 | /* controls */ | ||
32 | enum 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 */ | ||
43 | struct 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 */ | ||
57 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
58 | static void setcolors(struct gspca_dev *gspca_dev); | ||
59 | static void setgamma(struct gspca_dev *gspca_dev); | ||
60 | static void setsharpness(struct gspca_dev *gspca_dev); | ||
61 | static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val); | ||
62 | static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val); | ||
63 | |||
64 | static 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 | |||
141 | static 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 | |||
154 | static 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 */ | ||
166 | static 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 | |||
187 | static 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 | |||
199 | static 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 | |||
208 | static 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 | |||
220 | static 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 | |||
229 | static 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 | |||
238 | static 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 */ | ||
253 | static 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 */ | ||
269 | static 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 | |||
275 | static 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 | |||
371 | static 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 | |||
388 | static 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 | |||
426 | static 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 | |||
438 | static 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 | |||
450 | static 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 | |||
466 | static 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 */ | ||
479 | static 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 -- */ | ||
493 | static const struct usb_device_id device_table[] = { | ||
494 | {USB_DEVICE(0x093a, 0x050f)}, | ||
495 | {} | ||
496 | }; | ||
497 | MODULE_DEVICE_TABLE(usb, device_table); | ||
498 | |||
499 | /* -- device connect -- */ | ||
500 | static 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 | |||
507 | static 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 -- */ | ||
519 | static int __init sd_mod_init(void) | ||
520 | { | ||
521 | return usb_register(&sd_driver); | ||
522 | } | ||
523 | static void __exit sd_mod_exit(void) | ||
524 | { | ||
525 | usb_deregister(&sd_driver); | ||
526 | } | ||
527 | |||
528 | module_init(sd_mod_init); | ||
529 | module_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 | |||
72 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," | ||
73 | "Theodore Kilgore <kilgota@auburn.edu>"); | ||
74 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); | ||
75 | MODULE_LICENSE("GPL"); | ||
76 | |||
77 | /* global parameters */ | ||
78 | static int force_sensor_type = -1; | ||
79 | module_param(force_sensor_type, int, 0644); | ||
80 | MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); | ||
81 | |||
82 | /* specific webcam descriptor */ | ||
83 | struct 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 | |||
98 | struct sensor_w_data { | ||
99 | u8 reg; | ||
100 | u8 flags; | ||
101 | u8 data[16]; | ||
102 | int len; | ||
103 | }; | ||
104 | |||
105 | static void sd_stopN(struct gspca_dev *gspca_dev); | ||
106 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
109 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
110 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
111 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
112 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
113 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
114 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | ||
115 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | ||
116 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
117 | static void setexposure(struct gspca_dev *gspca_dev); | ||
118 | static void setgain(struct gspca_dev *gspca_dev); | ||
119 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
120 | |||
121 | /* V4L2 controls supported by the driver */ | ||
122 | static 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 | |||
233 | static 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 */ | ||
262 | static 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 */ | ||
276 | static 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 | |||
289 | static 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 | |||
300 | static 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 | |||
315 | static 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 | |||
340 | static 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 | |||
362 | static 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 | |||
446 | static 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 | |||
453 | static 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 | |||
461 | static 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 | |||
469 | static 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 */ | ||
477 | static 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 */ | ||
666 | static int sd_init(struct gspca_dev *gspca_dev) | ||
667 | { | ||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | static 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 | |||
773 | static 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 | |||
926 | static 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 | |||
961 | static 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 | |||
972 | static 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 | |||
1011 | static 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 | |||
1066 | static 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 | |||
1086 | static 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 | |||
1097 | static 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 | |||
1107 | static 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 | |||
1115 | static 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 | |||
1125 | static 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 | |||
1133 | static 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 | |||
1143 | static 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 | |||
1151 | static 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 | |||
1162 | static 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 | |||
1170 | static 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 | |||
1180 | static 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 | |||
1191 | static 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 */ | ||
1220 | static 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 -- */ | ||
1232 | static 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 | }; | ||
1239 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1240 | |||
1241 | /* -- device connect -- */ | ||
1242 | static 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 | |||
1249 | static 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 -- */ | ||
1261 | static int __init sd_mod_init(void) | ||
1262 | { | ||
1263 | return usb_register(&sd_driver); | ||
1264 | } | ||
1265 | static void __exit sd_mod_exit(void) | ||
1266 | { | ||
1267 | usb_deregister(&sd_driver); | ||
1268 | } | ||
1269 | |||
1270 | module_init(sd_mod_init); | ||
1271 | module_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 | |||
27 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
28 | MODULE_DESCRIPTION("NW80x USB Camera Driver"); | ||
29 | MODULE_LICENSE("GPL"); | ||
30 | |||
31 | static int webcam; | ||
32 | |||
33 | /* controls */ | ||
34 | enum 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 */ | ||
44 | struct 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 | |||
59 | enum bridges { | ||
60 | BRIDGE_NW800, /* and et31x110 */ | ||
61 | BRIDGE_NW801, | ||
62 | BRIDGE_NW802, | ||
63 | }; | ||
64 | enum 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 | |||
82 | static 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 | */ | ||
156 | static 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 | }; | ||
166 | static 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 | |||
187 | static 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 | }; | ||
195 | static 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 */ | ||
351 | static 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 | }; | ||
406 | static 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 | }; | ||
418 | static 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 | }; | ||
429 | static 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?) */ | ||
458 | static 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 */ | ||
540 | static 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 | }; | ||
548 | static 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 */ | ||
635 | static 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 */ | ||
734 | static 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 */ | ||
814 | static 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*/ | ||
896 | static 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) */ | ||
980 | static 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 | }; | ||
1033 | static 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 | }; | ||
1046 | static 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 | }; | ||
1058 | static 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 */ | ||
1078 | static 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 */ | ||
1158 | static 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) */ | ||
1238 | static const u8 proscope_init[] = { | ||
1239 | 0x04, 0x05, 0x01, 0x21, | ||
1240 | 0x04, 0x04, 0x01, 0x01, | ||
1241 | 0, 0, 0 | ||
1242 | }; | ||
1243 | static 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 | }; | ||
1296 | static 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 | }; | ||
1309 | static 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 | }; | ||
1327 | static 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 */ | ||
1343 | static 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 */ | ||
1446 | static 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 | |||
1531 | static 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 -- */ | ||
1549 | static 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 -- */ | ||
1580 | static 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 | |||
1608 | static 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 | |||
1634 | static 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 | |||
1654 | static 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 | |||
1668 | static 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 | |||
1691 | static 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 | |||
1714 | static 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 | |||
1742 | static 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 */ | ||
1756 | static 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 */ | ||
1865 | static 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 -- */ | ||
1894 | static 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 | |||
1933 | static 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 | |||
1967 | static 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 | |||
1987 | static 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 | |||
2003 | static 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 */ | ||
2031 | static 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 */ | ||
2072 | static 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 -- */ | ||
2085 | static 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 | }; | ||
2097 | MODULE_DEVICE_TABLE(usb, device_table); | ||
2098 | |||
2099 | /* -- device connect -- */ | ||
2100 | static 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 | |||
2107 | static 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 -- */ | ||
2119 | static int __init sd_mod_init(void) | ||
2120 | { | ||
2121 | return usb_register(&sd_driver); | ||
2122 | } | ||
2123 | static void __exit sd_mod_exit(void) | ||
2124 | { | ||
2125 | usb_deregister(&sd_driver); | ||
2126 | } | ||
2127 | |||
2128 | module_init(sd_mod_init); | ||
2129 | module_exit(sd_mod_exit); | ||
2130 | |||
2131 | module_param(webcam, int, 0644); | ||
2132 | MODULE_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 | |||
49 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
50 | MODULE_DESCRIPTION("OV519 USB Camera Driver"); | ||
51 | MODULE_LICENSE("GPL"); | ||
52 | |||
53 | /* global parameters */ | ||
54 | static 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..." */ | ||
58 | static int i2c_detect_tries = 10; | ||
59 | |||
60 | /* controls */ | ||
61 | enum 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 */ | ||
75 | struct 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 | }; | ||
121 | enum 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 */ | ||
146 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
147 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
148 | static void setexposure(struct gspca_dev *gspca_dev); | ||
149 | static void setcolors(struct gspca_dev *gspca_dev); | ||
150 | static void sethvflip(struct gspca_dev *gspca_dev); | ||
151 | static void setautobright(struct gspca_dev *gspca_dev); | ||
152 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
153 | static void setfreq(struct gspca_dev *gspca_dev); | ||
154 | static void setfreq_i(struct sd *sd); | ||
155 | |||
156 | static 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 */ | ||
270 | static 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 | |||
350 | static 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 | }; | ||
362 | static 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). */ | ||
391 | static 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 | }; | ||
403 | static 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 | |||
426 | static 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 | }; | ||
438 | static 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 | |||
461 | static 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 | }; | ||
473 | static 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 | }; | ||
495 | static 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 | }; | ||
506 | static 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 | }; | ||
533 | static 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 | |||
727 | struct ov_regvals { | ||
728 | u8 reg; | ||
729 | u8 val; | ||
730 | }; | ||
731 | struct ov_i2c_regvals { | ||
732 | u8 reg; | ||
733 | u8 val; | ||
734 | }; | ||
735 | |||
736 | /* Settings for OV2610 camera chip */ | ||
737 | static const struct ov_i2c_regvals norm_2610[] = { | ||
738 | { 0x12, 0x80 }, /* reset */ | ||
739 | }; | ||
740 | |||
741 | static 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 | |||
759 | static 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 | |||
1441 | static 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 | |||
1484 | static 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 | */ | ||
1580 | static 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 | |||
1610 | static 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. */ | ||
1678 | static const struct ov_i2c_regvals norm_7640[] = { | ||
1679 | { 0x12, 0x80 }, | ||
1680 | { 0x12, 0x14 }, | ||
1681 | }; | ||
1682 | |||
1683 | static 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 | }; | ||
1702 | static 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 | }; | ||
1826 | static 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 */ | ||
1845 | static 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 | |||
2039 | static 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 | |||
2127 | static 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 */ | ||
2135 | static 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); | ||
2172 | leave: | ||
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 */ | ||
2182 | static 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 */ | ||
2221 | static 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 | */ | ||
2251 | static 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 | */ | ||
2275 | static 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 | |||
2296 | static 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 | |||
2329 | static 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 | */ | ||
2399 | static 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 | */ | ||
2426 | static 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 | |||
2446 | static 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 | |||
2467 | static 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 | |||
2491 | static 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 | |||
2524 | static 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 | */ | ||
2560 | static 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 */ | ||
2579 | static 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). */ | ||
2608 | static 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 | |||
2640 | static 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 | */ | ||
2645 | static 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 | */ | ||
2682 | static 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 | |||
2698 | static 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 | |||
2708 | static 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 */ | ||
2725 | static 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 | */ | ||
2771 | static 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 | */ | ||
2792 | static 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. */ | ||
2876 | static 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 */ | ||
2924 | static 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 | |||
2944 | static 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 | |||
2974 | static 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 */ | ||
3048 | static 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 */ | ||
3114 | static 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 | |||
3185 | static 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 | |||
3206 | static 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 */ | ||
3225 | static 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 */ | ||
3262 | static 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 | |||
3308 | static 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 */ | ||
3316 | static 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 */ | ||
3362 | static 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; | ||
3558 | error: | ||
3559 | PDEBUG(D_ERR, "OV519 Config failed"); | ||
3560 | return -EINVAL; | ||
3561 | } | ||
3562 | |||
3563 | /* function called at start time before URB creation */ | ||
3564 | static 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 | */ | ||
3583 | static 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 | */ | ||
3707 | static 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 | */ | ||
3830 | static 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 | |||
3989 | static 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 */ | ||
4180 | static 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 | |||
4194 | static 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 -- */ | ||
4308 | static 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 | |||
4365 | static 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 | |||
4373 | static 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 | |||
4394 | static 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 | |||
4422 | static 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 | |||
4472 | static 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 | |||
4510 | static 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 | |||
4556 | static 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 | |||
4579 | static 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 | |||
4608 | static 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 | |||
4659 | static 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 | |||
4763 | static 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 | |||
4771 | static 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 | |||
4822 | static 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 | |||
4829 | static 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 | |||
4845 | static 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 | } | ||
4903 | static 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 | |||
4914 | static 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 | |||
4943 | static 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 | |||
4958 | static 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 */ | ||
4983 | static 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 -- */ | ||
5004 | static 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 | |||
5037 | MODULE_DEVICE_TABLE(usb, device_table); | ||
5038 | |||
5039 | /* -- device connect -- */ | ||
5040 | static 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 | |||
5047 | static 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 -- */ | ||
5059 | static int __init sd_mod_init(void) | ||
5060 | { | ||
5061 | return usb_register(&sd_driver); | ||
5062 | } | ||
5063 | static void __exit sd_mod_exit(void) | ||
5064 | { | ||
5065 | usb_deregister(&sd_driver); | ||
5066 | } | ||
5067 | |||
5068 | module_init(sd_mod_init); | ||
5069 | module_exit(sd_mod_exit); | ||
5070 | |||
5071 | module_param(frame_rate, int, 0644); | ||
5072 | MODULE_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 | |||
48 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
49 | MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver"); | ||
50 | MODULE_LICENSE("GPL"); | ||
51 | |||
52 | /* controls */ | ||
53 | enum 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 */ | ||
70 | struct 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 | }; | ||
81 | enum sensors { | ||
82 | SENSOR_OV767x, | ||
83 | SENSOR_OV772x, | ||
84 | NSENSORS | ||
85 | }; | ||
86 | |||
87 | /* V4L2 controls supported by the driver */ | ||
88 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
89 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
90 | static void setgain(struct gspca_dev *gspca_dev); | ||
91 | static void setexposure(struct gspca_dev *gspca_dev); | ||
92 | static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val); | ||
93 | static void setawb(struct gspca_dev *gspca_dev); | ||
94 | static void setaec(struct gspca_dev *gspca_dev); | ||
95 | static void setsharpness(struct gspca_dev *gspca_dev); | ||
96 | static void sethvflip(struct gspca_dev *gspca_dev); | ||
97 | static void setcolors(struct gspca_dev *gspca_dev); | ||
98 | static void setlightfreq(struct gspca_dev *gspca_dev); | ||
99 | |||
100 | static int sd_start(struct gspca_dev *gspca_dev); | ||
101 | static void sd_stopN(struct gspca_dev *gspca_dev); | ||
102 | |||
103 | static 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 | |||
250 | static 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 | }; | ||
262 | static 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 | |||
273 | static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30}; | ||
274 | static const u8 vga_rates[] = {60, 50, 40, 30, 15}; | ||
275 | |||
276 | static 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 | |||
287 | struct reg_array { | ||
288 | const u8 (*val)[2]; | ||
289 | int len; | ||
290 | }; | ||
291 | |||
292 | static 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 | }; | ||
337 | static 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 | }; | ||
492 | static 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 | }; | ||
522 | static const u8 sensor_start_vga_767x[][2] = { | ||
523 | {0x11, 0x01}, | ||
524 | {0x1e, 0x04}, | ||
525 | {0x19, 0x02}, | ||
526 | {0x1a, 0x7a}, | ||
527 | }; | ||
528 | static 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 | }; | ||
561 | static const u8 sensor_start_qvga_767x[][2] = { | ||
562 | {0x11, 0x01}, | ||
563 | {0x1e, 0x04}, | ||
564 | {0x19, 0x02}, | ||
565 | {0x1a, 0x7a}, | ||
566 | }; | ||
567 | |||
568 | static 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 | }; | ||
626 | static 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 | }; | ||
719 | static 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 | }; | ||
730 | static 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 | }; | ||
740 | static 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 | }; | ||
751 | static 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 | |||
762 | static 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 | |||
783 | static 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)? */ | ||
805 | static 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 | |||
830 | static 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 | |||
853 | static 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 | |||
866 | static 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) */ | ||
881 | static 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) */ | ||
891 | static 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 */ | ||
906 | static 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 | |||
956 | static 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 | |||
971 | static 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 | |||
983 | static 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 | |||
1013 | static 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 | |||
1039 | static 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 | |||
1058 | static 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 | |||
1077 | static 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 | |||
1099 | static 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 | |||
1109 | static 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 | |||
1133 | static 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 | |||
1153 | static 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 */ | ||
1169 | static 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 */ | ||
1192 | static 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 | |||
1265 | static 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 | |||
1324 | static 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 | |||
1340 | static 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 | |||
1409 | discard: | ||
1410 | /* Discard data until a new frame starts. */ | ||
1411 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1412 | |||
1413 | scan_next: | ||
1414 | remaining_len -= len; | ||
1415 | data += len; | ||
1416 | } while (remaining_len > 0); | ||
1417 | } | ||
1418 | |||
1419 | static 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 | |||
1442 | static 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) */ | ||
1462 | static 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) */ | ||
1475 | static 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 */ | ||
1493 | static 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 -- */ | ||
1508 | static const struct usb_device_id device_table[] = { | ||
1509 | {USB_DEVICE(0x1415, 0x2000)}, | ||
1510 | {USB_DEVICE(0x06f8, 0x3002)}, | ||
1511 | {} | ||
1512 | }; | ||
1513 | |||
1514 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1515 | |||
1516 | /* -- device connect -- */ | ||
1517 | static 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 | |||
1523 | static 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 -- */ | ||
1535 | static int __init sd_mod_init(void) | ||
1536 | { | ||
1537 | return usb_register(&sd_driver); | ||
1538 | } | ||
1539 | |||
1540 | static void __exit sd_mod_exit(void) | ||
1541 | { | ||
1542 | usb_deregister(&sd_driver); | ||
1543 | } | ||
1544 | |||
1545 | module_init(sd_mod_init); | ||
1546 | module_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 | |||
44 | MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>"); | ||
45 | MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | |||
48 | /* specific webcam descriptor */ | ||
49 | struct 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 */ | ||
64 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
65 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
66 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
71 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
72 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
73 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
74 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
75 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
76 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
77 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
78 | |||
79 | static 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 | |||
181 | static 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 | |||
209 | static 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 | |||
243 | static 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 | |||
425 | static 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 | |||
453 | static 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 | |||
495 | static 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 | |||
518 | static 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 | |||
540 | static 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 | |||
563 | static 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 | |||
586 | static 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 | |||
614 | static 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 | |||
641 | static 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 | |||
668 | static 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 | |||
695 | static 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 | |||
712 | static 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 | |||
730 | static 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 | |||
746 | static 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 | |||
760 | static 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 | |||
774 | static 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 | |||
793 | static 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 | |||
799 | static 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 | |||
819 | static 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 | |||
843 | static 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 | |||
854 | static 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) */ | ||
869 | static 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) */ | ||
879 | static 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)? */ | ||
895 | static 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 | |||
920 | static 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 | |||
934 | static 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 | |||
942 | static 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 | |||
957 | static 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 | |||
975 | static 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 | |||
997 | static 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 | |||
1025 | static 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 */ | ||
1048 | static 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 */ | ||
1078 | static 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 | |||
1118 | static 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 | |||
1177 | static 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 | |||
1194 | static 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 | |||
1255 | discard: | ||
1256 | /* Discard data until a new frame starts. */ | ||
1257 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1258 | |||
1259 | scan_next: | ||
1260 | remaining_len -= len; | ||
1261 | data += len; | ||
1262 | } while (remaining_len > 0); | ||
1263 | } | ||
1264 | |||
1265 | /* controls */ | ||
1266 | static 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 | |||
1276 | static 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 | |||
1284 | static 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 | |||
1294 | static 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 | |||
1302 | static 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 | |||
1318 | static 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 | |||
1326 | static 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 | |||
1336 | static 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 | |||
1344 | static 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 | |||
1354 | static 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 | |||
1362 | static 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 | |||
1372 | static 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 | } | ||
1379 | static 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 | |||
1389 | static 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 | |||
1397 | static 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 */ | ||
1419 | static 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 -- */ | ||
1432 | static const struct usb_device_id device_table[] = { | ||
1433 | {USB_DEVICE(0x06f8, 0x3003)}, | ||
1434 | {} | ||
1435 | }; | ||
1436 | |||
1437 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1438 | |||
1439 | /* -- device connect -- */ | ||
1440 | static 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 | |||
1446 | static 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 -- */ | ||
1458 | static int __init sd_mod_init(void) | ||
1459 | { | ||
1460 | return usb_register(&sd_driver); | ||
1461 | } | ||
1462 | |||
1463 | static void __exit sd_mod_exit(void) | ||
1464 | { | ||
1465 | usb_deregister(&sd_driver); | ||
1466 | } | ||
1467 | |||
1468 | module_init(sd_mod_init); | ||
1469 | module_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 | |||
31 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
32 | MODULE_DESCRIPTION("Pixart PAC207"); | ||
33 | MODULE_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 */ | ||
54 | struct 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 */ | ||
72 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
73 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
74 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
75 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
76 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
77 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
78 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
79 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
80 | |||
81 | static 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 | |||
145 | static 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 | |||
161 | static 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 | |||
168 | static 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 | |||
188 | static 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 | |||
203 | static 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 */ | ||
222 | static 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 */ | ||
257 | static 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 -- */ | ||
269 | static 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 | |||
312 | static 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 | |||
322 | static 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 | |||
338 | static 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 | |||
385 | static 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 | |||
394 | static 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 | |||
403 | static 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 | |||
412 | static 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 | |||
422 | static 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 | |||
430 | static 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 | |||
440 | static 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 | |||
448 | static 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 | |||
458 | static 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 | |||
466 | static 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 | |||
489 | static 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) | ||
498 | static 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 */ | ||
517 | static 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 -- */ | ||
533 | static 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 | }; | ||
549 | MODULE_DEVICE_TABLE(usb, device_table); | ||
550 | |||
551 | /* -- device connect -- */ | ||
552 | static 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 | |||
559 | static 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 -- */ | ||
571 | static int __init sd_mod_init(void) | ||
572 | { | ||
573 | return usb_register(&sd_driver); | ||
574 | } | ||
575 | static void __exit sd_mod_exit(void) | ||
576 | { | ||
577 | usb_deregister(&sd_driver); | ||
578 | } | ||
579 | |||
580 | module_init(sd_mod_init); | ||
581 | module_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 | |||
70 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | ||
71 | MODULE_DESCRIPTION("Pixart PAC7302"); | ||
72 | MODULE_LICENSE("GPL"); | ||
73 | |||
74 | /* specific webcam descriptor for pac7302 */ | ||
75 | struct 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 */ | ||
100 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
102 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
103 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
104 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
105 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
106 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); | ||
109 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
110 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); | ||
111 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
112 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
113 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
114 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
115 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
116 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
117 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
118 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
119 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
120 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
121 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
122 | |||
123 | static 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 | |||
286 | static 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 */ | ||
298 | static 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 | }; | ||
305 | static 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() */ | ||
371 | static 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 | |||
394 | static 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 | |||
418 | static 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 | |||
440 | static 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 */ | ||
450 | static 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 */ | ||
479 | static 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 */ | ||
518 | static 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 */ | ||
546 | static 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 */ | ||
573 | static 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 | |||
594 | static 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 | |||
605 | static 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 | |||
616 | static 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 | |||
627 | static 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 | |||
638 | static 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 | |||
679 | static 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 */ | ||
700 | static 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 | |||
706 | static 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 | |||
736 | static 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 */ | ||
745 | static 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 | |||
756 | static 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 */ | ||
776 | static 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 */ | ||
787 | static 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 | |||
803 | static 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 */ | ||
823 | static 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 | |||
877 | static 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 | |||
887 | static 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 | |||
895 | static 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 | |||
905 | static 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 | |||
913 | static 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 | |||
923 | static 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 | |||
931 | static 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 | |||
941 | static 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 | |||
949 | static 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 | |||
959 | static 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 | |||
967 | static 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 | |||
977 | static 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 | |||
985 | static 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 | |||
995 | static 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 | |||
1003 | static 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 | |||
1013 | static 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 | |||
1021 | static 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 | |||
1044 | static 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 | |||
1052 | static 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 | |||
1062 | static 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 | |||
1070 | static 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 | |||
1080 | static 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 | ||
1089 | static 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 | |||
1119 | static 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) | ||
1135 | static 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 */ | ||
1166 | static 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 -- */ | ||
1187 | static 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 | }; | ||
1201 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1202 | |||
1203 | /* -- device connect -- */ | ||
1204 | static 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 | |||
1211 | static 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 -- */ | ||
1223 | static int __init sd_mod_init(void) | ||
1224 | { | ||
1225 | return usb_register(&sd_driver); | ||
1226 | } | ||
1227 | static void __exit sd_mod_exit(void) | ||
1228 | { | ||
1229 | usb_deregister(&sd_driver); | ||
1230 | } | ||
1231 | |||
1232 | module_init(sd_mod_init); | ||
1233 | module_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 | |||
57 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | ||
58 | MODULE_DESCRIPTION("Pixart PAC7311"); | ||
59 | MODULE_LICENSE("GPL"); | ||
60 | |||
61 | /* specific webcam descriptor for pac7311 */ | ||
62 | struct 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 */ | ||
79 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
80 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
81 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
82 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
83 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
85 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
86 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
87 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
88 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
89 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
90 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
91 | |||
92 | static 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 | |||
186 | static 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 */ | ||
208 | static 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 | |||
221 | static 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() */ | ||
252 | static 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 | |||
262 | static 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 | |||
286 | static 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 | |||
308 | static 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 */ | ||
318 | static 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 */ | ||
347 | static 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 */ | ||
386 | static 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 */ | ||
408 | static 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 | |||
418 | static 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 | |||
435 | static 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 | |||
466 | static 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 */ | ||
480 | static 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 | |||
486 | static 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 | |||
529 | static 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 */ | ||
544 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
545 | { | ||
546 | } | ||
547 | |||
548 | /* Include pac common sof detection functions */ | ||
549 | #include "pac_common.h" | ||
550 | |||
551 | static 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 */ | ||
571 | static 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 */ | ||
582 | static 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 | |||
598 | static 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 */ | ||
618 | static 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 | |||
670 | static 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 | |||
680 | static 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 | |||
688 | static 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 | |||
698 | static 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 | |||
706 | static 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 | |||
716 | static 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 | |||
724 | static 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 | |||
747 | static 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 | |||
755 | static 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 | |||
765 | static 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 | |||
773 | static 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 | |||
783 | static 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) | ||
792 | static 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 */ | ||
823 | static 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 -- */ | ||
840 | static 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 | }; | ||
849 | MODULE_DEVICE_TABLE(usb, device_table); | ||
850 | |||
851 | /* -- device connect -- */ | ||
852 | static 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 | |||
859 | static 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 -- */ | ||
871 | static int __init sd_mod_init(void) | ||
872 | { | ||
873 | return usb_register(&sd_driver); | ||
874 | } | ||
875 | static void __exit sd_mod_exit(void) | ||
876 | { | ||
877 | usb_deregister(&sd_driver); | ||
878 | } | ||
879 | |||
880 | module_init(sd_mod_init); | ||
881 | module_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 | |||
32 | static 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 | |||
74 | static 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 | |||
42 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
43 | MODULE_DESCRIPTION("Endpoints se401"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | |||
46 | /* controls */ | ||
47 | enum e_ctrl { | ||
48 | BRIGHTNESS, | ||
49 | GAIN, | ||
50 | EXPOSURE, | ||
51 | FREQ, | ||
52 | NCTRL /* number of controls */ | ||
53 | }; | ||
54 | |||
55 | /* exposure change state machine states */ | ||
56 | enum { | ||
57 | EXPO_CHANGED, | ||
58 | EXPO_DROP_FRAME, | ||
59 | EXPO_NO_CHANGE, | ||
60 | }; | ||
61 | |||
62 | /* specific webcam descriptor */ | ||
63 | struct 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 | |||
78 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
79 | static void setgain(struct gspca_dev *gspca_dev); | ||
80 | static void setexposure(struct gspca_dev *gspca_dev); | ||
81 | |||
82 | static 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 | |||
133 | static 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 | |||
153 | static 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 | |||
177 | static 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 | |||
197 | static 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 | |||
223 | static 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 | |||
235 | static 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 | |||
248 | static 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 | |||
278 | static 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 */ | ||
388 | static int sd_init(struct gspca_dev *gspca_dev) | ||
389 | { | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | /* -- start the camera -- */ | ||
394 | static 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 | |||
450 | static 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 | |||
457 | static 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 | |||
518 | static 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 | |||
540 | static 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 | |||
617 | error: | ||
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 | |||
625 | static 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 | |||
643 | static 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 | |||
656 | static 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) | ||
678 | static 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 */ | ||
705 | static 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 -- */ | ||
722 | static 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 | }; | ||
730 | MODULE_DEVICE_TABLE(usb, device_table); | ||
731 | |||
732 | /* -- device connect -- */ | ||
733 | static 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 | |||
740 | static int sd_pre_reset(struct usb_interface *intf) | ||
741 | { | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static int sd_post_reset(struct usb_interface *intf) | ||
746 | { | ||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static 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 -- */ | ||
764 | static int __init sd_mod_init(void) | ||
765 | { | ||
766 | return usb_register(&sd_driver); | ||
767 | } | ||
768 | static void __exit sd_mod_exit(void) | ||
769 | { | ||
770 | usb_deregister(&sd_driver); | ||
771 | } | ||
772 | |||
773 | module_init(sd_mod_init); | ||
774 | module_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 | |||
25 | MODULE_AUTHOR("Theodore Kilgore"); | ||
26 | MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | u8 sof_read; | ||
33 | u16 model; | ||
34 | }; | ||
35 | |||
36 | struct 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 */ | ||
42 | static const struct ctrl sd_ctrls[] = { | ||
43 | }; | ||
44 | |||
45 | /* How to change the resolution of any of the VGA cams is unknown */ | ||
46 | static 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 */ | ||
55 | static 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 */ | ||
64 | static 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 | |||
86 | static 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 | |||
103 | static 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 | |||
121 | static 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 | |||
152 | static 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 */ | ||
168 | static 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 */ | ||
216 | static 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 | |||
227 | static 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 | |||
253 | static 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 | |||
318 | static 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 | |||
395 | static 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 | |||
463 | static 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 | |||
535 | static 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 | |||
617 | static 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 | |||
648 | static 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 | |||
667 | static 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 */ | ||
694 | static 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 -- */ | ||
706 | static 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 | }; | ||
717 | MODULE_DEVICE_TABLE(usb, device_table); | ||
718 | |||
719 | /* -- device connect -- */ | ||
720 | static 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 | |||
727 | static 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 -- */ | ||
739 | static int __init sd_mod_init(void) | ||
740 | { | ||
741 | return usb_register(&sd_driver); | ||
742 | } | ||
743 | |||
744 | static void __exit sd_mod_exit(void) | ||
745 | { | ||
746 | usb_deregister(&sd_driver); | ||
747 | } | ||
748 | |||
749 | module_init(sd_mod_init); | ||
750 | module_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 | |||
24 | static const unsigned char sn9c2028_sof_marker[5] = | ||
25 | { 0xff, 0xff, 0x00, 0xc4, 0xc4 }; | ||
26 | |||
27 | static 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 | |||
29 | MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " | ||
30 | "microdia project <microdia@googlegroups.com>"); | ||
31 | MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); | ||
32 | MODULE_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 */ | ||
68 | struct 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 | |||
103 | struct i2c_reg_u8 { | ||
104 | u8 reg; | ||
105 | u8 val; | ||
106 | }; | ||
107 | |||
108 | struct i2c_reg_u16 { | ||
109 | u8 reg; | ||
110 | u16 val; | ||
111 | }; | ||
112 | |||
113 | static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val); | ||
114 | static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val); | ||
115 | static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val); | ||
116 | static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val); | ||
117 | static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val); | ||
118 | static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val); | ||
119 | static int sd_sethue(struct gspca_dev *gspca_dev, s32 val); | ||
120 | static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val); | ||
121 | static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val); | ||
122 | static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val); | ||
123 | static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val); | ||
124 | static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val); | ||
125 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val); | ||
126 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val); | ||
127 | static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val); | ||
128 | static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val); | ||
129 | static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val); | ||
130 | static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val); | ||
131 | static int sd_setgain(struct gspca_dev *gspca_dev, s32 val); | ||
132 | static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val); | ||
133 | static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val); | ||
134 | static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); | ||
135 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); | ||
136 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); | ||
137 | |||
138 | static 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 | |||
178 | static 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 | |||
361 | static 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 | |||
409 | static 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 | |||
462 | static 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 | |||
485 | static 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 | |||
533 | static 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 | |||
581 | static 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 | |||
629 | static 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 | |||
677 | static 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 | |||
725 | static 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 | |||
773 | static 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 | |||
788 | static 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) */ | ||
812 | static 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) */ | ||
824 | static 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) */ | ||
845 | static 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 */ | ||
865 | static 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 | |||
876 | static 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 | |||
890 | static 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 | |||
902 | static 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 | |||
959 | static 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 | |||
989 | static 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 | |||
1016 | static 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 | |||
1035 | static 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 | |||
1045 | static 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 | |||
1072 | static 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 | |||
1088 | static 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 | |||
1095 | static 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 | |||
1102 | static 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 | |||
1113 | static 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 | |||
1132 | static 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 | |||
1153 | static 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 | |||
1159 | static 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 | |||
1175 | static 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 | |||
1197 | static 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 | |||
1218 | static 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 | |||
1243 | static 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 | |||
1268 | static 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 | |||
1294 | static 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 | |||
1313 | static 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 | |||
1333 | static 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 | |||
1350 | static 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 | |||
1369 | static 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 | |||
1439 | static 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 | |||
1457 | static 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 | |||
1475 | static 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 | |||
1512 | static 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 | |||
1529 | static 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 | |||
1568 | static 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 | |||
1596 | static 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 | |||
1604 | static 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 | |||
1678 | static 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 | |||
1714 | static 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 | |||
1757 | static 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 | |||
1767 | static 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 | |||
1775 | static 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 | |||
1785 | static 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 | |||
1792 | static 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 | |||
1802 | static 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 | |||
1809 | static 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 | |||
1819 | static 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 | |||
1826 | static 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 | |||
1836 | static 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 | |||
1843 | static 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 | |||
1853 | static 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 | |||
1860 | static 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 | |||
1870 | static 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 | |||
1877 | static 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 | |||
1887 | static 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 | |||
1894 | static 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 | |||
1904 | static 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 | |||
1911 | static 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 | |||
1921 | static 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 | |||
1928 | static 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 | |||
1938 | static 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 | |||
1945 | static 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 | |||
1952 | static 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 | ||
1960 | static 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 *)®->val) < 0) | ||
1980 | return -EINVAL; | ||
1981 | } else { | ||
1982 | if (i2c_r1(gspca_dev, reg->reg, (u8 *)®->val) < 0) | ||
1983 | return -EINVAL; | ||
1984 | } | ||
1985 | return 0; | ||
1986 | } | ||
1987 | return -EINVAL; | ||
1988 | } | ||
1989 | |||
1990 | static 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 | |||
2020 | static 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 | |||
2042 | static 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 | |||
2095 | static 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 | |||
2178 | static 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 | |||
2244 | static 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 | |||
2304 | static 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 | |||
2312 | static 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 | |||
2362 | static 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 | |||
2380 | static 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) | ||
2396 | static 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 | |||
2413 | static 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 */ | ||
2468 | static 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 | |||
2493 | static 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 | }; | ||
2533 | MODULE_DEVICE_TABLE(usb, device_table); | ||
2534 | |||
2535 | /* -- device connect -- */ | ||
2536 | static 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 | |||
2543 | static 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 -- */ | ||
2556 | static int __init sd_mod_init(void) | ||
2557 | { | ||
2558 | return usb_register(&sd_driver); | ||
2559 | } | ||
2560 | static void __exit sd_mod_exit(void) | ||
2561 | { | ||
2562 | usb_deregister(&sd_driver); | ||
2563 | } | ||
2564 | |||
2565 | module_init(sd_mod_init); | ||
2566 | module_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 | |||
25 | Reg Use | ||
26 | sn9c101 / sn9c102: | ||
27 | 0x10 high nibble red gain low nibble blue gain | ||
28 | 0x11 low nibble green gain | ||
29 | sn9c103: | ||
30 | 0x05 red gain 0-127 | ||
31 | 0x06 blue gain 0-127 | ||
32 | 0x07 green gain 0-127 | ||
33 | all: | ||
34 | 0x08-0x0f i2c / 3wire registers | ||
35 | 0x12 hstart | ||
36 | 0x13 vstart | ||
37 | 0x15 hsize (hsize = register-value * 16) | ||
38 | 0x16 vsize (vsize = register-value * 16) | ||
39 | 0x17 bit 0 toggle compression quality (according to sn9c102 driver) | ||
40 | 0x18 bit 7 enables compression, bit 4-5 set image down scaling: | ||
41 | 00 scale 1, 01 scale 1/2, 10, scale 1/4 | ||
42 | 0x19 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. | ||
44 | 0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) | ||
45 | 0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) | ||
46 | 0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) | ||
47 | 0x1f 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 | |||
55 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); | ||
56 | MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver"); | ||
57 | MODULE_LICENSE("GPL"); | ||
58 | |||
59 | /* controls */ | ||
60 | enum e_ctrl { | ||
61 | BRIGHTNESS, | ||
62 | GAIN, | ||
63 | EXPOSURE, | ||
64 | AUTOGAIN, | ||
65 | FREQ, | ||
66 | NCTRLS /* number of controls */ | ||
67 | }; | ||
68 | |||
69 | /* specific webcam descriptor */ | ||
70 | struct 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 | |||
103 | typedef const __u8 sensor_init_t[8]; | ||
104 | |||
105 | struct 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 */ | ||
151 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
152 | static void setgain(struct gspca_dev *gspca_dev); | ||
153 | static void setexposure(struct gspca_dev *gspca_dev); | ||
154 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
155 | static void setfreq(struct gspca_dev *gspca_dev); | ||
156 | |||
157 | static 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 | |||
231 | static 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 | }; | ||
253 | static 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 | |||
286 | static 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 | }; | ||
292 | static 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 | |||
300 | static 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 | }; | ||
306 | static 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 | }; | ||
313 | static 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 | }; | ||
319 | static 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 | |||
351 | static 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 | }; | ||
358 | static 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 | |||
380 | static 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 | |||
411 | static 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 | |||
453 | static 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 | */ | ||
477 | static 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 | |||
493 | static 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 */ | ||
500 | static 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) */ | ||
507 | static 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 | */ | ||
516 | static const __u8 tas5110d_sensor_init[][8] = { | ||
517 | {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */ | ||
518 | }; | ||
519 | |||
520 | static 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 | }; | ||
526 | static 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 | |||
534 | static const struct sensor_data sensor_data[] = { | ||
535 | SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), | ||
536 | SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), | ||
537 | SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60), | ||
538 | SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21), | ||
539 | SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0), | ||
540 | SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0), | ||
541 | SENS(initTas5110c, tas5110c_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO, | ||
542 | NO_BRIGHTNESS|NO_FREQ, 0), | ||
543 | SENS(initTas5110d, tas5110d_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO, | ||
544 | NO_BRIGHTNESS|NO_FREQ, 0), | ||
545 | SENS(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 */ | ||
550 | static 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 | |||
563 | static 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 | |||
585 | static 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 | |||
603 | static 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 | |||
615 | static 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; | ||
661 | err: | ||
662 | PDEBUG(D_ERR, "i2c error brightness"); | ||
663 | } | ||
664 | |||
665 | static 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; | ||
756 | err: | ||
757 | PDEBUG(D_ERR, "i2c error gain"); | ||
758 | } | ||
759 | |||
760 | static 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 | |||
786 | static 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, ®, 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; | ||
968 | err: | ||
969 | PDEBUG(D_ERR, "i2c error exposure"); | ||
970 | } | ||
971 | |||
972 | static 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 | |||
1005 | static 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 */ | ||
1051 | static 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 */ | ||
1092 | static 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 -- */ | ||
1102 | static 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(®s[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, ®s[0x01], 1); | ||
1180 | /* reg 0x17 SensorClk enable inv Clk 0x60 */ | ||
1181 | reg_w(gspca_dev, 0x17, ®s[0x17], 1); | ||
1182 | /* Set the registers from the template */ | ||
1183 | reg_w(gspca_dev, 0x01, ®s[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, ®s[0x15], 2); | ||
1212 | /* compression register */ | ||
1213 | reg_w(gspca_dev, 0x18, ®s[0x18], 1); | ||
1214 | /* H_start */ | ||
1215 | reg_w(gspca_dev, 0x12, ®s[0x12], 1); | ||
1216 | /* V_START */ | ||
1217 | reg_w(gspca_dev, 0x13, ®s[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, ®s[0x17], 1); | ||
1221 | /*MCKSIZE ->3 */ /*fixme: not ov7630*/ | ||
1222 | reg_w(gspca_dev, 0x19, ®s[0x19], 1); | ||
1223 | /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ | ||
1224 | reg_w(gspca_dev, 0x1c, ®s[0x1c], 4); | ||
1225 | /* Enable video transfert */ | ||
1226 | reg_w(gspca_dev, 0x01, ®s[0x01], 1); | ||
1227 | /* Compression */ | ||
1228 | reg_w(gspca_dev, 0x18, ®s[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 | |||
1246 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
1247 | { | ||
1248 | sd_init(gspca_dev); | ||
1249 | } | ||
1250 | |||
1251 | static 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 | |||
1319 | static 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 | |||
1385 | static 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 | |||
1416 | static 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) | ||
1438 | static 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 */ | ||
1457 | static 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 | |||
1478 | static 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 | }; | ||
1509 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1510 | |||
1511 | /* -- device connect -- */ | ||
1512 | static 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 | |||
1519 | static 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 -- */ | ||
1531 | static int __init sd_mod_init(void) | ||
1532 | { | ||
1533 | return usb_register(&sd_driver); | ||
1534 | } | ||
1535 | static void __exit sd_mod_exit(void) | ||
1536 | { | ||
1537 | usb_deregister(&sd_driver); | ||
1538 | } | ||
1539 | |||
1540 | module_init(sd_mod_init); | ||
1541 | module_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 | |||
28 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); | ||
29 | MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | /* controls */ | ||
33 | enum 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 */ | ||
50 | struct 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 | }; | ||
89 | enum 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 | |||
107 | static 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 */ | ||
127 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
128 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
129 | static void setcolors(struct gspca_dev *gspca_dev); | ||
130 | static void setredblue(struct gspca_dev *gspca_dev); | ||
131 | static void setgamma(struct gspca_dev *gspca_dev); | ||
132 | static void setautogain(struct gspca_dev *gspca_dev); | ||
133 | static void sethvflip(struct gspca_dev *gspca_dev); | ||
134 | static void setsharpness(struct gspca_dev *gspca_dev); | ||
135 | static void setillum(struct gspca_dev *gspca_dev); | ||
136 | static void setfreq(struct gspca_dev *gspca_dev); | ||
137 | |||
138 | static 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 */ | ||
290 | static 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 | |||
350 | static 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 | }; | ||
357 | static 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 | |||
376 | static 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 | |||
387 | static 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 | |||
398 | static 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 | |||
409 | static 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 | |||
420 | static 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 | |||
431 | static 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 | |||
442 | static 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 | |||
453 | static 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 | |||
464 | static 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 | |||
475 | static 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 | |||
486 | static 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 | |||
497 | static 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 | |||
508 | static 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 | |||
519 | static 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 | |||
530 | static 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 */ | ||
542 | static 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 */ | ||
561 | static 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 */ | ||
566 | static 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 */ | ||
571 | static 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 */ | ||
576 | static 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 */ | ||
581 | static 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 */ | ||
587 | static 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 | |||
596 | static 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 | }; | ||
616 | static 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 | }; | ||
632 | static 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 | }; | ||
673 | static 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 | |||
684 | static 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 | }; | ||
717 | static 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 | }; | ||
771 | static 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 | }; | ||
815 | static 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 | }; | ||
827 | static 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 | }; | ||
850 | static 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 | }; | ||
871 | static 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 | }; | ||
879 | static 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 | }; | ||
884 | static 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 | }; | ||
915 | static 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 | }; | ||
922 | static 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 | }; | ||
961 | static 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 | |||
979 | static 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 | }; | ||
1009 | static 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 | |||
1029 | static 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 | }; | ||
1095 | static 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 | |||
1124 | static 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 | }; | ||
1162 | static 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 | |||
1178 | static 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 | }; | ||
1231 | static 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 | |||
1254 | static 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 | }; | ||
1263 | static 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 | |||
1285 | static 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 | }; | ||
1359 | static 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 | |||
1370 | static 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 */ | ||
1389 | static 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 | |||
1416 | static 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 | } | ||
1439 | static 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 */ | ||
1471 | static 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 */ | ||
1511 | static 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 */ | ||
1536 | static 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 | |||
1567 | static 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 */ | ||
1581 | static 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 | |||
1599 | static 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 | |||
1654 | static 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 | |||
1680 | static 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 */ | ||
1717 | static 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 */ | ||
1756 | static 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 */ | ||
1790 | static 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 | |||
1863 | static 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 | |||
1967 | static 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 | |||
2016 | static 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 | |||
2033 | static 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 | |||
2061 | static 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 | |||
2070 | static 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 | |||
2108 | static 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 | |||
2135 | static 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 | |||
2178 | static 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 | |||
2185 | static 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 | |||
2206 | static 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 | |||
2263 | static 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. */ | ||
2294 | static 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 -- */ | ||
2306 | static 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 | |||
2630 | static 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 */ | ||
2705 | static 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 | |||
2717 | static 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 */ | ||
2780 | static 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. */ | ||
2804 | static 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 */ | ||
2879 | marker_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 | |||
2946 | static 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 | |||
2958 | static 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) | ||
2980 | static 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 */ | ||
2999 | static 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) | ||
3025 | static 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 | }; | ||
3087 | MODULE_DEVICE_TABLE(usb, device_table); | ||
3088 | |||
3089 | /* -- device connect -- */ | ||
3090 | static 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 | |||
3097 | static 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 -- */ | ||
3109 | static int __init sd_mod_init(void) | ||
3110 | { | ||
3111 | return usb_register(&sd_driver); | ||
3112 | } | ||
3113 | static void __exit sd_mod_exit(void) | ||
3114 | { | ||
3115 | usb_deregister(&sd_driver); | ||
3116 | } | ||
3117 | |||
3118 | module_init(sd_mod_init); | ||
3119 | module_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 | |||
26 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
27 | MODULE_DESCRIPTION("SPCA1528 USB Camera Driver"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* specific webcam descriptor */ | ||
31 | struct 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 */ | ||
46 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
47 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
48 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
50 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | ||
51 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | ||
52 | static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val); | ||
53 | static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val); | ||
54 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
55 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
56 | |||
57 | static 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 | |||
130 | static 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 */ | ||
151 | static 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 | |||
179 | static 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 | |||
201 | static 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 | |||
225 | static 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 | |||
240 | static 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 | |||
258 | static 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 | |||
265 | static 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 | |||
272 | static 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 | |||
279 | static 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 | |||
286 | static 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 */ | ||
294 | static 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 */ | ||
316 | static 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 */ | ||
337 | static 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 -- */ | ||
356 | static 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 | |||
389 | static 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 */ | ||
399 | static 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 | |||
419 | static 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 | } | ||
450 | err: | ||
451 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
452 | } | ||
453 | |||
454 | static 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 | |||
464 | static 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 | |||
472 | static 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 | |||
482 | static 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 | |||
490 | static 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 | |||
500 | static 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 | |||
508 | static 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 | |||
518 | static 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 | |||
526 | static 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 | |||
536 | static 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 */ | ||
545 | static 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 -- */ | ||
558 | static const struct usb_device_id device_table[] = { | ||
559 | {USB_DEVICE(0x04fc, 0x1528)}, | ||
560 | {} | ||
561 | }; | ||
562 | MODULE_DEVICE_TABLE(usb, device_table); | ||
563 | |||
564 | /* -- device connect -- */ | ||
565 | static 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 | |||
576 | static 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 -- */ | ||
588 | static int __init sd_mod_init(void) | ||
589 | { | ||
590 | return usb_register(&sd_driver); | ||
591 | } | ||
592 | static void __exit sd_mod_exit(void) | ||
593 | { | ||
594 | usb_deregister(&sd_driver); | ||
595 | } | ||
596 | |||
597 | module_init(sd_mod_init); | ||
598 | module_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 | |||
27 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
28 | MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver"); | ||
29 | MODULE_LICENSE("GPL"); | ||
30 | |||
31 | /* specific webcam descriptor */ | ||
32 | struct 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 */ | ||
64 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
65 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
66 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | |||
71 | static 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 | |||
116 | static 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 | |||
129 | static 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 | |||
157 | static 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 | }; | ||
181 | static 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 | |||
310 | static 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 | |||
331 | static 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 | |||
352 | static 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 */ | ||
375 | static 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 | |||
387 | static 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 */ | ||
404 | static 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 | */ | ||
432 | static 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 | |||
446 | static 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 | |||
460 | static 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 | |||
484 | static 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 | |||
491 | static 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 | |||
515 | static 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 | |||
531 | static 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 */ | ||
562 | static 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; | ||
583 | error: | ||
584 | return -EBUSY; | ||
585 | } | ||
586 | |||
587 | static 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 */ | ||
627 | static 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 */ | ||
650 | static 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 | |||
664 | static 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 | |||
880 | static 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 | |||
891 | static 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 | |||
935 | static 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 | |||
943 | static 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 | |||
950 | static 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 | |||
957 | static 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 | |||
967 | static 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 | |||
975 | static 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 | |||
985 | static 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 | |||
993 | static 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 | |||
1003 | static 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 | |||
1011 | static 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 | |||
1027 | static 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 */ | ||
1040 | static 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 -- */ | ||
1054 | static 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 | }; | ||
1072 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1073 | |||
1074 | /* -- device connect -- */ | ||
1075 | static 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 | |||
1082 | static 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 -- */ | ||
1094 | static int __init sd_mod_init(void) | ||
1095 | { | ||
1096 | return usb_register(&sd_driver); | ||
1097 | } | ||
1098 | static void __exit sd_mod_exit(void) | ||
1099 | { | ||
1100 | usb_deregister(&sd_driver); | ||
1101 | } | ||
1102 | |||
1103 | module_init(sd_mod_init); | ||
1104 | module_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 | |||
26 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
27 | MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* specific webcam descriptor */ | ||
31 | struct 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 */ | ||
51 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
52 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
53 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
54 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
55 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
56 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
57 | static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
58 | static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
59 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
60 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
61 | |||
62 | static 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 | |||
135 | static 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 */ | ||
197 | static 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) */ | ||
303 | static 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 | */ | ||
590 | static 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 | */ | ||
685 | static 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 | |||
707 | static 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 */ | ||
1641 | static 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 */ | ||
1692 | static 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 | |||
1842 | static 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 | |||
1860 | static 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 | |||
1879 | static 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 | |||
1886 | static 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 | |||
1896 | static 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 | |||
1903 | static 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 | |||
1910 | static 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 */ | ||
1918 | static 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 */ | ||
1936 | static 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; | ||
1960 | error: | ||
1961 | return -EINVAL; | ||
1962 | } | ||
1963 | |||
1964 | static 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 | |||
2019 | static 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 */ | ||
2027 | static 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 | |||
2034 | static 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 | |||
2054 | static 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 | |||
2064 | static 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 | |||
2072 | static 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 | |||
2082 | static 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 | |||
2090 | static 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 | |||
2100 | static 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 | |||
2108 | static 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 | |||
2118 | static 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 | |||
2126 | static 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 | |||
2136 | static 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 */ | ||
2145 | static 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 -- */ | ||
2158 | static 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 | }; | ||
2168 | MODULE_DEVICE_TABLE(usb, device_table); | ||
2169 | |||
2170 | /* -- device connect -- */ | ||
2171 | static 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 | |||
2178 | static 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 -- */ | ||
2190 | static int __init sd_mod_init(void) | ||
2191 | { | ||
2192 | return usb_register(&sd_driver); | ||
2193 | } | ||
2194 | static void __exit sd_mod_exit(void) | ||
2195 | { | ||
2196 | usb_deregister(&sd_driver); | ||
2197 | } | ||
2198 | |||
2199 | module_init(sd_mod_init); | ||
2200 | module_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 | |||
26 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
27 | MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* specific webcam descriptor */ | ||
31 | struct 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 */ | ||
42 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
43 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
44 | |||
45 | static 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 | |||
62 | static 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 | */ | ||
111 | static 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 | */ | ||
148 | static 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 | */ | ||
336 | static 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 | */ | ||
396 | static 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 | |||
568 | static 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 */ | ||
586 | static 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 | |||
605 | static 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 */ | ||
621 | static 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 */ | ||
640 | static 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 | |||
652 | static 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 | |||
661 | static 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 | |||
716 | static 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 */ | ||
723 | static 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 | |||
736 | static 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 | |||
757 | static 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 | |||
767 | static 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 */ | ||
776 | static 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 -- */ | ||
789 | static 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 | }; | ||
795 | MODULE_DEVICE_TABLE(usb, device_table); | ||
796 | |||
797 | /* -- device connect -- */ | ||
798 | static 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 | |||
805 | static 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 -- */ | ||
817 | static int __init sd_mod_init(void) | ||
818 | { | ||
819 | return usb_register(&sd_driver); | ||
820 | } | ||
821 | static void __exit sd_mod_exit(void) | ||
822 | { | ||
823 | usb_deregister(&sd_driver); | ||
824 | } | ||
825 | |||
826 | module_init(sd_mod_init); | ||
827 | module_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 | |||
28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
29 | MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | /* specific webcam descriptor */ | ||
33 | struct 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 */ | ||
45 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
47 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
48 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
49 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
50 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
51 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | ||
52 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | ||
53 | |||
54 | static 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 | |||
113 | static 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 */ | ||
150 | static 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 | |||
164 | static 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 | |||
177 | static void spca506_Initi2c(struct gspca_dev *gspca_dev) | ||
178 | { | ||
179 | reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004); | ||
180 | } | ||
181 | |||
182 | static 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 | |||
196 | static 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 | |||
237 | static 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 | |||
249 | static 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 */ | ||
281 | static 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 */ | ||
298 | static 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 | |||
406 | static 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 | |||
536 | static 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 | |||
545 | static 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 | |||
567 | static 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 | |||
576 | static 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 | |||
585 | static 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 | |||
594 | static 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 | |||
603 | static 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 | |||
613 | static 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 | |||
621 | static 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 | |||
631 | static 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 | |||
639 | static 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 | |||
649 | static 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 | |||
657 | static 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 | |||
667 | static 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 */ | ||
676 | static 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 -- */ | ||
688 | static 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 | }; | ||
696 | MODULE_DEVICE_TABLE(usb, device_table); | ||
697 | |||
698 | /* -- device connect -- */ | ||
699 | static 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 | |||
706 | static 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 -- */ | ||
718 | static 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 | } | ||
727 | static void __exit sd_mod_exit(void) | ||
728 | { | ||
729 | usb_deregister(&sd_driver); | ||
730 | PDEBUG(D_PROBE, "deregistered"); | ||
731 | } | ||
732 | |||
733 | module_init(sd_mod_init); | ||
734 | module_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 | |||
25 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
26 | MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct 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 */ | ||
45 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
47 | |||
48 | static 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 | |||
65 | static 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 | */ | ||
95 | static 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 | */ | ||
507 | static 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 | |||
591 | static 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 | |||
674 | static 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 | */ | ||
1021 | static 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 | |||
1265 | static 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 */ | ||
1284 | static 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 */ | ||
1307 | static 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 | |||
1346 | out: | ||
1347 | return ret; | ||
1348 | } | ||
1349 | |||
1350 | static 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 */ | ||
1373 | static 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 */ | ||
1419 | static int sd_init(struct gspca_dev *gspca_dev) | ||
1420 | { | ||
1421 | return 0; | ||
1422 | } | ||
1423 | |||
1424 | static 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 | |||
1445 | static 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 | |||
1451 | static 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 | |||
1472 | static 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 | |||
1484 | static 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 | |||
1494 | static 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 */ | ||
1503 | static 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 -- */ | ||
1515 | static 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 | }; | ||
1524 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1525 | |||
1526 | /* -- device connect -- */ | ||
1527 | static 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 | |||
1534 | static 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 -- */ | ||
1546 | static int __init sd_mod_init(void) | ||
1547 | { | ||
1548 | return usb_register(&sd_driver); | ||
1549 | } | ||
1550 | static void __exit sd_mod_exit(void) | ||
1551 | { | ||
1552 | usb_deregister(&sd_driver); | ||
1553 | } | ||
1554 | |||
1555 | module_init(sd_mod_init); | ||
1556 | module_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 | |||
28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
29 | MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | /* specific webcam descriptor */ | ||
33 | struct 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 | |||
77 | static 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 | |||
100 | static 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 | |||
149 | static 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 | }; | ||
155 | static 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 | }; | ||
164 | static 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 | }; | ||
179 | static 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 | }; | ||
217 | static 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 ********************/ | ||
230 | static 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 | }; | ||
245 | static const __u16 Pb100_2map8300[][2] = { | ||
246 | /* reg, value */ | ||
247 | {0x8339, 0x0000}, | ||
248 | {0x8307, 0x00aa}, | ||
249 | {} | ||
250 | }; | ||
251 | |||
252 | static 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 | }; | ||
261 | static 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 | |||
308 | static 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 | |||
321 | static 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 */ | ||
335 | static 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 */ | ||
347 | static 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 | |||
358 | static 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 | |||
373 | static 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 | |||
394 | static 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 | |||
405 | static 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 | |||
414 | static 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 */ | ||
424 | static 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 */ | ||
473 | static 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 | } | ||
479 | static 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 */ | ||
493 | static 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 | |||
508 | static 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 | |||
530 | static 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 */ | ||
549 | static 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 */ | ||
588 | static 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 | |||
606 | static 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 | |||
616 | static 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 | } | ||
653 | static 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 | |||
691 | static 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 | |||
705 | static 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 | |||
772 | static 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 */ | ||
821 | static 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 | |||
831 | static 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 */ | ||
840 | static 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 | |||
850 | static 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 | |||
858 | static 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 | |||
868 | static 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 | |||
876 | static 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 | |||
886 | static 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 */ | ||
895 | static 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 | |||
905 | static 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 */ | ||
914 | static 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 | |||
924 | static 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 */ | ||
933 | static 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 | |||
975 | static 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 */ | ||
1031 | static 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 | }; | ||
1044 | static 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 | }; | ||
1058 | static const struct sd_desc *sd_desc[2] = { | ||
1059 | &sd_desc_12a, | ||
1060 | &sd_desc_72a | ||
1061 | }; | ||
1062 | |||
1063 | /* -- module initialisation -- */ | ||
1064 | static 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 | |||
1084 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1085 | |||
1086 | /* -- device connect -- */ | ||
1087 | static 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 | |||
1096 | static 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 -- */ | ||
1108 | static int __init sd_mod_init(void) | ||
1109 | { | ||
1110 | return usb_register(&sd_driver); | ||
1111 | } | ||
1112 | static void __exit sd_mod_exit(void) | ||
1113 | { | ||
1114 | usb_deregister(&sd_driver); | ||
1115 | } | ||
1116 | |||
1117 | module_init(sd_mod_init); | ||
1118 | module_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 | |||
42 | MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, " | ||
43 | "Theodore Kilgore <kilgota@auburn.edu>"); | ||
44 | MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver"); | ||
45 | MODULE_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 */ | ||
83 | struct 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 | |||
93 | static 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 | */ | ||
114 | static 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 | */ | ||
149 | static 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 | */ | ||
171 | static int | ||
172 | sq905_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 | */ | ||
214 | static 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 | } | ||
287 | quit_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 */ | ||
297 | static 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 */ | ||
314 | static 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 */ | ||
327 | static 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. */ | ||
366 | static 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 */ | ||
399 | static const struct usb_device_id device_table[] = { | ||
400 | {USB_DEVICE(0x2770, 0x9120)}, | ||
401 | {} | ||
402 | }; | ||
403 | |||
404 | MODULE_DEVICE_TABLE(usb, device_table); | ||
405 | |||
406 | /* sub-driver description */ | ||
407 | static 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 -- */ | ||
416 | static 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 | |||
425 | static 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 -- */ | ||
437 | static int __init sd_mod_init(void) | ||
438 | { | ||
439 | return usb_register(&sd_driver); | ||
440 | } | ||
441 | |||
442 | static void __exit sd_mod_exit(void) | ||
443 | { | ||
444 | usb_deregister(&sd_driver); | ||
445 | } | ||
446 | |||
447 | module_init(sd_mod_init); | ||
448 | module_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 | |||
36 | MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); | ||
37 | MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver"); | ||
38 | MODULE_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 */ | ||
60 | struct 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 | */ | ||
73 | static 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. */ | ||
87 | static 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 | |||
106 | static 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 | */ | ||
136 | static 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 | } | ||
193 | quit_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 */ | ||
203 | static 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 */ | ||
246 | static 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 */ | ||
259 | static 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. */ | ||
269 | static 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 */ | ||
301 | static 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 | |||
310 | MODULE_DEVICE_TABLE(usb, device_table); | ||
311 | |||
312 | /* sub-driver description */ | ||
313 | static 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 -- */ | ||
322 | static 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 | |||
331 | static 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 -- */ | ||
343 | static int __init sd_mod_init(void) | ||
344 | { | ||
345 | return usb_register(&sd_driver); | ||
346 | } | ||
347 | |||
348 | static void __exit sd_mod_exit(void) | ||
349 | { | ||
350 | usb_deregister(&sd_driver); | ||
351 | } | ||
352 | |||
353 | module_init(sd_mod_init); | ||
354 | module_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 | |||
27 | MODULE_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>"); | ||
30 | MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | /* Structure to hold all of our device specific stuff */ | ||
34 | struct 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 | }; | ||
47 | enum sensors { | ||
48 | SENSOR_ICX098BQ, | ||
49 | SENSOR_LZ24BP, | ||
50 | SENSOR_MI0360, | ||
51 | SENSOR_MT9V111, /* = MI360SOC */ | ||
52 | SENSOR_OV7660, | ||
53 | SENSOR_OV9630, | ||
54 | }; | ||
55 | |||
56 | static int sd_setexpo(struct gspca_dev *gspca_dev, __s32 val); | ||
57 | static int sd_getexpo(struct gspca_dev *gspca_dev, __s32 *val); | ||
58 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
59 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
60 | |||
61 | static 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 | |||
92 | static 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 | |||
125 | struct ucbus_write_cmd { | ||
126 | u16 bw_addr; | ||
127 | u8 bw_data; | ||
128 | }; | ||
129 | struct i2c_write_cmd { | ||
130 | u8 reg; | ||
131 | u16 val; | ||
132 | }; | ||
133 | |||
134 | static 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 | }; | ||
162 | static 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 | |||
171 | static 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 | |||
182 | static 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 | }; | ||
210 | static 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 | |||
219 | static 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 | |||
228 | static 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 | |||
239 | static 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 | }; | ||
243 | static 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 | }; | ||
249 | static const struct i2c_write_cmd mi0360_init_24[] = { | ||
250 | {0x03, 0x01e5}, /* window height */ | ||
251 | {0x04, 0x0285}, /* window width */ | ||
252 | }; | ||
253 | static 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 | }; | ||
260 | static 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 | }; | ||
268 | static const struct i2c_write_cmd mi0360_start_2[] = { | ||
269 | {0x62, 0x041d}, /* reserved - def 0x0418 */ | ||
270 | }; | ||
271 | static const struct i2c_write_cmd mi0360_start_3[] = { | ||
272 | {0x05, 0x007b}, /* horiz blanking */ | ||
273 | }; | ||
274 | static const struct i2c_write_cmd mi0360_start_4[] = { | ||
275 | {0x05, 0x03f5}, /* horiz blanking */ | ||
276 | }; | ||
277 | |||
278 | static 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 | }; | ||
284 | static const struct i2c_write_cmd mt9v111_init_1[] = { | ||
285 | {0x03, 0x01e5}, /* window height */ | ||
286 | {0x04, 0x0285}, /* window width */ | ||
287 | }; | ||
288 | static 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 | }; | ||
298 | static 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 | }; | ||
306 | static const struct i2c_write_cmd mt9v111_init_3[] = { | ||
307 | {0x62, 0x0405}, | ||
308 | }; | ||
309 | static const struct i2c_write_cmd mt9v111_init_4[] = { | ||
310 | /* {0x05, 0x00ce}, */ | ||
311 | {0x05, 0x005d}, /* horizontal blanking */ | ||
312 | }; | ||
313 | |||
314 | static 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 | |||
319 | static 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] */ | ||
325 | static 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 | |||
379 | struct 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 | |||
388 | static 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 | |||
457 | static 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 | |||
476 | static 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 | |||
496 | static 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 | |||
519 | static 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 | |||
564 | static 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 | |||
626 | static 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 | |||
646 | static 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 | |||
656 | static 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 | |||
667 | static 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 | |||
705 | static 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 | |||
740 | static 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 | |||
781 | static 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 | |||
791 | static 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 */ | ||
846 | static 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 */ | ||
867 | static 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 */ | ||
928 | static 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 | |||
941 | static 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 */ | ||
947 | static 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 */ | ||
958 | static 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); | ||
1058 | out: | ||
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 | |||
1069 | static 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. */ | ||
1080 | static 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 | |||
1100 | static 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 | |||
1113 | static 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 | |||
1123 | static 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 | } | ||
1130 | static 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 | |||
1140 | static 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 */ | ||
1149 | static 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) | ||
1166 | static 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 | }; | ||
1175 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1176 | |||
1177 | |||
1178 | /* -- device connect -- */ | ||
1179 | static 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 | |||
1186 | static 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 -- */ | ||
1198 | static int __init sd_mod_init(void) | ||
1199 | { | ||
1200 | return usb_register(&sd_driver); | ||
1201 | } | ||
1202 | static void __exit sd_mod_exit(void) | ||
1203 | { | ||
1204 | usb_deregister(&sd_driver); | ||
1205 | } | ||
1206 | |||
1207 | module_init(sd_mod_init); | ||
1208 | module_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 | |||
26 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
27 | MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* controls */ | ||
31 | enum e_ctrl { | ||
32 | BRIGHTNESS, | ||
33 | CONTRAST, | ||
34 | COLORS, | ||
35 | LIGHTFREQ, | ||
36 | NCTRLS /* number of controls */ | ||
37 | }; | ||
38 | |||
39 | /* specific webcam descriptor */ | ||
40 | struct 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 */ | ||
54 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
55 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
56 | static void setcolors(struct gspca_dev *gspca_dev); | ||
57 | static void setlightfreq(struct gspca_dev *gspca_dev); | ||
58 | |||
59 | static 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 | |||
110 | static 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 -- */ | ||
124 | static 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 -- */ | ||
148 | static 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) -- */ | ||
171 | static 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 -- */ | ||
201 | static 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 */ | ||
250 | static void set_par(struct gspca_dev *gspca_dev, | ||
251 | int parval) | ||
252 | { | ||
253 | snd_val(gspca_dev, 0x003f08, parval); | ||
254 | } | ||
255 | |||
256 | static 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 | |||
266 | static 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 | |||
276 | static 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 | |||
286 | static 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 */ | ||
296 | static 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 */ | ||
309 | static 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 -- */ | ||
326 | static 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); | ||
381 | out: | ||
382 | return gspca_dev->usb_err; | ||
383 | } | ||
384 | |||
385 | static 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 | |||
404 | static 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 | |||
436 | static 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 | |||
451 | static 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 | |||
467 | static 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 */ | ||
480 | static 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 -- */ | ||
495 | static const struct usb_device_id device_table[] = { | ||
496 | {USB_DEVICE(0x05e1, 0x0893)}, | ||
497 | {} | ||
498 | }; | ||
499 | MODULE_DEVICE_TABLE(usb, device_table); | ||
500 | |||
501 | /* -- device connect -- */ | ||
502 | static 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 | |||
509 | static 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 -- */ | ||
521 | static int __init sd_mod_init(void) | ||
522 | { | ||
523 | return usb_register(&sd_driver); | ||
524 | } | ||
525 | static void __exit sd_mod_exit(void) | ||
526 | { | ||
527 | usb_deregister(&sd_driver); | ||
528 | } | ||
529 | |||
530 | module_init(sd_mod_init); | ||
531 | module_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 | |||
34 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
35 | MODULE_DESCRIPTION("STV0680 USB Camera Driver"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | /* specific webcam descriptor */ | ||
39 | struct 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 */ | ||
48 | static const struct ctrl sd_ctrls[] = { | ||
49 | }; | ||
50 | |||
51 | static 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 | |||
88 | static 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 | |||
96 | static 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 | |||
110 | static 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 */ | ||
137 | static 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 */ | ||
247 | static int sd_init(struct gspca_dev *gspca_dev) | ||
248 | { | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* -- start the camera -- */ | ||
253 | static 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 | |||
275 | static 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 | |||
282 | static 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 | |||
292 | static 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 */ | ||
317 | static 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 -- */ | ||
330 | static const struct usb_device_id device_table[] = { | ||
331 | {USB_DEVICE(0x0553, 0x0202)}, | ||
332 | {USB_DEVICE(0x041e, 0x4007)}, | ||
333 | {} | ||
334 | }; | ||
335 | MODULE_DEVICE_TABLE(usb, device_table); | ||
336 | |||
337 | /* -- device connect -- */ | ||
338 | static 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 | |||
345 | static 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 -- */ | ||
357 | static int __init sd_mod_init(void) | ||
358 | { | ||
359 | return usb_register(&sd_driver); | ||
360 | } | ||
361 | static void __exit sd_mod_exit(void) | ||
362 | { | ||
363 | usb_deregister(&sd_driver); | ||
364 | } | ||
365 | |||
366 | module_init(sd_mod_init); | ||
367 | module_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 @@ | |||
1 | config 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 @@ | |||
1 | obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o | ||
2 | |||
3 | gspca_stv06xx-objs := stv06xx.o \ | ||
4 | stv06xx_vv6410.o \ | ||
5 | stv06xx_hdcs.o \ | ||
6 | stv06xx_pb0100.o \ | ||
7 | stv06xx_st6422.o | ||
8 | |||
9 | EXTRA_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 | |||
33 | MODULE_AUTHOR("Erik Andrén"); | ||
34 | MODULE_DESCRIPTION("STV06XX USB Camera Driver"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | static int dump_bridge; | ||
38 | static int dump_sensor; | ||
39 | |||
40 | int 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 | |||
60 | int 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 */ | ||
80 | int 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 | |||
91 | static 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 | |||
108 | int 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 | |||
137 | int 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 | |||
168 | int 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 */ | ||
211 | static 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 */ | ||
243 | static 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 */ | ||
263 | static 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 | |||
290 | out: | ||
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 | |||
299 | static 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 | |||
312 | static 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 | |||
336 | static 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 | |||
348 | out: | ||
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 | */ | ||
367 | static 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: | ||
409 | frame_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) | ||
483 | static 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 | |||
505 | static int stv06xx_config(struct gspca_dev *gspca_dev, | ||
506 | const struct usb_device_id *id); | ||
507 | |||
508 | /* sub-driver description */ | ||
509 | static 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 */ | ||
524 | static 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 -- */ | ||
565 | static 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 | }; | ||
580 | MODULE_DEVICE_TABLE(usb, device_table); | ||
581 | |||
582 | /* -- device connect -- */ | ||
583 | static 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 | |||
591 | static 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 | |||
602 | static 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 -- */ | ||
614 | static int __init sd_mod_init(void) | ||
615 | { | ||
616 | return usb_register(&sd_driver); | ||
617 | } | ||
618 | static void __exit sd_mod_exit(void) | ||
619 | { | ||
620 | usb_deregister(&sd_driver); | ||
621 | } | ||
622 | |||
623 | module_init(sd_mod_init); | ||
624 | module_exit(sd_mod_exit); | ||
625 | |||
626 | module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); | ||
627 | MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); | ||
628 | |||
629 | module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); | ||
630 | MODULE_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 */ | ||
82 | struct 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 | |||
106 | int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data); | ||
107 | int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data); | ||
108 | |||
109 | int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len); | ||
110 | int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len); | ||
111 | |||
112 | int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value); | ||
113 | int 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 | |||
33 | static 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 | |||
63 | static 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 | |||
77 | static 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 | |||
107 | static 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 | |||
121 | enum hdcs_power_state { | ||
122 | HDCS_STATE_SLEEP, | ||
123 | HDCS_STATE_IDLE, | ||
124 | HDCS_STATE_RUN | ||
125 | }; | ||
126 | |||
127 | /* no lock? */ | ||
128 | struct 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 | |||
154 | static 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 | |||
174 | static 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 | |||
217 | static 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 | |||
233 | static 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 | |||
243 | static 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 | |||
335 | static 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 | |||
356 | static 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 | |||
366 | static 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 | |||
373 | static 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 | |||
421 | static 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 | |||
480 | static 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 | |||
524 | static 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 | |||
531 | static 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 | |||
538 | static void hdcs_disconnect(struct sd *sd) | ||
539 | { | ||
540 | PDEBUG(D_PROBE, "Disconnecting the sensor"); | ||
541 | kfree(sd->sensor_priv); | ||
542 | } | ||
543 | |||
544 | static 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 | |||
600 | static 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 | |||
130 | static int hdcs_probe_1x00(struct sd *sd); | ||
131 | static int hdcs_probe_1020(struct sd *sd); | ||
132 | static int hdcs_start(struct sd *sd); | ||
133 | static int hdcs_init(struct sd *sd); | ||
134 | static int hdcs_stop(struct sd *sd); | ||
135 | static int hdcs_dump(struct sd *sd); | ||
136 | static void hdcs_disconnect(struct sd *sd); | ||
137 | |||
138 | static int hdcs_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
139 | static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
140 | static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
141 | static int hdcs_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
142 | |||
143 | const 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 | |||
162 | const 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 | |||
180 | static 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 | |||
194 | static 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 | |||
49 | static 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 | |||
150 | static 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 | |||
175 | static 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 | |||
209 | static 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 | |||
269 | static 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"); | ||
282 | out: | ||
283 | return (err < 0) ? err : 0; | ||
284 | } | ||
285 | |||
286 | static 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 */ | ||
296 | static 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 | |||
358 | static int pb0100_dump(struct sd *sd) | ||
359 | { | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static 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 | |||
373 | static 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 | |||
398 | static 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 | |||
408 | static 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 | |||
430 | static 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 | |||
440 | static 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 | |||
462 | static 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 | |||
472 | static 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 | |||
488 | static 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 | |||
498 | static 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 | |||
521 | static 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 | |||
531 | static 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 | |||
555 | static 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 | |||
565 | static 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 | |||
112 | static int pb0100_probe(struct sd *sd); | ||
113 | static int pb0100_start(struct sd *sd); | ||
114 | static int pb0100_init(struct sd *sd); | ||
115 | static int pb0100_stop(struct sd *sd); | ||
116 | static int pb0100_dump(struct sd *sd); | ||
117 | static void pb0100_disconnect(struct sd *sd); | ||
118 | |||
119 | /* V4L2 controls supported by the driver */ | ||
120 | static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
121 | static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
122 | static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
123 | static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
124 | static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
125 | static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
126 | static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
127 | static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
128 | static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
129 | static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val); | ||
130 | static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val); | ||
131 | static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val); | ||
132 | static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val); | ||
133 | static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val); | ||
134 | |||
135 | const 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 | |||
37 | extern const struct stv06xx_sensor stv06xx_sensor_vv6410; | ||
38 | extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; | ||
39 | extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; | ||
40 | extern const struct stv06xx_sensor stv06xx_sensor_pb0100; | ||
41 | extern const struct stv06xx_sensor stv06xx_sensor_st6422; | ||
42 | |||
43 | struct 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 */ | ||
32 | enum e_ctrl { | ||
33 | BRIGHTNESS, | ||
34 | CONTRAST, | ||
35 | GAIN, | ||
36 | EXPOSURE, | ||
37 | NCTRLS /* number of controls */ | ||
38 | }; | ||
39 | |||
40 | /* sensor settings */ | ||
41 | struct st6422_settings { | ||
42 | struct gspca_ctrl ctrls[NCTRLS]; | ||
43 | }; | ||
44 | |||
45 | static 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 */ | ||
75 | static void st6422_set_brightness(struct gspca_dev *gspca_dev); | ||
76 | static void st6422_set_contrast(struct gspca_dev *gspca_dev); | ||
77 | static void st6422_set_gain(struct gspca_dev *gspca_dev); | ||
78 | static void st6422_set_exposure(struct gspca_dev *gspca_dev); | ||
79 | |||
80 | static 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 | |||
132 | static 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 | |||
155 | static 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 | |||
240 | static void st6422_disconnect(struct sd *sd) | ||
241 | { | ||
242 | sd->sensor = NULL; | ||
243 | kfree(sd->sensor_priv); | ||
244 | } | ||
245 | |||
246 | static 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 | |||
255 | static 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 | |||
264 | static 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 | |||
293 | static 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 | |||
307 | static 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 | |||
340 | static int st6422_stop(struct sd *sd) | ||
341 | { | ||
342 | PDEBUG(D_STREAM, "Halting stream"); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static 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 | |||
361 | static 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 | |||
375 | static 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 | |||
389 | static 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 | |||
34 | static int st6422_probe(struct sd *sd); | ||
35 | static int st6422_start(struct sd *sd); | ||
36 | static int st6422_init(struct sd *sd); | ||
37 | static int st6422_stop(struct sd *sd); | ||
38 | static void st6422_disconnect(struct sd *sd); | ||
39 | |||
40 | const 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 | |||
32 | static 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 | |||
45 | static 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 | |||
104 | static 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 | |||
135 | static 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 | |||
174 | static void vv6410_disconnect(struct sd *sd) | ||
175 | { | ||
176 | sd->sensor = NULL; | ||
177 | kfree(sd->sensor_priv); | ||
178 | } | ||
179 | |||
180 | static 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 | |||
222 | static 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 | |||
240 | static 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 | |||
254 | static 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 | |||
265 | static 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 | |||
288 | static 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 | |||
299 | static 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 | |||
322 | static 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 | |||
334 | static 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 | |||
347 | static 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 | |||
359 | static 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 | |||
390 | out: | ||
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 | |||
178 | static int vv6410_probe(struct sd *sd); | ||
179 | static int vv6410_start(struct sd *sd); | ||
180 | static int vv6410_init(struct sd *sd); | ||
181 | static int vv6410_stop(struct sd *sd); | ||
182 | static int vv6410_dump(struct sd *sd); | ||
183 | static void vv6410_disconnect(struct sd *sd); | ||
184 | |||
185 | /* V4L2 controls supported by the driver */ | ||
186 | static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
187 | static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
188 | static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
189 | static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
190 | static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
191 | static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
192 | static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
193 | static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
194 | |||
195 | const 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 */ | ||
213 | struct stv_init { | ||
214 | const u8 *data; | ||
215 | u16 start; | ||
216 | u8 len; | ||
217 | }; | ||
218 | |||
219 | static const u8 x1500[] = { /* 0x1500 - 0x150f */ | ||
220 | 0x0b, 0xa7, 0xb7, 0x00, 0x00 | ||
221 | }; | ||
222 | |||
223 | static const u8 x1536[] = { /* 0x1536 - 0x153b */ | ||
224 | 0x02, 0x00, 0x60, 0x01, 0x20, 0x01 | ||
225 | }; | ||
226 | |||
227 | static 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 | |||
237 | static 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 | |||
27 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
28 | MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver"); | ||
29 | MODULE_LICENSE("GPL"); | ||
30 | |||
31 | /* specific webcam descriptor */ | ||
32 | struct 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 */ | ||
61 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
62 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
63 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
64 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
65 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
66 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
67 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
68 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
69 | |||
70 | static 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 | |||
129 | static 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 | |||
142 | static 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 | |||
155 | static 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 | |||
190 | struct cmd { | ||
191 | u8 req; | ||
192 | u16 val; | ||
193 | u16 idx; | ||
194 | }; | ||
195 | |||
196 | /* Initialisation data for the Creative PC-CAM 600 */ | ||
197 | static 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 | */ | ||
226 | static 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 */ | ||
234 | static 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 ? */ | ||
261 | static 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 | |||
271 | static 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 | */ | ||
296 | static 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 */ | ||
319 | static 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 */ | ||
349 | static 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 */ | ||
374 | static 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 | |||
396 | static 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 | |||
405 | static 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 | |||
419 | static 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 | ||
433 | static 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 | |||
450 | static 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 | |||
479 | static 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 | |||
491 | static 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 | ||
508 | static 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 | |||
521 | static 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 | |||
577 | static 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 | |||
591 | static 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 | |||
598 | static 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 | |||
607 | static 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 | |||
616 | static 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 | |||
625 | static 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 */ | ||
657 | static 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 */ | ||
714 | static 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 | |||
800 | static 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 | |||
886 | static 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 | |||
919 | static 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 | |||
1013 | static 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 | |||
1023 | static 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 | |||
1031 | static 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 | |||
1041 | static 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 | |||
1049 | static 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 | |||
1059 | static 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 | |||
1067 | static 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 | |||
1075 | static 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 | |||
1083 | static 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 | |||
1099 | static 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 */ | ||
1112 | static 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) | ||
1129 | static 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 | }; | ||
1191 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1192 | |||
1193 | /* -- device connect -- */ | ||
1194 | static 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 | |||
1201 | static 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 -- */ | ||
1213 | static int __init sd_mod_init(void) | ||
1214 | { | ||
1215 | return usb_register(&sd_driver); | ||
1216 | } | ||
1217 | static void __exit sd_mod_exit(void) | ||
1218 | { | ||
1219 | usb_deregister(&sd_driver); | ||
1220 | } | ||
1221 | |||
1222 | module_init(sd_mod_init); | ||
1223 | module_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 | |||
36 | MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); | ||
37 | MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | struct 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 | }; | ||
59 | enum 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 */ | ||
67 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
68 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
69 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
70 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
71 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
72 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
73 | static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val); | ||
74 | static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val); | ||
75 | static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); | ||
76 | static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); | ||
77 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
78 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
79 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
80 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
81 | |||
82 | static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); | ||
84 | static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
87 | static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
88 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
89 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
90 | |||
91 | static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val); | ||
92 | static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val); | ||
93 | static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); | ||
94 | static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); | ||
95 | |||
96 | static 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 | |||
284 | static 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 */ | ||
313 | struct 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 | |||
325 | static 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 | }; | ||
336 | static 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 | }; | ||
346 | static 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 | }; | ||
355 | static 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 | |||
367 | static 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 */ | ||
455 | static char *effects_control[MAX_EFFECTS] = { | ||
456 | "Normal", | ||
457 | "Emboss", /* disabled */ | ||
458 | "Monochrome", | ||
459 | "Sepia", | ||
460 | "Sketch", | ||
461 | "Sun Effect", /* disabled */ | ||
462 | "Negative", | ||
463 | }; | ||
464 | static 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 | |||
474 | static 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 | |||
526 | static 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 | |||
532 | static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; | ||
533 | |||
534 | /* read 1 byte */ | ||
535 | static 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 | |||
548 | static 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 | |||
559 | static 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 */ | ||
589 | static 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 | |||
620 | static 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 */ | ||
679 | static 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 | |||
707 | static 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 | |||
724 | static 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 | |||
738 | static 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 | |||
747 | static 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 | |||
756 | static 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 */ | ||
769 | static 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 | |||
789 | static 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 | |||
810 | static 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 | |||
820 | static 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 */ | ||
853 | static 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 | |||
967 | static 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 | |||
979 | static 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 */ | ||
999 | static 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 | |||
1020 | static 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 | |||
1084 | static 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 | |||
1098 | static 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 | |||
1121 | static 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 | |||
1131 | static 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 | |||
1139 | static 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 | |||
1150 | static 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 | |||
1158 | static 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 | |||
1186 | static 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 | |||
1194 | static 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 | |||
1204 | static 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 | |||
1212 | static 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 | |||
1222 | static 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 | |||
1230 | static 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 | |||
1240 | static 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 | |||
1248 | static 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 | |||
1258 | static 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 | |||
1266 | static 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 | |||
1276 | static 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 | |||
1284 | static 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 | |||
1294 | static 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 | |||
1302 | static 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 | |||
1312 | static 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 | |||
1320 | static 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 | |||
1330 | static 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 | |||
1338 | static 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 | |||
1348 | static 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......*/ | ||
1357 | static 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 | |||
1369 | static 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 | |||
1377 | static 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 */ | ||
1401 | static 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 -- */ | ||
1414 | static const struct usb_device_id device_table[] = { | ||
1415 | {USB_DEVICE(0x17a1, 0x0128)}, | ||
1416 | {} | ||
1417 | }; | ||
1418 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1419 | |||
1420 | /* -- device connect -- */ | ||
1421 | static 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 | |||
1428 | static 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 -- */ | ||
1440 | static int __init sd_mod_init(void) | ||
1441 | { | ||
1442 | return usb_register(&sd_driver); | ||
1443 | } | ||
1444 | static void __exit sd_mod_exit(void) | ||
1445 | { | ||
1446 | usb_deregister(&sd_driver); | ||
1447 | } | ||
1448 | |||
1449 | module_init(sd_mod_init); | ||
1450 | module_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 | |||
25 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | ||
26 | MODULE_DESCRIPTION("TV8532 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct 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 */ | ||
40 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
41 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
42 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
43 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
44 | |||
45 | static 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 | |||
76 | static 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 | |||
140 | static 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 */ | ||
159 | static 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 */ | ||
172 | static 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 | |||
185 | static 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 */ | ||
202 | static 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 | |||
217 | static 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 */ | ||
237 | static int sd_init(struct gspca_dev *gspca_dev) | ||
238 | { | ||
239 | tv_8532WriteEEprom(gspca_dev); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static 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 | |||
253 | static 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 -- */ | ||
264 | static 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 | |||
306 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
307 | { | ||
308 | reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ | ||
309 | } | ||
310 | |||
311 | static 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 | |||
342 | static 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 | |||
352 | static 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 | |||
360 | static 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 | |||
370 | static 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 */ | ||
379 | static 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 -- */ | ||
391 | static 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 | |||
400 | MODULE_DEVICE_TABLE(usb, device_table); | ||
401 | |||
402 | /* -- device connect -- */ | ||
403 | static 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 | |||
410 | static 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 -- */ | ||
422 | static int __init sd_mod_init(void) | ||
423 | { | ||
424 | return usb_register(&sd_driver); | ||
425 | } | ||
426 | |||
427 | static void __exit sd_mod_exit(void) | ||
428 | { | ||
429 | usb_deregister(&sd_driver); | ||
430 | } | ||
431 | |||
432 | module_init(sd_mod_init); | ||
433 | module_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 | |||
27 | MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); | ||
28 | MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver"); | ||
29 | MODULE_LICENSE("GPL"); | ||
30 | |||
31 | /* specific webcam descriptor */ | ||
32 | struct 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 | }; | ||
56 | enum bridges { | ||
57 | BRIDGE_VC0321, | ||
58 | BRIDGE_VC0323, | ||
59 | }; | ||
60 | enum 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 */ | ||
75 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
76 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
77 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
78 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
79 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
80 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
81 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
82 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
83 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
85 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
86 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
87 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
88 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
89 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
90 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
91 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
92 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
93 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
94 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
95 | static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val); | ||
96 | static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val); | ||
97 | |||
98 | static 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 */ | ||
268 | static 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 | |||
321 | static 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 | }; | ||
333 | static 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 | }; | ||
350 | static 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 | }; | ||
367 | static 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 | |||
380 | static const u8 mi0360_matrix[9] = { | ||
381 | 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50 | ||
382 | }; | ||
383 | |||
384 | static 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 | }; | ||
493 | static 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 | |||
613 | static 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 | }; | ||
765 | static 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 | }; | ||
839 | static 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 | |||
1033 | static 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 | }; | ||
1037 | static const u8 mi1320_matrix[9] = { | ||
1038 | 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52 | ||
1039 | }; | ||
1040 | static 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 | }; | ||
1121 | static 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 | |||
1190 | static 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 | }; | ||
1293 | static 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 | }; | ||
1406 | static 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 | }; | ||
1529 | static 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 | }; | ||
1533 | static const u8 po3130_matrix[9] = { | ||
1534 | 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 | ||
1535 | }; | ||
1536 | |||
1537 | static 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 | }; | ||
1621 | static 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 | |||
1636 | static 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 | |||
1722 | static 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 | }; | ||
1726 | static const u8 hv7131r_matrix[9] = { | ||
1727 | 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 | ||
1728 | }; | ||
1729 | static 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 | |||
1817 | static 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 | |||
1915 | static 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 | }; | ||
1919 | static const u8 ov7660_matrix[9] = { | ||
1920 | 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62 | ||
1921 | }; | ||
1922 | static 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 | }; | ||
1981 | static 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 | |||
2050 | static const u8 ov7660_50HZ[][4] = { | ||
2051 | {0x00, 0x3b, 0x08, 0xaa}, | ||
2052 | {0x00, 0x9d, 0x40, 0xaa}, | ||
2053 | {0x00, 0x13, 0xa7, 0xaa}, | ||
2054 | {} | ||
2055 | }; | ||
2056 | |||
2057 | static const u8 ov7660_60HZ[][4] = { | ||
2058 | {0x00, 0x3b, 0x00, 0xaa}, | ||
2059 | {0x00, 0x9e, 0x40, 0xaa}, | ||
2060 | {0x00, 0x13, 0xa7, 0xaa}, | ||
2061 | {} | ||
2062 | }; | ||
2063 | |||
2064 | static const u8 ov7660_NoFliker[][4] = { | ||
2065 | {0x00, 0x13, 0x87, 0xaa}, | ||
2066 | {} | ||
2067 | }; | ||
2068 | |||
2069 | static 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 | |||
2307 | static 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 */ | ||
2556 | static 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 | }; | ||
2560 | static const u8 po1200_matrix[9] = { | ||
2561 | 0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e | ||
2562 | }; | ||
2563 | static 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 | |||
2825 | static 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 | }; | ||
2925 | static 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 | }; | ||
2969 | static 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 | }; | ||
3005 | static 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 | }; | ||
3021 | static 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 | }; | ||
3037 | static 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 | }; | ||
3051 | static 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 | |||
3058 | struct 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 */ | ||
3069 | static 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 | }; | ||
3110 | static 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 */ | ||
3155 | static 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 | } | ||
3176 | static 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 | |||
3197 | static 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 | } | ||
3217 | static 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 | |||
3230 | static 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 | |||
3267 | static 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 | |||
3322 | static 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 | |||
3355 | static 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 | |||
3365 | static 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 */ | ||
3395 | static 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 */ | ||
3423 | static 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 | |||
3536 | static 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 | |||
3551 | static 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 | |||
3560 | static 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 | |||
3572 | static 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 | |||
3612 | static 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 | |||
3623 | static 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 | } | ||
3647 | static 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 | |||
3656 | static 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 | |||
3669 | static 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 | |||
3679 | static void setgamma(struct gspca_dev *gspca_dev) | ||
3680 | { | ||
3681 | /*fixme:to do */ | ||
3682 | usb_exchange(gspca_dev, poxxxx_gamma); | ||
3683 | } | ||
3684 | |||
3685 | static 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 | |||
3715 | static 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 | |||
3724 | static 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 | |||
3894 | static 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 */ | ||
3914 | static 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 | |||
3933 | static 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 | |||
3962 | static 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 | |||
3972 | static 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 | |||
3980 | static 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 | |||
3990 | static 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 | |||
3998 | static 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 | |||
4008 | static 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 | |||
4016 | static 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 | |||
4026 | static 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 | |||
4034 | static 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 | |||
4044 | static 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 | |||
4052 | static 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 | |||
4062 | static 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 | |||
4070 | static 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 | |||
4080 | static 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 | |||
4088 | static 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 | |||
4098 | static 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 | |||
4106 | static 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 | |||
4116 | static 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 | |||
4124 | static 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 | |||
4135 | static 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 | |||
4143 | static 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 | |||
4154 | static 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 | |||
4162 | static 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 */ | ||
4178 | static 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) | ||
4195 | static 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 | }; | ||
4211 | MODULE_DEVICE_TABLE(usb, device_table); | ||
4212 | |||
4213 | /* -- device connect -- */ | ||
4214 | static 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 | |||
4221 | static 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 -- */ | ||
4233 | static int __init sd_mod_init(void) | ||
4234 | { | ||
4235 | return usb_register(&sd_driver); | ||
4236 | } | ||
4237 | static void __exit sd_mod_exit(void) | ||
4238 | { | ||
4239 | usb_deregister(&sd_driver); | ||
4240 | } | ||
4241 | |||
4242 | module_init(sd_mod_init); | ||
4243 | module_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 | |||
38 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
39 | MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver"); | ||
40 | MODULE_LICENSE("GPL"); | ||
41 | |||
42 | enum e_ctrl { | ||
43 | GAIN, | ||
44 | EXPOSURE, | ||
45 | NCTRL /* number of controls */ | ||
46 | }; | ||
47 | |||
48 | struct 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 :( */ | ||
58 | static 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 | |||
84 | static 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 | |||
109 | static 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 | |||
125 | static 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 | */ | ||
142 | static 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 | */ | ||
208 | static 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 | } | ||
238 | exit: | ||
239 | kfree(buffer); | ||
240 | } | ||
241 | |||
242 | /* This function is called at probe time just before sd_init */ | ||
243 | static 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 */ | ||
262 | static 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); | ||
290 | exit: | ||
291 | release_firmware(fw); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | /* Set up for getting frames. */ | ||
296 | static 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 */ | ||
314 | static 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 */ | ||
329 | static const struct usb_device_id device_table[] = { | ||
330 | {USB_DEVICE(0x04c1, 0x009d)}, | ||
331 | {USB_DEVICE(0x0602, 0x1001)}, | ||
332 | {} | ||
333 | }; | ||
334 | |||
335 | MODULE_DEVICE_TABLE(usb, device_table); | ||
336 | |||
337 | /* sub-driver description */ | ||
338 | static 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 -- */ | ||
349 | static 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 | |||
358 | static 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 -- */ | ||
370 | static int __init sd_mod_init(void) | ||
371 | { | ||
372 | return usb_register(&sd_driver); | ||
373 | } | ||
374 | |||
375 | static void __exit sd_mod_exit(void) | ||
376 | { | ||
377 | usb_deregister(&sd_driver); | ||
378 | } | ||
379 | |||
380 | module_init(sd_mod_init); | ||
381 | module_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 | |||
39 | static 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 | |||
62 | static 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 | --------------------------------------------------------------------------*/ | ||
68 | static 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 | --------------------------------------------------------------------------*/ | ||
93 | static 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 | --------------------------------------------------------------------------*/ | ||
120 | static 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 | --------------------------------------------------------------------------*/ | ||
152 | static 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 | |||
176 | static 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 | |||
182 | static 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 | |||
189 | static 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 | |||
206 | static 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 | |||
223 | static 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 | |||
231 | static 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 */ | ||
247 | static 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 */ | ||
296 | static 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 | --------------------------------------------------------------------------*/ | ||
336 | static 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 | |||
349 | static 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 | |||
391 | static 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 | |||
441 | static 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 | |||
513 | static 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. */ | ||
527 | static 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 | |||
35 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
36 | MODULE_DESCRIPTION("Xirlink C-IT"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | /* FIXME we should autodetect this */ | ||
40 | static int ibm_netcam_pro; | ||
41 | module_param(ibm_netcam_pro, int, 0); | ||
42 | MODULE_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 */ | ||
46 | static int rca_input; | ||
47 | module_param(rca_input, int, 0644); | ||
48 | MODULE_PARM_DESC(rca_input, | ||
49 | "Use rca input instead of ccd sensor on Model 3 cams"); | ||
50 | |||
51 | /* specific webcam descriptor */ | ||
52 | struct 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 */ | ||
75 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
76 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
77 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
78 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
79 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | ||
80 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | ||
81 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
82 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
83 | static int sd_setlighting(struct gspca_dev *gspca_dev, __s32 val); | ||
84 | static int sd_getlighting(struct gspca_dev *gspca_dev, __s32 *val); | ||
85 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
86 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
87 | static void sd_stop0(struct gspca_dev *gspca_dev); | ||
88 | |||
89 | static 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 | |||
187 | static 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 | |||
198 | static 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 | |||
213 | static 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 | |||
228 | static 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 | */ | ||
252 | static 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) */ | ||
791 | static const int cit_model1_ntries = 5; | ||
792 | static const int cit_model1_ntries2 = 2; | ||
793 | |||
794 | static 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 | |||
809 | static 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 | */ | ||
839 | static 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 | |||
846 | static 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 | |||
853 | static 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 | |||
859 | static 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 | |||
865 | static 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 | |||
873 | static 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 | |||
881 | static 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 | |||
890 | static 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 | |||
900 | static 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 | |||
914 | static 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 | |||
921 | static 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 | |||
927 | static 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 | */ | ||
948 | static 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 | |||
957 | static 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 | |||
966 | static 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 */ | ||
981 | static 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 | |||
1051 | static 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 | |||
1075 | static 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 */ | ||
1268 | static 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 | |||
1290 | static 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 | |||
1330 | static 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 | |||
1393 | static 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 | |||
1445 | static 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 | */ | ||
1513 | static 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 | |||
1533 | static 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 | |||
1553 | static 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 | |||
1582 | static 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 */ | ||
1598 | static 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 | |||
1622 | static 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 | |||
1676 | static 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 | |||
1877 | static 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 | |||
2068 | static 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 | |||
2308 | static 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 | |||
2633 | static 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 -- */ | ||
2728 | static 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 | |||
2774 | static 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 | |||
2798 | static 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 | |||
2832 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
2833 | { | ||
2834 | cit_write_reg(gspca_dev, 0x0000, 0x010c); | ||
2835 | } | ||
2836 | |||
2837 | static 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 | |||
2913 | static 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 | |||
3032 | static 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 | |||
3058 | static 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 | |||
3074 | static 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 | |||
3083 | static 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 | |||
3099 | static 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 | |||
3108 | static 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 | |||
3123 | static 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 | |||
3132 | static 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 | |||
3147 | static 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 | |||
3156 | static 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 | |||
3171 | static 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 | |||
3180 | static 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 | |||
3195 | static 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) | ||
3205 | static 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 */ | ||
3238 | static 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 | |||
3254 | static 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 -- */ | ||
3273 | static 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 | }; | ||
3283 | MODULE_DEVICE_TABLE(usb, device_table); | ||
3284 | |||
3285 | /* -- device connect -- */ | ||
3286 | static 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 | |||
3315 | static 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 -- */ | ||
3327 | static int __init sd_mod_init(void) | ||
3328 | { | ||
3329 | return usb_register(&sd_driver); | ||
3330 | } | ||
3331 | static void __exit sd_mod_exit(void) | ||
3332 | { | ||
3333 | usb_deregister(&sd_driver); | ||
3334 | } | ||
3335 | |||
3336 | module_init(sd_mod_init); | ||
3337 | module_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 | |||
28 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " | ||
29 | "Serge A. Suchkov <Serge.A.S@tochka.ru>"); | ||
30 | MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | static int force_sensor = -1; | ||
34 | |||
35 | #define QUANT_VAL 1 /* quantization table */ | ||
36 | #include "zc3xx-reg.h" | ||
37 | |||
38 | /* controls */ | ||
39 | enum 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 */ | ||
53 | struct 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 | }; | ||
69 | enum bridges { | ||
70 | BRIDGE_ZC301, | ||
71 | BRIDGE_ZC303, | ||
72 | }; | ||
73 | enum 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 */ | ||
97 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
98 | static void setexposure(struct gspca_dev *gspca_dev); | ||
99 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
100 | static void setlightfreq(struct gspca_dev *gspca_dev); | ||
101 | static void setsharpness(struct gspca_dev *gspca_dev); | ||
102 | |||
103 | static 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 | |||
191 | static 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 | |||
204 | static 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 | |||
217 | static 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 */ | ||
231 | struct usb_action { | ||
232 | u8 req; | ||
233 | u8 val; | ||
234 | u16 idx; | ||
235 | }; | ||
236 | |||
237 | static 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 | }; | ||
326 | static 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 | }; | ||
407 | static 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 | }; | ||
420 | static 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 | }; | ||
433 | static 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 | }; | ||
444 | static 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 | |||
496 | static 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 | }; | ||
547 | static 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 | }; | ||
569 | static 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 | }; | ||
591 | static 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 | }; | ||
613 | static 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 | }; | ||
635 | static 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 | }; | ||
657 | static 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 */ | ||
681 | static 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 | |||
940 | static 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 | |||
1318 | static 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 | }; | ||
1382 | static 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 | }; | ||
1445 | static 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 | }; | ||
1471 | static 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 | |||
1495 | static 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 | |||
1518 | static 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 | }; | ||
1650 | static 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 | }; | ||
1778 | static 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 | }; | ||
1799 | static 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 | }; | ||
1820 | static 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 | |||
1842 | static 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 | |||
1889 | static 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 | }; | ||
1935 | static 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 | }; | ||
1960 | static 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 | }; | ||
1985 | static 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 | }; | ||
2010 | static 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 | }; | ||
2035 | static 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 | }; | ||
2060 | static 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!) */ | ||
2087 | static 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 | }; | ||
2133 | static 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 | }; | ||
2179 | static 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 | }; | ||
2197 | static 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 | }; | ||
2215 | static 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 | }; | ||
2233 | static 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 | }; | ||
2251 | static 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 | }; | ||
2269 | static 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 | |||
2288 | static 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 | |||
2465 | static 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 | }; | ||
2644 | static 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 | }; | ||
2675 | static 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 | }; | ||
2708 | static 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 | }; | ||
2739 | static 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 | }; | ||
2772 | static 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 | }; | ||
2803 | static 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 | |||
2837 | static 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 | |||
2957 | static 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 | |||
3071 | static 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 | |||
3083 | static 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 | |||
3095 | static 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 | |||
3107 | static 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 | |||
3119 | static 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 | |||
3131 | static 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 */ | ||
3144 | static 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 | }; | ||
3213 | static 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 | }; | ||
3284 | static 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 | }; | ||
3302 | static 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 | }; | ||
3324 | static 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 | |||
3345 | static 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 | |||
3501 | static 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 | |||
3658 | static 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 | |||
3672 | static 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 | |||
3788 | static 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 | }; | ||
3910 | static 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 | }; | ||
3926 | static 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 | }; | ||
3942 | static 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 */ | ||
3960 | static 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 | }; | ||
4004 | static 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 | }; | ||
4050 | static 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 | }; | ||
4079 | static 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 | }; | ||
4108 | static 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 | }; | ||
4137 | static 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 | }; | ||
4166 | static 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 | }; | ||
4195 | static 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 */ | ||
4226 | static 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 | }; | ||
4280 | static 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 | }; | ||
4334 | static 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 | }; | ||
4357 | static 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 | }; | ||
4379 | static 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 | }; | ||
4402 | static 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 | }; | ||
4424 | static 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 | }; | ||
4447 | static 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) */ | ||
4471 | static 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 | }; | ||
4527 | static 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 | }; | ||
4581 | static 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 | }; | ||
4603 | static 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 | }; | ||
4625 | static 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 | }; | ||
4647 | static 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 | }; | ||
4669 | static 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 | }; | ||
4692 | static 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 | |||
4716 | static 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 | }; | ||
4765 | static 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 | }; | ||
4814 | static 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 | }; | ||
4836 | static 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 | }; | ||
4858 | static 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 | }; | ||
4880 | static 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 | }; | ||
4902 | static 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 | }; | ||
4924 | static 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 */ | ||
4948 | static 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 */ | ||
5025 | static 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 | |||
5101 | static 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 | |||
5123 | static 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 | |||
5146 | static 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 | |||
5157 | static 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 | }; | ||
5194 | static 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 | }; | ||
5230 | static 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 | }; | ||
5255 | static 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 | }; | ||
5280 | static 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 | }; | ||
5305 | static 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 | }; | ||
5330 | static 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 | |||
5356 | static 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 | |||
5382 | static 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 | |||
5449 | static 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 | }; | ||
5514 | static 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 | |||
5538 | static 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 | |||
5562 | static 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 | |||
5586 | static 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 | |||
5610 | static 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 | |||
5632 | static 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 | |||
5654 | static 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 | |||
5676 | static 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 | |||
5686 | static 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 | |||
5706 | static 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 | |||
5714 | static 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 | |||
5735 | static 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 | |||
5757 | static 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 | |||
5790 | static 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 | |||
5840 | static 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 | |||
5859 | static 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 | |||
5916 | static 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 | |||
5925 | static 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 | |||
5936 | static 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 | */ | ||
5973 | static 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 | |||
6086 | static 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 | |||
6098 | static 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 */ | ||
6130 | static 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 | |||
6140 | static 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 | |||
6157 | static 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 */ | ||
6223 | ov_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 | |||
6251 | struct sensor_by_chipset_revision { | ||
6252 | u16 revision; | ||
6253 | u8 internal_sensor_id; | ||
6254 | }; | ||
6255 | static 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 | |||
6265 | static 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 | |||
6387 | static 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 */ | ||
6411 | static 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 */ | ||
6435 | static 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 | |||
6655 | static 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 */ | ||
6831 | static 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 | |||
6840 | static 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 | |||
6873 | static 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 | |||
6890 | static 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 | |||
6911 | static 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 | |||
6927 | static 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) | ||
6940 | static 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 | |||
6955 | static 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 | |||
6972 | static 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 | }; | ||
7028 | MODULE_DEVICE_TABLE(usb, device_table); | ||
7029 | |||
7030 | /* -- device connect -- */ | ||
7031 | static 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 */ | ||
7039 | static 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 | |||
7050 | static int __init sd_mod_init(void) | ||
7051 | { | ||
7052 | return usb_register(&sd_driver); | ||
7053 | } | ||
7054 | |||
7055 | static void __exit sd_mod_exit(void) | ||
7056 | { | ||
7057 | usb_deregister(&sd_driver); | ||
7058 | } | ||
7059 | |||
7060 | module_init(sd_mod_init); | ||
7061 | module_exit(sd_mod_exit); | ||
7062 | |||
7063 | module_param(force_sensor, int, 0644); | ||
7064 | MODULE_PARM_DESC(force_sensor, | ||
7065 | "Force sensor. Only for experts!!!"); | ||