4 * Supports CPiA based Video Camera's.
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
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.
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.
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.
25 /* #define _CPIA_DEBUG_ define for verbose debug output */
26 #include <linux/config.h>
28 #include <linux/module.h>
29 #include <linux/version.h>
30 #include <linux/init.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>
39 #include <asm/semaphore.h>
40 #include <linux/wrapper.h>
43 #include <linux/kmod.h>
48 #ifdef CONFIG_VIDEO_CPIA_PP
49 extern int cpia_pp_init(void);
51 #ifdef CONFIG_VIDEO_CPIA_USB
52 extern int cpia_usb_init(void);
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");
61 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
63 #ifndef VID_HARDWARE_CPIA
64 #define VID_HARDWARE_CPIA 24 /* FIXME -> from linux/videodev.h */
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)
73 #define INPUT (DATA_IN << 8)
74 #define OUTPUT (DATA_OUT << 8)
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)
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)
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)
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)
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)
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) */
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
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} }
170 /* forward declaration of local function */
171 static void reset_camera_struct(struct cam_data
*cam
);
173 /**********************************************************************
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?)
183 * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
184 * there will be one, but apparentely not yet - jerdfelt
186 **********************************************************************/
188 /* Given PGD from the address space's page table, return the kernel
189 * virtual mapping of the physical memory mapped at ADR.
191 static inline unsigned long uvirt_to_kva(pgd_t
*pgd
, unsigned long adr
)
193 unsigned long ret
= 0UL;
197 if (!pgd_none(*pgd
)) {
198 pmd
= pmd_offset(pgd
, adr
);
199 if (!pmd_none(*pmd
)) {
200 ptep
= pte_offset(pmd
, adr
);
202 if (pte_present(pte
)) {
203 ret
= (unsigned long) page_address(pte_page(pte
));
204 ret
|= (adr
& (PAGE_SIZE
-1));
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.
215 static inline unsigned long kvirt_to_pa(unsigned long adr
)
217 unsigned long va
, kva
, ret
;
219 va
= VMALLOC_VMADDR(adr
);
220 kva
= uvirt_to_kva(pgd_offset_k(va
), va
);
225 static void *rvmalloc(unsigned long size
)
228 unsigned long adr
, page
;
230 /* Round it off to PAGE_SIZE */
231 size
+= (PAGE_SIZE
- 1);
232 size
&= ~(PAGE_SIZE
- 1);
234 mem
= vmalloc_32(size
);
238 memset(mem
, 0, size
); /* Clear the ram out, no junk to the user */
239 adr
= (unsigned long) mem
;
241 page
= kvirt_to_pa(adr
);
242 mem_map_reserve(virt_to_page(__va(page
)));
244 if (size
> PAGE_SIZE
)
253 static void rvfree(void *mem
, unsigned long size
)
255 unsigned long adr
, page
;
260 size
+= (PAGE_SIZE
- 1);
261 size
&= ~(PAGE_SIZE
- 1);
263 adr
= (unsigned long) mem
;
265 page
= kvirt_to_pa(adr
);
266 mem_map_unreserve(virt_to_page(__va(page
)));
268 if (size
> PAGE_SIZE
)
276 /**********************************************************************
280 **********************************************************************/
281 #ifdef CONFIG_PROC_FS
282 static struct proc_dir_entry
*cpia_proc_root
=NULL
;
284 static int cpia_read_proc(char *page
, char **start
, off_t off
,
285 int count
, int *eof
, void *data
)
289 struct cam_data
*cam
= data
;
292 /* IMPORTANT: This output MUST be kept under PAGE_SIZE
293 * or we need to get more sophisticated. */
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
);
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
?
330 out
+= sprintf(out
, "sub_sample: %s\n",
331 cam
->params
.format
.subSample
== SUBSAMPLE_420
?
333 out
+= sprintf(out
, "yuv_order: %s\n",
334 cam
->params
.format
.yuvOrder
== YUVORDER_YUYV
?
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",
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 */
357 out
+= sprintf(out
, "contrast: %8d %8d %8d %8d"
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",
374 if (cam
->params
.colourBalance
.balanceModeIsAuto
) {
375 sprintf(tmpstr
, "auto");
377 sprintf(tmpstr
, "manual");
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);
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);
393 sprintf(tmpstr
, "1,2,4,8");
395 if (cam
->params
.exposure
.gainMode
== 0)
396 out
+= sprintf(out
, "max_gain: unknown %18s"
397 " %8d\n", tmpstr
, 2);
399 out
+= sprintf(out
, "max_gain: %8d %18s %8d\n",
400 1<<(cam
->params
.exposure
.gainMode
-1), tmpstr
, 2);
402 switch(cam
->params
.exposure
.expMode
) {
405 sprintf(tmpstr
, "manual");
408 sprintf(tmpstr
, "auto");
411 sprintf(tmpstr
, "unknown");
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",
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 */
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 */
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);
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",
468 out
+= sprintf(out
, "mains_frequency: %8d %8d %8d %8d"
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,
474 out
+= sprintf(out
, "compression_mode: ");
475 switch(cam
->params
.compression
.mode
) {
476 case CPIA_COMPRESSION_NONE
:
477 out
+= sprintf(out
, "%8s", "none");
479 case CPIA_COMPRESSION_AUTO
:
480 out
+= sprintf(out
, "%8s", "auto");
482 case CPIA_COMPRESSION_MANUAL
:
483 out
+= sprintf(out
, "%8s", "manual");
486 out
+= sprintf(out
, "%8s", "unknown");
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",
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
,
518 out
+= sprintf(out
, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
519 cam
->params
.compressionParams
.frDiffStepThresh
,
521 out
+= sprintf(out
, "q_diff_step_thresh: %8d %8d %8d %8d\n",
522 cam
->params
.compressionParams
.qDiffStepThresh
,
524 out
+= sprintf(out
, "decimation_thresh_mod: %8d %8d %8d %8d\n",
525 cam
->params
.compressionParams
.decimationThreshMod
,
532 if (len
<= 0) return 0;
540 static int cpia_write_proc(struct file
*file
, const char *buffer
,
541 unsigned long count
, void *data
)
543 struct cam_data
*cam
= data
;
544 struct cam_params new_params
;
545 int retval
, find_colon
;
548 u32 command_flags
= 0;
551 if (down_interruptible(&cam
->param_lock
))
555 * Skip over leading whitespace
557 while (count
&& isspace(*buffer
)) {
562 memcpy(&new_params
, &cam
->params
, sizeof(struct cam_params
));
563 new_mains
= cam
->mainsFreq
;
567 int _len = strlen(x), _ret, _colon_found; \
568 _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
574 while (count && (*buffer == ' ' || *buffer == '\t' || \
575 (!_colon_found && *buffer == ':'))) { \
576 if (*buffer == ':') \
581 if (!count || !_colon_found) \
588 #define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
589 new_params.version.firmwareRevision == (y))
593 unsigned long int _ret; \
594 _ret = simple_strtoul(buffer, &_p, 0); \
598 count -= _p - buffer; \
605 while (count
&& !retval
) {
607 if (MATCH("brightness")) {
613 new_params
.colourParams
.brightness
= val
;
617 command_flags
|= COMMAND_SETCOLOURPARAMS
;
618 } else if (MATCH("contrast")) {
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)
630 new_params
.colourParams
.contrast
= val
;
634 command_flags
|= COMMAND_SETCOLOURPARAMS
;
635 } else if (MATCH("saturation")) {
641 new_params
.colourParams
.saturation
= val
;
645 command_flags
|= COMMAND_SETCOLOURPARAMS
;
646 } else if (MATCH("sensor_fps")) {
651 /* find values so that sensorFPS is minimized,
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;
674 new_params
.sensorFps
.divisor
= 3;
675 /* Either base rate would work here */
676 new_params
.sensorFps
.baserate
= 1;
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
;
685 command_flags
|= COMMAND_SETSENSORFPS
;
686 } else if (MATCH("stream_start_line")) {
693 if (new_params
.format
.videoSize
== VIDEOSIZE_QCIF
)
696 new_params
.streamStartLine
= val
/2;
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;
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;
717 command_flags
|= COMMAND_SETCOLOURBALANCE
;
718 } else if (MATCH("red_gain")) {
724 new_params
.colourBalance
.redGain
= val
;
728 command_flags
|= COMMAND_SETCOLOURBALANCE
;
729 } else if (MATCH("green_gain")) {
735 new_params
.colourBalance
.greenGain
= val
;
739 command_flags
|= COMMAND_SETCOLOURBALANCE
;
740 } else if (MATCH("blue_gain")) {
746 new_params
.colourBalance
.blueGain
= val
;
750 command_flags
|= COMMAND_SETCOLOURBALANCE
;
751 } else if (MATCH("max_gain")) {
756 /* 1-02 firmware limits gain to 2 */
757 if (FIRMWARE_VERSION(1,2) && val
> 2)
761 new_params
.exposure
.gainMode
= 1;
764 new_params
.exposure
.gainMode
= 2;
767 new_params
.exposure
.gainMode
= 3;
770 new_params
.exposure
.gainMode
= 4;
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
;
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;
798 command_flags
|= COMMAND_SETEXPOSURE
;
799 } else if (MATCH("gain")) {
806 new_params
.exposure
.gain
= 0;
807 new_params
.exposure
.expMode
= 1;
808 new_params
.flickerControl
.flickerMode
= 0;
809 command_flags
|= COMMAND_SETFLICKERCTRL
;
812 new_params
.exposure
.gain
= 1;
813 new_params
.exposure
.expMode
= 1;
814 new_params
.flickerControl
.flickerMode
= 0;
815 command_flags
|= COMMAND_SETFLICKERCTRL
;
818 new_params
.exposure
.gain
= 2;
819 new_params
.exposure
.expMode
= 1;
820 new_params
.flickerControl
.flickerMode
= 0;
821 command_flags
|= COMMAND_SETFLICKERCTRL
;
824 new_params
.exposure
.gain
= 3;
825 new_params
.exposure
.expMode
= 1;
826 new_params
.flickerControl
.flickerMode
= 0;
827 command_flags
|= COMMAND_SETFLICKERCTRL
;
833 command_flags
|= COMMAND_SETEXPOSURE
;
834 if (new_params
.exposure
.gain
>
835 new_params
.exposure
.gainMode
-1)
838 } else if (MATCH("fine_exp")) {
844 /* 1-02 firmware limits fineExp to 127*/
845 if (FIRMWARE_VERSION(1,2) && 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
;
855 } else if (MATCH("coarse_exp")) {
861 /* 1-02 firmware limits
862 * coarseExp to 255 */
863 if (FIRMWARE_VERSION(1,2) && val
> 255)
865 new_params
.exposure
.coarseExpLo
=
867 new_params
.exposure
.coarseExpHi
=
869 new_params
.exposure
.expMode
= 1;
870 command_flags
|= COMMAND_SETEXPOSURE
;
871 new_params
.flickerControl
.flickerMode
= 0;
872 command_flags
|= COMMAND_SETFLICKERCTRL
;
876 } else if (MATCH("red_comp")) {
881 if (val
>= 220 && val
<= 255) {
882 new_params
.exposure
.redComp
= val
;
883 command_flags
|= COMMAND_SETEXPOSURE
;
887 } else if (MATCH("green1_comp")) {
892 if (val
>= 214 && val
<= 255) {
893 new_params
.exposure
.green1Comp
= val
;
894 command_flags
|= COMMAND_SETEXPOSURE
;
898 } else if (MATCH("green2_comp")) {
903 if (val
>= 214 && val
<= 255) {
904 new_params
.exposure
.green2Comp
= val
;
905 command_flags
|= COMMAND_SETEXPOSURE
;
909 } else if (MATCH("blue_comp")) {
914 if (val
>= 230 && val
<= 255) {
915 new_params
.exposure
.blueComp
= val
;
916 command_flags
|= COMMAND_SETEXPOSURE
;
920 } else if (MATCH("apcor_gain1")) {
925 command_flags
|= COMMAND_SETAPCOR
;
927 new_params
.apcor
.gain1
= val
;
931 } else if (MATCH("apcor_gain2")) {
936 command_flags
|= COMMAND_SETAPCOR
;
938 new_params
.apcor
.gain2
= val
;
942 } else if (MATCH("apcor_gain4")) {
947 command_flags
|= COMMAND_SETAPCOR
;
949 new_params
.apcor
.gain4
= val
;
953 } else if (MATCH("apcor_gain8")) {
958 command_flags
|= COMMAND_SETAPCOR
;
960 new_params
.apcor
.gain8
= val
;
964 } else if (MATCH("vl_offset_gain1")) {
970 new_params
.vlOffset
.gain1
= val
;
974 command_flags
|= COMMAND_SETVLOFFSET
;
975 } else if (MATCH("vl_offset_gain2")) {
981 new_params
.vlOffset
.gain2
= val
;
985 command_flags
|= COMMAND_SETVLOFFSET
;
986 } else if (MATCH("vl_offset_gain4")) {
992 new_params
.vlOffset
.gain4
= val
;
996 command_flags
|= COMMAND_SETVLOFFSET
;
997 } else if (MATCH("vl_offset_gain8")) {
1003 new_params
.vlOffset
.gain8
= val
;
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;
1018 command_flags
|= COMMAND_SETFLICKERCTRL
;
1019 } else if (MATCH("mains_frequency")) {
1020 if (!retval
&& MATCH("50")) {
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")) {
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
;
1038 } else if (MATCH("allowable_overexposure")) {
1044 new_params
.flickerControl
.
1045 allowableOverExposure
= val
;
1046 command_flags
|= COMMAND_SETFLICKERCTRL
;
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
;
1063 command_flags
|= COMMAND_SETCOMPRESSION
;
1064 } else if (MATCH("decimation_enable")) {
1065 if (!retval
&& MATCH("off"))
1066 new_params
.compression
.decimation
= 0;
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
;
1081 command_flags
|= COMMAND_SETCOMPRESSIONTARGET
;
1082 } else if (MATCH("target_framerate")) {
1087 new_params
.compressionTarget
.targetFR
= val
;
1088 command_flags
|= COMMAND_SETCOMPRESSIONTARGET
;
1089 } else if (MATCH("target_quality")) {
1094 new_params
.compressionTarget
.targetQ
= val
;
1096 command_flags
|= COMMAND_SETCOMPRESSIONTARGET
;
1097 } else if (MATCH("y_threshold")) {
1103 new_params
.yuvThreshold
.yThreshold
= val
;
1107 command_flags
|= COMMAND_SETYUVTHRESH
;
1108 } else if (MATCH("uv_threshold")) {
1114 new_params
.yuvThreshold
.uvThreshold
= val
;
1118 command_flags
|= COMMAND_SETYUVTHRESH
;
1119 } else if (MATCH("hysteresis")) {
1125 new_params
.compressionParams
.hysteresis
= val
;
1129 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1130 } else if (MATCH("threshold_max")) {
1136 new_params
.compressionParams
.threshMax
= val
;
1140 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1141 } else if (MATCH("small_step")) {
1147 new_params
.compressionParams
.smallStep
= val
;
1151 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1152 } else if (MATCH("large_step")) {
1158 new_params
.compressionParams
.largeStep
= val
;
1162 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1163 } else if (MATCH("decimation_hysteresis")) {
1169 new_params
.compressionParams
.decimationHysteresis
= val
;
1173 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1174 } else if (MATCH("fr_diff_step_thresh")) {
1180 new_params
.compressionParams
.frDiffStepThresh
= val
;
1184 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1185 } else if (MATCH("q_diff_step_thresh")) {
1191 new_params
.compressionParams
.qDiffStepThresh
= val
;
1195 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1196 } else if (MATCH("decimation_thresh_mod")) {
1202 new_params
.compressionParams
.decimationThreshMod
= val
;
1206 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1208 DBG("No match found\n");
1213 while (count
&& isspace(*buffer
) && *buffer
!= '\n') {
1218 if (*buffer
!= '\n' && *buffer
!= ';')
1228 #undef FIRMWARE_VERSION
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;
1238 new_params
.colourParams
.contrast
*65535/100;
1240 new_params
.colourParams
.saturation
*65535/100;
1243 memcpy(&cam
->params
, &new_params
, sizeof(struct cam_params
));
1244 cam
->mainsFreq
= new_mains
;
1245 cam
->cmd_queue
|= command_flags
;
1248 DBG("error: %d\n", retval
);
1250 up(&cam
->param_lock
);
1255 static void create_proc_cpia_cam(struct cam_data
*cam
)
1258 struct proc_dir_entry
*ent
;
1260 if (!cpia_proc_root
|| !cam
)
1263 sprintf(name
, "video%d", cam
->vdev
.minor
);
1265 ent
= create_proc_entry(name
, S_IFREG
|S_IRUGO
|S_IWUSR
, cpia_proc_root
);
1270 ent
->read_proc
= cpia_read_proc
;
1271 ent
->write_proc
= cpia_write_proc
;
1273 cam
->proc_entry
= ent
;
1276 static void destroy_proc_cpia_cam(struct cam_data
*cam
)
1280 if (!cam
|| !cam
->proc_entry
)
1283 sprintf(name
, "video%d", cam
->vdev
.minor
);
1284 remove_proc_entry(name
, cpia_proc_root
);
1285 cam
->proc_entry
= NULL
;
1288 static void proc_cpia_create(void)
1290 cpia_proc_root
= create_proc_entry("cpia", S_IFDIR
, 0);
1293 cpia_proc_root
->owner
= THIS_MODULE
;
1295 LOG("Unable to initialise /proc/cpia\n");
1298 static void proc_cpia_destroy(void)
1300 remove_proc_entry("cpia", 0);
1302 #endif /* CONFIG_PROC_FS */
1304 /* ----------------------- debug functions ---------------------- */
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);
1313 /* ----------------------- v4l helpers -------------------------- */
1315 /* supported frame palettes and depths */
1316 static inline int valid_mode(u16 palette
, u16 depth
)
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);
1328 static int match_videosize( int width
, int height
)
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 */
1335 if (width
>=320 && height
>=240)
1336 return VIDEOSIZE_320_240
; /* SIF */
1338 if (width
>=288 && height
>=216)
1339 return VIDEOSIZE_288_216
;
1341 if (width
>=256 && height
>=192)
1342 return VIDEOSIZE_256_192
;
1344 if (width
>=224 && height
>=168)
1345 return VIDEOSIZE_224_168
;
1347 if (width
>=192 && height
>=144)
1348 return VIDEOSIZE_192_144
;
1350 if (width
>=176 && height
>=144)
1351 return VIDEOSIZE_176_144
; /* QCIF */
1353 if (width
>=160 && height
>=120)
1354 return VIDEOSIZE_160_120
; /* QSIF */
1356 if (width
>=128 && height
>=96)
1357 return VIDEOSIZE_128_96
;
1359 if (width
>=88 && height
>=72)
1360 return VIDEOSIZE_88_72
;
1362 if (width
>=64 && height
>=48)
1363 return VIDEOSIZE_64_48
;
1365 if (width
>=48 && height
>=48)
1366 return VIDEOSIZE_48_48
;
1371 /* these are the capture sizes we support */
1372 static void set_vw_size(struct cam_data
*cam
)
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
) {
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;
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;
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;
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;
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;
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;
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;
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;
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;
1469 case VIDEOSIZE_88_72
:
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;
1479 case VIDEOSIZE_64_48
:
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;
1489 case VIDEOSIZE_48_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;
1500 LOG("bad videosize value: %d\n", cam
->video_size
);
1506 static int allocate_frame_buf(struct cam_data
*cam
)
1510 cam
->frame_buf
= rvmalloc(FRAME_NUM
* CPIA_MAX_FRAME_SIZE
);
1511 if (!cam
->frame_buf
)
1514 for (i
= 0; i
< FRAME_NUM
; i
++)
1515 cam
->frame
[i
].data
= cam
->frame_buf
+ i
* CPIA_MAX_FRAME_SIZE
;
1520 static int free_frame_buf(struct cam_data
*cam
)
1524 rvfree(cam
->frame_buf
, FRAME_NUM
*CPIA_MAX_FRAME_SIZE
);
1526 for (i
=0; i
< FRAME_NUM
; i
++)
1527 cam
->frame
[i
].data
= NULL
;
1533 static void inline free_frames(struct cpia_frame frame
[FRAME_NUM
])
1537 for (i
=0; i
< FRAME_NUM
; i
++)
1538 frame
[i
].state
= FRAME_UNUSED
;
1542 /**********************************************************************
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
)
1550 int retval
, datasize
;
1554 case CPIA_COMMAND_GetCPIAVersion
:
1555 case CPIA_COMMAND_GetPnPID
:
1556 case CPIA_COMMAND_GetCameraStatus
:
1557 case CPIA_COMMAND_GetVPVersion
:
1560 case CPIA_COMMAND_GetColourParams
:
1561 case CPIA_COMMAND_GetColourBalance
:
1562 case CPIA_COMMAND_GetExposure
:
1563 down(&cam
->param_lock
);
1571 cmd
[0] = command
>>8;
1572 cmd
[1] = command
&0xff;
1580 retval
= cam
->ops
->transferCmd(cam
->lowlevel_data
, cmd
, data
);
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
);
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];
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);
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];
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);
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
);
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
);
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
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)
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;
1661 up(&cam
->param_lock
);
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
)
1679 cmd
[0] = command
>>8;
1680 cmd
[1] = command
&0xff;
1696 retval
= cam
->ops
->transferCmd(cam
->lowlevel_data
, cmd
, data
);
1698 LOG("%x - failed\n", command
);
1703 /**********************************************************************
1705 * Colorspace conversion
1707 **********************************************************************/
1708 #define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
1710 static int yuvconvert(unsigned char *yuv
, unsigned char *rgb
, int out_fmt
,
1711 int in_uyvy
, int mmap_kludge
)
1713 int y
, u
, v
, r
, g
, b
, y1
;
1716 case VIDEO_PALETTE_RGB555
:
1717 case VIDEO_PALETTE_RGB565
:
1718 case VIDEO_PALETTE_RGB24
:
1719 case VIDEO_PALETTE_RGB32
:
1722 y
= (*yuv
++ - 16) * 76310;
1724 y1
= (*yuv
- 16) * 76310;
1726 y
= (*yuv
++ - 16) * 76310;
1728 y1
= (*yuv
++ - 16) * 76310;
1732 g
= -25690 * u
+ -53294 * v
;
1740 /* Just to avoid compiler warnings */
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);
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);
1759 case VIDEO_PALETTE_RGB24
:
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
);
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
);
1776 case VIDEO_PALETTE_RGB32
:
1778 *rgb
++ = LIMIT(b
+y
);
1779 *rgb
++ = LIMIT(g
+y
);
1780 *rgb
++ = LIMIT(r
+y
);
1782 *rgb
++ = LIMIT(b
+y1
);
1783 *rgb
++ = LIMIT(g
+y1
);
1786 *rgb
++ = LIMIT(r
+y
);
1787 *rgb
++ = LIMIT(g
+y
);
1788 *rgb
++ = LIMIT(b
+y
);
1790 *rgb
++ = LIMIT(r
+y1
);
1791 *rgb
++ = LIMIT(g
+y1
);
1795 case VIDEO_PALETTE_GREY
:
1799 case VIDEO_PALETTE_YUV422
:
1800 case VIDEO_PALETTE_YUYV
:
1806 case VIDEO_PALETTE_UYVY
:
1813 DBG("Empty: %d\n", out_fmt
);
1818 static int skipcount(int count
, int 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
:
1828 case VIDEO_PALETTE_RGB24
:
1830 case VIDEO_PALETTE_RGB32
:
1837 static int parse_picture(struct cam_data
*cam
, int size
)
1839 u8
*obuf
, *ibuf
, *end_obuf
;
1840 int ll
, in_uyvy
, compressed
, origsize
, out_fmt
;
1842 /* make sure params don't change while we are decoding */
1843 down(&cam
->param_lock
);
1845 obuf
= cam
->decompressed_frame
.data
;
1846 end_obuf
= obuf
+CPIA_MAX_FRAME_SIZE
;
1847 ibuf
= cam
->raw_image
;
1849 out_fmt
= cam
->vp
.palette
;
1851 if ((ibuf
[0] != MAGIC_0
) || (ibuf
[1] != MAGIC_1
)) {
1852 LOG("header not found\n");
1853 up(&cam
->param_lock
);
1857 if ((ibuf
[16] != VIDEOSIZE_QCIF
) && (ibuf
[16] != VIDEOSIZE_CIF
)) {
1858 LOG("wrong video size\n");
1859 up(&cam
->param_lock
);
1863 if (ibuf
[17] != SUBSAMPLE_422
) {
1864 LOG("illegal subtype %d\n",ibuf
[17]);
1865 up(&cam
->param_lock
);
1869 if (ibuf
[18] != YUVORDER_YUYV
&& ibuf
[18] != YUVORDER_UYVY
) {
1870 LOG("illegal yuvorder %d\n",ibuf
[18]);
1871 up(&cam
->param_lock
);
1874 in_uyvy
= ibuf
[18] == YUVORDER_UYVY
;
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
);
1888 if ((ibuf
[28] != NOT_COMPRESSED
) && (ibuf
[28] != COMPRESSED
)) {
1889 LOG("illegal compression %d\n",ibuf
[28]);
1890 up(&cam
->param_lock
);
1893 compressed
= (ibuf
[28] == COMPRESSED
);
1895 if (ibuf
[29] != NO_DECIMATION
) {
1896 LOG("decimation not supported\n");
1897 up(&cam
->param_lock
);
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
);
1914 ibuf
+= FRAME_HEADER_SIZE
;
1915 size
-= FRAME_HEADER_SIZE
;
1916 ll
= ibuf
[0] | (ibuf
[1] << 8);
1922 LOG("Insufficient data in buffer\n");
1927 if (!compressed
|| (compressed
&& !(*ibuf
& 1))) {
1928 obuf
+= yuvconvert(ibuf
, obuf
, out_fmt
,
1929 in_uyvy
, cam
->mmap_kludge
);
1933 /*skip compressed interval from previous frame*/
1934 int skipsize
= skipcount(*ibuf
>> 1, out_fmt
);
1936 if (obuf
> end_obuf
) {
1937 LOG("Insufficient data in buffer\n");
1946 LOG("EOL not found giving up after %d/%d"
1947 " bytes\n", origsize
-size
, origsize
);
1951 ibuf
++; /* skip over EOL */
1953 if ((size
> 3) && (ibuf
[0] == EOI
) && (ibuf
[1] == EOI
) &&
1954 (ibuf
[2] == EOI
) && (ibuf
[3] == EOI
)) {
1960 ll
= ibuf
[0] | (ibuf
[1] << 8);
1961 ibuf
+= 2; /* skip over line length */
1964 LOG("line length was not 1 but %d after %d/%d bytes\n",
1965 ll
, origsize
-size
, origsize
);
1970 cam
->decompressed_frame
.count
= obuf
-cam
->decompressed_frame
.data
;
1972 return cam
->decompressed_frame
.count
;
1975 /* InitStreamCap wrapper to select correct start line */
1976 static inline int init_stream_cap(struct cam_data
*cam
)
1978 return do_command(cam
, CPIA_COMMAND_InitStreamCap
,
1979 0, cam
->params
.streamStartLine
, 0, 0);
1982 /* update various camera modes and settings */
1983 static void dispatch_commands(struct cam_data
*cam
)
1985 down(&cam
->param_lock
);
1986 if (cam
->cmd_queue
==COMMAND_NONE
) {
1987 up(&cam
->param_lock
);
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);
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);
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;
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);
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);
2025 if (cam
->cmd_queue
& COMMAND_SETECPTIMING
)
2026 do_command(cam
, CPIA_COMMAND_SetECPTiming
,
2027 cam
->params
.ecpTiming
, 0, 0, 0);
2029 if (cam
->cmd_queue
& COMMAND_SETCOMPRESSIONPARAMS
)
2030 do_command_extended(cam
, CPIA_COMMAND_SetCompressionParams
,
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
);
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
);
2056 if (cam
->cmd_queue
& COMMAND_SETCOLOURBALANCE
) {
2057 if (cam
->params
.colourBalance
.balanceModeIsAuto
) {
2058 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2061 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2063 cam
->params
.colourBalance
.redGain
,
2064 cam
->params
.colourBalance
.greenGain
,
2065 cam
->params
.colourBalance
.blueGain
);
2066 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
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);
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
);
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);
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
);
2096 if (cam
->cmd_queue
& COMMAND_PAUSE
)
2097 do_command(cam
, CPIA_COMMAND_EndStreamCap
, 0, 0, 0, 0);
2099 if (cam
->cmd_queue
& COMMAND_RESUME
)
2100 init_stream_cap(cam
);
2102 up(&cam
->param_lock
);
2103 cam
->cmd_queue
= COMMAND_NONE
;
2107 /* kernel thread function to read image from camera */
2108 static void fetch_frame(void *data
)
2110 int image_size
, retry
;
2111 struct cam_data
*cam
= (struct cam_data
*)data
;
2112 unsigned long oldjif
, rate
, diff
;
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
) {
2118 DBG("retry=%d\n", retry
);
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);
2130 /* init camera upload */
2131 if (do_command(cam
, CPIA_COMMAND_SetGrabMode
,
2132 CPIA_GRAB_CONTINUOUS
, 0, 0, 0))
2135 if (do_command(cam
, CPIA_COMMAND_GrabFrame
, 0,
2136 cam
->params
.streamStartLine
, 0, 0))
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
)
2146 current
->state
= TASK_INTERRUPTIBLE
;
2148 /* sleep for 10 ms, hopefully ;) */
2149 schedule_timeout(10*HZ
/1000);
2150 if (signal_pending(current
))
2153 do_command(cam
, CPIA_COMMAND_GetCameraStatus
,
2158 /* grab image from camera */
2159 if (current
->need_resched
)
2163 image_size
= cam
->ops
->streamRead(cam
->lowlevel_data
,
2165 if (image_size
<= 0) {
2166 DBG("streamRead failed: %d\n", image_size
);
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 */
2175 /* camera idle now so dispatch queued commands */
2176 dispatch_commands(cam
);
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);
2182 /* decompress and convert image to by copying it from
2183 * raw_image to decompressed_frame
2185 if (current
->need_resched
)
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
);
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
;
2203 cam
->decompressed_frame
.state
= FRAME_DONE
;
2206 if (cam
->first_frame
&&
2207 cam
->params
.compression
.mode
!= CPIA_COMPRESSION_NONE
) {
2208 cam
->first_frame
= 0;
2209 cam
->cmd_queue
|= COMMAND_SETCOMPRESSION
;
2212 if (cam
->first_frame
) {
2213 cam
->first_frame
= 0;
2214 cam
->cmd_queue
|= COMMAND_SETCOMPRESSION
;
2215 cam
->cmd_queue
|= COMMAND_SETEXPOSURE
;
2221 static int capture_frame(struct cam_data
*cam
, struct video_mmap
*vm
)
2225 if (!cam
->frame_buf
) {
2226 /* we do lazy allocation */
2227 if ((retval
= allocate_frame_buf(cam
)))
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, ...)
2236 if (cam
->first_frame
) {
2237 cam
->curframe
= vm
->frame
;
2238 cam
->frame
[cam
->curframe
].state
= FRAME_READY
;
2240 if (cam
->frame
[cam
->curframe
].state
!= FRAME_DONE
)
2243 cam
->curframe
= vm
->frame
;
2244 cam
->frame
[cam
->curframe
].state
= FRAME_READY
;
2246 if (cam
->frame
[cam
->curframe
].state
!= FRAME_DONE
)
2252 static int goto_high_power(struct cam_data
*cam
)
2254 if (do_command(cam
, CPIA_COMMAND_GotoHiPower
, 0, 0, 0, 0))
2256 mdelay(100); /* windows driver does it too */
2257 if (do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0))
2259 if (cam
->params
.status
.systemState
== HI_POWER_STATE
) {
2260 DBG("camera now in HIGH power state\n");
2267 static int goto_low_power(struct cam_data
*cam
)
2269 if (do_command(cam
, CPIA_COMMAND_GotoLoPower
, 0, 0, 0, 0))
2271 if (do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0))
2273 if (cam
->params
.status
.systemState
== LO_POWER_STATE
) {
2274 DBG("camera now in LOW power state\n");
2281 static void save_camera_state(struct cam_data
*cam
)
2283 do_command(cam
, CPIA_COMMAND_GetColourBalance
, 0, 0, 0, 0);
2284 do_command(cam
, CPIA_COMMAND_GetExposure
, 0, 0, 0, 0);
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
);
2296 cam
->params
.colourBalance
.redGain
,
2297 cam
->params
.colourBalance
.greenGain
,
2298 cam
->params
.colourBalance
.blueGain
);
2301 static void set_camera_state(struct cam_data
*cam
)
2303 if(cam
->params
.colourBalance
.balanceModeIsAuto
) {
2304 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2307 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2309 cam
->params
.colourBalance
.redGain
,
2310 cam
->params
.colourBalance
.greenGain
,
2311 cam
->params
.colourBalance
.blueGain
);
2312 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
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
,
2330 0, 0, 0, 0, 0, 0, 0, 0);
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;
2339 cam
->cmd_queue
= COMMAND_SETCOMPRESSION
|
2340 COMMAND_SETCOMPRESSIONTARGET
|
2341 COMMAND_SETCOLOURPARAMS
|
2343 COMMAND_SETYUVTHRESH
|
2344 COMMAND_SETECPTIMING
|
2345 COMMAND_SETCOMPRESSIONPARAMS
|
2347 COMMAND_SETEXPOSURE
|
2349 COMMAND_SETCOLOURBALANCE
|
2350 COMMAND_SETSENSORFPS
|
2352 COMMAND_SETFLICKERCTRL
|
2353 COMMAND_SETVLOFFSET
;
2354 dispatch_commands(cam
);
2355 save_camera_state(cam
);
2360 static void get_version_information(struct cam_data
*cam
)
2362 /* GetCPIAVersion */
2363 do_command(cam
, CPIA_COMMAND_GetCPIAVersion
, 0, 0, 0, 0);
2366 do_command(cam
, CPIA_COMMAND_GetPnPID
, 0, 0, 0, 0);
2369 /* initialize camera */
2370 static int reset_camera(struct cam_data
*cam
)
2372 /* Start the camera in low power mode */
2373 if (goto_low_power(cam
)) {
2374 if (cam
->params
.status
.systemState
!= WARM_BOOT_STATE
)
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
))
2385 /* procedure described in developer's guide p3-28 */
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)
2393 /* The fatal error checking should be done after
2394 * the camera powers up (developer's guide p 3-38) */
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);
2402 if (goto_high_power(cam
))
2405 /* Check the camera status */
2406 if (do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0))
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 */
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);
2425 /* Check the camera status again */
2426 if (cam
->params
.status
.fatalError
) {
2427 if (cam
->params
.status
.fatalError
)
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);
2435 /* set camera to a known state */
2436 set_camera_state(cam
);
2441 /* ------------------------- V4L interface --------------------- */
2442 static int cpia_open(struct video_device
*dev
, int flags
)
2445 struct cam_data
*cam
= dev
->priv
;
2448 DBG("Internal error, cam_data not found!\n");
2452 if (cam
->open_count
> 0) {
2453 DBG("Camera already open\n");
2457 if (!cam
->raw_image
) {
2458 cam
->raw_image
= rvmalloc(CPIA_MAX_IMAGE_SIZE
);
2459 if (!cam
->raw_image
)
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
;
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
;
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
;
2491 /* Set ownership of /proc/cpia/videoX to current user */
2493 cam
->proc_entry
->uid
= current
->uid
;
2495 /* set mark for loading first frame uncompressed */
2496 cam
->first_frame
= 1;
2498 /* init it to something */
2499 cam
->mmap_kludge
= 0;
2508 static void cpia_close(struct video_device
*dev
)
2510 struct cam_data
*cam
;
2515 /* Return ownership of /proc/cpia/videoX to root */
2517 cam
->proc_entry
->uid
= 0;
2519 /* save camera state for later open (developers guide ch 3.5.3) */
2520 save_camera_state(cam
);
2523 goto_low_power(cam
);
2525 /* Update the camera ststus */
2526 do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0);
2528 /* cleanup internal state stuff */
2529 free_frames(cam
->frame
);
2532 cam
->ops
->close(cam
->lowlevel_data
);
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
;
2542 if (cam
->decompressed_frame
.data
) {
2543 rvfree(cam
->decompressed_frame
.data
, CPIA_MAX_FRAME_SIZE
);
2544 cam
->decompressed_frame
.data
= NULL
;
2548 free_frame_buf(cam
);
2551 video_unregister_device(dev
);
2563 static long cpia_read(struct video_device
*dev
, char *buf
,
2564 unsigned long count
, int noblock
)
2566 struct cam_data
*cam
= dev
->priv
;
2568 /* make this _really_ smp and multithredi-safe */
2569 if (down_interruptible(&cam
->busy_lock
))
2574 up(&cam
->busy_lock
);
2580 up(&cam
->busy_lock
);
2586 up(&cam
->busy_lock
);
2591 cam
->decompressed_frame
.state
= FRAME_READY
;
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
);
2600 cam
->decompressed_frame
.state
= FRAME_UNUSED
;
2602 /* copy data to user space */
2603 if (cam
->decompressed_frame
.count
> count
) {
2604 DBG("count wrong: %d, %lu\n", cam
->decompressed_frame
.count
,
2606 up(&cam
->busy_lock
);
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
);
2616 up(&cam
->busy_lock
);
2617 return cam
->decompressed_frame
.count
;
2620 static int cpia_ioctl(struct video_device
*dev
, unsigned int ioctlnr
, void *arg
)
2622 struct cam_data
*cam
= dev
->priv
;
2625 if (!cam
|| !cam
->ops
)
2628 /* make this _really_ smp-safe */
2629 if (down_interruptible(&cam
->busy_lock
))
2632 //DBG("cpia_ioctl: %u\n", ioctlnr);
2635 /* query capabilites */
2638 struct video_capability b
;
2640 DBG("VIDIOCGCAP\n");
2641 strcpy(b
.name
, "CPiA Camera");
2642 b
.type
= VID_TYPE_CAPTURE
;
2645 b
.maxwidth
= 352; /* VIDEOSIZE_CIF */
2647 b
.minwidth
= 48; /* VIDEOSIZE_48_48 */
2650 if (copy_to_user(arg
, &b
, sizeof(b
)))
2656 /* get/set video source - we are a camera and nothing else */
2659 struct video_channel v
;
2661 DBG("VIDIOCGCHAN\n");
2662 if (copy_from_user(&v
, arg
, sizeof(v
))) {
2666 if (v
.channel
!= 0) {
2672 strcpy(v
.name
, "Camera");
2675 v
.type
= VIDEO_TYPE_CAMERA
;
2678 if (copy_to_user(arg
, &v
, sizeof(v
)))
2687 DBG("VIDIOCSCHAN\n");
2688 if (copy_from_user(&v
, arg
, sizeof(v
)))
2691 if (retval
== 0 && v
!= 0)
2697 /* image properties */
2699 DBG("VIDIOCGPICT\n");
2700 if (copy_to_user(arg
, &cam
->vp
, sizeof(struct video_picture
)))
2706 struct video_picture vp
;
2708 DBG("VIDIOCSPICT\n");
2710 /* copy_from_user */
2711 if (copy_from_user(&vp
, arg
, sizeof(vp
))) {
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
)) {
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;
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
,
2750 /* get/set capture window */
2752 DBG("VIDIOCGWIN\n");
2754 if (copy_to_user(arg
, &cam
->vw
, sizeof(struct video_window
)))
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
))) {
2768 if (vw
.clipcount
!= 0) { /* clipping not supported */
2772 if (vw
.clips
!= NULL
) { /* clipping not supported */
2777 /* we set the video window to something smaller or equal to what
2778 * is requested by the user???
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
);
2784 if (video_size
< 0) {
2786 up(&cam
->param_lock
);
2789 cam
->video_size
= video_size
;
2791 DBG("%d / %d\n", cam
->vw
.width
, cam
->vw
.height
);
2792 cam
->cmd_queue
|= COMMAND_SETFORMAT
;
2795 // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw));
2796 up(&cam
->param_lock
);
2798 /* setformat ignored by camera during streaming,
2799 * so stop/dispatch/start */
2800 if (cam
->cmd_queue
& COMMAND_SETFORMAT
) {
2802 dispatch_commands(cam
);
2804 DBG("%d/%d:%d\n", cam
->video_size
,
2805 cam
->vw
.width
, cam
->vw
.height
);
2809 /* mmap interface */
2812 struct video_mbuf vm
;
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
;
2822 if (copy_to_user((void *)arg
, (void *)&vm
, sizeof(vm
)))
2828 case VIDIOCMCAPTURE
:
2830 struct video_mmap vm
;
2833 if (copy_from_user((void *)&vm
, (void *)arg
, sizeof(vm
))) {
2838 DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm
.format
, vm
.frame
,
2839 vm
.width
, vm
.height
);
2841 if (vm
.frame
<0||vm
.frame
>FRAME_NUM
) {
2846 /* set video format */
2847 cam
->vp
.palette
= 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
:
2857 case VIDEO_PALETTE_RGB24
:
2860 case VIDEO_PALETTE_RGB32
:
2870 /* set video size */
2871 video_size
= match_videosize(vm
.width
, vm
.height
);
2872 if (cam
->video_size
< 0) {
2876 if (video_size
!= cam
->video_size
) {
2877 cam
->video_size
= video_size
;
2879 cam
->cmd_queue
|= COMMAND_SETFORMAT
;
2880 dispatch_commands(cam
);
2883 DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam
->video_size
,
2884 cam
->vw
.width
, cam
->vw
.height
);
2886 /* according to v4l-spec we must start streaming here */
2887 cam
->mmap_kludge
= 1;
2888 retval
= capture_frame(cam
, &vm
);
2897 if (copy_from_user((void *)&frame
, arg
, sizeof(int))) {
2901 //DBG("VIDIOCSYNC: %d\n", frame);
2903 if (frame
<0 || frame
>= FRAME_NUM
) {
2908 switch (cam
->frame
[frame
].state
) {
2911 case FRAME_GRABBING
:
2912 DBG("sync to unused frame %d\n", frame
);
2917 cam
->frame
[frame
].state
= FRAME_UNUSED
;
2918 //DBG("VIDIOCSYNC: %d synced\n", frame);
2921 if (retval
== -EINTR
) {
2922 /* FIXME - xawtv does not handle this nice */
2928 /* pointless to implement overlay with this camera */
2942 /* tuner interface - we have none */
2956 /* audio interface - we have none */
2964 retval
= -ENOIOCTLCMD
;
2968 up(&cam
->param_lock
);
2969 up(&cam
->busy_lock
);
2974 static int cpia_mmap(struct video_device
*dev
, const char *adr
,
2977 unsigned long start
= (unsigned long)adr
;
2978 unsigned long page
, pos
;
2979 struct cam_data
*cam
= dev
->priv
;
2982 if (!cam
|| !cam
->ops
)
2985 DBG("cpia_mmap: %ld\n", size
);
2987 if (size
> FRAME_NUM
*CPIA_MAX_FRAME_SIZE
)
2990 if (!cam
|| !cam
->ops
)
2993 /* make this _really_ smp-safe */
2994 if (down_interruptible(&cam
->busy_lock
))
2997 if (!cam
->frame_buf
) { /* we do lazy allocation */
2998 if ((retval
= allocate_frame_buf(cam
))) {
2999 up(&cam
->busy_lock
);
3004 pos
= (unsigned long)(cam
->frame_buf
);
3006 page
= kvirt_to_pa(pos
);
3007 if (remap_page_range(start
, page
, PAGE_SIZE
, PAGE_SHARED
)) {
3008 up(&cam
->busy_lock
);
3013 if (size
> PAGE_SIZE
)
3019 DBG("cpia_mmap: %ld\n", size
);
3020 up(&cam
->busy_lock
);
3025 int cpia_video_init(struct video_device
*vdev
)
3027 #ifdef CONFIG_PROC_FS
3028 create_proc_cpia_cam(vdev
->priv
);
3033 static struct video_device cpia_template
= {
3036 VID_HARDWARE_CPIA
, /* FIXME */
3037 cpia_open
, /* open */
3038 cpia_close
, /* close */
3039 cpia_read
, /* read */
3040 NULL
, /* no write */
3042 cpia_ioctl
, /* ioctl */
3043 cpia_mmap
, /* mmap */
3044 cpia_video_init
, /* initialize */
3047 -1 /* minor - unset */
3050 /* initialise cam_data structure */
3051 static void reset_camera_struct(struct cam_data
*cam
)
3053 /* The following parameter values are the defaults from
3054 * "Software Developer's Guide for CPiA Cameras". Any changes
3055 * to the defaults are noted in comments. */
3056 cam
->params
.colourParams
.brightness
= 50;
3057 cam
->params
.colourParams
.contrast
= 48;
3058 cam
->params
.colourParams
.saturation
= 50;
3059 cam
->params
.exposure
.gainMode
= 2;
3060 cam
->params
.exposure
.expMode
= 2; /* AEC */
3061 cam
->params
.exposure
.compMode
= 1;
3062 cam
->params
.exposure
.centreWeight
= 1;
3063 cam
->params
.exposure
.gain
= 0;
3064 cam
->params
.exposure
.fineExp
= 0;
3065 cam
->params
.exposure
.coarseExpLo
= 185;
3066 cam
->params
.exposure
.coarseExpHi
= 0;
3067 cam
->params
.exposure
.redComp
= 220;
3068 cam
->params
.exposure
.green1Comp
= 214;
3069 cam
->params
.exposure
.green2Comp
= 214;
3070 cam
->params
.exposure
.blueComp
= 230;
3071 cam
->params
.colourBalance
.balanceModeIsAuto
= 1;
3072 cam
->params
.colourBalance
.redGain
= 32;
3073 cam
->params
.colourBalance
.greenGain
= 6;
3074 cam
->params
.colourBalance
.blueGain
= 92;
3075 cam
->params
.apcor
.gain1
= 0x1c;
3076 cam
->params
.apcor
.gain2
= 0x1a;
3077 cam
->params
.apcor
.gain4
= 0x2d;
3078 cam
->params
.apcor
.gain8
= 0x2a;
3079 cam
->params
.flickerControl
.flickerMode
= 0;
3080 cam
->params
.flickerControl
.coarseJump
=
3081 flicker_jumps
[cam
->mainsFreq
]
3082 [cam
->params
.sensorFps
.baserate
]
3083 [cam
->params
.sensorFps
.divisor
];
3084 cam
->params
.vlOffset
.gain1
= 24;
3085 cam
->params
.vlOffset
.gain2
= 28;
3086 cam
->params
.vlOffset
.gain4
= 30;
3087 cam
->params
.vlOffset
.gain8
= 30;
3088 cam
->params
.compressionParams
.hysteresis
= 3;
3089 cam
->params
.compressionParams
.threshMax
= 11;
3090 cam
->params
.compressionParams
.smallStep
= 1;
3091 cam
->params
.compressionParams
.largeStep
= 3;
3092 cam
->params
.compressionParams
.decimationHysteresis
= 2;
3093 cam
->params
.compressionParams
.frDiffStepThresh
= 5;
3094 cam
->params
.compressionParams
.qDiffStepThresh
= 3;
3095 cam
->params
.compressionParams
.decimationThreshMod
= 2;
3096 /* End of default values from Software Developer's Guide */
3098 cam
->transfer_rate
= 0;
3100 /* Set Sensor FPS to 15fps. This seems better than 30fps
3101 * for indoor lighting. */
3102 cam
->params
.sensorFps
.divisor
= 1;
3103 cam
->params
.sensorFps
.baserate
= 1;
3105 cam
->params
.yuvThreshold
.yThreshold
= 15; /* FIXME? */
3106 cam
->params
.yuvThreshold
.uvThreshold
= 15; /* FIXME? */
3108 cam
->params
.format
.subSample
= SUBSAMPLE_422
;
3109 cam
->params
.format
.yuvOrder
= YUVORDER_YUYV
;
3111 cam
->params
.compression
.mode
= CPIA_COMPRESSION_AUTO
;
3112 cam
->params
.compressionTarget
.frTargeting
=
3113 CPIA_COMPRESSION_TARGET_QUALITY
;
3114 cam
->params
.compressionTarget
.targetFR
= 7; /* FIXME? */
3115 cam
->params
.compressionTarget
.targetQ
= 10; /* FIXME? */
3117 cam
->video_size
= VIDEOSIZE_CIF
;
3119 cam
->vp
.colour
= 32768; /* 50% */
3120 cam
->vp
.hue
= 32768; /* 50% */
3121 cam
->vp
.brightness
= 32768; /* 50% */
3122 cam
->vp
.contrast
= 32768; /* 50% */
3123 cam
->vp
.whiteness
= 0; /* not used -> grayscale only */
3124 cam
->vp
.depth
= 0; /* FIXME: to be set by user? */
3125 cam
->vp
.palette
= VIDEO_PALETTE_RGB24
; /* FIXME: to be set by user? */
3130 cam
->vw
.chromakey
= 0;
3131 /* PP NOTE: my extension to use vw.flags for this, bear it! */
3133 cam
->vw
.clipcount
= 0;
3134 cam
->vw
.clips
= NULL
;
3136 cam
->cmd_queue
= COMMAND_NONE
;
3137 cam
->first_frame
= 0;
3142 /* initialize cam_data structure */
3143 static void init_camera_struct(struct cam_data
*cam
,
3144 struct cpia_camera_ops
*ops
)
3148 /* Default everything to 0 */
3149 memset(cam
, 0, sizeof(struct cam_data
));
3152 init_MUTEX(&cam
->param_lock
);
3153 init_MUTEX(&cam
->busy_lock
);
3155 reset_camera_struct(cam
);
3157 cam
->proc_entry
= NULL
;
3159 memcpy(&cam
->vdev
, &cpia_template
, sizeof(cpia_template
));
3160 cam
->vdev
.priv
= cam
;
3163 for (i
= 0; i
< FRAME_NUM
; i
++) {
3164 cam
->frame
[i
].width
= 0;
3165 cam
->frame
[i
].height
= 0;
3166 cam
->frame
[i
].state
= FRAME_UNUSED
;
3167 cam
->frame
[i
].data
= NULL
;
3169 cam
->decompressed_frame
.width
= 0;
3170 cam
->decompressed_frame
.height
= 0;
3171 cam
->decompressed_frame
.state
= FRAME_UNUSED
;
3172 cam
->decompressed_frame
.data
= NULL
;
3175 struct cam_data
*cpia_register_camera(struct cpia_camera_ops
*ops
, void *lowlevel
)
3177 struct cam_data
*camera
;
3179 /* Need a lock when adding/removing cameras. This doesn't happen
3180 * often and doesn't take very long, so grabbing the kernel lock
3183 if ((camera
= kmalloc(sizeof(struct cam_data
), GFP_KERNEL
)) == NULL
) {
3188 init_camera_struct( camera
, ops
);
3189 camera
->lowlevel_data
= lowlevel
;
3191 /* register v4l device */
3192 if (video_register_device(&camera
->vdev
, VFL_TYPE_GRABBER
) == -1) {
3195 printk(KERN_DEBUG
"video_register_device failed\n");
3199 /* get version information from camera: open/reset/close */
3202 if (camera
->ops
->open(camera
->lowlevel_data
))
3205 /* reset the camera */
3206 if (reset_camera(camera
) != 0) {
3207 camera
->ops
->close(camera
->lowlevel_data
);
3212 camera
->ops
->close(camera
->lowlevel_data
);
3214 /* Eh? Feeling happy? - jerdfelt */
3216 camera->ops->open(camera->lowlevel_data);
3217 camera->ops->close(camera->lowlevel_data);
3220 printk(KERN_INFO
" CPiA Version: %d.%02d (%d.%d)\n",
3221 camera
->params
.version
.firmwareVersion
,
3222 camera
->params
.version
.firmwareRevision
,
3223 camera
->params
.version
.vcVersion
,
3224 camera
->params
.version
.vcRevision
);
3225 printk(KERN_INFO
" CPiA PnP-ID: %04x:%04x:%04x\n",
3226 camera
->params
.pnpID
.vendor
,
3227 camera
->params
.pnpID
.product
,
3228 camera
->params
.pnpID
.deviceRevision
);
3229 printk(KERN_INFO
" VP-Version: %d.%d %04x\n",
3230 camera
->params
.vpVersion
.vpVersion
,
3231 camera
->params
.vpVersion
.vpRevision
,
3232 camera
->params
.vpVersion
.cameraHeadID
);
3237 void cpia_unregister_camera(struct cam_data
*cam
)
3239 if (!cam
->open_count
) {
3240 DBG("unregistering video\n");
3241 video_unregister_device(&cam
->vdev
);
3243 LOG("/dev/video%d removed while open, "
3244 "deferring video_unregister_device\n", cam
->vdev
.minor
);
3245 DBG("camera open -- setting ops to NULL\n");
3249 #ifdef CONFIG_PROC_FS
3250 DBG("destroying /proc/cpia/video%d\n", cam
->vdev
.minor
);
3251 destroy_proc_cpia_cam(cam
);
3253 if (!cam
->open_count
) {
3254 DBG("freeing camera\n");
3259 /****************************************************************************
3263 ***************************************************************************/
3266 int init_module(void)
3268 printk(KERN_INFO
"%s v%d.%d.%d\n", ABOUT
,
3269 CPIA_MAJ_VER
, CPIA_MIN_VER
, CPIA_PATCH_VER
);
3270 #ifdef CONFIG_PROC_FS
3274 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
3275 request_module("cpia_pp");
3277 #ifdef CONFIG_VIDEO_CPIA_USB_MODULE
3278 request_module("cpia_usb");
3284 void cleanup_module(void)
3286 #ifdef CONFIG_PROC_FS
3287 proc_cpia_destroy();
3293 int cpia_init(struct video_init
*unused
)
3295 printk(KERN_INFO
"%s v%d.%d.%d\n", ABOUT
,
3296 CPIA_MAJ_VER
, CPIA_MIN_VER
, CPIA_PATCH_VER
);
3297 #ifdef CONFIG_PROC_FS
3301 #ifdef CONFIG_VIDEO_CPIA_PP
3305 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
3306 request_module("cpia_pp");
3309 #ifdef CONFIG_VIDEO_CPIA_USB_MODULE
3310 request_module("cpia_usb");
3312 #endif /* CONFIG_KMOD */
3313 #ifdef CONFIG_VIDEO_CPIA_USB
3319 /* Exported symbols for modules. */
3321 EXPORT_SYMBOL(cpia_register_camera
);
3322 EXPORT_SYMBOL(cpia_unregister_camera
);