1 /*
2 * cpia CPiA driver
3 *
4 * Supports CPiA based Video Camera's.
5 *
6 * (C) Copyright 1999-2000 Peter Pregler,
7 * (C) Copyright 1999-2000 Scott J. Bertin,
8 * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@valinux.com
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., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 /* #define _CPIA_DEBUG_ define for verbose debug output */
26 #include <linux/config.h>
27
28 #include <linux/module.h>
29 #include <linux/version.h>
30 #include <linux/init.h>
31 #include <linux/fs.h>
32 #include <linux/vmalloc.h>
33 #include <linux/delay.h>
34 #include <linux/slab.h>
35 #include <linux/proc_fs.h>
36 #include <linux/ctype.h>
37 #include <linux/pagemap.h>
38 #include <asm/io.h>
39 #include <asm/semaphore.h>
40 #include <linux/wrapper.h>
41
42 #ifdef CONFIG_KMOD
43 #include <linux/kmod.h>
44 #endif
45
46 #include "cpia.h"
47
48 #ifdef CONFIG_VIDEO_CPIA_PP
49 extern int cpia_pp_init(void);
50 #endif
51 #ifdef CONFIG_VIDEO_CPIA_USB
52 extern int cpia_usb_init(void);
53 #endif
54
55 #ifdef MODULE
56 MODULE_AUTHOR("Scott J. Bertin <sbertin@mindspring.com> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <jerdfelt@valinux.com>");
57 MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
58 MODULE_SUPPORTED_DEVICE("video");
59 #endif
60
61 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
62
63 #ifndef VID_HARDWARE_CPIA
64 #define VID_HARDWARE_CPIA 24 /* FIXME -> from linux/videodev.h */
65 #endif
66
67 #define CPIA_MODULE_CPIA (0<<5)
68 #define CPIA_MODULE_SYSTEM (1<<5)
69 #define CPIA_MODULE_VP_CTRL (5<<5)
70 #define CPIA_MODULE_CAPTURE (6<<5)
71 #define CPIA_MODULE_DEBUG (7<<5)
72
73 #define INPUT (DATA_IN << 8)
74 #define OUTPUT (DATA_OUT << 8)
75
76 #define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
77 #define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
78 #define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
79 #define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
80 #define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
81 #define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
82 #define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
83 #define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
84
85 #define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
86 #define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
87 #define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
88 #define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
89 #define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
90 #define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
91 #define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
92 #define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
93 #define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
94 #define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
95 #define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
96 #define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
97 #define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
98
99 #define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
100 #define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
101 #define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
102 #define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
103 #define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
104 #define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
105 #define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
106 #define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
107 #define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
108 #define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
109 #define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
110 #define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
111 #define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
112 #define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
113 #define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
114 #define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
115
116 #define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
117 #define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
118 #define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
119 #define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
120 #define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
121 #define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
122 #define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
123 #define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
124 #define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
125 #define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
126 #define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
127 #define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
128 #define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
129 #define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
130
131 #define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
132 #define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
133 #define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
134 #define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
135 #define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
136 #define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
137 #define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
138
139 enum {
140 FRAME_READY, /* Ready to grab into */
141 FRAME_GRABBING, /* In the process of being grabbed into */
142 FRAME_DONE, /* Finished grabbing, but not been synced yet */
143 FRAME_UNUSED, /* Unused (no MCAPTURE) */
144 };
145
146 #define COMMAND_NONE 0x0000
147 #define COMMAND_SETCOMPRESSION 0x0001
148 #define COMMAND_SETCOMPRESSIONTARGET 0x0002
149 #define COMMAND_SETCOLOURPARAMS 0x0004
150 #define COMMAND_SETFORMAT 0x0008
151 #define COMMAND_PAUSE 0x0010
152 #define COMMAND_RESUME 0x0020
153 #define COMMAND_SETYUVTHRESH 0x0040
154 #define COMMAND_SETECPTIMING 0x0080
155 #define COMMAND_SETCOMPRESSIONPARAMS 0x0100
156 #define COMMAND_SETEXPOSURE 0x0200
157 #define COMMAND_SETCOLOURBALANCE 0x0400
158 #define COMMAND_SETSENSORFPS 0x0800
159 #define COMMAND_SETAPCOR 0x1000
160 #define COMMAND_SETFLICKERCTRL 0x2000
161 #define COMMAND_SETVLOFFSET 0x4000
162
163 /* Developer's Guide Table 5 p 3-34
164 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
165 static u8 flicker_jumps[2][2][4] =
166 { { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
167 { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
168 };
169
170 /* forward declaration of local function */
171 static void reset_camera_struct(struct cam_data *cam);
172
173 /**********************************************************************
174 *
175 * Memory management
176 *
177 * This is a shameless copy from the USB-cpia driver (linux kernel
178 * version 2.3.29 or so, I have no idea what this code actually does ;).
179 * Actually it seems to be a copy of a shameless copy of the bttv-driver.
180 * Or that is a copy of a shameless copy of ... (To the powers: is there
181 * no generic kernel-function to do this sort of stuff?)
182 *
183 * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
184 * there will be one, but apparentely not yet - jerdfelt
185 *
186 **********************************************************************/
187
188 /* Given PGD from the address space's page table, return the kernel
189 * virtual mapping of the physical memory mapped at ADR.
190 */
191 static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
192 {
193 unsigned long ret = 0UL;
194 pmd_t *pmd;
195 pte_t *ptep, pte;
196
197 if (!pgd_none(*pgd)) {
198 pmd = pmd_offset(pgd, adr);
199 if (!pmd_none(*pmd)) {
200 ptep = pte_offset(pmd, adr);
201 pte = *ptep;
202 if (pte_present(pte)) {
203 ret = (unsigned long) page_address(pte_page(pte));
204 ret |= (adr & (PAGE_SIZE-1));
205 }
206 }
207 }
208 return ret;
209 }
210
211 /* Here we want the physical address of the memory.
212 * This is used when initializing the contents of the
213 * area and marking the pages as reserved.
214 */
215 static inline unsigned long kvirt_to_pa(unsigned long adr)
216 {
217 unsigned long va, kva, ret;
218
219 va = VMALLOC_VMADDR(adr);
220 kva = uvirt_to_kva(pgd_offset_k(va), va);
221 ret = __pa(kva);
222 return ret;
223 }
224
225 static void *rvmalloc(unsigned long size)
226 {
227 void *mem;
228 unsigned long adr, page;
229
230 /* Round it off to PAGE_SIZE */
231 size += (PAGE_SIZE - 1);
232 size &= ~(PAGE_SIZE - 1);
233
234 mem = vmalloc_32(size);
235 if (!mem)
236 return NULL;
237
238 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
239 adr = (unsigned long) mem;
240 while (size > 0) {
241 page = kvirt_to_pa(adr);
242 mem_map_reserve(virt_to_page(__va(page)));
243 adr += PAGE_SIZE;
244 if (size > PAGE_SIZE)
245 size -= PAGE_SIZE;
246 else
247 size = 0;
248 }
249
250 return mem;
251 }
252
253 static void rvfree(void *mem, unsigned long size)
254 {
255 unsigned long adr, page;
256
257 if (!mem)
258 return;
259
260 size += (PAGE_SIZE - 1);
261 size &= ~(PAGE_SIZE - 1);
262
263 adr = (unsigned long) mem;
264 while (size > 0) {
265 page = kvirt_to_pa(adr);
266 mem_map_unreserve(virt_to_page(__va(page)));
267 adr += PAGE_SIZE;
268 if (size > PAGE_SIZE)
269 size -= PAGE_SIZE;
270 else
271 size = 0;
272 }
273 vfree(mem);
274 }
275
276 /**********************************************************************
277 *
278 * /proc interface
279 *
280 **********************************************************************/
281 #ifdef CONFIG_PROC_FS
282 static struct proc_dir_entry *cpia_proc_root=NULL;
283
284 static int cpia_read_proc(char *page, char **start, off_t off,
285 int count, int *eof, void *data)
286 {
287 char *out = page;
288 int len, tmp;
289 struct cam_data *cam = data;
290 char tmpstr[20];
291
292 /* IMPORTANT: This output MUST be kept under PAGE_SIZE
293 * or we need to get more sophisticated. */
294
295 out += sprintf(out, "read-only\n-----------------------\n");
296 out += sprintf(out, "V4L Driver version: %d.%d.%d\n",
297 CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
298 out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n",
299 cam->params.version.firmwareVersion,
300 cam->params.version.firmwareRevision,
301 cam->params.version.vcVersion,
302 cam->params.version.vcRevision);
303 out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n",
304 cam->params.pnpID.vendor, cam->params.pnpID.product,
305 cam->params.pnpID.deviceRevision);
306 out += sprintf(out, "VP-Version: %d.%d %04x\n",
307 cam->params.vpVersion.vpVersion,
308 cam->params.vpVersion.vpRevision,
309 cam->params.vpVersion.cameraHeadID);
310
311 out += sprintf(out, "system_state: %#04x\n",
312 cam->params.status.systemState);
313 out += sprintf(out, "grab_state: %#04x\n",
314 cam->params.status.grabState);
315 out += sprintf(out, "stream_state: %#04x\n",
316 cam->params.status.streamState);
317 out += sprintf(out, "fatal_error: %#04x\n",
318 cam->params.status.fatalError);
319 out += sprintf(out, "cmd_error: %#04x\n",
320 cam->params.status.cmdError);
321 out += sprintf(out, "debug_flags: %#04x\n",
322 cam->params.status.debugFlags);
323 out += sprintf(out, "vp_status: %#04x\n",
324 cam->params.status.vpStatus);
325 out += sprintf(out, "error_code: %#04x\n",
326 cam->params.status.errorCode);
327 out += sprintf(out, "video_size: %s\n",
328 cam->params.format.videoSize == VIDEOSIZE_CIF ?
329 "CIF " : "QCIF");
330 out += sprintf(out, "sub_sample: %s\n",
331 cam->params.format.subSample == SUBSAMPLE_420 ?
332 "420" : "422");
333 out += sprintf(out, "yuv_order: %s\n",
334 cam->params.format.yuvOrder == YUVORDER_YUYV ?
335 "YUYV" : "UYVY");
336 out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n",
337 cam->params.roi.colStart*8,
338 cam->params.roi.rowStart*4,
339 cam->params.roi.colEnd*8,
340 cam->params.roi.rowEnd*4);
341 out += sprintf(out, "actual_fps: %3d\n", cam->fps);
342 out += sprintf(out, "transfer_rate: %4dkB/s\n",
343 cam->transfer_rate);
344
345 out += sprintf(out, "\nread-write\n");
346 out += sprintf(out, "----------------------- current min"
347 " max default comment\n");
348 out += sprintf(out, "brightness: %8d %8d %8d %8d\n",
349 cam->params.colourParams.brightness, 0, 100, 50);
350 if (cam->params.version.firmwareVersion == 1 &&
351 cam->params.version.firmwareRevision == 2)
352 /* 1-02 firmware limits contrast to 80 */
353 tmp = 80;
354 else
355 tmp = 96;
356
357 out += sprintf(out, "contrast: %8d %8d %8d %8d"
358 " steps of 8\n",
359 cam->params.colourParams.contrast, 0, tmp, 48);
360 out += sprintf(out, "saturation: %8d %8d %8d %8d\n",
361 cam->params.colourParams.saturation, 0, 100, 50);
362 tmp = (25000+5000*cam->params.sensorFps.baserate)/
363 (1<<cam->params.sensorFps.divisor);
364 out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n",
365 tmp/1000, tmp%1000, 3, 30, 15);
366 out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n",
367 2*cam->params.streamStartLine, 0,
368 cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
369 cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
370 out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n",
371 cam->params.ecpTiming ? "slow" : "normal", "slow",
372 "normal", "normal");
373
374 if (cam->params.colourBalance.balanceModeIsAuto) {
375 sprintf(tmpstr, "auto");
376 } else {
377 sprintf(tmpstr, "manual");
378 }
379 out += sprintf(out, "color_balance_mode: %8s %8s %8s"
380 " %8s\n", tmpstr, "manual", "auto", "auto");
381 out += sprintf(out, "red_gain: %8d %8d %8d %8d\n",
382 cam->params.colourBalance.redGain, 0, 212, 32);
383 out += sprintf(out, "green_gain: %8d %8d %8d %8d\n",
384 cam->params.colourBalance.greenGain, 0, 212, 6);
385 out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n",
386 cam->params.colourBalance.blueGain, 0, 212, 92);
387
388 if (cam->params.version.firmwareVersion == 1 &&
389 cam->params.version.firmwareRevision == 2)
390 /* 1-02 firmware limits gain to 2 */
391 sprintf(tmpstr, "%8d %8d", 1, 2);
392 else
393 sprintf(tmpstr, "1,2,4,8");
394
395 if (cam->params.exposure.gainMode == 0)
396 out += sprintf(out, "max_gain: unknown %18s"
397 " %8d\n", tmpstr, 2);
398 else
399 out += sprintf(out, "max_gain: %8d %18s %8d\n",
400 1<<(cam->params.exposure.gainMode-1), tmpstr, 2);
401
402 switch(cam->params.exposure.expMode) {
403 case 1:
404 case 3:
405 sprintf(tmpstr, "manual");
406 break;
407 case 2:
408 sprintf(tmpstr, "auto");
409 break;
410 default:
411 sprintf(tmpstr, "unknown");
412 break;
413 }
414 out += sprintf(out, "exposure_mode: %8s %8s %8s"
415 " %8s\n", tmpstr, "manual", "auto", "auto");
416 out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n",
417 (2-cam->params.exposure.centreWeight) ? "on" : "off",
418 "off", "on", "on");
419 out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
420 1<<cam->params.exposure.gain, 1, 1);
421 if (cam->params.version.firmwareVersion == 1 &&
422 cam->params.version.firmwareRevision == 2)
423 /* 1-02 firmware limits fineExp to 127 */
424 tmp = 255;
425 else
426 tmp = 511;
427
428 out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n",
429 cam->params.exposure.fineExp*2, 0, tmp, 0);
430 if (cam->params.version.firmwareVersion == 1 &&
431 cam->params.version.firmwareRevision == 2)
432 /* 1-02 firmware limits coarseExpHi to 0 */
433 tmp = 255;
434 else
435 tmp = 65535;
436
437 out += sprintf(out, "coarse_exp: %8d %8d %8d"
438 " %8d\n", cam->params.exposure.coarseExpLo+
439 256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
440 out += sprintf(out, "red_comp: %8d %8d %8d %8d\n",
441 cam->params.exposure.redComp, 220, 255, 220);
442 out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n",
443 cam->params.exposure.green1Comp, 214, 255, 214);
444 out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n",
445 cam->params.exposure.green2Comp, 214, 255, 214);
446 out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n",
447 cam->params.exposure.blueComp, 230, 255, 230);
448
449 out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
450 cam->params.apcor.gain1, 0, 0xff, 0x1c);
451 out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
452 cam->params.apcor.gain2, 0, 0xff, 0x1a);
453 out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
454 cam->params.apcor.gain4, 0, 0xff, 0x2d);
455 out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
456 cam->params.apcor.gain8, 0, 0xff, 0x2a);
457 out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n",
458 cam->params.vlOffset.gain1, 0, 255, 24);
459 out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n",
460 cam->params.vlOffset.gain2, 0, 255, 28);
461 out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n",
462 cam->params.vlOffset.gain4, 0, 255, 30);
463 out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n",
464 cam->params.vlOffset.gain8, 0, 255, 30);
465 out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n",
466 cam->params.flickerControl.flickerMode ? "on" : "off",
467 "off", "on", "off");
468 out += sprintf(out, "mains_frequency: %8d %8d %8d %8d"
469 " only 50/60\n",
470 cam->mainsFreq ? 60 : 50, 50, 60, 50);
471 out += sprintf(out, "allowable_overexposure: %8d %8d %8d %8d\n",
472 cam->params.flickerControl.allowableOverExposure, 0,
473 255, 0);
474 out += sprintf(out, "compression_mode: ");
475 switch(cam->params.compression.mode) {
476 case CPIA_COMPRESSION_NONE:
477 out += sprintf(out, "%8s", "none");
478 break;
479 case CPIA_COMPRESSION_AUTO:
480 out += sprintf(out, "%8s", "auto");
481 break;
482 case CPIA_COMPRESSION_MANUAL:
483 out += sprintf(out, "%8s", "manual");
484 break;
485 default:
486 out += sprintf(out, "%8s", "unknown");
487 break;
488 }
489 out += sprintf(out, " none,auto,manual auto\n");
490 out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n",
491 cam->params.compression.decimation ==
492 DECIMATION_ENAB ? "on":"off", "off", "off",
493 "off");
494 out += sprintf(out, "compression_target: %9s %9s %9s %9s\n",
495 cam->params.compressionTarget.frTargeting ==
496 CPIA_COMPRESSION_TARGET_FRAMERATE ?
497 "framerate":"quality",
498 "framerate", "quality", "quality");
499 out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n",
500 cam->params.compressionTarget.targetFR, 0, 30, 7);
501 out += sprintf(out, "target_quality: %8d %8d %8d %8d\n",
502 cam->params.compressionTarget.targetQ, 0, 255, 10);
503 out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n",
504 cam->params.yuvThreshold.yThreshold, 0, 31, 15);
505 out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n",
506 cam->params.yuvThreshold.uvThreshold, 0, 31, 15);
507 out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n",
508 cam->params.compressionParams.hysteresis, 0, 255, 3);
509 out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n",
510 cam->params.compressionParams.threshMax, 0, 255, 11);
511 out += sprintf(out, "small_step: %8d %8d %8d %8d\n",
512 cam->params.compressionParams.smallStep, 0, 255, 1);
513 out += sprintf(out, "large_step: %8d %8d %8d %8d\n",
514 cam->params.compressionParams.largeStep, 0, 255, 3);
515 out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n",
516 cam->params.compressionParams.decimationHysteresis,
517 0, 255, 2);
518 out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
519 cam->params.compressionParams.frDiffStepThresh,
520 0, 255, 5);
521 out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n",
522 cam->params.compressionParams.qDiffStepThresh,
523 0, 255, 3);
524 out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n",
525 cam->params.compressionParams.decimationThreshMod,
526 0, 255, 2);
527
528 len = out - page;
529 len -= off;
530 if (len < count) {
531 *eof = 1;
532 if (len <= 0) return 0;
533 } else
534 len = count;
535
536 *start = page + off;
537 return len;
538 }
539
540 static int cpia_write_proc(struct file *file, const char *buffer,
541 unsigned long count, void *data)
542 {
543 struct cam_data *cam = data;
544 struct cam_params new_params;
545 int retval, find_colon;
546 int size = count;
547 unsigned long val;
548 u32 command_flags = 0;
549 u8 new_mains;
550
551 if (down_interruptible(&cam->param_lock))
552 return -ERESTARTSYS;
553
554 /*
555 * Skip over leading whitespace
556 */
557 while (count && isspace(*buffer)) {
558 --count;
559 ++buffer;
560 }
561
562 memcpy(&new_params, &cam->params, sizeof(struct cam_params));
563 new_mains = cam->mainsFreq;
564
565 #define MATCH(x) \
566 ({ \
567 int _len = strlen(x), _ret, _colon_found; \
568 _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
569 if (_ret) { \
570 buffer += _len; \
571 count -= _len; \
572 if (find_colon) { \
573 _colon_found = 0; \
574 while (count && (*buffer == ' ' || *buffer == '\t' || \
575 (!_colon_found && *buffer == ':'))) { \
576 if (*buffer == ':') \
577 _colon_found = 1; \
578 --count; \
579 ++buffer; \
580 } \
581 if (!count || !_colon_found) \
582 retval = -EINVAL; \
583 find_colon = 0; \
584 } \
585 } \
586 _ret; \
587 })
588 #define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
589 new_params.version.firmwareRevision == (y))
590 #define VALUE \
591 ({ \
592 char *_p; \
593 unsigned long int _ret; \
594 _ret = simple_strtoul(buffer, &_p, 0); \
595 if (_p == buffer) \
596 retval = -EINVAL; \
597 else { \
598 count -= _p - buffer; \
599 buffer = _p; \
600 } \
601 _ret; \
602 })
603
604 retval = 0;
605 while (count && !retval) {
606 find_colon = 1;
607 if (MATCH("brightness")) {
608 if (!retval)
609 val = VALUE;
610
611 if (!retval) {
612 if (val <= 100)
613 new_params.colourParams.brightness = val;
614 else
615 retval = -EINVAL;
616 }
617 command_flags |= COMMAND_SETCOLOURPARAMS;
618 } else if (MATCH("contrast")) {
619 if (!retval)
620 val = VALUE;
621
622 if (!retval) {
623 if (val <= 100) {
624 /* contrast is in steps of 8, so round*/
625 val = ((val + 3) / 8) * 8;
626 /* 1-02 firmware limits contrast to 80*/
627 if (FIRMWARE_VERSION(1,2) && val > 80)
628 val = 80;
629
630 new_params.colourParams.contrast = val;
631 } else
632 retval = -EINVAL;
633 }
634 command_flags |= COMMAND_SETCOLOURPARAMS;
635 } else if (MATCH("saturation")) {
636 if (!retval)
637 val = VALUE;
638
639 if (!retval) {
640 if (val <= 100)
641 new_params.colourParams.saturation = val;
642 else
643 retval = -EINVAL;
644 }
645 command_flags |= COMMAND_SETCOLOURPARAMS;
646 } else if (MATCH("sensor_fps")) {
647 if (!retval)
648 val = VALUE;
649
650 if (!retval) {
651 /* find values so that sensorFPS is minimized,
652 * but >= val */
653 if (val > 30)
654 retval = -EINVAL;
655 else if (val > 25) {
656 new_params.sensorFps.divisor = 0;
657 new_params.sensorFps.baserate = 1;
658 } else if (val > 15) {
659 new_params.sensorFps.divisor = 0;
660 new_params.sensorFps.baserate = 0;
661 } else if (val > 12) {
662 new_params.sensorFps.divisor = 1;
663 new_params.sensorFps.baserate = 1;
664 } else if (val > 7) {
665 new_params.sensorFps.divisor = 1;
666 new_params.sensorFps.baserate = 0;
667 } else if (val > 6) {
668 new_params.sensorFps.divisor = 2;
669 new_params.sensorFps.baserate = 1;
670 } else if (val > 3) {
671 new_params.sensorFps.divisor = 2;
672 new_params.sensorFps.baserate = 0;
673 } else {
674 new_params.sensorFps.divisor = 3;
675 /* Either base rate would work here */
676 new_params.sensorFps.baserate = 1;
677 }
678 new_params.flickerControl.coarseJump =
679 flicker_jumps[new_mains]
680 [new_params.sensorFps.baserate]
681 [new_params.sensorFps.divisor];
682 if (new_params.flickerControl.flickerMode)
683 command_flags |= COMMAND_SETFLICKERCTRL;
684 }
685 command_flags |= COMMAND_SETSENSORFPS;
686 } else if (MATCH("stream_start_line")) {
687 if (!retval)
688 val = VALUE;
689
690 if (!retval) {
691 int max_line = 288;
692
693 if (new_params.format.videoSize == VIDEOSIZE_QCIF)
694 max_line = 144;
695 if (val <= max_line)
696 new_params.streamStartLine = val/2;
697 else
698 retval = -EINVAL;
699 }
700 } else if (MATCH("ecp_timing")) {
701 if (!retval && MATCH("normal"))
702 new_params.ecpTiming = 0;
703 else if (!retval && MATCH("slow"))
704 new_params.ecpTiming = 1;
705 else
706 retval = -EINVAL;
707
708 command_flags |= COMMAND_SETECPTIMING;
709 } else if (MATCH("color_balance_mode")) {
710 if (!retval && MATCH("manual"))
711 new_params.colourBalance.balanceModeIsAuto = 0;
712 else if (!retval && MATCH("auto"))
713 new_params.colourBalance.balanceModeIsAuto = 1;
714 else
715 retval = -EINVAL;
716
717 command_flags |= COMMAND_SETCOLOURBALANCE;
718 } else if (MATCH("red_gain")) {
719 if (!retval)
720 val = VALUE;
721
722 if (!retval) {
723 if (val <= 212)
724 new_params.colourBalance.redGain = val;
725 else
726 retval = -EINVAL;
727 }
728 command_flags |= COMMAND_SETCOLOURBALANCE;
729 } else if (MATCH("green_gain")) {
730 if (!retval)
731 val = VALUE;
732
733 if (!retval) {
734 if (val <= 212)
735 new_params.colourBalance.greenGain = val;
736 else
737 retval = -EINVAL;
738 }
739 command_flags |= COMMAND_SETCOLOURBALANCE;
740 } else if (MATCH("blue_gain")) {
741 if (!retval)
742 val = VALUE;
743
744 if (!retval) {
745 if (val <= 212)
746 new_params.colourBalance.blueGain = val;
747 else
748 retval = -EINVAL;
749 }
750 command_flags |= COMMAND_SETCOLOURBALANCE;
751 } else if (MATCH("max_gain")) {
752 if (!retval)
753 val = VALUE;
754
755 if (!retval) {
756 /* 1-02 firmware limits gain to 2 */
757 if (FIRMWARE_VERSION(1,2) && val > 2)
758 val = 2;
759 switch(val) {
760 case 1:
761 new_params.exposure.gainMode = 1;
762 break;
763 case 2:
764 new_params.exposure.gainMode = 2;
765 break;
766 case 4:
767 new_params.exposure.gainMode = 3;
768 break;
769 case 8:
770 new_params.exposure.gainMode = 4;
771 break;
772 default:
773 retval = -EINVAL;
774 break;
775 }
776 }
777 command_flags |= COMMAND_SETEXPOSURE;
778 } else if (MATCH("exposure_mode")) {
779 if (!retval && MATCH("auto"))
780 new_params.exposure.expMode = 2;
781 else if (!retval && MATCH("manual")) {
782 if (new_params.exposure.expMode == 2)
783 new_params.exposure.expMode = 3;
784 new_params.flickerControl.flickerMode = 0;
785 command_flags |= COMMAND_SETFLICKERCTRL;
786 } else
787 retval = -EINVAL;
788
789 command_flags |= COMMAND_SETEXPOSURE;
790 } else if (MATCH("centre_weight")) {
791 if (!retval && MATCH("on"))
792 new_params.exposure.centreWeight = 1;
793 else if (!retval && MATCH("off"))
794 new_params.exposure.centreWeight = 2;
795 else
796 retval = -EINVAL;
797
798 command_flags |= COMMAND_SETEXPOSURE;
799 } else if (MATCH("gain")) {
800 if (!retval)
801 val = VALUE;
802
803 if (!retval) {
804 switch(val) {
805 case 1:
806 new_params.exposure.gain = 0;
807 new_params.exposure.expMode = 1;
808 new_params.flickerControl.flickerMode = 0;
809 command_flags |= COMMAND_SETFLICKERCTRL;
810 break;
811 case 2:
812 new_params.exposure.gain = 1;
813 new_params.exposure.expMode = 1;
814 new_params.flickerControl.flickerMode = 0;
815 command_flags |= COMMAND_SETFLICKERCTRL;
816 break;
817 case 4:
818 new_params.exposure.gain = 2;
819 new_params.exposure.expMode = 1;
820 new_params.flickerControl.flickerMode = 0;
821 command_flags |= COMMAND_SETFLICKERCTRL;
822 break;
823 case 8:
824 new_params.exposure.gain = 3;
825 new_params.exposure.expMode = 1;
826 new_params.flickerControl.flickerMode = 0;
827 command_flags |= COMMAND_SETFLICKERCTRL;
828 break;
829 default:
830 retval = -EINVAL;
831 break;
832 }
833 command_flags |= COMMAND_SETEXPOSURE;
834 if (new_params.exposure.gain >
835 new_params.exposure.gainMode-1)
836 retval = -EINVAL;
837 }
838 } else if (MATCH("fine_exp")) {
839 if (!retval)
840 val = VALUE;
841
842 if (!retval) {
843 if (val < 256) {
844 /* 1-02 firmware limits fineExp to 127*/
845 if (FIRMWARE_VERSION(1,2) && val > 127)
846 val = 127;
847 new_params.exposure.fineExp = val;
848 new_params.exposure.expMode = 1;
849 command_flags |= COMMAND_SETEXPOSURE;
850 new_params.flickerControl.flickerMode = 0;
851 command_flags |= COMMAND_SETFLICKERCTRL;
852 } else
853 retval = -EINVAL;
854 }
855 } else if (MATCH("coarse_exp")) {
856 if (!retval)
857 val = VALUE;
858
859 if (!retval) {
860 if (val < 65536) {
861 /* 1-02 firmware limits
862 * coarseExp to 255 */
863 if (FIRMWARE_VERSION(1,2) && val > 255)
864 val = 255;
865 new_params.exposure.coarseExpLo =
866 val & 0xff;
867 new_params.exposure.coarseExpHi =
868 val >> 8;
869 new_params.exposure.expMode = 1;
870 command_flags |= COMMAND_SETEXPOSURE;
871 new_params.flickerControl.flickerMode = 0;
872 command_flags |= COMMAND_SETFLICKERCTRL;
873 } else
874 retval = -EINVAL;
875 }
876 } else if (MATCH("red_comp")) {
877 if (!retval)
878 val = VALUE;
879
880 if (!retval) {
881 if (val >= 220 && val <= 255) {
882 new_params.exposure.redComp = val;
883 command_flags |= COMMAND_SETEXPOSURE;
884 } else
885 retval = -EINVAL;
886 }
887 } else if (MATCH("green1_comp")) {
888 if (!retval)
889 val = VALUE;
890
891 if (!retval) {
892 if (val >= 214 && val <= 255) {
893 new_params.exposure.green1Comp = val;
894 command_flags |= COMMAND_SETEXPOSURE;
895 } else
896 retval = -EINVAL;
897 }
898 } else if (MATCH("green2_comp")) {
899 if (!retval)
900 val = VALUE;
901
902 if (!retval) {
903 if (val >= 214 && val <= 255) {
904 new_params.exposure.green2Comp = val;
905 command_flags |= COMMAND_SETEXPOSURE;
906 } else
907 retval = -EINVAL;
908 }
909 } else if (MATCH("blue_comp")) {
910 if (!retval)
911 val = VALUE;
912
913 if (!retval) {
914 if (val >= 230 && val <= 255) {
915 new_params.exposure.blueComp = val;
916 command_flags |= COMMAND_SETEXPOSURE;
917 } else
918 retval = -EINVAL;
919 }
920 } else if (MATCH("apcor_gain1")) {
921 if (!retval)
922 val = VALUE;
923
924 if (!retval) {
925 command_flags |= COMMAND_SETAPCOR;
926 if (val <= 0xff)
927 new_params.apcor.gain1 = val;
928 else
929 retval = -EINVAL;
930 }
931 } else if (MATCH("apcor_gain2")) {
932 if (!retval)
933 val = VALUE;
934
935 if (!retval) {
936 command_flags |= COMMAND_SETAPCOR;
937 if (val <= 0xff)
938 new_params.apcor.gain2 = val;
939 else
940 retval = -EINVAL;
941 }
942 } else if (MATCH("apcor_gain4")) {
943 if (!retval)
944 val = VALUE;
945
946 if (!retval) {
947 command_flags |= COMMAND_SETAPCOR;
948 if (val <= 0xff)
949 new_params.apcor.gain4 = val;
950 else
951 retval = -EINVAL;
952 }
953 } else if (MATCH("apcor_gain8")) {
954 if (!retval)
955 val = VALUE;
956
957 if (!retval) {
958 command_flags |= COMMAND_SETAPCOR;
959 if (val <= 0xff)
960 new_params.apcor.gain8 = val;
961 else
962 retval = -EINVAL;
963 }
964 } else if (MATCH("vl_offset_gain1")) {
965 if (!retval)
966 val = VALUE;
967
968 if (!retval) {
969 if (val <= 0xff)
970 new_params.vlOffset.gain1 = val;
971 else
972 retval = -EINVAL;
973 }
974 command_flags |= COMMAND_SETVLOFFSET;
975 } else if (MATCH("vl_offset_gain2")) {
976 if (!retval)
977 val = VALUE;
978
979 if (!retval) {
980 if (val <= 0xff)
981 new_params.vlOffset.gain2 = val;
982 else
983 retval = -EINVAL;
984 }
985 command_flags |= COMMAND_SETVLOFFSET;
986 } else if (MATCH("vl_offset_gain4")) {
987 if (!retval)
988 val = VALUE;
989
990 if (!retval) {
991 if (val <= 0xff)
992 new_params.vlOffset.gain4 = val;
993 else
994 retval = -EINVAL;
995 }
996 command_flags |= COMMAND_SETVLOFFSET;
997 } else if (MATCH("vl_offset_gain8")) {
998 if (!retval)
999 val = VALUE;
1000
1001 if (!retval) {
1002 if (val <= 0xff)
1003 new_params.vlOffset.gain8 = val;
1004 else
1005 retval = -EINVAL;
1006 }
1007 command_flags |= COMMAND_SETVLOFFSET;
1008 } else if (MATCH("flicker_control")) {
1009 if (!retval && MATCH("on")) {
1010 new_params.flickerControl.flickerMode = 1;
1011 new_params.exposure.expMode = 2;
1012 command_flags |= COMMAND_SETEXPOSURE;
1013 } else if (!retval && MATCH("off"))
1014 new_params.flickerControl.flickerMode = 0;
1015 else
1016 retval = -EINVAL;
1017
1018 command_flags |= COMMAND_SETFLICKERCTRL;
1019 } else if (MATCH("mains_frequency")) {
1020 if (!retval && MATCH("50")) {
1021 new_mains = 0;
1022 new_params.flickerControl.coarseJump =
1023 flicker_jumps[new_mains]
1024 [new_params.sensorFps.baserate]
1025 [new_params.sensorFps.divisor];
1026 if (new_params.flickerControl.flickerMode)
1027 command_flags |= COMMAND_SETFLICKERCTRL;
1028 } else if (!retval && MATCH("60")) {
1029 new_mains = 1;
1030 new_params.flickerControl.coarseJump =
1031 flicker_jumps[new_mains]
1032 [new_params.sensorFps.baserate]
1033 [new_params.sensorFps.divisor];
1034 if (new_params.flickerControl.flickerMode)
1035 command_flags |= COMMAND_SETFLICKERCTRL;
1036 } else
1037 retval = -EINVAL;
1038 } else if (MATCH("allowable_overexposure")) {
1039 if (!retval)
1040 val = VALUE;
1041
1042 if (!retval) {
1043 if (val <= 0xff) {
1044 new_params.flickerControl.
1045 allowableOverExposure = val;
1046 command_flags |= COMMAND_SETFLICKERCTRL;
1047 } else
1048 retval = -EINVAL;
1049 }
1050 } else if (MATCH("compression_mode")) {
1051 if (!retval && MATCH("none"))
1052 new_params.compression.mode =
1053 CPIA_COMPRESSION_NONE;
1054 else if (!retval && MATCH("auto"))
1055 new_params.compression.mode =
1056 CPIA_COMPRESSION_AUTO;
1057 else if (!retval && MATCH("manual"))
1058 new_params.compression.mode =
1059 CPIA_COMPRESSION_MANUAL;
1060 else
1061 retval = -EINVAL;
1062
1063 command_flags |= COMMAND_SETCOMPRESSION;
1064 } else if (MATCH("decimation_enable")) {
1065 if (!retval && MATCH("off"))
1066 new_params.compression.decimation = 0;
1067 else
1068 retval = -EINVAL;
1069
1070 command_flags |= COMMAND_SETCOMPRESSION;
1071 } else if (MATCH("compression_target")) {
1072 if (!retval && MATCH("quality"))
1073 new_params.compressionTarget.frTargeting =
1074 CPIA_COMPRESSION_TARGET_QUALITY;
1075 else if (!retval && MATCH("framerate"))
1076 new_params.compressionTarget.frTargeting =
1077 CPIA_COMPRESSION_TARGET_FRAMERATE;
1078 else
1079 retval = -EINVAL;
1080
1081 command_flags |= COMMAND_SETCOMPRESSIONTARGET;
1082 } else if (MATCH("target_framerate")) {
1083 if (!retval)
1084 val = VALUE;
1085
1086 if (!retval)
1087 new_params.compressionTarget.targetFR = val;
1088 command_flags |= COMMAND_SETCOMPRESSIONTARGET;
1089 } else if (MATCH("target_quality")) {
1090 if (!retval)
1091 val = VALUE;
1092
1093 if (!retval)
1094 new_params.compressionTarget.targetQ = val;
1095
1096 command_flags |= COMMAND_SETCOMPRESSIONTARGET;
1097 } else if (MATCH("y_threshold")) {
1098 if (!retval)
1099 val = VALUE;
1100
1101 if (!retval) {
1102 if (val < 32)
1103 new_params.yuvThreshold.yThreshold = val;
1104 else
1105 retval = -EINVAL;
1106 }
1107 command_flags |= COMMAND_SETYUVTHRESH;
1108 } else if (MATCH("uv_threshold")) {
1109 if (!retval)
1110 val = VALUE;
1111
1112 if (!retval) {
1113 if (val < 32)
1114 new_params.yuvThreshold.uvThreshold = val;
1115 else
1116 retval = -EINVAL;
1117 }
1118 command_flags |= COMMAND_SETYUVTHRESH;
1119 } else if (MATCH("hysteresis")) {
1120 if (!retval)
1121 val = VALUE;
1122
1123 if (!retval) {
1124 if (val <= 0xff)
1125 new_params.compressionParams.hysteresis = val;
1126 else
1127 retval = -EINVAL;
1128 }
1129 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1130 } else if (MATCH("threshold_max")) {
1131 if (!retval)
1132 val = VALUE;
1133
1134 if (!retval) {
1135 if (val <= 0xff)
1136 new_params.compressionParams.threshMax = val;
1137 else
1138 retval = -EINVAL;
1139 }
1140 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1141 } else if (MATCH("small_step")) {
1142 if (!retval)
1143 val = VALUE;
1144
1145 if (!retval) {
1146 if (val <= 0xff)
1147 new_params.compressionParams.smallStep = val;
1148 else
1149 retval = -EINVAL;
1150 }
1151 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1152 } else if (MATCH("large_step")) {
1153 if (!retval)
1154 val = VALUE;
1155
1156 if (!retval) {
1157 if (val <= 0xff)
1158 new_params.compressionParams.largeStep = val;
1159 else
1160 retval = -EINVAL;
1161 }
1162 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1163 } else if (MATCH("decimation_hysteresis")) {
1164 if (!retval)
1165 val = VALUE;
1166
1167 if (!retval) {
1168 if (val <= 0xff)
1169 new_params.compressionParams.decimationHysteresis = val;
1170 else
1171 retval = -EINVAL;
1172 }
1173 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1174 } else if (MATCH("fr_diff_step_thresh")) {
1175 if (!retval)
1176 val = VALUE;
1177
1178 if (!retval) {
1179 if (val <= 0xff)
1180 new_params.compressionParams.frDiffStepThresh = val;
1181 else
1182 retval = -EINVAL;
1183 }
1184 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1185 } else if (MATCH("q_diff_step_thresh")) {
1186 if (!retval)
1187 val = VALUE;
1188
1189 if (!retval) {
1190 if (val <= 0xff)
1191 new_params.compressionParams.qDiffStepThresh = val;
1192 else
1193 retval = -EINVAL;
1194 }
1195 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1196 } else if (MATCH("decimation_thresh_mod")) {
1197 if (!retval)
1198 val = VALUE;
1199
1200 if (!retval) {
1201 if (val <= 0xff)
1202 new_params.compressionParams.decimationThreshMod = val;
1203 else
1204 retval = -EINVAL;
1205 }
1206 command_flags |= COMMAND_SETCOMPRESSIONPARAMS;
1207 } else {
1208 DBG("No match found\n");
1209 retval = -EINVAL;
1210 }
1211
1212 if (!retval) {
1213 while (count && isspace(*buffer) && *buffer != '\n') {
1214 --count;
1215 ++buffer;
1216 }
1217 if (count) {
1218 if (*buffer != '\n' && *buffer != ';')
1219 retval = -EINVAL;
1220 else {
1221 --count;
1222 ++buffer;
1223 }
1224 }
1225 }
1226 }
1227 #undef MATCH
1228 #undef FIRMWARE_VERSION
1229 #undef VALUE
1230 #undef FIND_VALUE
1231 #undef FIND_END
1232 if (!retval) {
1233 if (command_flags & COMMAND_SETCOLOURPARAMS) {
1234 /* Adjust cam->vp to reflect these changes */
1235 cam->vp.brightness =
1236 new_params.colourParams.brightness*65535/100;
1237 cam->vp.contrast =
1238 new_params.colourParams.contrast*65535/100;
1239 cam->vp.colour =
1240 new_params.colourParams.saturation*65535/100;
1241 }
1242
1243 memcpy(&cam->params, &new_params, sizeof(struct cam_params));
1244 cam->mainsFreq = new_mains;
1245 cam->cmd_queue |= command_flags;
1246 retval = size;
1247 } else
1248 DBG("error: %d\n", retval);
1249
1250 up(&cam->param_lock);
1251
1252 return retval;
1253 }
1254
1255 static void create_proc_cpia_cam(struct cam_data *cam)
1256 {
1257 char name[7];
1258 struct proc_dir_entry *ent;
1259
1260 if (!cpia_proc_root || !cam)
1261 return;
1262
1263 sprintf(name, "video%d", cam->vdev.minor);
1264
1265 ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
1266 if (!ent)
1267 return;
1268
1269 ent->data = cam;
1270 ent->read_proc = cpia_read_proc;
1271 ent->write_proc = cpia_write_proc;
1272 ent->size = 3626;
1273 cam->proc_entry = ent;
1274 }
1275
1276 static void destroy_proc_cpia_cam(struct cam_data *cam)
1277 {
1278 char name[7];
1279
1280 if (!cam || !cam->proc_entry)
1281 return;
1282
1283 sprintf(name, "video%d", cam->vdev.minor);
1284 remove_proc_entry(name, cpia_proc_root);
1285 cam->proc_entry = NULL;
1286 }
1287
1288 static void proc_cpia_create(void)
1289 {
1290 cpia_proc_root = create_proc_entry("cpia", S_IFDIR, 0);
1291
1292 if (cpia_proc_root)
1293 cpia_proc_root->owner = THIS_MODULE;
1294 else
1295 LOG("Unable to initialise /proc/cpia\n");
1296 }
1297
1298 static void proc_cpia_destroy(void)
1299 {
1300 remove_proc_entry("cpia", 0);
1301 }
1302 #endif /* CONFIG_PROC_FS */
1303
1304 /* ----------------------- debug functions ---------------------- */
1305
1306 #define printstatus(cam) \
1307 DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\
1308 cam->params.status.systemState, cam->params.status.grabState, \
1309 cam->params.status.streamState, cam->params.status.fatalError, \
1310 cam->params.status.cmdError, cam->params.status.debugFlags, \
1311 cam->params.status.vpStatus, cam->params.status.errorCode);
1312
1313 /* ----------------------- v4l helpers -------------------------- */
1314
1315 /* supported frame palettes and depths */
1316 static inline int valid_mode(u16 palette, u16 depth)
1317 {
1318 return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
1319 (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
1320 (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
1321 (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
1322 (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
1323 (palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
1324 (palette == VIDEO_PALETTE_YUYV && depth == 16) ||
1325 (palette == VIDEO_PALETTE_UYVY && depth == 16);
1326 }
1327
1328 static int match_videosize( int width, int height )
1329 {
1330 /* return the best match, where 'best' is as always
1331 * the largest that is not bigger than what is requested. */
1332 if (width>=352 && height>=288)
1333 return VIDEOSIZE_352_288; /* CIF */
1334
1335 if (width>=320 && height>=240)
1336 return VIDEOSIZE_320_240; /* SIF */
1337
1338 if (width>=288 && height>=216)
1339 return VIDEOSIZE_288_216;
1340
1341 if (width>=256 && height>=192)
1342 return VIDEOSIZE_256_192;
1343
1344 if (width>=224 && height>=168)
1345 return VIDEOSIZE_224_168;
1346
1347 if (width>=192 && height>=144)
1348 return VIDEOSIZE_192_144;
1349
1350 if (width>=176 && height>=144)
1351 return VIDEOSIZE_176_144; /* QCIF */
1352
1353 if (width>=160 && height>=120)
1354 return VIDEOSIZE_160_120; /* QSIF */
1355
1356 if (width>=128 && height>=96)
1357 return VIDEOSIZE_128_96;
1358
1359 if (width>=88 && height>=72)
1360 return VIDEOSIZE_88_72;
1361
1362 if (width>=64 && height>=48)
1363 return VIDEOSIZE_64_48;
1364
1365 if (width>=48 && height>=48)
1366 return VIDEOSIZE_48_48;
1367
1368 return -1;
1369 }
1370
1371 /* these are the capture sizes we support */
1372 static void set_vw_size(struct cam_data *cam)
1373 {
1374 /* the col/row/start/end values are the result of simple math */
1375 /* study the SetROI-command in cpia developers guide p 2-22 */
1376 /* streamStartLine is set to the recommended value in the cpia */
1377 /* developers guide p 3-37 */
1378 switch(cam->video_size) {
1379 case VIDEOSIZE_CIF:
1380 cam->vw.width = 352;
1381 cam->vw.height = 288;
1382 cam->params.format.videoSize=VIDEOSIZE_CIF;
1383 cam->params.roi.colStart=0;
1384 cam->params.roi.colEnd=44;
1385 cam->params.roi.rowStart=0;
1386 cam->params.roi.rowEnd=72;
1387 cam->params.streamStartLine = 120;
1388 break;
1389 case VIDEOSIZE_SIF:
1390 cam->vw.width = 320;
1391 cam->vw.height = 240;
1392 cam->params.format.videoSize=VIDEOSIZE_CIF;
1393 cam->params.roi.colStart=2;
1394 cam->params.roi.colEnd=42;
1395 cam->params.roi.rowStart=6;
1396 cam->params.roi.rowEnd=66;
1397 cam->params.streamStartLine = 120;
1398 break;
1399 case VIDEOSIZE_288_216:
1400 cam->vw.width = 288;
1401 cam->vw.height = 216;
1402 cam->params.format.videoSize=VIDEOSIZE_CIF;
1403 cam->params.roi.colStart=4;
1404 cam->params.roi.colEnd=40;
1405 cam->params.roi.rowStart=9;
1406 cam->params.roi.rowEnd=63;
1407 cam->params.streamStartLine = 120;
1408 break;
1409 case VIDEOSIZE_256_192:
1410 cam->vw.width = 256;
1411 cam->vw.height = 192;
1412 cam->params.format.videoSize=VIDEOSIZE_CIF;
1413 cam->params.roi.colStart=6;
1414 cam->params.roi.colEnd=38;
1415 cam->params.roi.rowStart=12;
1416 cam->params.roi.rowEnd=60;
1417 cam->params.streamStartLine = 120;
1418 break;
1419 case VIDEOSIZE_224_168:
1420 cam->vw.width = 224;
1421 cam->vw.height = 168;
1422 cam->params.format.videoSize=VIDEOSIZE_CIF;
1423 cam->params.roi.colStart=8;
1424 cam->params.roi.colEnd=36;
1425 cam->params.roi.rowStart=15;
1426 cam->params.roi.rowEnd=57;
1427 cam->params.streamStartLine = 120;
1428 break;
1429 case VIDEOSIZE_192_144:
1430 cam->vw.width = 192;
1431 cam->vw.height = 144;
1432 cam->params.format.videoSize=VIDEOSIZE_CIF;
1433 cam->params.roi.colStart=10;
1434 cam->params.roi.colEnd=34;
1435 cam->params.roi.rowStart=18;
1436 cam->params.roi.rowEnd=54;
1437 cam->params.streamStartLine = 120;
1438 break;
1439 case VIDEOSIZE_QCIF:
1440 cam->vw.width = 176;
1441 cam->vw.height = 144;
1442 cam->params.format.videoSize=VIDEOSIZE_QCIF;
1443 cam->params.roi.colStart=0;
1444 cam->params.roi.colEnd=22;
1445 cam->params.roi.rowStart=0;
1446 cam->params.roi.rowEnd=36;
1447 cam->params.streamStartLine = 60;
1448 break;
1449 case VIDEOSIZE_QSIF:
1450 cam->vw.width = 160;
1451 cam->vw.height = 120;
1452 cam->params.format.videoSize=VIDEOSIZE_QCIF;
1453 cam->params.roi.colStart=1;
1454 cam->params.roi.colEnd=21;
1455 cam->params.roi.rowStart=3;
1456 cam->params.roi.rowEnd=33;
1457 cam->params.streamStartLine = 60;
1458 break;
1459 case VIDEOSIZE_128_96:
1460 cam->vw.width = 128;
1461 cam->vw.height = 96;
1462 cam->params.format.videoSize=VIDEOSIZE_QCIF;
1463 cam->params.roi.colStart=3;
1464 cam->params.roi.colEnd=19;
1465 cam->params.roi.rowStart=6;
1466 cam->params.roi.rowEnd=30;
1467 cam->params.streamStartLine = 60;
1468 break;
1469 case VIDEOSIZE_88_72:
1470 cam->vw.width = 88;
1471 cam->vw.height = 72;
1472 cam->params.format.videoSize=VIDEOSIZE_QCIF;
1473 cam->params.roi.colStart=5;
1474 cam->params.roi.colEnd=16;
1475 cam->params.roi.rowStart=9;
1476 cam->params.roi.rowEnd=27;
1477 cam->params.streamStartLine = 60;
1478 break;
1479 case VIDEOSIZE_64_48:
1480 cam->vw.width = 64;
1481 cam->vw.height = 48;
1482 cam->params.format.videoSize=VIDEOSIZE_QCIF;
1483 cam->params.roi.colStart=7;
1484 cam->params.roi.colEnd=15;
1485 cam->params.roi.rowStart=12;
1486 cam->params.roi.rowEnd=24;
1487 cam->params.streamStartLine = 60;
1488 break;
1489 case VIDEOSIZE_48_48:
1490 cam->vw.width = 48;
1491 cam->vw.height = 48;
1492 cam->params.format.videoSize=VIDEOSIZE_QCIF;
1493 cam->params.roi.colStart=8;
1494 cam->params.roi.colEnd=14;
1495 cam->params.roi.rowStart=6;
1496 cam->params.roi.rowEnd=30;
1497 cam->params.streamStartLine = 60;
1498 break;
1499 default:
1500 LOG("bad videosize value: %d\n", cam->video_size);
1501 }
1502
1503 return;
1504 }
1505
1506 static int allocate_frame_buf(struct cam_data *cam)
1507 {
1508 int i;
1509
1510 cam->frame_buf = rvmalloc(FRAME_NUM * CPIA_MAX_FRAME_SIZE);
1511 if (!cam->frame_buf)
1512 return -ENOBUFS;
1513
1514 for (i = 0; i < FRAME_NUM; i++)
1515 cam->frame[i].data = cam->frame_buf + i * CPIA_MAX_FRAME_SIZE;
1516
1517 return 0;
1518 }
1519
1520 static int free_frame_buf(struct cam_data *cam)
1521 {
1522 int i;
1523
1524 rvfree(cam->frame_buf, FRAME_NUM*CPIA_MAX_FRAME_SIZE);
1525 cam->frame_buf = 0;
1526 for (i=0; i < FRAME_NUM; i++)
1527 cam->frame[i].data = NULL;
1528
1529 return 0;
1530 }
1531
1532
1533 static void inline free_frames(struct cpia_frame frame[FRAME_NUM])
1534 {
1535 int i;
1536
1537 for (i=0; i < FRAME_NUM; i++)
1538 frame[i].state = FRAME_UNUSED;
1539 return;
1540 }
1541
1542 /**********************************************************************
1543 *
1544 * General functions
1545 *
1546 **********************************************************************/
1547 /* send an arbitrary command to the camera */
1548 static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
1549 {
1550 int retval, datasize;
1551 u8 cmd[8], data[8];
1552
1553 switch(command) {
1554 case CPIA_COMMAND_GetCPIAVersion:
1555 case CPIA_COMMAND_GetPnPID:
1556 case CPIA_COMMAND_GetCameraStatus:
1557 case CPIA_COMMAND_GetVPVersion:
1558 datasize=8;
1559 break;
1560 case CPIA_COMMAND_GetColourParams:
1561 case CPIA_COMMAND_GetColourBalance:
1562 case CPIA_COMMAND_GetExposure:
1563 down(&cam->param_lock);
1564 datasize=8;
1565 break;
1566 default:
1567 datasize=0;
1568 break;
1569 }
1570
1571 cmd[0] = command>>8;
1572 cmd[1] = command&0xff;
1573 cmd[2] = a;
1574 cmd[3] = b;
1575 cmd[4] = c;
1576 cmd[5] = d;
1577 cmd[6] = datasize;
1578 cmd[7] = 0;
1579
1580 retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
1581 if (retval) {
1582 DBG("%x - failed, retval=%d\n", command, retval);
1583 if (command == CPIA_COMMAND_GetColourParams ||
1584 command == CPIA_COMMAND_GetColourBalance ||
1585 command == CPIA_COMMAND_GetExposure)
1586 up(&cam->param_lock);
1587 } else {
1588 switch(command) {
1589 case CPIA_COMMAND_GetCPIAVersion:
1590 cam->params.version.firmwareVersion = data[0];
1591 cam->params.version.firmwareRevision = data[1];
1592 cam->params.version.vcVersion = data[2];
1593 cam->params.version.vcRevision = data[3];
1594 break;
1595 case CPIA_COMMAND_GetPnPID:
1596 cam->params.pnpID.vendor = data[0]+(((u16)data[1])<<8);
1597 cam->params.pnpID.product = data[2]+(((u16)data[3])<<8);
1598 cam->params.pnpID.deviceRevision =
1599 data[4]+(((u16)data[5])<<8);
1600 break;
1601 case CPIA_COMMAND_GetCameraStatus:
1602 cam->params.status.systemState = data[0];
1603 cam->params.status.grabState = data[1];
1604 cam->params.status.streamState = data[2];
1605 cam->params.status.fatalError = data[3];
1606 cam->params.status.cmdError = data[4];
1607 cam->params.status.debugFlags = data[5];
1608 cam->params.status.vpStatus = data[6];
1609 cam->params.status.errorCode = data[7];
1610 break;
1611 case CPIA_COMMAND_GetVPVersion:
1612 cam->params.vpVersion.vpVersion = data[0];
1613 cam->params.vpVersion.vpRevision = data[1];
1614 cam->params.vpVersion.cameraHeadID =
1615 data[2]+(((u16)data[3])<<8);
1616 break;
1617 case CPIA_COMMAND_GetColourParams:
1618 cam->params.colourParams.brightness = data[0];
1619 cam->params.colourParams.contrast = data[1];
1620 cam->params.colourParams.saturation = data[2];
1621 up(&cam->param_lock);
1622 break;
1623 case CPIA_COMMAND_GetColourBalance:
1624 cam->params.colourBalance.redGain = data[0];
1625 cam->params.colourBalance.greenGain = data[1];
1626 cam->params.colourBalance.blueGain = data[2];
1627 up(&cam->param_lock);
1628 break;
1629 case CPIA_COMMAND_GetExposure:
1630 cam->params.exposure.gain = data[0];
1631 cam->params.exposure.fineExp = data[1];
1632 cam->params.exposure.coarseExpLo = data[2];
1633 cam->params.exposure.coarseExpHi = data[3];
1634 cam->params.exposure.redComp = data[4];
1635 cam->params.exposure.green1Comp = data[5];
1636 cam->params.exposure.green2Comp = data[6];
1637 cam->params.exposure.blueComp = data[7];
1638 /* If the *Comp parameters are wacko, generate
1639 * a warning, and reset them back to default
1640 * values. - rich@annexia.org
1641 */
1642 if (cam->params.exposure.redComp < 220 ||
1643 cam->params.exposure.redComp > 255 ||
1644 cam->params.exposure.green1Comp < 214 ||
1645 cam->params.exposure.green1Comp > 255 ||
1646 cam->params.exposure.green2Comp < 214 ||
1647 cam->params.exposure.green2Comp > 255 ||
1648 cam->params.exposure.blueComp < 230 ||
1649 cam->params.exposure.blueComp > 255)
1650 {
1651 printk (KERN_WARNING "*_comp parameters have gone AWOL (%d/%d/%d/%d) - reseting them\n",
1652 cam->params.exposure.redComp,
1653 cam->params.exposure.green1Comp,
1654 cam->params.exposure.green2Comp,
1655 cam->params.exposure.blueComp);
1656 cam->params.exposure.redComp = 220;
1657 cam->params.exposure.green1Comp = 214;
1658 cam->params.exposure.green2Comp = 214;
1659 cam->params.exposure.blueComp = 230;
1660 }
1661 up(&cam->param_lock);
1662 break;
1663 default:
1664 break;
1665 }
1666 }
1667 return retval;
1668 }
1669
1670 /* send a command to the camera with an additional data transaction */
1671 static int do_command_extended(struct cam_data *cam, u16 command,
1672 u8 a, u8 b, u8 c, u8 d,
1673 u8 e, u8 f, u8 g, u8 h,
1674 u8 i, u8 j, u8 k, u8 l)
1675 {
1676 int retval;
1677 u8 cmd[8], data[8];
1678
1679 cmd[0] = command>>8;
1680 cmd[1] = command&0xff;
1681 cmd[2] = a;
1682 cmd[3] = b;
1683 cmd[4] = c;
1684 cmd[5] = d;
1685 cmd[6] = 8;
1686 cmd[7] = 0;
1687 data[0] = e;
1688 data[1] = f;
1689 data[2] = g;
1690 data[3] = h;
1691 data[4] = i;
1692 data[5] = j;
1693 data[6] = k;
1694 data[7] = l;
1695
1696 retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
1697 if (retval)
1698 LOG("%x - failed\n", command);
1699
1700 return retval;
1701 }
1702
1703 /**********************************************************************
1704 *
1705 * Colorspace conversion
1706 *
1707 **********************************************************************/
1708 #define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
1709
1710 static int yuvconvert(unsigned char *yuv, unsigned char *rgb, int out_fmt,
1711 int in_uyvy, int mmap_kludge)
1712 {
1713 int y, u, v, r, g, b, y1;
1714
1715 switch(out_fmt) {
1716 case VIDEO_PALETTE_RGB555:
1717 case VIDEO_PALETTE_RGB565:
1718 case VIDEO_PALETTE_RGB24:
1719 case VIDEO_PALETTE_RGB32:
1720 if (in_uyvy) {
1721 u = *yuv++ - 128;
1722 y = (*yuv++ - 16) * 76310;
1723 v = *yuv++ - 128;
1724 y1 = (*yuv - 16) * 76310;
1725 } else {
1726 y = (*yuv++ - 16) * 76310;
1727 u = *yuv++ - 128;
1728 y1 = (*yuv++ - 16) * 76310;
1729 v = *yuv - 128;
1730 }
1731 r = 104635 * v;
1732 g = -25690 * u + -53294 * v;
1733 b = 132278 * u;
1734 break;
1735 default:
1736 y = *yuv++;
1737 u = *yuv++;
1738 y1 = *yuv++;
1739 v = *yuv;
1740 /* Just to avoid compiler warnings */
1741 r = 0;
1742 g = 0;
1743 b = 0;
1744 break;
1745 }
1746 switch(out_fmt) {
1747 case VIDEO_PALETTE_RGB555:
1748 *rgb++ = ((LIMIT(g+y) & 0xf8) << 2) | (LIMIT(b+y) >> 3);
1749 *rgb++ = ((LIMIT(r+y) & 0xf8) >> 1) | (LIMIT(g+y) >> 6);
1750 *rgb++ = ((LIMIT(g+y1) & 0xf8) << 2) | (LIMIT(b+y1) >> 3);
1751 *rgb = ((LIMIT(r+y1) & 0xf8) >> 1) | (LIMIT(g+y1) >> 6);
1752 return 4;
1753 case VIDEO_PALETTE_RGB565:
1754 *rgb++ = ((LIMIT(g+y) & 0xfc) << 3) | (LIMIT(b+y) >> 3);
1755 *rgb++ = (LIMIT(r+y) & 0xf8) | (LIMIT(g+y) >> 5);
1756 *rgb++ = ((LIMIT(g+y1) & 0xfc) << 3) | (LIMIT(b+y1) >> 3);
1757 *rgb = (LIMIT(r+y1) & 0xf8) | (LIMIT(g+y1) >> 5);
1758 return 4;
1759 case VIDEO_PALETTE_RGB24:
1760 if (mmap_kludge) {
1761 *rgb++ = LIMIT(b+y);
1762 *rgb++ = LIMIT(g+y);
1763 *rgb++ = LIMIT(r+y);
1764 *rgb++ = LIMIT(b+y1);
1765 *rgb++ = LIMIT(g+y1);
1766 *rgb = LIMIT(r+y1);
1767 } else {
1768 *rgb++ = LIMIT(r+y);
1769 *rgb++ = LIMIT(g+y);
1770 *rgb++ = LIMIT(b+y);
1771 *rgb++ = LIMIT(r+y1);
1772 *rgb++ = LIMIT(g+y1);
1773 *rgb = LIMIT(b+y1);
1774 }
1775 return 6;
1776 case VIDEO_PALETTE_RGB32:
1777 if (mmap_kludge) {
1778 *rgb++ = LIMIT(b+y);
1779 *rgb++ = LIMIT(g+y);
1780 *rgb++ = LIMIT(r+y);
1781 rgb++;
1782 *rgb++ = LIMIT(b+y1);
1783 *rgb++ = LIMIT(g+y1);
1784 *rgb = LIMIT(r+y1);
1785 } else {
1786 *rgb++ = LIMIT(r+y);
1787 *rgb++ = LIMIT(g+y);
1788 *rgb++ = LIMIT(b+y);
1789 rgb++;
1790 *rgb++ = LIMIT(r+y1);
1791 *rgb++ = LIMIT(g+y1);
1792 *rgb = LIMIT(b+y1);
1793 }
1794 return 8;
1795 case VIDEO_PALETTE_GREY:
1796 *rgb++ = y;
1797 *rgb = y1;
1798 return 2;
1799 case VIDEO_PALETTE_YUV422:
1800 case VIDEO_PALETTE_YUYV:
1801 *rgb++ = y;
1802 *rgb++ = u;
1803 *rgb++ = y1;
1804 *rgb = v;
1805 return 4;
1806 case VIDEO_PALETTE_UYVY:
1807 *rgb++ = u;
1808 *rgb++ = y;
1809 *rgb++ = v;
1810 *rgb = y1;
1811 return 4;
1812 default:
1813 DBG("Empty: %d\n", out_fmt);
1814 return 0;
1815 }
1816 }
1817
1818 static int skipcount(int count, int fmt)
1819 {
1820 switch(fmt) {
1821 case VIDEO_PALETTE_GREY:
1822 case VIDEO_PALETTE_RGB555:
1823 case VIDEO_PALETTE_RGB565:
1824 case VIDEO_PALETTE_YUV422:
1825 case VIDEO_PALETTE_YUYV:
1826 case VIDEO_PALETTE_UYVY:
1827 return 2*count;
1828 case VIDEO_PALETTE_RGB24:
1829 return 3*count;
1830 case VIDEO_PALETTE_RGB32:
1831 return 4*count;
1832 default:
1833 return 0;
1834 }
1835 }
1836
1837 static int parse_picture(struct cam_data *cam, int size)
1838 {
1839 u8 *obuf, *ibuf, *end_obuf;
1840 int ll, in_uyvy, compressed, origsize, out_fmt;
1841
1842 /* make sure params don't change while we are decoding */
1843 down(&cam->param_lock);
1844
1845 obuf = cam->decompressed_frame.data;
1846 end_obuf = obuf+CPIA_MAX_FRAME_SIZE;
1847 ibuf = cam->raw_image;
1848 origsize = size;
1849 out_fmt = cam->vp.palette;
1850
1851 if ((ibuf[0] != MAGIC_0) || (ibuf[1] != MAGIC_1)) {
1852 LOG("header not found\n");
1853 up(&cam->param_lock);
1854 return -1;
1855 }
1856
1857 if ((ibuf[16] != VIDEOSIZE_QCIF) && (ibuf[16] != VIDEOSIZE_CIF)) {
1858 LOG("wrong video size\n");
1859 up(&cam->param_lock);
1860 return -1;
1861 }
1862
1863 if (ibuf[17] != SUBSAMPLE_422) {
1864 LOG("illegal subtype %d\n",ibuf[17]);
1865 up(&cam->param_lock);
1866 return -1;
1867 }
1868
1869 if (ibuf[18] != YUVORDER_YUYV && ibuf[18] != YUVORDER_UYVY) {
1870 LOG("illegal yuvorder %d\n",ibuf[18]);
1871 up(&cam->param_lock);
1872 return -1;
1873 }
1874 in_uyvy = ibuf[18] == YUVORDER_UYVY;
1875
1876 #if 0
1877 /* FIXME: ROI mismatch occurs when switching capture sizes */
1878 if ((ibuf[24] != cam->params.roi.colStart) ||
1879 (ibuf[25] != cam->params.roi.colEnd) ||
1880 (ibuf[26] != cam->params.roi.rowStart) ||
1881 (ibuf[27] != cam->params.roi.rowEnd)) {
1882 LOG("ROI mismatch\n");
1883 up(&cam->param_lock);
1884 return -1;
1885 }
1886 #endif
1887
1888 if ((ibuf[28] != NOT_COMPRESSED) && (ibuf[28] != COMPRESSED)) {
1889 LOG("illegal compression %d\n",ibuf[28]);
1890 up(&cam->param_lock);
1891 return -1;
1892 }
1893 compressed = (ibuf[28] == COMPRESSED);
1894
1895 if (ibuf[29] != NO_DECIMATION) {
1896 LOG("decimation not supported\n");
1897 up(&cam->param_lock);
1898 return -1;
1899 }
1900
1901 cam->params.yuvThreshold.yThreshold = ibuf[30];
1902 cam->params.yuvThreshold.uvThreshold = ibuf[31];
1903 cam->params.status.systemState = ibuf[32];
1904 cam->params.status.grabState = ibuf[33];
1905 cam->params.status.streamState = ibuf[34];
1906 cam->params.status.fatalError = ibuf[35];
1907 cam->params.status.cmdError = ibuf[36];
1908 cam->params.status.debugFlags = ibuf[37];
1909 cam->params.status.vpStatus = ibuf[38];
1910 cam->params.status.errorCode = ibuf[39];
1911 cam->fps = ibuf[41];
1912 up(&cam->param_lock);
1913
1914 ibuf += FRAME_HEADER_SIZE;
1915 size -= FRAME_HEADER_SIZE;
1916 ll = ibuf[0] | (ibuf[1] << 8);
1917 ibuf += 2;
1918
1919 while (size > 0) {
1920 size -= (ll+2);
1921 if (size < 0) {
1922 LOG("Insufficient data in buffer\n");
1923 return -1;
1924 }
1925
1926 while (ll > 1) {
1927 if (!compressed || (compressed && !(*ibuf & 1))) {
1928 obuf += yuvconvert(ibuf, obuf, out_fmt,
1929 in_uyvy, cam->mmap_kludge);
1930 ibuf += 4;
1931 ll -= 4;
1932 } else {
1933 /*skip compressed interval from previous frame*/
1934 int skipsize = skipcount(*ibuf >> 1, out_fmt);
1935 obuf += skipsize;
1936 if (obuf > end_obuf) {
1937 LOG("Insufficient data in buffer\n");
1938 return -1;
1939 }
1940 ++ibuf;
1941 ll--;
1942 }
1943 }
1944 if (ll == 1) {
1945 if (*ibuf != EOL) {
1946 LOG("EOL not found giving up after %d/%d"
1947 " bytes\n", origsize-size, origsize);
1948 return -1;
1949 }
1950
1951 ibuf++; /* skip over EOL */
1952
1953 if ((size > 3) && (ibuf[0] == EOI) && (ibuf[1] == EOI) &&
1954 (ibuf[2] == EOI) && (ibuf[3] == EOI)) {
1955 size -= 4;
1956 break;
1957 }
1958
1959 if (size > 1) {
1960 ll = ibuf[0] | (ibuf[1] << 8);
1961 ibuf += 2; /* skip over line length */
1962 }
1963 } else {
1964 LOG("line length was not 1 but %d after %d/%d bytes\n",
1965 ll, origsize-size, origsize);
1966 return -1;
1967 }
1968 }
1969
1970 cam->decompressed_frame.count = obuf-cam->decompressed_frame.data;
1971
1972 return cam->decompressed_frame.count;
1973 }
1974
1975 /* InitStreamCap wrapper to select correct start line */
1976 static inline int init_stream_cap(struct cam_data *cam)
1977 {
1978 return do_command(cam, CPIA_COMMAND_InitStreamCap,
1979 0, cam->params.streamStartLine, 0, 0);
1980 }
1981
1982 /* update various camera modes and settings */
1983 static void dispatch_commands(struct cam_data *cam)
1984 {
1985 down(&cam->param_lock);
1986 if (cam->cmd_queue==COMMAND_NONE) {
1987 up(&cam->param_lock);
1988 return;
1989 }
1990 DEB_BYTE(cam->cmd_queue);
1991 DEB_BYTE(cam->cmd_queue>>8);
1992 if (cam->cmd_queue & COMMAND_SETCOLOURPARAMS)
1993 do_command(cam, CPIA_COMMAND_SetColourParams,
1994 cam->params.colourParams.brightness,
1995 cam->params.colourParams.contrast,
1996 cam->params.colourParams.saturation, 0);
1997
1998 if (cam->cmd_queue & COMMAND_SETCOMPRESSION)
1999 do_command(cam, CPIA_COMMAND_SetCompression,
2000 cam->params.compression.mode,
2001 cam->params.compression.decimation, 0, 0);
2002
2003 if (cam->cmd_queue & COMMAND_SETFORMAT) {
2004 do_command(cam, CPIA_COMMAND_SetFormat,
2005 cam->params.format.videoSize,
2006 cam->params.format.subSample,
2007 cam->params.format.yuvOrder, 0);
2008 do_command(cam, CPIA_COMMAND_SetROI,
2009 cam->params.roi.colStart, cam->params.roi.colEnd,
2010 cam->params.roi.rowStart, cam->params.roi.rowEnd);
2011 cam->first_frame = 1;
2012 }
2013
2014 if (cam->cmd_queue & COMMAND_SETCOMPRESSIONTARGET)
2015 do_command(cam, CPIA_COMMAND_SetCompressionTarget,
2016 cam->params.compressionTarget.frTargeting,
2017 cam->params.compressionTarget.targetFR,
2018 cam->params.compressionTarget.targetQ, 0);
2019
2020 if (cam->cmd_queue & COMMAND_SETYUVTHRESH)
2021 do_command(cam, CPIA_COMMAND_SetYUVThresh,
2022 cam->params.yuvThreshold.yThreshold,
2023 cam->params.yuvThreshold.uvThreshold, 0, 0);
2024
2025 if (cam->cmd_queue & COMMAND_SETECPTIMING)
2026 do_command(cam, CPIA_COMMAND_SetECPTiming,
2027 cam->params.ecpTiming, 0, 0, 0);
2028
2029 if (cam->cmd_queue & COMMAND_SETCOMPRESSIONPARAMS)
2030 do_command_extended(cam, CPIA_COMMAND_SetCompressionParams,
2031 0, 0, 0, 0,
2032 cam->params.compressionParams.hysteresis,
2033 cam->params.compressionParams.threshMax,
2034 cam->params.compressionParams.smallStep,
2035 cam->params.compressionParams.largeStep,
2036 cam->params.compressionParams.decimationHysteresis,
2037 cam->params.compressionParams.frDiffStepThresh,
2038 cam->params.compressionParams.qDiffStepThresh,
2039 cam->params.compressionParams.decimationThreshMod);
2040
2041 if (cam->cmd_queue & COMMAND_SETEXPOSURE)
2042 do_command_extended(cam, CPIA_COMMAND_SetExposure,
2043 cam->params.exposure.gainMode,
2044 cam->params.exposure.expMode,
2045 cam->params.exposure.compMode,
2046 cam->params.exposure.centreWeight,
2047 cam->params.exposure.gain,
2048 cam->params.exposure.fineExp,
2049 cam->params.exposure.coarseExpLo,
2050 cam->params.exposure.coarseExpHi,
2051 cam->params.exposure.redComp,
2052 cam->params.exposure.green1Comp,
2053 cam->params.exposure.green2Comp,
2054 cam->params.exposure.blueComp);
2055
2056 if (cam->cmd_queue & COMMAND_SETCOLOURBALANCE) {
2057 if (cam->params.colourBalance.balanceModeIsAuto) {
2058 do_command(cam, CPIA_COMMAND_SetColourBalance,
2059 2, 0, 0, 0);
2060 } else {
2061 do_command(cam, CPIA_COMMAND_SetColourBalance,
2062 1,
2063 cam->params.colourBalance.redGain,
2064 cam->params.colourBalance.greenGain,
2065 cam->params.colourBalance.blueGain);
2066 do_command(cam, CPIA_COMMAND_SetColourBalance,
2067 3, 0, 0, 0);
2068 }
2069 }
2070
2071 if (cam->cmd_queue & COMMAND_SETSENSORFPS)
2072 do_command(cam, CPIA_COMMAND_SetSensorFPS,
2073 cam->params.sensorFps.divisor,
2074 cam->params.sensorFps.baserate, 0, 0);
2075
2076 if (cam->cmd_queue & COMMAND_SETAPCOR)
2077 do_command(cam, CPIA_COMMAND_SetApcor,
2078 cam->params.apcor.gain1,
2079 cam->params.apcor.gain2,
2080 cam->params.apcor.gain4,
2081 cam->params.apcor.gain8);
2082
2083 if (cam->cmd_queue & COMMAND_SETFLICKERCTRL)
2084 do_command(cam, CPIA_COMMAND_SetFlickerCtrl,
2085 cam->params.flickerControl.flickerMode,
2086 cam->params.flickerControl.coarseJump,
2087 cam->params.flickerControl.allowableOverExposure, 0);
2088
2089 if (cam->cmd_queue & COMMAND_SETVLOFFSET)
2090 do_command(cam, CPIA_COMMAND_SetVLOffset,
2091 cam->params.vlOffset.gain1,
2092 cam->params.vlOffset.gain2,
2093 cam->params.vlOffset.gain4,
2094 cam->params.vlOffset.gain8);
2095
2096 if (cam->cmd_queue & COMMAND_PAUSE)
2097 do_command(cam, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
2098
2099 if (cam->cmd_queue & COMMAND_RESUME)
2100 init_stream_cap(cam);
2101
2102 up(&cam->param_lock);
2103 cam->cmd_queue = COMMAND_NONE;
2104 return;
2105 }
2106
2107 /* kernel thread function to read image from camera */
2108 static void fetch_frame(void *data)
2109 {
2110 int image_size, retry;
2111 struct cam_data *cam = (struct cam_data *)data;
2112 unsigned long oldjif, rate, diff;
2113
2114 /* Allow up to two bad images in a row to be read and
2115 * ignored before an error is reported */
2116 for (retry = 0; retry < 3; ++retry) {
2117 if (retry)
2118 DBG("retry=%d\n", retry);
2119
2120 if (!cam->ops)
2121 continue;
2122
2123 /* load first frame always uncompressed */
2124 if (cam->first_frame &&
2125 cam->params.compression.mode != CPIA_COMPRESSION_NONE)
2126 do_command(cam, CPIA_COMMAND_SetCompression,
2127 CPIA_COMPRESSION_NONE,
2128 NO_DECIMATION, 0, 0);
2129
2130 /* init camera upload */
2131 if (do_command(cam, CPIA_COMMAND_SetGrabMode,
2132 CPIA_GRAB_CONTINUOUS, 0, 0, 0))
2133 continue;
2134
2135 if (do_command(cam, CPIA_COMMAND_GrabFrame, 0,
2136 cam->params.streamStartLine, 0, 0))
2137 continue;
2138
2139 if (cam->ops->wait_for_stream_ready) {
2140 /* loop until image ready */
2141 do_command(cam, CPIA_COMMAND_GetCameraStatus,0,0,0,0);
2142 while (cam->params.status.streamState != STREAM_READY) {
2143 if (current->need_resched)
2144 schedule();
2145
2146 current->state = TASK_INTERRUPTIBLE;
2147
2148 /* sleep for 10 ms, hopefully ;) */
2149 schedule_timeout(10*HZ/1000);
2150 if (signal_pending(current))
2151 return;
2152
2153 do_command(cam, CPIA_COMMAND_GetCameraStatus,
2154 0, 0, 0, 0);
2155 }
2156 }
2157
2158 /* grab image from camera */
2159 if (current->need_resched)
2160 schedule();
2161
2162 oldjif = jiffies;
2163 image_size = cam->ops->streamRead(cam->lowlevel_data,
2164 cam->raw_image, 0);
2165 if (image_size <= 0) {
2166 DBG("streamRead failed: %d\n", image_size);
2167 continue;
2168 }
2169
2170 rate = image_size * HZ / 1024;
2171 diff = jiffies-oldjif;
2172 cam->transfer_rate = diff==0 ? rate : rate/diff;
2173 /* diff==0 ? unlikely but possible */
2174
2175 /* camera idle now so dispatch queued commands */
2176 dispatch_commands(cam);
2177
2178 /* Update our knowledge of the camera state - FIXME: necessary? */
2179 do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
2180 do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
2181
2182 /* decompress and convert image to by copying it from
2183 * raw_image to decompressed_frame
2184 */
2185 if (current->need_resched)
2186 schedule();
2187
2188 cam->image_size = parse_picture(cam, image_size);
2189 if (cam->image_size <= 0)
2190 DBG("parse_picture failed %d\n", cam->image_size);
2191 else
2192 break;
2193 }
2194
2195 if (retry < 3) {
2196 /* FIXME: this only works for double buffering */
2197 if (cam->frame[cam->curframe].state == FRAME_READY) {
2198 memcpy(cam->frame[cam->curframe].data,
2199 cam->decompressed_frame.data,
2200 cam->decompressed_frame.count);
2201 cam->frame[cam->curframe].state = FRAME_DONE;
2202 } else
2203 cam->decompressed_frame.state = FRAME_DONE;
2204
2205 #if 0
2206 if (cam->first_frame &&
2207 cam->params.compression.mode != CPIA_COMPRESSION_NONE) {
2208 cam->first_frame = 0;
2209 cam->cmd_queue |= COMMAND_SETCOMPRESSION;
2210 }
2211 #else
2212 if (cam->first_frame) {
2213 cam->first_frame = 0;
2214 cam->cmd_queue |= COMMAND_SETCOMPRESSION;
2215 cam->cmd_queue |= COMMAND_SETEXPOSURE;
2216 }
2217 #endif
2218 }
2219 }
2220
2221 static int capture_frame(struct cam_data *cam, struct video_mmap *vm)
2222 {
2223 int retval = 0;
2224
2225 if (!cam->frame_buf) {
2226 /* we do lazy allocation */
2227 if ((retval = allocate_frame_buf(cam)))
2228 return retval;
2229 }
2230
2231 /* FIXME: the first frame seems to be captured by the camera
2232 without regards to any initial settings, so we throw away
2233 that one, the next one is generated with our settings
2234 (exposure, color balance, ...)
2235 */
2236 if (cam->first_frame) {
2237 cam->curframe = vm->frame;
2238 cam->frame[cam->curframe].state = FRAME_READY;
2239 fetch_frame(cam);
2240 if (cam->frame[cam->curframe].state != FRAME_DONE)
2241 retval = -EIO;
2242 }
2243 cam->curframe = vm->frame;
2244 cam->frame[cam->curframe].state = FRAME_READY;
2245 fetch_frame(cam);
2246 if (cam->frame[cam->curframe].state != FRAME_DONE)
2247 retval=-EIO;
2248
2249 return retval;
2250 }
2251
2252 static int goto_high_power(struct cam_data *cam)
2253 {
2254 if (do_command(cam, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0))
2255 return -1;
2256 mdelay(100); /* windows driver does it too */
2257 if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
2258 return -1;
2259 if (cam->params.status.systemState == HI_POWER_STATE) {
2260 DBG("camera now in HIGH power state\n");
2261 return 0;
2262 }
2263 printstatus(cam);
2264 return -1;
2265 }
2266
2267 static int goto_low_power(struct cam_data *cam)
2268 {
2269 if (do_command(cam, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0))
2270 return -1;
2271 if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
2272 return -1;
2273 if (cam->params.status.systemState == LO_POWER_STATE) {
2274 DBG("camera now in LOW power state\n");
2275 return 0;
2276 }
2277 printstatus(cam);
2278 return -1;
2279 }
2280
2281 static void save_camera_state(struct cam_data *cam)
2282 {
2283 do_command(cam, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
2284 do_command(cam, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
2285
2286 DBG("%d/%d/%d/%d/%d/%d/%d/%d\n",
2287 cam->params.exposure.gain,
2288 cam->params.exposure.fineExp,
2289 cam->params.exposure.coarseExpLo,
2290 cam->params.exposure.coarseExpHi,
2291 cam->params.exposure.redComp,
2292 cam->params.exposure.green1Comp,
2293 cam->params.exposure.green2Comp,
2294 cam->params.exposure.blueComp);
2295 DBG("%d/%d/%d\n",
2296 cam->params.colourBalance.redGain,
2297 cam->params.colourBalance.greenGain,
2298 cam->params.colourBalance.blueGain);
2299 }
2300
2301 static void set_camera_state(struct cam_data *cam)
2302 {
2303 if(cam->params.colourBalance.balanceModeIsAuto) {
2304 do_command(cam, CPIA_COMMAND_SetColourBalance,
2305 2, 0, 0, 0);
2306 } else {
2307 do_command(cam, CPIA_COMMAND_SetColourBalance,
2308 1,
2309 cam->params.colourBalance.redGain,
2310 cam->params.colourBalance.greenGain,
2311 cam->params.colourBalance.blueGain);
2312 do_command(cam, CPIA_COMMAND_SetColourBalance,
2313 3, 0, 0, 0);
2314 }
2315
2316
2317 do_command_extended(cam, CPIA_COMMAND_SetExposure,
2318 cam->params.exposure.gainMode, 1, 1,
2319 cam->params.exposure.centreWeight,
2320 cam->params.exposure.gain,
2321 cam->params.exposure.fineExp,
2322 cam->params.exposure.coarseExpLo,
2323 cam->params.exposure.coarseExpHi,
2324 cam->params.exposure.redComp,
2325 cam->params.exposure.green1Comp,
2326 cam->params.exposure.green2Comp,
2327 cam->params.exposure.blueComp);
2328 do_command_extended(cam, CPIA_COMMAND_SetExposure,
2329 0, 3, 0, 0,
2330 0, 0, 0, 0, 0, 0, 0, 0);
2331
2332 if (!cam->params.exposure.gainMode)
2333 cam->params.exposure.gainMode = 2;
2334 if (!cam->params.exposure.expMode)
2335 cam->params.exposure.expMode = 2;
2336 if (!cam->params.exposure.centreWeight)
2337 cam->params.exposure.centreWeight = 1;
2338
2339 cam->cmd_queue = COMMAND_SETCOMPRESSION |
2340 COMMAND_SETCOMPRESSIONTARGET |
2341 COMMAND_SETCOLOURPARAMS |
2342 COMMAND_SETFORMAT |
2343 COMMAND_SETYUVTHRESH |
2344 COMMAND_SETECPTIMING |
2345 COMMAND_SETCOMPRESSIONPARAMS |
2346 #if 0
2347 COMMAND_SETEXPOSURE |
2348 #endif
2349 COMMAND_SETCOLOURBALANCE |
2350 COMMAND_SETSENSORFPS |
2351 COMMAND_SETAPCOR |
2352 COMMAND_SETFLICKERCTRL |
2353 COMMAND_SETVLOFFSET;
2354 dispatch_commands(cam);
2355 save_camera_state(cam);
2356
2357 return;
2358 }
2359
2360 static void get_version_information(struct cam_data *cam)
2361 {
2362 /* GetCPIAVersion */
2363 do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
2364
2365 /* GetPnPID */
2366 do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
2367 }
2368
2369 /* initialize camera */
2370 static int reset_camera(struct cam_data *cam)
2371 {
2372 /* Start the camera in low power mode */
2373 if (goto_low_power(cam)) {
2374 if (cam->params.status.systemState != WARM_BOOT_STATE)
2375 return -ENODEV;
2376
2377 /* FIXME: this is just dirty trial and error */
2378 reset_camera_struct(cam);
2379 goto_high_power(cam);
2380 do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
2381 if (goto_low_power(cam))
2382 return -NODEV;
2383 }
2384
2385 /* procedure described in developer's guide p3-28 */
2386
2387 /* Check the firmware version FIXME: should we check PNPID? */
2388 cam->params.version.firmwareVersion = 0;
2389 get_version_information(cam);
2390 if (cam->params.version.firmwareVersion != 1)
2391 return -ENODEV;
2392
2393 /* The fatal error checking should be done after
2394 * the camera powers up (developer's guide p 3-38) */
2395
2396 /* Set streamState before transition to high power to avoid bug
2397 * in firmware 1-02 */
2398 do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
2399 STREAM_NOT_READY, 0);
2400
2401 /* GotoHiPower */
2402 if (goto_high_power(cam))
2403 return -ENODEV;
2404
2405 /* Check the camera status */
2406 if (do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0))
2407 return -EIO;
2408
2409 if (cam->params.status.fatalError) {
2410 DBG("fatal_error: %#04x\n",
2411 cam->params.status.fatalError);
2412 DBG("vp_status: %#04x\n",
2413 cam->params.status.vpStatus);
2414 if (cam->params.status.fatalError & ~(COM_FLAG|CPIA_FLAG)) {
2415 /* Fatal error in camera */
2416 return -EIO;
2417 } else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) {
2418 /* Firmware 1-02 may do this for parallel port cameras,
2419 * just clear the flags (developer's guide p 3-38) */
2420 do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
2421 FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
2422 }
2423 }
2424
2425 /* Check the camera status again */
2426 if (cam->params.status.fatalError) {
2427 if (cam->params.status.fatalError)
2428 return -EIO;
2429 }
2430
2431 /* VPVersion can't be retrieved before the camera is in HiPower,
2432 * so get it here instead of in get_version_information. */
2433 do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
2434
2435 /* set camera to a known state */
2436 set_camera_state(cam);
2437
2438 return 0;
2439 }
2440
2441 /* ------------------------- V4L interface --------------------- */
2442 static int cpia_open(struct video_device *dev, int flags)
2443 {
2444 int i;
2445 struct cam_data *cam = dev->priv;
2446
2447 if (!cam) {
2448 DBG("Internal error, cam_data not found!\n");
2449 return -EBUSY;
2450 }
2451
2452 if (cam->open_count > 0) {
2453 DBG("Camera already open\n");
2454 return -EBUSY;
2455 }
2456
2457 if (!cam->raw_image) {
2458 cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE);
2459 if (!cam->raw_image)
2460 return -ENOMEM;
2461 }
2462
2463 if (!cam->decompressed_frame.data) {
2464 cam->decompressed_frame.data = rvmalloc(CPIA_MAX_FRAME_SIZE);
2465 if (!cam->decompressed_frame.data) {
2466 rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
2467 cam->raw_image = NULL;
2468 return -ENOMEM;
2469 }
2470 }
2471
2472 /* open cpia */
2473 if (cam->ops->open(cam->lowlevel_data)) {
2474 rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
2475 cam->decompressed_frame.data = NULL;
2476 rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
2477 cam->raw_image = NULL;
2478 return -ENODEV;
2479 }
2480
2481 /* reset the camera */
2482 if ((i = reset_camera(cam)) != 0) {
2483 cam->ops->close(cam->lowlevel_data);
2484 rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
2485 cam->decompressed_frame.data = NULL;
2486 rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
2487 cam->raw_image = NULL;
2488 return i;
2489 }
2490
2491 /* Set ownership of /proc/cpia/videoX to current user */
2492 if(cam->proc_entry)
2493 cam->proc_entry->uid = current->uid;
2494
2495 /* set mark for loading first frame uncompressed */
2496 cam->first_frame = 1;
2497
2498 /* init it to something */
2499 cam->mmap_kludge = 0;
2500
2501 ++cam->open_count;
2502 #ifdef MODULE
2503 MOD_INC_USE_COUNT;
2504 #endif
2505 return 0;
2506 }
2507
2508 static void cpia_close(struct video_device *dev)
2509 {
2510 struct cam_data *cam;
2511
2512 cam = dev->priv;
2513
2514 if (cam->ops) {
2515 /* Return ownership of /proc/cpia/videoX to root */
2516 if(cam->proc_entry)
2517 cam->proc_entry->uid = 0;
2518
2519 /* save camera state for later open (developers guide ch 3.5.3) */
2520 save_camera_state(cam);
2521
2522 /* GotoLoPower */
2523 goto_low_power(cam);
2524
2525 /* Update the camera ststus */
2526 do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
2527
2528 /* cleanup internal state stuff */
2529 free_frames(cam->frame);
2530
2531 /* close cpia */
2532 cam->ops->close(cam->lowlevel_data);
2533 }
2534
2535 if (--cam->open_count == 0) {
2536 /* clean up capture-buffers */
2537 if (cam->raw_image) {
2538 rvfree(cam->raw_image, CPIA_MAX_IMAGE_SIZE);
2539 cam->raw_image = NULL;
2540 }
2541
2542 if (cam->decompressed_frame.data) {
2543 rvfree(cam->decompressed_frame.data, CPIA_MAX_FRAME_SIZE);
2544 cam->decompressed_frame.data = NULL;
2545 }
2546
2547 if (cam->frame_buf)
2548 free_frame_buf(cam);
2549
2550 if (!cam->ops) {
2551 video_unregister_device(dev);
2552 kfree(cam);
2553 }
2554 }
2555
2556
2557 #ifdef MODULE
2558 MOD_DEC_USE_COUNT;
2559 #endif
2560 return;
2561 }
2562
2563 static long cpia_read(struct video_device *dev, char *buf,
2564 unsigned long count, int noblock)
2565 {
2566 struct cam_data *cam = dev->priv;
2567
2568 /* make this _really_ smp and multithredi-safe */
2569 if (down_interruptible(&cam->busy_lock))
2570 return -EINTR;
2571
2572 if (!buf) {
2573 DBG("buf NULL\n");
2574 up(&cam->busy_lock);
2575 return -EINVAL;
2576 }
2577
2578 if (!count) {
2579 DBG("count 0\n");
2580 up(&cam->busy_lock);
2581 return 0;
2582 }
2583
2584 if (!cam->ops) {
2585 DBG("ops NULL\n");
2586 up(&cam->busy_lock);
2587 return -ENODEV;
2588 }
2589
2590 /* upload frame */
2591 cam->decompressed_frame.state = FRAME_READY;
2592 cam->mmap_kludge=0;
2593 fetch_frame(cam);
2594 if (cam->decompressed_frame.state != FRAME_DONE) {
2595 DBG("upload failed %d/%d\n", cam->decompressed_frame.count,
2596 cam->decompressed_frame.state);
2597 up(&cam->busy_lock);
2598 return -EIO;
2599 }
2600 cam->decompressed_frame.state = FRAME_UNUSED;
2601
2602 /* copy data to user space */
2603 if (cam->decompressed_frame.count > count) {
2604 DBG("count wrong: %d, %lu\n", cam->decompressed_frame.count,
2605 count);
2606 up(&cam->busy_lock);
2607 return -EFAULT;
2608 }
2609 if (copy_to_user(buf, cam->decompressed_frame.data,
2610 cam->decompressed_frame.count)) {
2611 DBG("copy_to_user failed\n");
2612 up(&cam->busy_lock);
2613 return -EFAULT;
2614 }
2615
2616 up(&cam->busy_lock);
2617 return cam->decompressed_frame.count;
2618 }
2619
2620 static int cpia_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg)
2621 {
2622 struct cam_data *cam = dev->priv;
2623 int retval = 0;
2624
2625 if (!cam || !cam->ops)
2626 return -ENODEV;
2627
2628 /* make this _really_ smp-safe */
2629 if (down_interruptible(&cam->busy_lock))
2630 return -EINTR;
2631
2632 //DBG("cpia_ioctl: %u\n", ioctlnr);
2633
2634 switch (ioctlnr) {
2635 /* query capabilites */
2636 case VIDIOCGCAP:
2637 {
2638 struct video_capability b;
2639
2640 DBG("VIDIOCGCAP\n");
2641 strcpy(b.name, "CPiA Camera");
2642 b.type = VID_TYPE_CAPTURE;
2643 b.channels = 1;
2644 b.audios = 0;
2645 b.maxwidth = 352; /* VIDEOSIZE_CIF */
2646 b.maxheight = 288;
2647 b.minwidth = 48; /* VIDEOSIZE_48_48 */
2648 b.minheight = 48;
2649
2650 if (copy_to_user(arg, &b, sizeof(b)))
2651 retval = -EFAULT;
2652
2653 break;
2654 }
2655
2656 /* get/set video source - we are a camera and nothing else */
2657 case VIDIOCGCHAN:
2658 {
2659 struct video_channel v;
2660
2661 DBG("VIDIOCGCHAN\n");
2662 if (copy_from_user(&v, arg, sizeof(v))) {
2663 retval = -EFAULT;
2664 break;
2665 }
2666 if (v.channel != 0) {
2667 retval = -EINVAL;
2668 break;
2669 }
2670
2671 v.channel = 0;
2672 strcpy(v.name, "Camera");
2673 v.tuners = 0;
2674 v.flags = 0;
2675 v.type = VIDEO_TYPE_CAMERA;
2676 v.norm = 0;
2677
2678 if (copy_to_user(arg, &v, sizeof(v)))
2679 retval = -EFAULT;
2680 break;
2681 }
2682
2683 case VIDIOCSCHAN:
2684 {
2685 int v;
2686
2687 DBG("VIDIOCSCHAN\n");
2688 if (copy_from_user(&v, arg, sizeof(v)))
2689 retval = -EFAULT;
2690
2691 if (retval == 0 && v != 0)
2692 retval = -EINVAL;
2693
2694 break;
2695 }
2696
2697 /* image properties */
2698 case VIDIOCGPICT:
2699 DBG("VIDIOCGPICT\n");
2700 if (copy_to_user(arg, &cam->vp, sizeof(struct video_picture)))
2701 retval = -EFAULT;
2702 break;
2703
2704 case VIDIOCSPICT:
2705 {
2706 struct video_picture vp;
2707
2708 DBG("VIDIOCSPICT\n");
2709
2710 /* copy_from_user */
2711 if (copy_from_user(&vp, arg, sizeof(vp))) {
2712 retval = -EFAULT;
2713 break;
2714 }
2715
2716 /* check validity */
2717 DBG("palette: %d\n", vp.palette);
2718 DBG("depth: %d\n", vp.depth);
2719 if (!valid_mode(vp.palette, vp.depth)) {
2720 retval = -EINVAL;
2721 break;
2722 }
2723
2724 down(&cam->param_lock);
2725 /* brightness, colour, contrast need no check 0-65535 */
2726 memcpy( &cam->vp, &vp, sizeof(vp) );
2727 /* update cam->params.colourParams */
2728 cam->params.colourParams.brightness = vp.brightness*100/65535;
2729 cam->params.colourParams.contrast = vp.contrast*100/65535;
2730 cam->params.colourParams.saturation = vp.colour*100/65535;
2731 /* contrast is in steps of 8, so round */
2732 cam->params.colourParams.contrast =
2733 ((cam->params.colourParams.contrast + 3) / 8) * 8;
2734 if (cam->params.version.firmwareVersion == 1 &&
2735 cam->params.version.firmwareRevision == 2 &&
2736 cam->params.colourParams.contrast > 80) {
2737 /* 1-02 firmware limits contrast to 80 */
2738 cam->params.colourParams.contrast = 80;
2739 }
2740
2741 /* queue command to update camera */
2742 cam->cmd_queue |= COMMAND_SETCOLOURPARAMS;
2743 up(&cam->param_lock);
2744 DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n",
2745 vp.depth, vp.palette, vp.brightness, vp.hue, vp.colour,
2746 vp.contrast);
2747 break;
2748 }
2749
2750 /* get/set capture window */
2751 case VIDIOCGWIN:
2752 DBG("VIDIOCGWIN\n");
2753
2754 if (copy_to_user(arg, &cam->vw, sizeof(struct video_window)))
2755 retval = -EFAULT;
2756 break;
2757
2758 case VIDIOCSWIN:
2759 {
2760 /* copy_from_user, check validity, copy to internal structure */
2761 struct video_window vw;
2762 DBG("VIDIOCSWIN\n");
2763 if (copy_from_user(&vw, arg, sizeof(vw))) {
2764 retval = -EFAULT;
2765 break;
2766 }
2767
2768 if (vw.clipcount != 0) { /* clipping not supported */
2769 retval = -EINVAL;
2770 break;
2771 }
2772 if (vw.clips != NULL) { /* clipping not supported */
2773 retval = -EINVAL;
2774 break;
2775 }
2776
2777 /* we set the video window to something smaller or equal to what
2778 * is requested by the user???
2779 */
2780 down(&cam->param_lock);
2781 if (vw.width != cam->vw.width || vw.height != cam->vw.height) {
2782 int video_size = match_videosize(vw.width, vw.height);
2783
2784 if (video_size < 0) {
2785 retval = -EINVAL;
2786 up(&cam->param_lock);
2787 break;
2788 }
2789 cam->video_size = video_size;
2790 set_vw_size(cam);
2791 DBG("%d / %d\n", cam->vw.width, cam->vw.height);
2792 cam->cmd_queue |= COMMAND_SETFORMAT;
2793 }
2794
2795 // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw));
2796 up(&cam->param_lock);
2797
2798 /* setformat ignored by camera during streaming,
2799 * so stop/dispatch/start */
2800 if (cam->cmd_queue & COMMAND_SETFORMAT) {
2801 DBG("\n");
2802 dispatch_commands(cam);
2803 }
2804 DBG("%d/%d:%d\n", cam->video_size,
2805 cam->vw.width, cam->vw.height);
2806 break;
2807 }
2808
2809 /* mmap interface */
2810 case VIDIOCGMBUF:
2811 {
2812 struct video_mbuf vm;
2813 int i;
2814
2815 DBG("VIDIOCGMBUF\n");
2816 memset(&vm, 0, sizeof(vm));
2817 vm.size = CPIA_MAX_FRAME_SIZE*FRAME_NUM;
2818 vm.frames = FRAME_NUM;
2819 for (i = 0; i < FRAME_NUM; i++)
2820 vm.offsets[i] = CPIA_MAX_FRAME_SIZE * i;
2821
2822 if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
2823 retval = -EFAULT;
2824
2825 break;
2826 }
2827
2828 case VIDIOCMCAPTURE:
2829 {
2830 struct video_mmap vm;
2831 int video_size;
2832
2833 if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) {
2834 retval = -EFAULT;
2835 break;
2836 }
2837 #if 1
2838 DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm.format, vm.frame,
2839 vm.width, vm.height);
2840 #endif
2841 if (vm.frame<0||vm.frame>FRAME_NUM) {
2842 retval = -EINVAL;
2843 break;
2844 }
2845
2846 /* set video format */
2847 cam->vp.palette = vm.format;
2848 switch(vm.format) {
2849 case VIDEO_PALETTE_GREY:
2850 case VIDEO_PALETTE_RGB555:
2851 case VIDEO_PALETTE_RGB565:
2852 case VIDEO_PALETTE_YUV422:
2853 case VIDEO_PALETTE_YUYV:
2854 case VIDEO_PALETTE_UYVY:
2855 cam->vp.depth = 16;
2856 break;
2857 case VIDEO_PALETTE_RGB24:
2858 cam->vp.depth = 24;
2859 break;
2860 case VIDEO_PALETTE_RGB32:
2861 cam->vp.depth = 32;
2862 break;
2863 default:
2864 retval = -EINVAL;
2865 break;
2866 }
2867 if (retval)
2868 break;
2869
2870 /* set video size */
2871 video_size = match_videosize(vm.width, vm.height);
2872 if (cam->video_size < 0) {
2873 retval = -EINVAL;
2874 break;
2875 }
2876 if (video_size != cam->video_size) {
2877 cam->video_size = video_size;
2878 set_vw_size(cam);
2879 cam->cmd_queue |= COMMAND_SETFORMAT;
2880 dispatch_commands(cam);
2881 }
2882 #if 0
2883 DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam->video_size,
2884 cam->vw.width, cam->vw.height);
2885 #endif
2886 /* according to v4l-spec we must start streaming here */
2887 cam->mmap_kludge = 1;
2888 retval = capture_frame(cam, &vm);
2889
2890 break;
2891 }
2892
2893 case VIDIOCSYNC:
2894 {
2895 int frame;
2896
2897 if (copy_from_user((void *)&frame, arg, sizeof(int))) {
2898 retval = -EFAULT;
2899 break;
2900 }
2901 //DBG("VIDIOCSYNC: %d\n", frame);
2902
2903 if (frame<0 || frame >= FRAME_NUM) {
2904 retval = -EINVAL;
2905 break;
2906 }
2907
2908 switch (cam->frame[frame].state) {
2909 case FRAME_UNUSED:
2910 case FRAME_READY:
2911 case FRAME_GRABBING:
2912 DBG("sync to unused frame %d\n", frame);
2913 retval = -EINVAL;
2914 break;
2915
2916 case FRAME_DONE:
2917 cam->frame[frame].state = FRAME_UNUSED;
2918 //DBG("VIDIOCSYNC: %d synced\n", frame);
2919 break;
2920 }
2921 if (retval == -EINTR) {
2922 /* FIXME - xawtv does not handle this nice */
2923 retval = 0;
2924 }
2925 break;
2926 }
2927
2928 /* pointless to implement overlay with this camera */
2929 case VIDIOCCAPTURE:
2930 retval = -EINVAL;
2931 break;
2932 case VIDIOCGFBUF:
2933 retval = -EINVAL;
2934 break;
2935 case VIDIOCSFBUF:
2936 retval = -EINVAL;
2937 break;
2938 case VIDIOCKEY:
2939 retval = -EINVAL;
2940 break;
2941
2942 /* tuner interface - we have none */
2943 case VIDIOCGTUNER:
2944 retval = -EINVAL;
2945 break;
2946 case VIDIOCSTUNER:
2947 retval = -EINVAL;
2948 break;
2949 case VIDIOCGFREQ:
2950 retval = -EINVAL;
2951 break;
2952 case VIDIOCSFREQ:
2953 retval = -EINVAL;
2954 break;
2955
2956 /* audio interface - we have none */
2957 case VIDIOCGAUDIO:
2958 retval = -EINVAL;
2959 break;
2960 case VIDIOCSAUDIO:
2961 retval = -EINVAL;
2962 break;
2963 default:
2964 retval = -ENOIOCTLCMD;
2965 break;
2966 }
2967
2968 up(&cam->param_lock);
2969 up(&cam->busy_lock);
2970 return retval;
2971 }
2972
2973 /* FIXME */
2974 static int cpia_mmap(struct video_device *dev, const char *adr,
2975 unsigned long size)
2976 {
2977 unsigned long start = (unsigned long)adr;
2978 unsigned long page, pos;
2979 struct cam_data *cam = dev->priv;
2980 int retval;
2981
2982 if (!cam || !cam->ops)
2983 return -ENODEV;
2984
2985 DBG("cpia_mmap: %ld\n", size);
2986
2987 if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE)
2988 return -EINVAL;
2989
2990 if (!cam || !cam->ops)
2991 return -ENODEV;
2992
2993 /* make this _really_ smp-safe */
2994 if (down_interruptible(&cam->busy_lock))
2995 return -EINTR;
2996
2997 if (!cam->frame_buf) { /* we do lazy allocation */
2998 if ((retval = allocate_frame_buf(cam))) {
2999 up(&cam->busy_lock);
3000 return retval;
3001 }
3002 }
3003
3004 pos = (unsigned long)(cam->frame_buf);
3005 while (size > 0) {
3006 page = kvirt_to_pa(pos);
3007 if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
3008 up(&cam->busy_lock);
3009 return -EAGAIN;
3010 }
3011 start += PAGE_SIZE;
3012 pos += PAGE_SIZE;
3013 if (size > PAGE_SIZE)
3014 size -= PAGE_SIZE;
3015 else
3016 size = 0;
3017 }
3018
3019 DBG("cpia_mmap: %ld\n", size);
3020 up(&cam->busy_lock);
3021
3022 return 0;
3023 }
3024
3025 int cpia_video_init(struct video_device *vdev)
3026 {
3027 #ifdef CONFIG_PROC_FS
3028 create_proc_cpia_cam(vdev->priv);
3029 #endif
3030 return 0;
3031 }
3032
3033 static struct video_device cpia_template = {
3034 name: "CPiA Camera",
3035 type: VID_TYPE_CAPTURE,
3036 hardware: VID_HARDWARE_CPIA, /* FIXME */
3037 open: cpia_open,
3038 close: cpia_close,
3039 read: cpia_read,
3040 ioctl: cpia_ioctl,
3041 mmap: cpia_mmap,
3042 initialize: cpia_video_init,
3043 minor: -1,
3044 };
3045
3046 /* initialise cam_data structure */
3047 static void reset_camera_struct(struct cam_data *cam)
3048 {
3049 /* The following parameter values are the defaults from
3050 * "Software Developer's Guide for CPiA Cameras". Any changes
3051 * to the defaults are noted in comments. */
3052 cam->params.colourParams.brightness = 50;
3053 cam->params.colourParams.contrast = 48;
3054 cam->params.colourParams.saturation = 50;
3055 cam->params.exposure.gainMode = 2;
3056 cam->params.exposure.expMode = 2; /* AEC */
3057 cam->params.exposure.compMode = 1;
3058 cam->params.exposure.centreWeight = 1;
3059 cam->params.exposure.gain = 0;
3060 cam->params.exposure.fineExp = 0;
3061 cam->params.exposure.coarseExpLo = 185;
3062 cam->params.exposure.coarseExpHi = 0;
3063 cam->params.exposure.redComp = 220;
3064 cam->params.exposure.green1Comp = 214;
3065 cam->params.exposure.green2Comp = 214;
3066 cam->params.exposure.blueComp = 230;
3067 cam->params.colourBalance.balanceModeIsAuto = 1;
3068 cam->params.colourBalance.redGain = 32;
3069 cam->params.colourBalance.greenGain = 6;
3070 cam->params.colourBalance.blueGain = 92;
3071 cam->params.apcor.gain1 = 0x1c;
3072 cam->params.apcor.gain2 = 0x1a;
3073 cam->params.apcor.gain4 = 0x2d;
3074 cam->params.apcor.gain8 = 0x2a;
3075 cam->params.flickerControl.flickerMode = 0;
3076 cam->params.flickerControl.coarseJump =
3077 flicker_jumps[cam->mainsFreq]
3078 [cam->params.sensorFps.baserate]
3079 [cam->params.sensorFps.divisor];
3080 cam->params.vlOffset.gain1 = 24;
3081 cam->params.vlOffset.gain2 = 28;
3082 cam->params.vlOffset.gain4 = 30;
3083 cam->params.vlOffset.gain8 = 30;
3084 cam->params.compressionParams.hysteresis = 3;
3085 cam->params.compressionParams.threshMax = 11;
3086 cam->params.compressionParams.smallStep = 1;
3087 cam->params.compressionParams.largeStep = 3;
3088 cam->params.compressionParams.decimationHysteresis = 2;
3089 cam->params.compressionParams.frDiffStepThresh = 5;
3090 cam->params.compressionParams.qDiffStepThresh = 3;
3091 cam->params.compressionParams.decimationThreshMod = 2;
3092 /* End of default values from Software Developer's Guide */
3093
3094 cam->transfer_rate = 0;
3095
3096 /* Set Sensor FPS to 15fps. This seems better than 30fps
3097 * for indoor lighting. */
3098 cam->params.sensorFps.divisor = 1;
3099 cam->params.sensorFps.baserate = 1;
3100
3101 cam->params.yuvThreshold.yThreshold = 15; /* FIXME? */
3102 cam->params.yuvThreshold.uvThreshold = 15; /* FIXME? */
3103
3104 cam->params.format.subSample = SUBSAMPLE_422;
3105 cam->params.format.yuvOrder = YUVORDER_YUYV;
3106
3107 cam->params.compression.mode = CPIA_COMPRESSION_AUTO;
3108 cam->params.compressionTarget.frTargeting =
3109 CPIA_COMPRESSION_TARGET_QUALITY;
3110 cam->params.compressionTarget.targetFR = 7; /* FIXME? */
3111 cam->params.compressionTarget.targetQ = 10; /* FIXME? */
3112
3113 cam->video_size = VIDEOSIZE_CIF;
3114
3115 cam->vp.colour = 32768; /* 50% */
3116 cam->vp.hue = 32768; /* 50% */
3117 cam->vp.brightness = 32768; /* 50% */
3118 cam->vp.contrast = 32768; /* 50% */
3119 cam->vp.whiteness = 0; /* not used -> grayscale only */
3120 cam->vp.depth = 0; /* FIXME: to be set by user? */
3121 cam->vp.palette = VIDEO_PALETTE_RGB24; /* FIXME: to be set by user? */
3122
3123 cam->vw.x = 0;
3124 cam->vw.y = 0;
3125 set_vw_size(cam);
3126 cam->vw.chromakey = 0;
3127 /* PP NOTE: my extension to use vw.flags for this, bear it! */
3128 cam->vw.flags = 0;
3129 cam->vw.clipcount = 0;
3130 cam->vw.clips = NULL;
3131
3132 cam->cmd_queue = COMMAND_NONE;
3133 cam->first_frame = 0;
3134
3135 return;
3136 }
3137
3138 /* initialize cam_data structure */
3139 static void init_camera_struct(struct cam_data *cam,
3140 struct cpia_camera_ops *ops )
3141 {
3142 int i;
3143
3144 /* Default everything to 0 */
3145 memset(cam, 0, sizeof(struct cam_data));
3146
3147 cam->ops = ops;
3148 init_MUTEX(&cam->param_lock);
3149 init_MUTEX(&cam->busy_lock);
3150
3151 reset_camera_struct(cam);
3152
3153 cam->proc_entry = NULL;
3154
3155 memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
3156 cam->vdev.priv = cam;
3157
3158 cam->curframe = 0;
3159 for (i = 0; i < FRAME_NUM; i++) {
3160 cam->frame[i].width = 0;
3161 cam->frame[i].height = 0;
3162 cam->frame[i].state = FRAME_UNUSED;
3163 cam->frame[i].data = NULL;
3164 }
3165 cam->decompressed_frame.width = 0;
3166 cam->decompressed_frame.height = 0;
3167 cam->decompressed_frame.state = FRAME_UNUSED;
3168 cam->decompressed_frame.data = NULL;
3169 }
3170
3171 struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowlevel)
3172 {
3173 struct cam_data *camera;
3174
3175 /* Need a lock when adding/removing cameras. This doesn't happen
3176 * often and doesn't take very long, so grabbing the kernel lock
3177 * should be OK. */
3178
3179 if ((camera = kmalloc(sizeof(struct cam_data), GFP_KERNEL)) == NULL) {
3180 unlock_kernel();
3181 return NULL;
3182 }
3183
3184 init_camera_struct( camera, ops );
3185 camera->lowlevel_data = lowlevel;
3186
3187 /* register v4l device */
3188 if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER) == -1) {
3189 kfree(camera);
3190 unlock_kernel();
3191 printk(KERN_DEBUG "video_register_device failed\n");
3192 return NULL;
3193 }
3194
3195 /* get version information from camera: open/reset/close */
3196
3197 /* open cpia */
3198 if (camera->ops->open(camera->lowlevel_data))
3199 return camera;
3200
3201 /* reset the camera */
3202 if (reset_camera(camera) != 0) {
3203 camera->ops->close(camera->lowlevel_data);
3204 return camera;
3205 }
3206
3207 /* close cpia */
3208 camera->ops->close(camera->lowlevel_data);
3209
3210 /* Eh? Feeling happy? - jerdfelt */
3211 /*
3212 camera->ops->open(camera->lowlevel_data);
3213 camera->ops->close(camera->lowlevel_data);
3214 */
3215
3216 printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n",
3217 camera->params.version.firmwareVersion,
3218 camera->params.version.firmwareRevision,
3219 camera->params.version.vcVersion,
3220 camera->params.version.vcRevision);
3221 printk(KERN_INFO " CPiA PnP-ID: %04x:%04x:%04x\n",
3222 camera->params.pnpID.vendor,
3223 camera->params.pnpID.product,
3224 camera->params.pnpID.deviceRevision);
3225 printk(KERN_INFO " VP-Version: %d.%d %04x\n",
3226 camera->params.vpVersion.vpVersion,
3227 camera->params.vpVersion.vpRevision,
3228 camera->params.vpVersion.cameraHeadID);
3229
3230 return camera;
3231 }
3232
3233 void cpia_unregister_camera(struct cam_data *cam)
3234 {
3235 if (!cam->open_count) {
3236 DBG("unregistering video\n");
3237 video_unregister_device(&cam->vdev);
3238 } else {
3239 LOG("/dev/video%d removed while open, "
3240 "deferring video_unregister_device\n", cam->vdev.minor);
3241 DBG("camera open -- setting ops to NULL\n");
3242 cam->ops = NULL;
3243 }
3244
3245 #ifdef CONFIG_PROC_FS
3246 DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor);
3247 destroy_proc_cpia_cam(cam);
3248 #endif
3249 if (!cam->open_count) {
3250 DBG("freeing camera\n");
3251 kfree(cam);
3252 }
3253 }
3254
3255 /****************************************************************************
3256 *
3257 * Module routines
3258 *
3259 ***************************************************************************/
3260
3261 #ifdef MODULE
3262 int init_module(void)
3263 {
3264 printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
3265 CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
3266 #ifdef CONFIG_PROC_FS
3267 proc_cpia_create();
3268 #endif
3269 #ifdef CONFIG_KMOD
3270 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
3271 request_module("cpia_pp");
3272 #endif
3273 #ifdef CONFIG_VIDEO_CPIA_USB_MODULE
3274 request_module("cpia_usb");
3275 #endif
3276 #endif
3277 return 0;
3278 }
3279
3280 void cleanup_module(void)
3281 {
3282 #ifdef CONFIG_PROC_FS
3283 proc_cpia_destroy();
3284 #endif
3285 }
3286
3287 #else
3288
3289 int cpia_init(struct video_init *unused)
3290 {
3291 printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
3292 CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
3293 #ifdef CONFIG_PROC_FS
3294 proc_cpia_create();
3295 #endif
3296
3297 #ifdef CONFIG_VIDEO_CPIA_PP
3298 cpia_pp_init();
3299 #endif
3300 #ifdef CONFIG_KMOD
3301 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
3302 request_module("cpia_pp");
3303 #endif
3304
3305 #ifdef CONFIG_VIDEO_CPIA_USB_MODULE
3306 request_module("cpia_usb");
3307 #endif
3308 #endif /* CONFIG_KMOD */
3309 #ifdef CONFIG_VIDEO_CPIA_USB
3310 cpia_usb_init();
3311 #endif
3312 return 0;
3313 }
3314
3315 /* Exported symbols for modules. */
3316
3317 EXPORT_SYMBOL(cpia_register_camera);
3318 EXPORT_SYMBOL(cpia_unregister_camera);
3319
3320 #endif
3321
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.