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