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
= page_address(pte_page(pte
)) |
204 (adr
& (PAGE_SIZE
-1));
210 /* Here we want the physical address of the memory.
211 * This is used when initializing the contents of the
212 * area and marking the pages as reserved.
214 static inline unsigned long kvirt_to_pa(unsigned long adr
)
216 unsigned long va
, kva
, ret
;
218 va
= VMALLOC_VMADDR(adr
);
219 kva
= uvirt_to_kva(pgd_offset_k(va
), va
);
224 static void *rvmalloc(unsigned long size
)
227 unsigned long adr
, page
;
229 /* Round it off to PAGE_SIZE */
230 size
+= (PAGE_SIZE
- 1);
231 size
&= ~(PAGE_SIZE
- 1);
233 mem
= vmalloc_32(size
);
237 memset(mem
, 0, size
); /* Clear the ram out, no junk to the user */
238 adr
= (unsigned long) mem
;
240 page
= kvirt_to_pa(adr
);
241 mem_map_reserve(MAP_NR(__va(page
)));
243 if (size
> PAGE_SIZE
)
252 static void rvfree(void *mem
, unsigned long size
)
254 unsigned long adr
, page
;
259 size
+= (PAGE_SIZE
- 1);
260 size
&= ~(PAGE_SIZE
- 1);
262 adr
= (unsigned long) mem
;
264 page
= kvirt_to_pa(adr
);
265 mem_map_unreserve(MAP_NR(__va(page
)));
267 if (size
> PAGE_SIZE
)
275 /**********************************************************************
279 **********************************************************************/
280 #ifdef CONFIG_PROC_FS
281 static struct proc_dir_entry
*cpia_proc_root
=NULL
;
283 static int cpia_read_proc(char *page
, char **start
, off_t off
,
284 int count
, int *eof
, void *data
)
288 struct cam_data
*cam
= data
;
291 /* IMPORTANT: This output MUST be kept under PAGE_SIZE
292 * or we need to get more sophisticated. */
294 out
+= sprintf(out
, "read-only\n-----------------------\n");
295 out
+= sprintf(out
, "V4L Driver version: %d.%d.%d\n",
296 CPIA_MAJ_VER
, CPIA_MIN_VER
, CPIA_PATCH_VER
);
297 out
+= sprintf(out
, "CPIA Version: %d.%02d (%d.%d)\n",
298 cam
->params
.version
.firmwareVersion
,
299 cam
->params
.version
.firmwareRevision
,
300 cam
->params
.version
.vcVersion
,
301 cam
->params
.version
.vcRevision
);
302 out
+= sprintf(out
, "CPIA PnP-ID: %04x:%04x:%04x\n",
303 cam
->params
.pnpID
.vendor
, cam
->params
.pnpID
.product
,
304 cam
->params
.pnpID
.deviceRevision
);
305 out
+= sprintf(out
, "VP-Version: %d.%d %04x\n",
306 cam
->params
.vpVersion
.vpVersion
,
307 cam
->params
.vpVersion
.vpRevision
,
308 cam
->params
.vpVersion
.cameraHeadID
);
310 out
+= sprintf(out
, "system_state: %#04x\n",
311 cam
->params
.status
.systemState
);
312 out
+= sprintf(out
, "grab_state: %#04x\n",
313 cam
->params
.status
.grabState
);
314 out
+= sprintf(out
, "stream_state: %#04x\n",
315 cam
->params
.status
.streamState
);
316 out
+= sprintf(out
, "fatal_error: %#04x\n",
317 cam
->params
.status
.fatalError
);
318 out
+= sprintf(out
, "cmd_error: %#04x\n",
319 cam
->params
.status
.cmdError
);
320 out
+= sprintf(out
, "debug_flags: %#04x\n",
321 cam
->params
.status
.debugFlags
);
322 out
+= sprintf(out
, "vp_status: %#04x\n",
323 cam
->params
.status
.vpStatus
);
324 out
+= sprintf(out
, "error_code: %#04x\n",
325 cam
->params
.status
.errorCode
);
326 out
+= sprintf(out
, "video_size: %s\n",
327 cam
->params
.format
.videoSize
== VIDEOSIZE_CIF
?
329 out
+= sprintf(out
, "sub_sample: %s\n",
330 cam
->params
.format
.subSample
== SUBSAMPLE_420
?
332 out
+= sprintf(out
, "yuv_order: %s\n",
333 cam
->params
.format
.yuvOrder
== YUVORDER_YUYV
?
335 out
+= sprintf(out
, "roi: (%3d, %3d) to (%3d, %3d)\n",
336 cam
->params
.roi
.colStart
*8,
337 cam
->params
.roi
.rowStart
*4,
338 cam
->params
.roi
.colEnd
*8,
339 cam
->params
.roi
.rowEnd
*4);
340 out
+= sprintf(out
, "actual_fps: %3d\n", cam
->fps
);
341 out
+= sprintf(out
, "transfer_rate: %4dkB/s\n",
344 out
+= sprintf(out
, "\nread-write\n");
345 out
+= sprintf(out
, "----------------------- current min"
346 " max default comment\n");
347 out
+= sprintf(out
, "brightness: %8d %8d %8d %8d\n",
348 cam
->params
.colourParams
.brightness
, 0, 100, 50);
349 if (cam
->params
.version
.firmwareVersion
== 1 &&
350 cam
->params
.version
.firmwareRevision
== 2)
351 /* 1-02 firmware limits contrast to 80 */
356 out
+= sprintf(out
, "contrast: %8d %8d %8d %8d"
358 cam
->params
.colourParams
.contrast
, 0, tmp
, 48);
359 out
+= sprintf(out
, "saturation: %8d %8d %8d %8d\n",
360 cam
->params
.colourParams
.saturation
, 0, 100, 50);
361 tmp
= (25000+5000*cam
->params
.sensorFps
.baserate
)/
362 (1<<cam
->params
.sensorFps
.divisor
);
363 out
+= sprintf(out
, "sensor_fps: %4d.%03d %8d %8d %8d\n",
364 tmp
/1000, tmp
%1000, 3, 30, 15);
365 out
+= sprintf(out
, "stream_start_line: %8d %8d %8d %8d\n",
366 2*cam
->params
.streamStartLine
, 0,
367 cam
->params
.format
.videoSize
== VIDEOSIZE_CIF
? 288:144,
368 cam
->params
.format
.videoSize
== VIDEOSIZE_CIF
? 240:120);
369 out
+= sprintf(out
, "ecp_timing: %8s %8s %8s %8s\n",
370 cam
->params
.ecpTiming
? "slow" : "normal", "slow",
373 if (cam
->params
.colourBalance
.balanceModeIsAuto
) {
374 sprintf(tmpstr
, "auto");
376 sprintf(tmpstr
, "manual");
378 out
+= sprintf(out
, "color_balance_mode: %8s %8s %8s"
379 " %8s\n", tmpstr
, "manual", "auto", "auto");
380 out
+= sprintf(out
, "red_gain: %8d %8d %8d %8d\n",
381 cam
->params
.colourBalance
.redGain
, 0, 212, 32);
382 out
+= sprintf(out
, "green_gain: %8d %8d %8d %8d\n",
383 cam
->params
.colourBalance
.greenGain
, 0, 212, 6);
384 out
+= sprintf(out
, "blue_gain: %8d %8d %8d %8d\n",
385 cam
->params
.colourBalance
.blueGain
, 0, 212, 92);
387 if (cam
->params
.version
.firmwareVersion
== 1 &&
388 cam
->params
.version
.firmwareRevision
== 2)
389 /* 1-02 firmware limits gain to 2 */
390 sprintf(tmpstr
, "%8d %8d", 1, 2);
392 sprintf(tmpstr
, "1,2,4,8");
394 if (cam
->params
.exposure
.gainMode
== 0)
395 out
+= sprintf(out
, "max_gain: unknown %18s"
396 " %8d\n", tmpstr
, 2);
398 out
+= sprintf(out
, "max_gain: %8d %18s %8d\n",
399 1<<(cam
->params
.exposure
.gainMode
-1), tmpstr
, 2);
401 switch(cam
->params
.exposure
.expMode
) {
404 sprintf(tmpstr
, "manual");
407 sprintf(tmpstr
, "auto");
410 sprintf(tmpstr
, "unknown");
413 out
+= sprintf(out
, "exposure_mode: %8s %8s %8s"
414 " %8s\n", tmpstr
, "manual", "auto", "auto");
415 out
+= sprintf(out
, "centre_weight: %8s %8s %8s %8s\n",
416 (2-cam
->params
.exposure
.centreWeight
) ? "on" : "off",
418 out
+= sprintf(out
, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
419 1<<cam
->params
.exposure
.gain
, 1, 1);
420 if (cam
->params
.version
.firmwareVersion
== 1 &&
421 cam
->params
.version
.firmwareRevision
== 2)
422 /* 1-02 firmware limits fineExp to 127 */
427 out
+= sprintf(out
, "fine_exp: %8d %8d %8d %8d\n",
428 cam
->params
.exposure
.fineExp
*2, 0, tmp
, 0);
429 if (cam
->params
.version
.firmwareVersion
== 1 &&
430 cam
->params
.version
.firmwareRevision
== 2)
431 /* 1-02 firmware limits coarseExpHi to 0 */
436 out
+= sprintf(out
, "coarse_exp: %8d %8d %8d"
437 " %8d\n", cam
->params
.exposure
.coarseExpLo
+
438 256*cam
->params
.exposure
.coarseExpHi
, 0, tmp
, 185);
439 out
+= sprintf(out
, "red_comp: %8d %8d %8d %8d\n",
440 cam
->params
.exposure
.redComp
, 220, 255, 220);
441 out
+= sprintf(out
, "green1_comp: %8d %8d %8d %8d\n",
442 cam
->params
.exposure
.green1Comp
, 214, 255, 214);
443 out
+= sprintf(out
, "green2_comp: %8d %8d %8d %8d\n",
444 cam
->params
.exposure
.green2Comp
, 214, 255, 214);
445 out
+= sprintf(out
, "blue_comp: %8d %8d %8d %8d\n",
446 cam
->params
.exposure
.blueComp
, 230, 255, 230);
448 out
+= sprintf(out
, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
449 cam
->params
.apcor
.gain1
, 0, 0xff, 0x1c);
450 out
+= sprintf(out
, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
451 cam
->params
.apcor
.gain2
, 0, 0xff, 0x1a);
452 out
+= sprintf(out
, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
453 cam
->params
.apcor
.gain4
, 0, 0xff, 0x2d);
454 out
+= sprintf(out
, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
455 cam
->params
.apcor
.gain8
, 0, 0xff, 0x2a);
456 out
+= sprintf(out
, "vl_offset_gain1: %8d %8d %8d %8d\n",
457 cam
->params
.vlOffset
.gain1
, 0, 255, 24);
458 out
+= sprintf(out
, "vl_offset_gain2: %8d %8d %8d %8d\n",
459 cam
->params
.vlOffset
.gain2
, 0, 255, 28);
460 out
+= sprintf(out
, "vl_offset_gain4: %8d %8d %8d %8d\n",
461 cam
->params
.vlOffset
.gain4
, 0, 255, 30);
462 out
+= sprintf(out
, "vl_offset_gain8: %8d %8d %8d %8d\n",
463 cam
->params
.vlOffset
.gain8
, 0, 255, 30);
464 out
+= sprintf(out
, "flicker_control: %8s %8s %8s %8s\n",
465 cam
->params
.flickerControl
.flickerMode
? "on" : "off",
467 out
+= sprintf(out
, "mains_frequency: %8d %8d %8d %8d"
469 cam
->mainsFreq
? 60 : 50, 50, 60, 50);
470 out
+= sprintf(out
, "allowable_overexposure: %8d %8d %8d %8d\n",
471 cam
->params
.flickerControl
.allowableOverExposure
, 0,
473 out
+= sprintf(out
, "compression_mode: ");
474 switch(cam
->params
.compression
.mode
) {
475 case CPIA_COMPRESSION_NONE
:
476 out
+= sprintf(out
, "%8s", "none");
478 case CPIA_COMPRESSION_AUTO
:
479 out
+= sprintf(out
, "%8s", "auto");
481 case CPIA_COMPRESSION_MANUAL
:
482 out
+= sprintf(out
, "%8s", "manual");
485 out
+= sprintf(out
, "%8s", "unknown");
488 out
+= sprintf(out
, " none,auto,manual auto\n");
489 out
+= sprintf(out
, "decimation_enable: %8s %8s %8s %8s\n",
490 cam
->params
.compression
.decimation
==
491 DECIMATION_ENAB
? "on":"off", "off", "off",
493 out
+= sprintf(out
, "compression_target: %9s %9s %9s %9s\n",
494 cam
->params
.compressionTarget
.frTargeting
==
495 CPIA_COMPRESSION_TARGET_FRAMERATE
?
496 "framerate":"quality",
497 "framerate", "quality", "quality");
498 out
+= sprintf(out
, "target_framerate: %8d %8d %8d %8d\n",
499 cam
->params
.compressionTarget
.targetFR
, 0, 30, 7);
500 out
+= sprintf(out
, "target_quality: %8d %8d %8d %8d\n",
501 cam
->params
.compressionTarget
.targetQ
, 0, 255, 10);
502 out
+= sprintf(out
, "y_threshold: %8d %8d %8d %8d\n",
503 cam
->params
.yuvThreshold
.yThreshold
, 0, 31, 15);
504 out
+= sprintf(out
, "uv_threshold: %8d %8d %8d %8d\n",
505 cam
->params
.yuvThreshold
.uvThreshold
, 0, 31, 15);
506 out
+= sprintf(out
, "hysteresis: %8d %8d %8d %8d\n",
507 cam
->params
.compressionParams
.hysteresis
, 0, 255, 3);
508 out
+= sprintf(out
, "threshold_max: %8d %8d %8d %8d\n",
509 cam
->params
.compressionParams
.threshMax
, 0, 255, 11);
510 out
+= sprintf(out
, "small_step: %8d %8d %8d %8d\n",
511 cam
->params
.compressionParams
.smallStep
, 0, 255, 1);
512 out
+= sprintf(out
, "large_step: %8d %8d %8d %8d\n",
513 cam
->params
.compressionParams
.largeStep
, 0, 255, 3);
514 out
+= sprintf(out
, "decimation_hysteresis: %8d %8d %8d %8d\n",
515 cam
->params
.compressionParams
.decimationHysteresis
,
517 out
+= sprintf(out
, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
518 cam
->params
.compressionParams
.frDiffStepThresh
,
520 out
+= sprintf(out
, "q_diff_step_thresh: %8d %8d %8d %8d\n",
521 cam
->params
.compressionParams
.qDiffStepThresh
,
523 out
+= sprintf(out
, "decimation_thresh_mod: %8d %8d %8d %8d\n",
524 cam
->params
.compressionParams
.decimationThreshMod
,
531 if (len
<= 0) return 0;
539 static int cpia_write_proc(struct file
*file
, const char *buffer
,
540 unsigned long count
, void *data
)
542 struct cam_data
*cam
= data
;
543 struct cam_params new_params
;
544 int retval
, find_colon
;
547 u32 command_flags
= 0;
550 if (down_interruptible(&cam
->param_lock
))
554 * Skip over leading whitespace
556 while (count
&& isspace(*buffer
)) {
561 memcpy(&new_params
, &cam
->params
, sizeof(struct cam_params
));
562 new_mains
= cam
->mainsFreq
;
566 int _len = strlen(x), _ret, _colon_found; \
567 _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
573 while (count && (*buffer == ' ' || *buffer == '\t' || \
574 (!_colon_found && *buffer == ':'))) { \
575 if (*buffer == ':') \
580 if (!count || !_colon_found) \
587 #define FIRMWARE_VERSION(x,y) (new_params.version.firmwareVersion == (x) && \
588 new_params.version.firmwareRevision == (y))
592 unsigned long int _ret; \
593 _ret = simple_strtoul(buffer, &_p, 0); \
597 count -= _p - buffer; \
604 while (count
&& !retval
) {
606 if (MATCH("brightness")) {
612 new_params
.colourParams
.brightness
= val
;
616 command_flags
|= COMMAND_SETCOLOURPARAMS
;
617 } else if (MATCH("contrast")) {
623 /* contrast is in steps of 8, so round*/
624 val
= ((val
+ 3) / 8) * 8;
625 /* 1-02 firmware limits contrast to 80*/
626 if (FIRMWARE_VERSION(1,2) && val
> 80)
629 new_params
.colourParams
.contrast
= val
;
633 command_flags
|= COMMAND_SETCOLOURPARAMS
;
634 } else if (MATCH("saturation")) {
640 new_params
.colourParams
.saturation
= val
;
644 command_flags
|= COMMAND_SETCOLOURPARAMS
;
645 } else if (MATCH("sensor_fps")) {
650 /* find values so that sensorFPS is minimized,
655 new_params
.sensorFps
.divisor
= 0;
656 new_params
.sensorFps
.baserate
= 1;
657 } else if (val
> 15) {
658 new_params
.sensorFps
.divisor
= 0;
659 new_params
.sensorFps
.baserate
= 0;
660 } else if (val
> 12) {
661 new_params
.sensorFps
.divisor
= 1;
662 new_params
.sensorFps
.baserate
= 1;
663 } else if (val
> 7) {
664 new_params
.sensorFps
.divisor
= 1;
665 new_params
.sensorFps
.baserate
= 0;
666 } else if (val
> 6) {
667 new_params
.sensorFps
.divisor
= 2;
668 new_params
.sensorFps
.baserate
= 1;
669 } else if (val
> 3) {
670 new_params
.sensorFps
.divisor
= 2;
671 new_params
.sensorFps
.baserate
= 0;
673 new_params
.sensorFps
.divisor
= 3;
674 /* Either base rate would work here */
675 new_params
.sensorFps
.baserate
= 1;
677 new_params
.flickerControl
.coarseJump
=
678 flicker_jumps
[new_mains
]
679 [new_params
.sensorFps
.baserate
]
680 [new_params
.sensorFps
.divisor
];
681 if (new_params
.flickerControl
.flickerMode
)
682 command_flags
|= COMMAND_SETFLICKERCTRL
;
684 command_flags
|= COMMAND_SETSENSORFPS
;
685 } else if (MATCH("stream_start_line")) {
692 if (new_params
.format
.videoSize
== VIDEOSIZE_QCIF
)
695 new_params
.streamStartLine
= val
/2;
699 } else if (MATCH("ecp_timing")) {
700 if (!retval
&& MATCH("normal"))
701 new_params
.ecpTiming
= 0;
702 else if (!retval
&& MATCH("slow"))
703 new_params
.ecpTiming
= 1;
707 command_flags
|= COMMAND_SETECPTIMING
;
708 } else if (MATCH("color_balance_mode")) {
709 if (!retval
&& MATCH("manual"))
710 new_params
.colourBalance
.balanceModeIsAuto
= 0;
711 else if (!retval
&& MATCH("auto"))
712 new_params
.colourBalance
.balanceModeIsAuto
= 1;
716 command_flags
|= COMMAND_SETCOLOURBALANCE
;
717 } else if (MATCH("red_gain")) {
723 new_params
.colourBalance
.redGain
= val
;
727 command_flags
|= COMMAND_SETCOLOURBALANCE
;
728 } else if (MATCH("green_gain")) {
734 new_params
.colourBalance
.greenGain
= val
;
738 command_flags
|= COMMAND_SETCOLOURBALANCE
;
739 } else if (MATCH("blue_gain")) {
745 new_params
.colourBalance
.blueGain
= val
;
749 command_flags
|= COMMAND_SETCOLOURBALANCE
;
750 } else if (MATCH("max_gain")) {
755 /* 1-02 firmware limits gain to 2 */
756 if (FIRMWARE_VERSION(1,2) && val
> 2)
760 new_params
.exposure
.gainMode
= 1;
763 new_params
.exposure
.gainMode
= 2;
766 new_params
.exposure
.gainMode
= 3;
769 new_params
.exposure
.gainMode
= 4;
776 command_flags
|= COMMAND_SETEXPOSURE
;
777 } else if (MATCH("exposure_mode")) {
778 if (!retval
&& MATCH("auto"))
779 new_params
.exposure
.expMode
= 2;
780 else if (!retval
&& MATCH("manual")) {
781 if (new_params
.exposure
.expMode
== 2)
782 new_params
.exposure
.expMode
= 3;
783 new_params
.flickerControl
.flickerMode
= 0;
784 command_flags
|= COMMAND_SETFLICKERCTRL
;
788 command_flags
|= COMMAND_SETEXPOSURE
;
789 } else if (MATCH("centre_weight")) {
790 if (!retval
&& MATCH("on"))
791 new_params
.exposure
.centreWeight
= 1;
792 else if (!retval
&& MATCH("off"))
793 new_params
.exposure
.centreWeight
= 2;
797 command_flags
|= COMMAND_SETEXPOSURE
;
798 } else if (MATCH("gain")) {
805 new_params
.exposure
.gain
= 0;
806 new_params
.exposure
.expMode
= 1;
807 new_params
.flickerControl
.flickerMode
= 0;
808 command_flags
|= COMMAND_SETFLICKERCTRL
;
811 new_params
.exposure
.gain
= 1;
812 new_params
.exposure
.expMode
= 1;
813 new_params
.flickerControl
.flickerMode
= 0;
814 command_flags
|= COMMAND_SETFLICKERCTRL
;
817 new_params
.exposure
.gain
= 2;
818 new_params
.exposure
.expMode
= 1;
819 new_params
.flickerControl
.flickerMode
= 0;
820 command_flags
|= COMMAND_SETFLICKERCTRL
;
823 new_params
.exposure
.gain
= 3;
824 new_params
.exposure
.expMode
= 1;
825 new_params
.flickerControl
.flickerMode
= 0;
826 command_flags
|= COMMAND_SETFLICKERCTRL
;
832 command_flags
|= COMMAND_SETEXPOSURE
;
833 if (new_params
.exposure
.gain
>
834 new_params
.exposure
.gainMode
-1)
837 } else if (MATCH("fine_exp")) {
843 /* 1-02 firmware limits fineExp to 127*/
844 if (FIRMWARE_VERSION(1,2) && val
> 127)
846 new_params
.exposure
.fineExp
= val
;
847 new_params
.exposure
.expMode
= 1;
848 command_flags
|= COMMAND_SETEXPOSURE
;
849 new_params
.flickerControl
.flickerMode
= 0;
850 command_flags
|= COMMAND_SETFLICKERCTRL
;
854 } else if (MATCH("coarse_exp")) {
860 /* 1-02 firmware limits
861 * coarseExp to 255 */
862 if (FIRMWARE_VERSION(1,2) && val
> 255)
864 new_params
.exposure
.coarseExpLo
=
866 new_params
.exposure
.coarseExpHi
=
868 new_params
.exposure
.expMode
= 1;
869 command_flags
|= COMMAND_SETEXPOSURE
;
870 new_params
.flickerControl
.flickerMode
= 0;
871 command_flags
|= COMMAND_SETFLICKERCTRL
;
875 } else if (MATCH("red_comp")) {
880 if (val
>= 220 && val
<= 255) {
881 new_params
.exposure
.redComp
= val
;
882 command_flags
|= COMMAND_SETEXPOSURE
;
886 } else if (MATCH("green1_comp")) {
891 if (val
>= 214 && val
<= 255) {
892 new_params
.exposure
.green1Comp
= val
;
893 command_flags
|= COMMAND_SETEXPOSURE
;
897 } else if (MATCH("green2_comp")) {
902 if (val
>= 214 && val
<= 255) {
903 new_params
.exposure
.green2Comp
= val
;
904 command_flags
|= COMMAND_SETEXPOSURE
;
908 } else if (MATCH("blue_comp")) {
913 if (val
>= 230 && val
<= 255) {
914 new_params
.exposure
.blueComp
= val
;
915 command_flags
|= COMMAND_SETEXPOSURE
;
919 } else if (MATCH("apcor_gain1")) {
924 command_flags
|= COMMAND_SETAPCOR
;
926 new_params
.apcor
.gain1
= val
;
930 } else if (MATCH("apcor_gain2")) {
935 command_flags
|= COMMAND_SETAPCOR
;
937 new_params
.apcor
.gain2
= val
;
941 } else if (MATCH("apcor_gain4")) {
946 command_flags
|= COMMAND_SETAPCOR
;
948 new_params
.apcor
.gain4
= val
;
952 } else if (MATCH("apcor_gain8")) {
957 command_flags
|= COMMAND_SETAPCOR
;
959 new_params
.apcor
.gain8
= val
;
963 } else if (MATCH("vl_offset_gain1")) {
969 new_params
.vlOffset
.gain1
= val
;
973 command_flags
|= COMMAND_SETVLOFFSET
;
974 } else if (MATCH("vl_offset_gain2")) {
980 new_params
.vlOffset
.gain2
= val
;
984 command_flags
|= COMMAND_SETVLOFFSET
;
985 } else if (MATCH("vl_offset_gain4")) {
991 new_params
.vlOffset
.gain4
= val
;
995 command_flags
|= COMMAND_SETVLOFFSET
;
996 } else if (MATCH("vl_offset_gain8")) {
1002 new_params
.vlOffset
.gain8
= val
;
1006 command_flags
|= COMMAND_SETVLOFFSET
;
1007 } else if (MATCH("flicker_control")) {
1008 if (!retval
&& MATCH("on")) {
1009 new_params
.flickerControl
.flickerMode
= 1;
1010 new_params
.exposure
.expMode
= 2;
1011 command_flags
|= COMMAND_SETEXPOSURE
;
1012 } else if (!retval
&& MATCH("off"))
1013 new_params
.flickerControl
.flickerMode
= 0;
1017 command_flags
|= COMMAND_SETFLICKERCTRL
;
1018 } else if (MATCH("mains_frequency")) {
1019 if (!retval
&& MATCH("50")) {
1021 new_params
.flickerControl
.coarseJump
=
1022 flicker_jumps
[new_mains
]
1023 [new_params
.sensorFps
.baserate
]
1024 [new_params
.sensorFps
.divisor
];
1025 if (new_params
.flickerControl
.flickerMode
)
1026 command_flags
|= COMMAND_SETFLICKERCTRL
;
1027 } else if (!retval
&& MATCH("60")) {
1029 new_params
.flickerControl
.coarseJump
=
1030 flicker_jumps
[new_mains
]
1031 [new_params
.sensorFps
.baserate
]
1032 [new_params
.sensorFps
.divisor
];
1033 if (new_params
.flickerControl
.flickerMode
)
1034 command_flags
|= COMMAND_SETFLICKERCTRL
;
1037 } else if (MATCH("allowable_overexposure")) {
1043 new_params
.flickerControl
.
1044 allowableOverExposure
= val
;
1045 command_flags
|= COMMAND_SETFLICKERCTRL
;
1049 } else if (MATCH("compression_mode")) {
1050 if (!retval
&& MATCH("none"))
1051 new_params
.compression
.mode
=
1052 CPIA_COMPRESSION_NONE
;
1053 else if (!retval
&& MATCH("auto"))
1054 new_params
.compression
.mode
=
1055 CPIA_COMPRESSION_AUTO
;
1056 else if (!retval
&& MATCH("manual"))
1057 new_params
.compression
.mode
=
1058 CPIA_COMPRESSION_MANUAL
;
1062 command_flags
|= COMMAND_SETCOMPRESSION
;
1063 } else if (MATCH("decimation_enable")) {
1064 if (!retval
&& MATCH("off"))
1065 new_params
.compression
.decimation
= 0;
1069 command_flags
|= COMMAND_SETCOMPRESSION
;
1070 } else if (MATCH("compression_target")) {
1071 if (!retval
&& MATCH("quality"))
1072 new_params
.compressionTarget
.frTargeting
=
1073 CPIA_COMPRESSION_TARGET_QUALITY
;
1074 else if (!retval
&& MATCH("framerate"))
1075 new_params
.compressionTarget
.frTargeting
=
1076 CPIA_COMPRESSION_TARGET_FRAMERATE
;
1080 command_flags
|= COMMAND_SETCOMPRESSIONTARGET
;
1081 } else if (MATCH("target_framerate")) {
1086 new_params
.compressionTarget
.targetFR
= val
;
1087 command_flags
|= COMMAND_SETCOMPRESSIONTARGET
;
1088 } else if (MATCH("target_quality")) {
1093 new_params
.compressionTarget
.targetQ
= val
;
1095 command_flags
|= COMMAND_SETCOMPRESSIONTARGET
;
1096 } else if (MATCH("y_threshold")) {
1102 new_params
.yuvThreshold
.yThreshold
= val
;
1106 command_flags
|= COMMAND_SETYUVTHRESH
;
1107 } else if (MATCH("uv_threshold")) {
1113 new_params
.yuvThreshold
.uvThreshold
= val
;
1117 command_flags
|= COMMAND_SETYUVTHRESH
;
1118 } else if (MATCH("hysteresis")) {
1124 new_params
.compressionParams
.hysteresis
= val
;
1128 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1129 } else if (MATCH("threshold_max")) {
1135 new_params
.compressionParams
.threshMax
= val
;
1139 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1140 } else if (MATCH("small_step")) {
1146 new_params
.compressionParams
.smallStep
= val
;
1150 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1151 } else if (MATCH("large_step")) {
1157 new_params
.compressionParams
.largeStep
= val
;
1161 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1162 } else if (MATCH("decimation_hysteresis")) {
1168 new_params
.compressionParams
.decimationHysteresis
= val
;
1172 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1173 } else if (MATCH("fr_diff_step_thresh")) {
1179 new_params
.compressionParams
.frDiffStepThresh
= val
;
1183 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1184 } else if (MATCH("q_diff_step_thresh")) {
1190 new_params
.compressionParams
.qDiffStepThresh
= val
;
1194 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1195 } else if (MATCH("decimation_thresh_mod")) {
1201 new_params
.compressionParams
.decimationThreshMod
= val
;
1205 command_flags
|= COMMAND_SETCOMPRESSIONPARAMS
;
1207 DBG("No match found\n");
1212 while (count
&& isspace(*buffer
) && *buffer
!= '\n') {
1217 if (*buffer
!= '\n' && *buffer
!= ';')
1227 #undef FIRMWARE_VERSION
1232 if (command_flags
& COMMAND_SETCOLOURPARAMS
) {
1233 /* Adjust cam->vp to reflect these changes */
1234 cam
->vp
.brightness
=
1235 new_params
.colourParams
.brightness
*65535/100;
1237 new_params
.colourParams
.contrast
*65535/100;
1239 new_params
.colourParams
.saturation
*65535/100;
1242 memcpy(&cam
->params
, &new_params
, sizeof(struct cam_params
));
1243 cam
->mainsFreq
= new_mains
;
1244 cam
->cmd_queue
|= command_flags
;
1247 DBG("error: %d\n", retval
);
1249 up(&cam
->param_lock
);
1254 static void create_proc_cpia_cam(struct cam_data
*cam
)
1257 struct proc_dir_entry
*ent
;
1259 if (!cpia_proc_root
|| !cam
)
1262 sprintf(name
, "video%d", cam
->vdev
.minor
);
1264 ent
= create_proc_entry(name
, S_IFREG
|S_IRUGO
|S_IWUSR
, cpia_proc_root
);
1269 ent
->read_proc
= cpia_read_proc
;
1270 ent
->write_proc
= cpia_write_proc
;
1272 cam
->proc_entry
= ent
;
1275 static void destroy_proc_cpia_cam(struct cam_data
*cam
)
1279 if (!cam
|| !cam
->proc_entry
)
1282 sprintf(name
, "video%d", cam
->vdev
.minor
);
1283 remove_proc_entry(name
, cpia_proc_root
);
1284 cam
->proc_entry
= NULL
;
1287 static void proc_cpia_create(void)
1289 cpia_proc_root
= create_proc_entry("cpia", S_IFDIR
, 0);
1292 cpia_proc_root
->owner
= THIS_MODULE
;
1294 LOG("Unable to initialise /proc/cpia\n");
1297 static void proc_cpia_destroy(void)
1299 remove_proc_entry("cpia", 0);
1301 #endif /* CONFIG_PROC_FS */
1303 /* ----------------------- debug functions ---------------------- */
1305 #define printstatus(cam) \
1306 DBG("%02x %02x %02x %02x %02x %02x %02x %02x\n",\
1307 cam->params.status.systemState, cam->params.status.grabState, \
1308 cam->params.status.streamState, cam->params.status.fatalError, \
1309 cam->params.status.cmdError, cam->params.status.debugFlags, \
1310 cam->params.status.vpStatus, cam->params.status.errorCode);
1312 /* ----------------------- v4l helpers -------------------------- */
1314 /* supported frame palettes and depths */
1315 static inline int valid_mode(u16 palette
, u16 depth
)
1317 return (palette
== VIDEO_PALETTE_GREY
&& depth
== 8) ||
1318 (palette
== VIDEO_PALETTE_RGB555
&& depth
== 16) ||
1319 (palette
== VIDEO_PALETTE_RGB565
&& depth
== 16) ||
1320 (palette
== VIDEO_PALETTE_RGB24
&& depth
== 24) ||
1321 (palette
== VIDEO_PALETTE_RGB32
&& depth
== 32) ||
1322 (palette
== VIDEO_PALETTE_YUV422
&& depth
== 16) ||
1323 (palette
== VIDEO_PALETTE_YUYV
&& depth
== 16) ||
1324 (palette
== VIDEO_PALETTE_UYVY
&& depth
== 16);
1327 static int match_videosize( int width
, int height
)
1329 /* return the best match, where 'best' is as always
1330 * the largest that is not bigger than what is requested. */
1331 if (width
>=352 && height
>=288)
1332 return VIDEOSIZE_352_288
; /* CIF */
1334 if (width
>=320 && height
>=240)
1335 return VIDEOSIZE_320_240
; /* SIF */
1337 if (width
>=288 && height
>=216)
1338 return VIDEOSIZE_288_216
;
1340 if (width
>=256 && height
>=192)
1341 return VIDEOSIZE_256_192
;
1343 if (width
>=224 && height
>=168)
1344 return VIDEOSIZE_224_168
;
1346 if (width
>=192 && height
>=144)
1347 return VIDEOSIZE_192_144
;
1349 if (width
>=176 && height
>=144)
1350 return VIDEOSIZE_176_144
; /* QCIF */
1352 if (width
>=160 && height
>=120)
1353 return VIDEOSIZE_160_120
; /* QSIF */
1355 if (width
>=128 && height
>=96)
1356 return VIDEOSIZE_128_96
;
1358 if (width
>=88 && height
>=72)
1359 return VIDEOSIZE_88_72
;
1361 if (width
>=64 && height
>=48)
1362 return VIDEOSIZE_64_48
;
1364 if (width
>=48 && height
>=48)
1365 return VIDEOSIZE_48_48
;
1370 /* these are the capture sizes we support */
1371 static void set_vw_size(struct cam_data
*cam
)
1373 /* the col/row/start/end values are the result of simple math */
1374 /* study the SetROI-command in cpia developers guide p 2-22 */
1375 /* streamStartLine is set to the recommended value in the cpia */
1376 /* developers guide p 3-37 */
1377 switch(cam
->video_size
) {
1379 cam
->vw
.width
= 352;
1380 cam
->vw
.height
= 288;
1381 cam
->params
.format
.videoSize
=VIDEOSIZE_CIF
;
1382 cam
->params
.roi
.colStart
=0;
1383 cam
->params
.roi
.colEnd
=44;
1384 cam
->params
.roi
.rowStart
=0;
1385 cam
->params
.roi
.rowEnd
=72;
1386 cam
->params
.streamStartLine
= 120;
1389 cam
->vw
.width
= 320;
1390 cam
->vw
.height
= 240;
1391 cam
->params
.format
.videoSize
=VIDEOSIZE_CIF
;
1392 cam
->params
.roi
.colStart
=2;
1393 cam
->params
.roi
.colEnd
=42;
1394 cam
->params
.roi
.rowStart
=6;
1395 cam
->params
.roi
.rowEnd
=66;
1396 cam
->params
.streamStartLine
= 120;
1398 case VIDEOSIZE_288_216
:
1399 cam
->vw
.width
= 288;
1400 cam
->vw
.height
= 216;
1401 cam
->params
.format
.videoSize
=VIDEOSIZE_CIF
;
1402 cam
->params
.roi
.colStart
=4;
1403 cam
->params
.roi
.colEnd
=40;
1404 cam
->params
.roi
.rowStart
=9;
1405 cam
->params
.roi
.rowEnd
=63;
1406 cam
->params
.streamStartLine
= 120;
1408 case VIDEOSIZE_256_192
:
1409 cam
->vw
.width
= 256;
1410 cam
->vw
.height
= 192;
1411 cam
->params
.format
.videoSize
=VIDEOSIZE_CIF
;
1412 cam
->params
.roi
.colStart
=6;
1413 cam
->params
.roi
.colEnd
=38;
1414 cam
->params
.roi
.rowStart
=12;
1415 cam
->params
.roi
.rowEnd
=60;
1416 cam
->params
.streamStartLine
= 120;
1418 case VIDEOSIZE_224_168
:
1419 cam
->vw
.width
= 224;
1420 cam
->vw
.height
= 168;
1421 cam
->params
.format
.videoSize
=VIDEOSIZE_CIF
;
1422 cam
->params
.roi
.colStart
=8;
1423 cam
->params
.roi
.colEnd
=36;
1424 cam
->params
.roi
.rowStart
=15;
1425 cam
->params
.roi
.rowEnd
=57;
1426 cam
->params
.streamStartLine
= 120;
1428 case VIDEOSIZE_192_144
:
1429 cam
->vw
.width
= 192;
1430 cam
->vw
.height
= 144;
1431 cam
->params
.format
.videoSize
=VIDEOSIZE_CIF
;
1432 cam
->params
.roi
.colStart
=10;
1433 cam
->params
.roi
.colEnd
=34;
1434 cam
->params
.roi
.rowStart
=18;
1435 cam
->params
.roi
.rowEnd
=54;
1436 cam
->params
.streamStartLine
= 120;
1438 case VIDEOSIZE_QCIF
:
1439 cam
->vw
.width
= 176;
1440 cam
->vw
.height
= 144;
1441 cam
->params
.format
.videoSize
=VIDEOSIZE_QCIF
;
1442 cam
->params
.roi
.colStart
=0;
1443 cam
->params
.roi
.colEnd
=22;
1444 cam
->params
.roi
.rowStart
=0;
1445 cam
->params
.roi
.rowEnd
=36;
1446 cam
->params
.streamStartLine
= 60;
1448 case VIDEOSIZE_QSIF
:
1449 cam
->vw
.width
= 160;
1450 cam
->vw
.height
= 120;
1451 cam
->params
.format
.videoSize
=VIDEOSIZE_QCIF
;
1452 cam
->params
.roi
.colStart
=1;
1453 cam
->params
.roi
.colEnd
=21;
1454 cam
->params
.roi
.rowStart
=3;
1455 cam
->params
.roi
.rowEnd
=33;
1456 cam
->params
.streamStartLine
= 60;
1458 case VIDEOSIZE_128_96
:
1459 cam
->vw
.width
= 128;
1460 cam
->vw
.height
= 96;
1461 cam
->params
.format
.videoSize
=VIDEOSIZE_QCIF
;
1462 cam
->params
.roi
.colStart
=3;
1463 cam
->params
.roi
.colEnd
=19;
1464 cam
->params
.roi
.rowStart
=6;
1465 cam
->params
.roi
.rowEnd
=30;
1466 cam
->params
.streamStartLine
= 60;
1468 case VIDEOSIZE_88_72
:
1470 cam
->vw
.height
= 72;
1471 cam
->params
.format
.videoSize
=VIDEOSIZE_QCIF
;
1472 cam
->params
.roi
.colStart
=5;
1473 cam
->params
.roi
.colEnd
=16;
1474 cam
->params
.roi
.rowStart
=9;
1475 cam
->params
.roi
.rowEnd
=27;
1476 cam
->params
.streamStartLine
= 60;
1478 case VIDEOSIZE_64_48
:
1480 cam
->vw
.height
= 48;
1481 cam
->params
.format
.videoSize
=VIDEOSIZE_QCIF
;
1482 cam
->params
.roi
.colStart
=7;
1483 cam
->params
.roi
.colEnd
=15;
1484 cam
->params
.roi
.rowStart
=12;
1485 cam
->params
.roi
.rowEnd
=24;
1486 cam
->params
.streamStartLine
= 60;
1488 case VIDEOSIZE_48_48
:
1490 cam
->vw
.height
= 48;
1491 cam
->params
.format
.videoSize
=VIDEOSIZE_QCIF
;
1492 cam
->params
.roi
.colStart
=8;
1493 cam
->params
.roi
.colEnd
=14;
1494 cam
->params
.roi
.rowStart
=6;
1495 cam
->params
.roi
.rowEnd
=30;
1496 cam
->params
.streamStartLine
= 60;
1499 LOG("bad videosize value: %d\n", cam
->video_size
);
1505 static int allocate_frame_buf(struct cam_data
*cam
)
1509 cam
->frame_buf
= rvmalloc(FRAME_NUM
* CPIA_MAX_FRAME_SIZE
);
1510 if (!cam
->frame_buf
)
1513 for (i
= 0; i
< FRAME_NUM
; i
++)
1514 cam
->frame
[i
].data
= cam
->frame_buf
+ i
* CPIA_MAX_FRAME_SIZE
;
1519 static int free_frame_buf(struct cam_data
*cam
)
1523 rvfree(cam
->frame_buf
, FRAME_NUM
*CPIA_MAX_FRAME_SIZE
);
1525 for (i
=0; i
< FRAME_NUM
; i
++)
1526 cam
->frame
[i
].data
= NULL
;
1532 static void inline free_frames(struct cpia_frame frame
[FRAME_NUM
])
1536 for (i
=0; i
< FRAME_NUM
; i
++)
1537 frame
[i
].state
= FRAME_UNUSED
;
1541 /**********************************************************************
1545 **********************************************************************/
1546 /* send an arbitrary command to the camera */
1547 static int do_command(struct cam_data
*cam
, u16 command
, u8 a
, u8 b
, u8 c
, u8 d
)
1549 int retval
, datasize
;
1553 case CPIA_COMMAND_GetCPIAVersion
:
1554 case CPIA_COMMAND_GetPnPID
:
1555 case CPIA_COMMAND_GetCameraStatus
:
1556 case CPIA_COMMAND_GetVPVersion
:
1559 case CPIA_COMMAND_GetColourParams
:
1560 case CPIA_COMMAND_GetColourBalance
:
1561 case CPIA_COMMAND_GetExposure
:
1562 down(&cam
->param_lock
);
1570 cmd
[0] = command
>>8;
1571 cmd
[1] = command
&0xff;
1579 retval
= cam
->ops
->transferCmd(cam
->lowlevel_data
, cmd
, data
);
1581 DBG("%x - failed, retval=%d\n", command
, retval
);
1582 if (command
== CPIA_COMMAND_GetColourParams
||
1583 command
== CPIA_COMMAND_GetColourBalance
||
1584 command
== CPIA_COMMAND_GetExposure
)
1585 up(&cam
->param_lock
);
1588 case CPIA_COMMAND_GetCPIAVersion
:
1589 cam
->params
.version
.firmwareVersion
= data
[0];
1590 cam
->params
.version
.firmwareRevision
= data
[1];
1591 cam
->params
.version
.vcVersion
= data
[2];
1592 cam
->params
.version
.vcRevision
= data
[3];
1594 case CPIA_COMMAND_GetPnPID
:
1595 cam
->params
.pnpID
.vendor
= data
[0]+(((u16
)data
[1])<<8);
1596 cam
->params
.pnpID
.product
= data
[2]+(((u16
)data
[3])<<8);
1597 cam
->params
.pnpID
.deviceRevision
=
1598 data
[4]+(((u16
)data
[5])<<8);
1600 case CPIA_COMMAND_GetCameraStatus
:
1601 cam
->params
.status
.systemState
= data
[0];
1602 cam
->params
.status
.grabState
= data
[1];
1603 cam
->params
.status
.streamState
= data
[2];
1604 cam
->params
.status
.fatalError
= data
[3];
1605 cam
->params
.status
.cmdError
= data
[4];
1606 cam
->params
.status
.debugFlags
= data
[5];
1607 cam
->params
.status
.vpStatus
= data
[6];
1608 cam
->params
.status
.errorCode
= data
[7];
1610 case CPIA_COMMAND_GetVPVersion
:
1611 cam
->params
.vpVersion
.vpVersion
= data
[0];
1612 cam
->params
.vpVersion
.vpRevision
= data
[1];
1613 cam
->params
.vpVersion
.cameraHeadID
=
1614 data
[2]+(((u16
)data
[3])<<8);
1616 case CPIA_COMMAND_GetColourParams
:
1617 cam
->params
.colourParams
.brightness
= data
[0];
1618 cam
->params
.colourParams
.contrast
= data
[1];
1619 cam
->params
.colourParams
.saturation
= data
[2];
1620 up(&cam
->param_lock
);
1622 case CPIA_COMMAND_GetColourBalance
:
1623 cam
->params
.colourBalance
.redGain
= data
[0];
1624 cam
->params
.colourBalance
.greenGain
= data
[1];
1625 cam
->params
.colourBalance
.blueGain
= data
[2];
1626 up(&cam
->param_lock
);
1628 case CPIA_COMMAND_GetExposure
:
1629 cam
->params
.exposure
.gain
= data
[0];
1630 cam
->params
.exposure
.fineExp
= data
[1];
1631 cam
->params
.exposure
.coarseExpLo
= data
[2];
1632 cam
->params
.exposure
.coarseExpHi
= data
[3];
1633 cam
->params
.exposure
.redComp
= data
[4];
1634 cam
->params
.exposure
.green1Comp
= data
[5];
1635 cam
->params
.exposure
.green2Comp
= data
[6];
1636 cam
->params
.exposure
.blueComp
= data
[7];
1637 /* If the *Comp parameters are wacko, generate
1638 * a warning, and reset them back to default
1639 * values. - rich@annexia.org
1641 if (cam
->params
.exposure
.redComp
< 220 ||
1642 cam
->params
.exposure
.redComp
> 255 ||
1643 cam
->params
.exposure
.green1Comp
< 214 ||
1644 cam
->params
.exposure
.green1Comp
> 255 ||
1645 cam
->params
.exposure
.green2Comp
< 214 ||
1646 cam
->params
.exposure
.green2Comp
> 255 ||
1647 cam
->params
.exposure
.blueComp
< 230 ||
1648 cam
->params
.exposure
.blueComp
> 255)
1650 printk (KERN_WARNING
"*_comp parameters have gone AWOL (%d/%d/%d/%d) - reseting them\n",
1651 cam
->params
.exposure
.redComp
,
1652 cam
->params
.exposure
.green1Comp
,
1653 cam
->params
.exposure
.green2Comp
,
1654 cam
->params
.exposure
.blueComp
);
1655 cam
->params
.exposure
.redComp
= 220;
1656 cam
->params
.exposure
.green1Comp
= 214;
1657 cam
->params
.exposure
.green2Comp
= 214;
1658 cam
->params
.exposure
.blueComp
= 230;
1660 up(&cam
->param_lock
);
1669 /* send a command to the camera with an additional data transaction */
1670 static int do_command_extended(struct cam_data
*cam
, u16 command
,
1671 u8 a
, u8 b
, u8 c
, u8 d
,
1672 u8 e
, u8 f
, u8 g
, u8 h
,
1673 u8 i
, u8 j
, u8 k
, u8 l
)
1678 cmd
[0] = command
>>8;
1679 cmd
[1] = command
&0xff;
1695 retval
= cam
->ops
->transferCmd(cam
->lowlevel_data
, cmd
, data
);
1697 LOG("%x - failed\n", command
);
1702 /**********************************************************************
1704 * Colorspace conversion
1706 **********************************************************************/
1707 #define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
1709 static int yuvconvert(unsigned char *yuv
, unsigned char *rgb
, int out_fmt
,
1710 int in_uyvy
, int mmap_kludge
)
1712 int y
, u
, v
, r
, g
, b
, y1
;
1715 case VIDEO_PALETTE_RGB555
:
1716 case VIDEO_PALETTE_RGB565
:
1717 case VIDEO_PALETTE_RGB24
:
1718 case VIDEO_PALETTE_RGB32
:
1721 y
= (*yuv
++ - 16) * 76310;
1723 y1
= (*yuv
- 16) * 76310;
1725 y
= (*yuv
++ - 16) * 76310;
1727 y1
= (*yuv
++ - 16) * 76310;
1731 g
= -25690 * u
+ -53294 * v
;
1739 /* Just to avoid compiler warnings */
1746 case VIDEO_PALETTE_RGB555
:
1747 *rgb
++ = ((LIMIT(g
+y
) & 0xf8) << 2) | (LIMIT(b
+y
) >> 3);
1748 *rgb
++ = ((LIMIT(r
+y
) & 0xf8) >> 1) | (LIMIT(g
+y
) >> 6);
1749 *rgb
++ = ((LIMIT(g
+y1
) & 0xf8) << 2) | (LIMIT(b
+y1
) >> 3);
1750 *rgb
= ((LIMIT(r
+y1
) & 0xf8) >> 1) | (LIMIT(g
+y1
) >> 6);
1752 case VIDEO_PALETTE_RGB565
:
1753 *rgb
++ = ((LIMIT(g
+y
) & 0xfc) << 3) | (LIMIT(b
+y
) >> 3);
1754 *rgb
++ = (LIMIT(r
+y
) & 0xf8) | (LIMIT(g
+y
) >> 5);
1755 *rgb
++ = ((LIMIT(g
+y1
) & 0xfc) << 3) | (LIMIT(b
+y1
) >> 3);
1756 *rgb
= (LIMIT(r
+y1
) & 0xf8) | (LIMIT(g
+y1
) >> 5);
1758 case VIDEO_PALETTE_RGB24
:
1760 *rgb
++ = LIMIT(b
+y
);
1761 *rgb
++ = LIMIT(g
+y
);
1762 *rgb
++ = LIMIT(r
+y
);
1763 *rgb
++ = LIMIT(b
+y1
);
1764 *rgb
++ = LIMIT(g
+y1
);
1767 *rgb
++ = LIMIT(r
+y
);
1768 *rgb
++ = LIMIT(g
+y
);
1769 *rgb
++ = LIMIT(b
+y
);
1770 *rgb
++ = LIMIT(r
+y1
);
1771 *rgb
++ = LIMIT(g
+y1
);
1775 case VIDEO_PALETTE_RGB32
:
1777 *rgb
++ = LIMIT(b
+y
);
1778 *rgb
++ = LIMIT(g
+y
);
1779 *rgb
++ = LIMIT(r
+y
);
1781 *rgb
++ = LIMIT(b
+y1
);
1782 *rgb
++ = LIMIT(g
+y1
);
1785 *rgb
++ = LIMIT(r
+y
);
1786 *rgb
++ = LIMIT(g
+y
);
1787 *rgb
++ = LIMIT(b
+y
);
1789 *rgb
++ = LIMIT(r
+y1
);
1790 *rgb
++ = LIMIT(g
+y1
);
1794 case VIDEO_PALETTE_GREY
:
1798 case VIDEO_PALETTE_YUV422
:
1799 case VIDEO_PALETTE_YUYV
:
1805 case VIDEO_PALETTE_UYVY
:
1812 DBG("Empty: %d\n", out_fmt
);
1817 static int skipcount(int count
, int fmt
)
1820 case VIDEO_PALETTE_GREY
:
1821 case VIDEO_PALETTE_RGB555
:
1822 case VIDEO_PALETTE_RGB565
:
1823 case VIDEO_PALETTE_YUV422
:
1824 case VIDEO_PALETTE_YUYV
:
1825 case VIDEO_PALETTE_UYVY
:
1827 case VIDEO_PALETTE_RGB24
:
1829 case VIDEO_PALETTE_RGB32
:
1836 static int parse_picture(struct cam_data
*cam
, int size
)
1838 u8
*obuf
, *ibuf
, *end_obuf
;
1839 int ll
, in_uyvy
, compressed
, origsize
, out_fmt
;
1841 /* make sure params don't change while we are decoding */
1842 down(&cam
->param_lock
);
1844 obuf
= cam
->decompressed_frame
.data
;
1845 end_obuf
= obuf
+CPIA_MAX_FRAME_SIZE
;
1846 ibuf
= cam
->raw_image
;
1848 out_fmt
= cam
->vp
.palette
;
1850 if ((ibuf
[0] != MAGIC_0
) || (ibuf
[1] != MAGIC_1
)) {
1851 LOG("header not found\n");
1852 up(&cam
->param_lock
);
1856 if ((ibuf
[16] != VIDEOSIZE_QCIF
) && (ibuf
[16] != VIDEOSIZE_CIF
)) {
1857 LOG("wrong video size\n");
1858 up(&cam
->param_lock
);
1862 if (ibuf
[17] != SUBSAMPLE_422
) {
1863 LOG("illegal subtype %d\n",ibuf
[17]);
1864 up(&cam
->param_lock
);
1868 if (ibuf
[18] != YUVORDER_YUYV
&& ibuf
[18] != YUVORDER_UYVY
) {
1869 LOG("illegal yuvorder %d\n",ibuf
[18]);
1870 up(&cam
->param_lock
);
1873 in_uyvy
= ibuf
[18] == YUVORDER_UYVY
;
1876 /* FIXME: ROI mismatch occurs when switching capture sizes */
1877 if ((ibuf
[24] != cam
->params
.roi
.colStart
) ||
1878 (ibuf
[25] != cam
->params
.roi
.colEnd
) ||
1879 (ibuf
[26] != cam
->params
.roi
.rowStart
) ||
1880 (ibuf
[27] != cam
->params
.roi
.rowEnd
)) {
1881 LOG("ROI mismatch\n");
1882 up(&cam
->param_lock
);
1887 if ((ibuf
[28] != NOT_COMPRESSED
) && (ibuf
[28] != COMPRESSED
)) {
1888 LOG("illegal compression %d\n",ibuf
[28]);
1889 up(&cam
->param_lock
);
1892 compressed
= (ibuf
[28] == COMPRESSED
);
1894 if (ibuf
[29] != NO_DECIMATION
) {
1895 LOG("decimation not supported\n");
1896 up(&cam
->param_lock
);
1900 cam
->params
.yuvThreshold
.yThreshold
= ibuf
[30];
1901 cam
->params
.yuvThreshold
.uvThreshold
= ibuf
[31];
1902 cam
->params
.status
.systemState
= ibuf
[32];
1903 cam
->params
.status
.grabState
= ibuf
[33];
1904 cam
->params
.status
.streamState
= ibuf
[34];
1905 cam
->params
.status
.fatalError
= ibuf
[35];
1906 cam
->params
.status
.cmdError
= ibuf
[36];
1907 cam
->params
.status
.debugFlags
= ibuf
[37];
1908 cam
->params
.status
.vpStatus
= ibuf
[38];
1909 cam
->params
.status
.errorCode
= ibuf
[39];
1910 cam
->fps
= ibuf
[41];
1911 up(&cam
->param_lock
);
1913 ibuf
+= FRAME_HEADER_SIZE
;
1914 size
-= FRAME_HEADER_SIZE
;
1915 ll
= ibuf
[0] | (ibuf
[1] << 8);
1921 LOG("Insufficient data in buffer\n");
1926 if (!compressed
|| (compressed
&& !(*ibuf
& 1))) {
1927 obuf
+= yuvconvert(ibuf
, obuf
, out_fmt
,
1928 in_uyvy
, cam
->mmap_kludge
);
1932 /*skip compressed interval from previous frame*/
1933 int skipsize
= skipcount(*ibuf
>> 1, out_fmt
);
1935 if (obuf
> end_obuf
) {
1936 LOG("Insufficient data in buffer\n");
1945 LOG("EOL not found giving up after %d/%d"
1946 " bytes\n", origsize
-size
, origsize
);
1950 ibuf
++; /* skip over EOL */
1952 if ((size
> 3) && (ibuf
[0] == EOI
) && (ibuf
[1] == EOI
) &&
1953 (ibuf
[2] == EOI
) && (ibuf
[3] == EOI
)) {
1959 ll
= ibuf
[0] | (ibuf
[1] << 8);
1960 ibuf
+= 2; /* skip over line length */
1963 LOG("line length was not 1 but %d after %d/%d bytes\n",
1964 ll
, origsize
-size
, origsize
);
1969 cam
->decompressed_frame
.count
= obuf
-cam
->decompressed_frame
.data
;
1971 return cam
->decompressed_frame
.count
;
1974 /* InitStreamCap wrapper to select correct start line */
1975 static inline int init_stream_cap(struct cam_data
*cam
)
1977 return do_command(cam
, CPIA_COMMAND_InitStreamCap
,
1978 0, cam
->params
.streamStartLine
, 0, 0);
1981 /* update various camera modes and settings */
1982 static void dispatch_commands(struct cam_data
*cam
)
1984 down(&cam
->param_lock
);
1985 if (cam
->cmd_queue
==COMMAND_NONE
) {
1986 up(&cam
->param_lock
);
1989 DEB_BYTE(cam
->cmd_queue
);
1990 DEB_BYTE(cam
->cmd_queue
>>8);
1991 if (cam
->cmd_queue
& COMMAND_SETCOLOURPARAMS
)
1992 do_command(cam
, CPIA_COMMAND_SetColourParams
,
1993 cam
->params
.colourParams
.brightness
,
1994 cam
->params
.colourParams
.contrast
,
1995 cam
->params
.colourParams
.saturation
, 0);
1997 if (cam
->cmd_queue
& COMMAND_SETCOMPRESSION
)
1998 do_command(cam
, CPIA_COMMAND_SetCompression
,
1999 cam
->params
.compression
.mode
,
2000 cam
->params
.compression
.decimation
, 0, 0);
2002 if (cam
->cmd_queue
& COMMAND_SETFORMAT
) {
2003 do_command(cam
, CPIA_COMMAND_SetFormat
,
2004 cam
->params
.format
.videoSize
,
2005 cam
->params
.format
.subSample
,
2006 cam
->params
.format
.yuvOrder
, 0);
2007 do_command(cam
, CPIA_COMMAND_SetROI
,
2008 cam
->params
.roi
.colStart
, cam
->params
.roi
.colEnd
,
2009 cam
->params
.roi
.rowStart
, cam
->params
.roi
.rowEnd
);
2010 cam
->first_frame
= 1;
2013 if (cam
->cmd_queue
& COMMAND_SETCOMPRESSIONTARGET
)
2014 do_command(cam
, CPIA_COMMAND_SetCompressionTarget
,
2015 cam
->params
.compressionTarget
.frTargeting
,
2016 cam
->params
.compressionTarget
.targetFR
,
2017 cam
->params
.compressionTarget
.targetQ
, 0);
2019 if (cam
->cmd_queue
& COMMAND_SETYUVTHRESH
)
2020 do_command(cam
, CPIA_COMMAND_SetYUVThresh
,
2021 cam
->params
.yuvThreshold
.yThreshold
,
2022 cam
->params
.yuvThreshold
.uvThreshold
, 0, 0);
2024 if (cam
->cmd_queue
& COMMAND_SETECPTIMING
)
2025 do_command(cam
, CPIA_COMMAND_SetECPTiming
,
2026 cam
->params
.ecpTiming
, 0, 0, 0);
2028 if (cam
->cmd_queue
& COMMAND_SETCOMPRESSIONPARAMS
)
2029 do_command_extended(cam
, CPIA_COMMAND_SetCompressionParams
,
2031 cam
->params
.compressionParams
.hysteresis
,
2032 cam
->params
.compressionParams
.threshMax
,
2033 cam
->params
.compressionParams
.smallStep
,
2034 cam
->params
.compressionParams
.largeStep
,
2035 cam
->params
.compressionParams
.decimationHysteresis
,
2036 cam
->params
.compressionParams
.frDiffStepThresh
,
2037 cam
->params
.compressionParams
.qDiffStepThresh
,
2038 cam
->params
.compressionParams
.decimationThreshMod
);
2040 if (cam
->cmd_queue
& COMMAND_SETEXPOSURE
)
2041 do_command_extended(cam
, CPIA_COMMAND_SetExposure
,
2042 cam
->params
.exposure
.gainMode
,
2043 cam
->params
.exposure
.expMode
,
2044 cam
->params
.exposure
.compMode
,
2045 cam
->params
.exposure
.centreWeight
,
2046 cam
->params
.exposure
.gain
,
2047 cam
->params
.exposure
.fineExp
,
2048 cam
->params
.exposure
.coarseExpLo
,
2049 cam
->params
.exposure
.coarseExpHi
,
2050 cam
->params
.exposure
.redComp
,
2051 cam
->params
.exposure
.green1Comp
,
2052 cam
->params
.exposure
.green2Comp
,
2053 cam
->params
.exposure
.blueComp
);
2055 if (cam
->cmd_queue
& COMMAND_SETCOLOURBALANCE
) {
2056 if (cam
->params
.colourBalance
.balanceModeIsAuto
) {
2057 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2060 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2062 cam
->params
.colourBalance
.redGain
,
2063 cam
->params
.colourBalance
.greenGain
,
2064 cam
->params
.colourBalance
.blueGain
);
2065 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2070 if (cam
->cmd_queue
& COMMAND_SETSENSORFPS
)
2071 do_command(cam
, CPIA_COMMAND_SetSensorFPS
,
2072 cam
->params
.sensorFps
.divisor
,
2073 cam
->params
.sensorFps
.baserate
, 0, 0);
2075 if (cam
->cmd_queue
& COMMAND_SETAPCOR
)
2076 do_command(cam
, CPIA_COMMAND_SetApcor
,
2077 cam
->params
.apcor
.gain1
,
2078 cam
->params
.apcor
.gain2
,
2079 cam
->params
.apcor
.gain4
,
2080 cam
->params
.apcor
.gain8
);
2082 if (cam
->cmd_queue
& COMMAND_SETFLICKERCTRL
)
2083 do_command(cam
, CPIA_COMMAND_SetFlickerCtrl
,
2084 cam
->params
.flickerControl
.flickerMode
,
2085 cam
->params
.flickerControl
.coarseJump
,
2086 cam
->params
.flickerControl
.allowableOverExposure
, 0);
2088 if (cam
->cmd_queue
& COMMAND_SETVLOFFSET
)
2089 do_command(cam
, CPIA_COMMAND_SetVLOffset
,
2090 cam
->params
.vlOffset
.gain1
,
2091 cam
->params
.vlOffset
.gain2
,
2092 cam
->params
.vlOffset
.gain4
,
2093 cam
->params
.vlOffset
.gain8
);
2095 if (cam
->cmd_queue
& COMMAND_PAUSE
)
2096 do_command(cam
, CPIA_COMMAND_EndStreamCap
, 0, 0, 0, 0);
2098 if (cam
->cmd_queue
& COMMAND_RESUME
)
2099 init_stream_cap(cam
);
2101 up(&cam
->param_lock
);
2102 cam
->cmd_queue
= COMMAND_NONE
;
2106 /* kernel thread function to read image from camera */
2107 static void fetch_frame(void *data
)
2109 int image_size
, retry
;
2110 struct cam_data
*cam
= (struct cam_data
*)data
;
2111 unsigned long oldjif
, rate
, diff
;
2113 /* Allow up to two bad images in a row to be read and
2114 * ignored before an error is reported */
2115 for (retry
= 0; retry
< 3; ++retry
) {
2117 DBG("retry=%d\n", retry
);
2122 /* load first frame always uncompressed */
2123 if (cam
->first_frame
&&
2124 cam
->params
.compression
.mode
!= CPIA_COMPRESSION_NONE
)
2125 do_command(cam
, CPIA_COMMAND_SetCompression
,
2126 CPIA_COMPRESSION_NONE
,
2127 NO_DECIMATION
, 0, 0);
2129 /* init camera upload */
2130 if (do_command(cam
, CPIA_COMMAND_SetGrabMode
,
2131 CPIA_GRAB_CONTINUOUS
, 0, 0, 0))
2134 if (do_command(cam
, CPIA_COMMAND_GrabFrame
, 0,
2135 cam
->params
.streamStartLine
, 0, 0))
2138 if (cam
->ops
->wait_for_stream_ready
) {
2139 /* loop until image ready */
2140 do_command(cam
, CPIA_COMMAND_GetCameraStatus
,0,0,0,0);
2141 while (cam
->params
.status
.streamState
!= STREAM_READY
) {
2142 if (current
->need_resched
)
2145 current
->state
= TASK_INTERRUPTIBLE
;
2147 /* sleep for 10 ms, hopefully ;) */
2148 schedule_timeout(10*HZ
/1000);
2149 if (signal_pending(current
))
2152 do_command(cam
, CPIA_COMMAND_GetCameraStatus
,
2157 /* grab image from camera */
2158 if (current
->need_resched
)
2162 image_size
= cam
->ops
->streamRead(cam
->lowlevel_data
,
2164 if (image_size
<= 0) {
2165 DBG("streamRead failed: %d\n", image_size
);
2169 rate
= image_size
* HZ
/ 1024;
2170 diff
= jiffies
-oldjif
;
2171 cam
->transfer_rate
= diff
==0 ? rate
: rate
/diff
;
2172 /* diff==0 ? unlikely but possible */
2174 /* camera idle now so dispatch queued commands */
2175 dispatch_commands(cam
);
2177 /* Update our knowledge of the camera state - FIXME: necessary? */
2178 do_command(cam
, CPIA_COMMAND_GetColourBalance
, 0, 0, 0, 0);
2179 do_command(cam
, CPIA_COMMAND_GetExposure
, 0, 0, 0, 0);
2181 /* decompress and convert image to by copying it from
2182 * raw_image to decompressed_frame
2184 if (current
->need_resched
)
2187 cam
->image_size
= parse_picture(cam
, image_size
);
2188 if (cam
->image_size
<= 0)
2189 DBG("parse_picture failed %d\n", cam
->image_size
);
2195 /* FIXME: this only works for double buffering */
2196 if (cam
->frame
[cam
->curframe
].state
== FRAME_READY
) {
2197 memcpy(cam
->frame
[cam
->curframe
].data
,
2198 cam
->decompressed_frame
.data
,
2199 cam
->decompressed_frame
.count
);
2200 cam
->frame
[cam
->curframe
].state
= FRAME_DONE
;
2202 cam
->decompressed_frame
.state
= FRAME_DONE
;
2205 if (cam
->first_frame
&&
2206 cam
->params
.compression
.mode
!= CPIA_COMPRESSION_NONE
) {
2207 cam
->first_frame
= 0;
2208 cam
->cmd_queue
|= COMMAND_SETCOMPRESSION
;
2211 if (cam
->first_frame
) {
2212 cam
->first_frame
= 0;
2213 cam
->cmd_queue
|= COMMAND_SETCOMPRESSION
;
2214 cam
->cmd_queue
|= COMMAND_SETEXPOSURE
;
2220 static int capture_frame(struct cam_data
*cam
, struct video_mmap
*vm
)
2224 if (!cam
->frame_buf
) {
2225 /* we do lazy allocation */
2226 if ((retval
= allocate_frame_buf(cam
)))
2230 /* FIXME: the first frame seems to be captured by the camera
2231 without regards to any initial settings, so we throw away
2232 that one, the next one is generated with our settings
2233 (exposure, color balance, ...)
2235 if (cam
->first_frame
) {
2236 cam
->curframe
= vm
->frame
;
2237 cam
->frame
[cam
->curframe
].state
= FRAME_READY
;
2239 if (cam
->frame
[cam
->curframe
].state
!= FRAME_DONE
)
2242 cam
->curframe
= vm
->frame
;
2243 cam
->frame
[cam
->curframe
].state
= FRAME_READY
;
2245 if (cam
->frame
[cam
->curframe
].state
!= FRAME_DONE
)
2251 static int goto_high_power(struct cam_data
*cam
)
2253 if (do_command(cam
, CPIA_COMMAND_GotoHiPower
, 0, 0, 0, 0))
2255 mdelay(100); /* windows driver does it too */
2256 if (do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0))
2258 if (cam
->params
.status
.systemState
== HI_POWER_STATE
) {
2259 DBG("camera now in HIGH power state\n");
2266 static int goto_low_power(struct cam_data
*cam
)
2268 if (do_command(cam
, CPIA_COMMAND_GotoLoPower
, 0, 0, 0, 0))
2270 if (do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0))
2272 if (cam
->params
.status
.systemState
== LO_POWER_STATE
) {
2273 DBG("camera now in LOW power state\n");
2280 static void save_camera_state(struct cam_data
*cam
)
2282 do_command(cam
, CPIA_COMMAND_GetColourBalance
, 0, 0, 0, 0);
2283 do_command(cam
, CPIA_COMMAND_GetExposure
, 0, 0, 0, 0);
2285 DBG("%d/%d/%d/%d/%d/%d/%d/%d\n",
2286 cam
->params
.exposure
.gain
,
2287 cam
->params
.exposure
.fineExp
,
2288 cam
->params
.exposure
.coarseExpLo
,
2289 cam
->params
.exposure
.coarseExpHi
,
2290 cam
->params
.exposure
.redComp
,
2291 cam
->params
.exposure
.green1Comp
,
2292 cam
->params
.exposure
.green2Comp
,
2293 cam
->params
.exposure
.blueComp
);
2295 cam
->params
.colourBalance
.redGain
,
2296 cam
->params
.colourBalance
.greenGain
,
2297 cam
->params
.colourBalance
.blueGain
);
2300 static void set_camera_state(struct cam_data
*cam
)
2302 if(cam
->params
.colourBalance
.balanceModeIsAuto
) {
2303 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2306 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2308 cam
->params
.colourBalance
.redGain
,
2309 cam
->params
.colourBalance
.greenGain
,
2310 cam
->params
.colourBalance
.blueGain
);
2311 do_command(cam
, CPIA_COMMAND_SetColourBalance
,
2316 do_command_extended(cam
, CPIA_COMMAND_SetExposure
,
2317 cam
->params
.exposure
.gainMode
, 1, 1,
2318 cam
->params
.exposure
.centreWeight
,
2319 cam
->params
.exposure
.gain
,
2320 cam
->params
.exposure
.fineExp
,
2321 cam
->params
.exposure
.coarseExpLo
,
2322 cam
->params
.exposure
.coarseExpHi
,
2323 cam
->params
.exposure
.redComp
,
2324 cam
->params
.exposure
.green1Comp
,
2325 cam
->params
.exposure
.green2Comp
,
2326 cam
->params
.exposure
.blueComp
);
2327 do_command_extended(cam
, CPIA_COMMAND_SetExposure
,
2329 0, 0, 0, 0, 0, 0, 0, 0);
2331 if (!cam
->params
.exposure
.gainMode
)
2332 cam
->params
.exposure
.gainMode
= 2;
2333 if (!cam
->params
.exposure
.expMode
)
2334 cam
->params
.exposure
.expMode
= 2;
2335 if (!cam
->params
.exposure
.centreWeight
)
2336 cam
->params
.exposure
.centreWeight
= 1;
2338 cam
->cmd_queue
= COMMAND_SETCOMPRESSION
|
2339 COMMAND_SETCOMPRESSIONTARGET
|
2340 COMMAND_SETCOLOURPARAMS
|
2342 COMMAND_SETYUVTHRESH
|
2343 COMMAND_SETECPTIMING
|
2344 COMMAND_SETCOMPRESSIONPARAMS
|
2346 COMMAND_SETEXPOSURE
|
2348 COMMAND_SETCOLOURBALANCE
|
2349 COMMAND_SETSENSORFPS
|
2351 COMMAND_SETFLICKERCTRL
|
2352 COMMAND_SETVLOFFSET
;
2353 dispatch_commands(cam
);
2354 save_camera_state(cam
);
2359 static void get_version_information(struct cam_data
*cam
)
2361 /* GetCPIAVersion */
2362 do_command(cam
, CPIA_COMMAND_GetCPIAVersion
, 0, 0, 0, 0);
2365 do_command(cam
, CPIA_COMMAND_GetPnPID
, 0, 0, 0, 0);
2368 /* initialize camera */
2369 static int reset_camera(struct cam_data
*cam
)
2371 /* Start the camera in low power mode */
2372 if (goto_low_power(cam
)) {
2373 if (cam
->params
.status
.systemState
!= WARM_BOOT_STATE
)
2376 /* FIXME: this is just dirty trial and error */
2377 reset_camera_struct(cam
);
2378 goto_high_power(cam
);
2379 do_command(cam
, CPIA_COMMAND_DiscardFrame
, 0, 0, 0, 0);
2380 if (goto_low_power(cam
))
2384 /* procedure described in developer's guide p3-28 */
2386 /* Check the firmware version FIXME: should we check PNPID? */
2387 cam
->params
.version
.firmwareVersion
= 0;
2388 get_version_information(cam
);
2389 if (cam
->params
.version
.firmwareVersion
!= 1)
2392 /* The fatal error checking should be done after
2393 * the camera powers up (developer's guide p 3-38) */
2395 /* Set streamState before transition to high power to avoid bug
2396 * in firmware 1-02 */
2397 do_command(cam
, CPIA_COMMAND_ModifyCameraStatus
, STREAMSTATE
, 0,
2398 STREAM_NOT_READY
, 0);
2401 if (goto_high_power(cam
))
2404 /* Check the camera status */
2405 if (do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0))
2408 if (cam
->params
.status
.fatalError
) {
2409 DBG("fatal_error: %#04x\n",
2410 cam
->params
.status
.fatalError
);
2411 DBG("vp_status: %#04x\n",
2412 cam
->params
.status
.vpStatus
);
2413 if (cam
->params
.status
.fatalError
& ~(COM_FLAG
|CPIA_FLAG
)) {
2414 /* Fatal error in camera */
2416 } else if (cam
->params
.status
.fatalError
& (COM_FLAG
|CPIA_FLAG
)) {
2417 /* Firmware 1-02 may do this for parallel port cameras,
2418 * just clear the flags (developer's guide p 3-38) */
2419 do_command(cam
, CPIA_COMMAND_ModifyCameraStatus
,
2420 FATALERROR
, ~(COM_FLAG
|CPIA_FLAG
), 0, 0);
2424 /* Check the camera status again */
2425 if (cam
->params
.status
.fatalError
) {
2426 if (cam
->params
.status
.fatalError
)
2430 /* VPVersion can't be retrieved before the camera is in HiPower,
2431 * so get it here instead of in get_version_information. */
2432 do_command(cam
, CPIA_COMMAND_GetVPVersion
, 0, 0, 0, 0);
2434 /* set camera to a known state */
2435 set_camera_state(cam
);
2440 /* ------------------------- V4L interface --------------------- */
2441 static int cpia_open(struct video_device
*dev
, int flags
)
2444 struct cam_data
*cam
= dev
->priv
;
2447 DBG("Internal error, cam_data not found!\n");
2451 if (cam
->open_count
> 0) {
2452 DBG("Camera already open\n");
2456 if (!cam
->raw_image
) {
2457 cam
->raw_image
= rvmalloc(CPIA_MAX_IMAGE_SIZE
);
2458 if (!cam
->raw_image
)
2462 if (!cam
->decompressed_frame
.data
) {
2463 cam
->decompressed_frame
.data
= rvmalloc(CPIA_MAX_FRAME_SIZE
);
2464 if (!cam
->decompressed_frame
.data
) {
2465 rvfree(cam
->raw_image
, CPIA_MAX_IMAGE_SIZE
);
2466 cam
->raw_image
= NULL
;
2472 if (cam
->ops
->open(cam
->lowlevel_data
)) {
2473 rvfree(cam
->decompressed_frame
.data
, CPIA_MAX_FRAME_SIZE
);
2474 cam
->decompressed_frame
.data
= NULL
;
2475 rvfree(cam
->raw_image
, CPIA_MAX_IMAGE_SIZE
);
2476 cam
->raw_image
= NULL
;
2480 /* reset the camera */
2481 if ((i
= reset_camera(cam
)) != 0) {
2482 cam
->ops
->close(cam
->lowlevel_data
);
2483 rvfree(cam
->decompressed_frame
.data
, CPIA_MAX_FRAME_SIZE
);
2484 cam
->decompressed_frame
.data
= NULL
;
2485 rvfree(cam
->raw_image
, CPIA_MAX_IMAGE_SIZE
);
2486 cam
->raw_image
= NULL
;
2490 /* Set ownership of /proc/cpia/videoX to current user */
2492 cam
->proc_entry
->uid
= current
->uid
;
2494 /* set mark for loading first frame uncompressed */
2495 cam
->first_frame
= 1;
2497 /* init it to something */
2498 cam
->mmap_kludge
= 0;
2507 static void cpia_close(struct video_device
*dev
)
2509 struct cam_data
*cam
;
2514 /* Return ownership of /proc/cpia/videoX to root */
2516 cam
->proc_entry
->uid
= 0;
2518 /* save camera state for later open (developers guide ch 3.5.3) */
2519 save_camera_state(cam
);
2522 goto_low_power(cam
);
2524 /* Update the camera ststus */
2525 do_command(cam
, CPIA_COMMAND_GetCameraStatus
, 0, 0, 0, 0);
2527 /* cleanup internal state stuff */
2528 free_frames(cam
->frame
);
2531 cam
->ops
->close(cam
->lowlevel_data
);
2534 if (--cam
->open_count
== 0) {
2535 /* clean up capture-buffers */
2536 if (cam
->raw_image
) {
2537 rvfree(cam
->raw_image
, CPIA_MAX_IMAGE_SIZE
);
2538 cam
->raw_image
= NULL
;
2541 if (cam
->decompressed_frame
.data
) {
2542 rvfree(cam
->decompressed_frame
.data
, CPIA_MAX_FRAME_SIZE
);
2543 cam
->decompressed_frame
.data
= NULL
;
2547 free_frame_buf(cam
);
2550 video_unregister_device(dev
);
2562 static long cpia_read(struct video_device
*dev
, char *buf
,
2563 unsigned long count
, int noblock
)
2565 struct cam_data
*cam
= dev
->priv
;
2567 /* make this _really_ smp and multithredi-safe */
2568 if (down_interruptible(&cam
->busy_lock
))
2573 up(&cam
->busy_lock
);
2579 up(&cam
->busy_lock
);
2585 up(&cam
->busy_lock
);
2590 cam
->decompressed_frame
.state
= FRAME_READY
;
2593 if (cam
->decompressed_frame
.state
!= FRAME_DONE
) {
2594 DBG("upload failed %d/%d\n", cam
->decompressed_frame
.count
,
2595 cam
->decompressed_frame
.state
);
2596 up(&cam
->busy_lock
);
2599 cam
->decompressed_frame
.state
= FRAME_UNUSED
;
2601 /* copy data to user space */
2602 if (cam
->decompressed_frame
.count
> count
) {
2603 DBG("count wrong: %d, %lu\n", cam
->decompressed_frame
.count
,
2605 up(&cam
->busy_lock
);
2608 if (copy_to_user(buf
, cam
->decompressed_frame
.data
,
2609 cam
->decompressed_frame
.count
)) {
2610 DBG("copy_to_user failed\n");
2611 up(&cam
->busy_lock
);
2615 up(&cam
->busy_lock
);
2616 return cam
->decompressed_frame
.count
;
2619 static int cpia_ioctl(struct video_device
*dev
, unsigned int ioctlnr
, void *arg
)
2621 struct cam_data
*cam
= dev
->priv
;
2624 if (!cam
|| !cam
->ops
)
2627 /* make this _really_ smp-safe */
2628 if (down_interruptible(&cam
->busy_lock
))
2631 //DBG("cpia_ioctl: %u\n", ioctlnr);
2634 /* query capabilites */
2637 struct video_capability b
;
2639 DBG("VIDIOCGCAP\n");
2640 strcpy(b
.name
, "CPiA Camera");
2641 b
.type
= VID_TYPE_CAPTURE
;
2644 b
.maxwidth
= 352; /* VIDEOSIZE_CIF */
2646 b
.minwidth
= 48; /* VIDEOSIZE_48_48 */
2649 if (copy_to_user(arg
, &b
, sizeof(b
)))
2655 /* get/set video source - we are a camera and nothing else */
2658 struct video_channel v
;
2660 DBG("VIDIOCGCHAN\n");
2661 if (copy_from_user(&v
, arg
, sizeof(v
))) {
2665 if (v
.channel
!= 0) {
2671 strcpy(v
.name
, "Camera");
2674 v
.type
= VIDEO_TYPE_CAMERA
;
2677 if (copy_to_user(arg
, &v
, sizeof(v
)))
2686 DBG("VIDIOCSCHAN\n");
2687 if (copy_from_user(&v
, arg
, sizeof(v
)))
2690 if (retval
== 0 && v
!= 0)
2696 /* image properties */
2698 DBG("VIDIOCGPICT\n");
2699 if (copy_to_user(arg
, &cam
->vp
, sizeof(struct video_picture
)))
2705 struct video_picture vp
;
2707 DBG("VIDIOCSPICT\n");
2709 /* copy_from_user */
2710 if (copy_from_user(&vp
, arg
, sizeof(vp
))) {
2715 /* check validity */
2716 DBG("palette: %d\n", vp
.palette
);
2717 DBG("depth: %d\n", vp
.depth
);
2718 if (!valid_mode(vp
.palette
, vp
.depth
)) {
2723 down(&cam
->param_lock
);
2724 /* brightness, colour, contrast need no check 0-65535 */
2725 memcpy( &cam
->vp
, &vp
, sizeof(vp
) );
2726 /* update cam->params.colourParams */
2727 cam
->params
.colourParams
.brightness
= vp
.brightness
*100/65535;
2728 cam
->params
.colourParams
.contrast
= vp
.contrast
*100/65535;
2729 cam
->params
.colourParams
.saturation
= vp
.colour
*100/65535;
2730 /* contrast is in steps of 8, so round */
2731 cam
->params
.colourParams
.contrast
=
2732 ((cam
->params
.colourParams
.contrast
+ 3) / 8) * 8;
2733 if (cam
->params
.version
.firmwareVersion
== 1 &&
2734 cam
->params
.version
.firmwareRevision
== 2 &&
2735 cam
->params
.colourParams
.contrast
> 80) {
2736 /* 1-02 firmware limits contrast to 80 */
2737 cam
->params
.colourParams
.contrast
= 80;
2740 /* queue command to update camera */
2741 cam
->cmd_queue
|= COMMAND_SETCOLOURPARAMS
;
2742 up(&cam
->param_lock
);
2743 DBG("VIDIOCSPICT: %d / %d // %d / %d / %d / %d\n",
2744 vp
.depth
, vp
.palette
, vp
.brightness
, vp
.hue
, vp
.colour
,
2749 /* get/set capture window */
2751 DBG("VIDIOCGWIN\n");
2753 if (copy_to_user(arg
, &cam
->vw
, sizeof(struct video_window
)))
2759 /* copy_from_user, check validity, copy to internal structure */
2760 struct video_window vw
;
2761 DBG("VIDIOCSWIN\n");
2762 if (copy_from_user(&vw
, arg
, sizeof(vw
))) {
2767 if (vw
.clipcount
!= 0) { /* clipping not supported */
2771 if (vw
.clips
!= NULL
) { /* clipping not supported */
2776 /* we set the video window to something smaller or equal to what
2777 * is requested by the user???
2779 down(&cam
->param_lock
);
2780 if (vw
.width
!= cam
->vw
.width
|| vw
.height
!= cam
->vw
.height
) {
2781 int video_size
= match_videosize(vw
.width
, vw
.height
);
2783 if (video_size
< 0) {
2785 up(&cam
->param_lock
);
2788 cam
->video_size
= video_size
;
2790 DBG("%d / %d\n", cam
->vw
.width
, cam
->vw
.height
);
2791 cam
->cmd_queue
|= COMMAND_SETFORMAT
;
2794 // FIXME needed??? memcpy(&cam->vw, &vw, sizeof(vw));
2795 up(&cam
->param_lock
);
2797 /* setformat ignored by camera during streaming,
2798 * so stop/dispatch/start */
2799 if (cam
->cmd_queue
& COMMAND_SETFORMAT
) {
2801 dispatch_commands(cam
);
2803 DBG("%d/%d:%d\n", cam
->video_size
,
2804 cam
->vw
.width
, cam
->vw
.height
);
2808 /* mmap interface */
2811 struct video_mbuf vm
;
2814 DBG("VIDIOCGMBUF\n");
2815 memset(&vm
, 0, sizeof(vm
));
2816 vm
.size
= CPIA_MAX_FRAME_SIZE
*FRAME_NUM
;
2817 vm
.frames
= FRAME_NUM
;
2818 for (i
= 0; i
< FRAME_NUM
; i
++)
2819 vm
.offsets
[i
] = CPIA_MAX_FRAME_SIZE
* i
;
2821 if (copy_to_user((void *)arg
, (void *)&vm
, sizeof(vm
)))
2827 case VIDIOCMCAPTURE
:
2829 struct video_mmap vm
;
2832 if (copy_from_user((void *)&vm
, (void *)arg
, sizeof(vm
))) {
2837 DBG("VIDIOCMCAPTURE: %d / %d / %dx%d\n", vm
.format
, vm
.frame
,
2838 vm
.width
, vm
.height
);
2840 if (vm
.frame
<0||vm
.frame
>FRAME_NUM
) {
2845 /* set video format */
2846 cam
->vp
.palette
= vm
.format
;
2848 case VIDEO_PALETTE_GREY
:
2849 case VIDEO_PALETTE_RGB555
:
2850 case VIDEO_PALETTE_RGB565
:
2851 case VIDEO_PALETTE_YUV422
:
2852 case VIDEO_PALETTE_YUYV
:
2853 case VIDEO_PALETTE_UYVY
:
2856 case VIDEO_PALETTE_RGB24
:
2859 case VIDEO_PALETTE_RGB32
:
2869 /* set video size */
2870 video_size
= match_videosize(vm
.width
, vm
.height
);
2871 if (cam
->video_size
< 0) {
2875 if (video_size
!= cam
->video_size
) {
2876 cam
->video_size
= video_size
;
2878 cam
->cmd_queue
|= COMMAND_SETFORMAT
;
2879 dispatch_commands(cam
);
2882 DBG("VIDIOCMCAPTURE: %d / %d/%d\n", cam
->video_size
,
2883 cam
->vw
.width
, cam
->vw
.height
);
2885 /* according to v4l-spec we must start streaming here */
2886 cam
->mmap_kludge
= 1;
2887 retval
= capture_frame(cam
, &vm
);
2896 if (copy_from_user((void *)&frame
, arg
, sizeof(int))) {
2900 //DBG("VIDIOCSYNC: %d\n", frame);
2902 if (frame
<0 || frame
>= FRAME_NUM
) {
2907 switch (cam
->frame
[frame
].state
) {
2910 case FRAME_GRABBING
:
2911 DBG("sync to unused frame %d\n", frame
);
2916 cam
->frame
[frame
].state
= FRAME_UNUSED
;
2917 //DBG("VIDIOCSYNC: %d synced\n", frame);
2920 if (retval
== -EINTR
) {
2921 /* FIXME - xawtv does not handle this nice */
2927 /* pointless to implement overlay with this camera */
2941 /* tuner interface - we have none */
2955 /* audio interface - we have none */
2963 retval
= -ENOIOCTLCMD
;
2967 up(&cam
->param_lock
);
2968 up(&cam
->busy_lock
);
2973 static int cpia_mmap(struct video_device
*dev
, const char *adr
,
2976 unsigned long start
= (unsigned long)adr
;
2977 unsigned long page
, pos
;
2978 struct cam_data
*cam
= dev
->priv
;
2981 if (!cam
|| !cam
->ops
)
2984 DBG("cpia_mmap: %ld\n", size
);
2986 if (size
> FRAME_NUM
*CPIA_MAX_FRAME_SIZE
)
2989 if (!cam
|| !cam
->ops
)
2992 /* make this _really_ smp-safe */
2993 if (down_interruptible(&cam
->busy_lock
))
2996 if (!cam
->frame_buf
) { /* we do lazy allocation */
2997 if ((retval
= allocate_frame_buf(cam
))) {
2998 up(&cam
->busy_lock
);
3003 pos
= (unsigned long)(cam
->frame_buf
);
3005 page
= kvirt_to_pa(pos
);
3006 if (remap_page_range(start
, page
, PAGE_SIZE
, PAGE_SHARED
)) {
3007 up(&cam
->busy_lock
);
3012 if (size
> PAGE_SIZE
)
3018 DBG("cpia_mmap: %ld\n", size
);
3019 up(&cam
->busy_lock
);
3024 int cpia_video_init(struct video_device
*vdev
)
3026 #ifdef CONFIG_PROC_FS
3027 create_proc_cpia_cam(vdev
->priv
);
3032 static struct video_device cpia_template
= {
3035 VID_HARDWARE_CPIA
, /* FIXME */
3036 cpia_open
, /* open */
3037 cpia_close
, /* close */
3038 cpia_read
, /* read */
3039 NULL
, /* no write */
3041 cpia_ioctl
, /* ioctl */
3042 cpia_mmap
, /* mmap */
3043 cpia_video_init
, /* initialize */
3046 -1 /* minor - unset */
3049 /* initialise cam_data structure */
3050 static void reset_camera_struct(struct cam_data
*cam
)
3052 /* The following parameter values are the defaults from
3053 * "Software Developer's Guide for CPiA Cameras". Any changes
3054 * to the defaults are noted in comments. */
3055 cam
->params
.colourParams
.brightness
= 50;
3056 cam
->params
.colourParams
.contrast
= 48;
3057 cam
->params
.colourParams
.saturation
= 50;
3058 cam
->params
.exposure
.gainMode
= 2;
3059 cam
->params
.exposure
.expMode
= 2; /* AEC */
3060 cam
->params
.exposure
.compMode
= 1;
3061 cam
->params
.exposure
.centreWeight
= 1;
3062 cam
->params
.exposure
.gain
= 0;
3063 cam
->params
.exposure
.fineExp
= 0;
3064 cam
->params
.exposure
.coarseExpLo
= 185;
3065 cam
->params
.exposure
.coarseExpHi
= 0;
3066 cam
->params
.exposure
.redComp
= 220;
3067 cam
->params
.exposure
.green1Comp
= 214;
3068 cam
->params
.exposure
.green2Comp
= 214;
3069 cam
->params
.exposure
.blueComp
= 230;
3070 cam
->params
.colourBalance
.balanceModeIsAuto
= 1;
3071 cam
->params
.colourBalance
.redGain
= 32;
3072 cam
->params
.colourBalance
.greenGain
= 6;
3073 cam
->params
.colourBalance
.blueGain
= 92;
3074 cam
->params
.apcor
.gain1
= 0x1c;
3075 cam
->params
.apcor
.gain2
= 0x1a;
3076 cam
->params
.apcor
.gain4
= 0x2d;
3077 cam
->params
.apcor
.gain8
= 0x2a;
3078 cam
->params
.flickerControl
.flickerMode
= 0;
3079 cam
->params
.flickerControl
.coarseJump
=
3080 flicker_jumps
[cam
->mainsFreq
]
3081 [cam
->params
.sensorFps
.baserate
]
3082 [cam
->params
.sensorFps
.divisor
];
3083 cam
->params
.vlOffset
.gain1
= 24;
3084 cam
->params
.vlOffset
.gain2
= 28;
3085 cam
->params
.vlOffset
.gain4
= 30;
3086 cam
->params
.vlOffset
.gain8
= 30;
3087 cam
->params
.compressionParams
.hysteresis
= 3;
3088 cam
->params
.compressionParams
.threshMax
= 11;
3089 cam
->params
.compressionParams
.smallStep
= 1;
3090 cam
->params
.compressionParams
.largeStep
= 3;
3091 cam
->params
.compressionParams
.decimationHysteresis
= 2;
3092 cam
->params
.compressionParams
.frDiffStepThresh
= 5;
3093 cam
->params
.compressionParams
.qDiffStepThresh
= 3;
3094 cam
->params
.compressionParams
.decimationThreshMod
= 2;
3095 /* End of default values from Software Developer's Guide */
3097 cam
->transfer_rate
= 0;
3099 /* Set Sensor FPS to 15fps. This seems better than 30fps
3100 * for indoor lighting. */
3101 cam
->params
.sensorFps
.divisor
= 1;
3102 cam
->params
.sensorFps
.baserate
= 1;
3104 cam
->params
.yuvThreshold
.yThreshold
= 15; /* FIXME? */
3105 cam
->params
.yuvThreshold
.uvThreshold
= 15; /* FIXME? */
3107 cam
->params
.format
.subSample
= SUBSAMPLE_422
;
3108 cam
->params
.format
.yuvOrder
= YUVORDER_YUYV
;
3110 cam
->params
.compression
.mode
= CPIA_COMPRESSION_AUTO
;
3111 cam
->params
.compressionTarget
.frTargeting
=
3112 CPIA_COMPRESSION_TARGET_QUALITY
;
3113 cam
->params
.compressionTarget
.targetFR
= 7; /* FIXME? */
3114 cam
->params
.compressionTarget
.targetQ
= 10; /* FIXME? */
3116 cam
->video_size
= VIDEOSIZE_CIF
;
3118 cam
->vp
.colour
= 32768; /* 50% */
3119 cam
->vp
.hue
= 32768; /* 50% */
3120 cam
->vp
.brightness
= 32768; /* 50% */
3121 cam
->vp
.contrast
= 32768; /* 50% */
3122 cam
->vp
.whiteness
= 0; /* not used -> grayscale only */
3123 cam
->vp
.depth
= 0; /* FIXME: to be set by user? */
3124 cam
->vp
.palette
= VIDEO_PALETTE_RGB24
; /* FIXME: to be set by user? */
3129 cam
->vw
.chromakey
= 0;
3130 /* PP NOTE: my extension to use vw.flags for this, bear it! */
3132 cam
->vw
.clipcount
= 0;
3133 cam
->vw
.clips
= NULL
;
3135 cam
->cmd_queue
= COMMAND_NONE
;
3136 cam
->first_frame
= 0;
3141 /* initialize cam_data structure */
3142 static void init_camera_struct(struct cam_data
*cam
,
3143 struct cpia_camera_ops
*ops
)
3147 /* Default everything to 0 */
3148 memset(cam
, 0, sizeof(struct cam_data
));
3151 init_MUTEX(&cam
->param_lock
);
3152 init_MUTEX(&cam
->busy_lock
);
3154 reset_camera_struct(cam
);
3156 cam
->proc_entry
= NULL
;
3158 memcpy(&cam
->vdev
, &cpia_template
, sizeof(cpia_template
));
3159 cam
->vdev
.priv
= cam
;
3162 for (i
= 0; i
< FRAME_NUM
; i
++) {
3163 cam
->frame
[i
].width
= 0;
3164 cam
->frame
[i
].height
= 0;
3165 cam
->frame
[i
].state
= FRAME_UNUSED
;
3166 cam
->frame
[i
].data
= NULL
;
3168 cam
->decompressed_frame
.width
= 0;
3169 cam
->decompressed_frame
.height
= 0;
3170 cam
->decompressed_frame
.state
= FRAME_UNUSED
;
3171 cam
->decompressed_frame
.data
= NULL
;
3174 struct cam_data
*cpia_register_camera(struct cpia_camera_ops
*ops
, void *lowlevel
)
3176 struct cam_data
*camera
;
3178 /* Need a lock when adding/removing cameras. This doesn't happen
3179 * often and doesn't take very long, so grabbing the kernel lock
3182 if ((camera
= kmalloc(sizeof(struct cam_data
), GFP_KERNEL
)) == NULL
) {
3187 init_camera_struct( camera
, ops
);
3188 camera
->lowlevel_data
= lowlevel
;
3190 /* register v4l device */
3191 if (video_register_device(&camera
->vdev
, VFL_TYPE_GRABBER
) == -1) {
3194 printk(KERN_DEBUG
"video_register_device failed\n");
3198 /* get version information from camera: open/reset/close */
3201 if (camera
->ops
->open(camera
->lowlevel_data
))
3204 /* reset the camera */
3205 if (reset_camera(camera
) != 0) {
3206 camera
->ops
->close(camera
->lowlevel_data
);
3211 camera
->ops
->close(camera
->lowlevel_data
);
3213 /* Eh? Feeling happy? - jerdfelt */
3215 camera->ops->open(camera->lowlevel_data);
3216 camera->ops->close(camera->lowlevel_data);
3219 printk(KERN_INFO
" CPiA Version: %d.%02d (%d.%d)\n",
3220 camera
->params
.version
.firmwareVersion
,
3221 camera
->params
.version
.firmwareRevision
,
3222 camera
->params
.version
.vcVersion
,
3223 camera
->params
.version
.vcRevision
);
3224 printk(KERN_INFO
" CPiA PnP-ID: %04x:%04x:%04x\n",
3225 camera
->params
.pnpID
.vendor
,
3226 camera
->params
.pnpID
.product
,
3227 camera
->params
.pnpID
.deviceRevision
);
3228 printk(KERN_INFO
" VP-Version: %d.%d %04x\n",
3229 camera
->params
.vpVersion
.vpVersion
,
3230 camera
->params
.vpVersion
.vpRevision
,
3231 camera
->params
.vpVersion
.cameraHeadID
);
3236 void cpia_unregister_camera(struct cam_data
*cam
)
3238 if (!cam
->open_count
) {
3239 DBG("unregistering video\n");
3240 video_unregister_device(&cam
->vdev
);
3242 LOG("/dev/video%d removed while open, "
3243 "deferring video_unregister_device\n", cam
->vdev
.minor
);
3244 DBG("camera open -- setting ops to NULL\n");
3248 #ifdef CONFIG_PROC_FS
3249 DBG("destroying /proc/cpia/video%d\n", cam
->vdev
.minor
);
3250 destroy_proc_cpia_cam(cam
);
3252 if (!cam
->open_count
) {
3253 DBG("freeing camera\n");
3258 /****************************************************************************
3262 ***************************************************************************/
3265 int init_module(void)
3267 printk(KERN_INFO
"%s v%d.%d.%d\n", ABOUT
,
3268 CPIA_MAJ_VER
, CPIA_MIN_VER
, CPIA_PATCH_VER
);
3269 #ifdef CONFIG_PROC_FS
3273 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
3274 request_module("cpia_pp");
3276 #ifdef CONFIG_VIDEO_CPIA_USB_MODULE
3277 request_module("cpia_usb");
3283 void cleanup_module(void)
3285 #ifdef CONFIG_PROC_FS
3286 proc_cpia_destroy();
3292 int cpia_init(struct video_init
*unused
)
3294 printk(KERN_INFO
"%s v%d.%d.%d\n", ABOUT
,
3295 CPIA_MAJ_VER
, CPIA_MIN_VER
, CPIA_PATCH_VER
);
3296 #ifdef CONFIG_PROC_FS
3300 #ifdef CONFIG_VIDEO_CPIA_PP
3304 #ifdef CONFIG_VIDEO_CPIA_PP_MODULE
3305 request_module("cpia_pp");
3308 #ifdef CONFIG_VIDEO_CPIA_USB_MODULE
3309 request_module("cpia_usb");
3311 #endif /* CONFIG_KMOD */
3312 #ifdef CONFIG_VIDEO_CPIA_USB
3318 /* Exported symbols for modules. */
3320 EXPORT_SYMBOL(cpia_register_camera
);
3321 EXPORT_SYMBOL(cpia_unregister_camera
);