1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
52extern int cpia_pp_init(void);
53#endif
54#ifdef CONFIG_VIDEO_CPIA_USB
55extern int cpia_usb_init(void);
56#endif
57
58static int video_nr = -1;
59
60#ifdef MODULE
61MODULE_PARM(video_nr,"i");
62MODULE_AUTHOR("Scott J. Bertin <sbertin@securenym.net> & Peter Pregler <Peter_Pregler@email.com> & Johannes Erdfelt <johannes@erdfeld.com>");
63MODULE_DESCRIPTION("V4L-driver for Vision CPiA based cameras");
64MODULE_LICENSE("GPL");
65MODULE_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
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
146enum {
147 FRAME_READY,
148 FRAME_GRABBING,
149 FRAME_DONE,
150 FRAME_UNUSED,
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
172
173static 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
179static void reset_camera_struct(struct cam_data *cam);
180
181
182
183
184
185
186
187
188
189
190static 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);
196 ret = __pa(kva);
197 return ret;
198}
199
200static 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);
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
221static 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
240
241
242#ifdef CONFIG_PROC_FS
243static struct proc_dir_entry *cpia_proc_root=NULL;
244
245static 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
254
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
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
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
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
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
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
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
518static 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
544static 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
558static 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
572
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
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
639 val = ((val + 3) / 8) * 8;
640
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
666
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
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
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
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
876
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
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
1284out:
1285 free_page((unsigned long)page);
1286 return retval;
1287}
1288
1289static 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
1308
1309
1310
1311 ent->size = 3672 + 188;
1312 cam->proc_entry = ent;
1313}
1314
1315static 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
1327static 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
1337static void proc_cpia_destroy(void)
1338{
1339 remove_proc_entry("cpia", 0);
1340}
1341#endif
1342
1343
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
1353
1354
1355static 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
1367static int match_videosize( int width, int height )
1368{
1369
1370
1371 if (width>=352 && height>=288)
1372 return VIDEOSIZE_352_288;
1373
1374 if (width>=320 && height>=240)
1375 return VIDEOSIZE_320_240;
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;
1391
1392 if (width>=160 && height>=120)
1393 return VIDEOSIZE_160_120;
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
1411static void set_vw_size(struct cam_data *cam)
1412{
1413
1414
1415
1416
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
1545static 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
1559static 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
1572static 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
1584
1585
1586
1587static 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
1682
1683
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
1707 cam->params.qx3.button = ((data[1] & 0x02) == 0);
1708 if (cam->params.qx3.button) {
1709
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
1715 cam->params.qx3.cradled = ((data[2] & 0x40) == 0);
1716 break;
1717
1718 default:
1719 break;
1720 }
1721 }
1722 return retval;
1723}
1724
1725
1726static 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
1761
1762
1763#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
1764
1765static 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
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
1873static 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
1893static 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
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
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
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++;
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;
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
2032static 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
2039static 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
2171static 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
2178
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
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
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
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
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
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
2237
2238
2239 dispatch_commands(cam);
2240
2241
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
2247
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
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
2285static int capture_frame(struct cam_data *cam, struct video_mmap *vm)
2286{
2287 int retval = 0;
2288
2289 if (!cam->frame_buf) {
2290
2291 if ((retval = allocate_frame_buf(cam)))
2292 return retval;
2293 }
2294
2295
2296
2297
2298
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
2316static 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);
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
2331static 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
2345static 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
2365static 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
2424static void get_version_information(struct cam_data *cam)
2425{
2426
2427 do_command(cam, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
2428
2429
2430 do_command(cam, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
2431}
2432
2433
2434static int reset_camera(struct cam_data *cam)
2435{
2436
2437 if (goto_low_power(cam)) {
2438 if (cam->params.status.systemState != WARM_BOOT_STATE)
2439 return -ENODEV;
2440
2441
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
2450
2451
2452 cam->params.version.firmwareVersion = 0;
2453 get_version_information(cam);
2454 if (cam->params.version.firmwareVersion != 1)
2455 return -ENODEV;
2456
2457
2458 cam->params.qx3.qx3_detected = (cam->params.pnpID.vendor == 0x0813 &&
2459 cam->params.pnpID.product == 0x0001);
2460
2461
2462
2463
2464
2465
2466 do_command(cam, CPIA_COMMAND_ModifyCameraStatus, STREAMSTATE, 0,
2467 STREAM_NOT_READY, 0);
2468
2469
2470 if (goto_high_power(cam))
2471 return -ENODEV;
2472
2473
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
2484 return -EIO;
2485 } else if (cam->params.status.fatalError & (COM_FLAG|CPIA_FLAG)) {
2486
2487
2488 do_command(cam, CPIA_COMMAND_ModifyCameraStatus,
2489 FATALERROR, ~(COM_FLAG|CPIA_FLAG), 0, 0);
2490 }
2491 }
2492
2493
2494 if (cam->params.status.fatalError) {
2495 if (cam->params.status.fatalError)
2496 return -EIO;
2497 }
2498
2499
2500
2501 do_command(cam, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
2502
2503
2504 set_camera_state(cam);
2505
2506 return 0;
2507}
2508
2509static void put_cam(struct cpia_camera_ops* ops)
2510{
2511 if (ops->owner)
2512 __MOD_DEC_USE_COUNT(ops->owner);
2513}
2514
2515
2516static 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
2551 err = -ENODEV;
2552 if (cam->ops->open(cam->lowlevel_data))
2553 goto oops;
2554
2555
2556 if ((err = reset_camera(cam)) != 0) {
2557 cam->ops->close(cam->lowlevel_data);
2558 goto oops;
2559 }
2560
2561
2562 if(cam->proc_entry)
2563 cam->proc_entry->uid = current->uid;
2564
2565
2566 cam->first_frame = 1;
2567
2568
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
2590static 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
2597 if(cam->proc_entry)
2598 cam->proc_entry->uid = 0;
2599
2600
2601 save_camera_state(cam);
2602
2603
2604 goto_low_power(cam);
2605
2606
2607 do_command(cam, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
2608
2609
2610 free_frames(cam->frame);
2611
2612
2613 cam->ops->close(cam->lowlevel_data);
2614 put_cam(cam->ops);
2615 }
2616
2617 if (--cam->open_count == 0) {
2618
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
2641static 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
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
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
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
2699static 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
2710 if (down_interruptible(&cam->busy_lock))
2711 return -EINTR;
2712
2713
2714
2715 switch (ioctlnr) {
2716
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;
2727 b->maxheight = 288;
2728 b->minwidth = 48;
2729 b->minheight = 48;
2730
2731 break;
2732 }
2733
2734
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
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
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
2792 cam->vp = *vp;
2793
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
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
2804 cam->params.colourParams.contrast = 80;
2805 }
2806
2807
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
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
2830 struct video_window *vw = arg;
2831 DBG("VIDIOCSWIN\n");
2832
2833 if (vw->clipcount != 0) {
2834 retval = -EINVAL;
2835 break;
2836 }
2837 if (vw->clips != NULL) {
2838 retval = -EINVAL;
2839 break;
2840 }
2841
2842
2843
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
2863
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
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
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
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
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
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
2968 break;
2969 }
2970 if (retval == -EINTR) {
2971
2972 retval = 0;
2973 }
2974 break;
2975 }
2976
2977
2978 case VIDIOCCAPTURE:
2979 case VIDIOCGFBUF:
2980 case VIDIOCSFBUF:
2981 case VIDIOCKEY:
2982 retval = -EINVAL;
2983 break;
2984
2985
2986 case VIDIOCGTUNER:
2987 case VIDIOCSTUNER:
2988 case VIDIOCGFREQ:
2989 case VIDIOCSFREQ:
2990 retval = -EINVAL;
2991 break;
2992
2993
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
3007static 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
3015static 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
3036 if (down_interruptible(&cam->busy_lock))
3037 return -EINTR;
3038
3039 if (!cam->frame_buf) {
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
3067static 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
3077static 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
3087static void reset_camera_struct(struct cam_data *cam)
3088{
3089
3090
3091
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;
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
3133
3134 cam->transfer_rate = 0;
3135
3136
3137
3138 cam->params.sensorFps.divisor = 1;
3139 cam->params.sensorFps.baserate = 1;
3140
3141 cam->params.yuvThreshold.yThreshold = 6;
3142 cam->params.yuvThreshold.uvThreshold = 6;
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;
3151 cam->params.compressionTarget.targetQ = 5;
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;
3162 cam->vp.hue = 32768;
3163 cam->vp.brightness = 32768;
3164 cam->vp.contrast = 32768;
3165 cam->vp.whiteness = 0;
3166 cam->vp.depth = 24;
3167 cam->vp.palette = VIDEO_PALETTE_RGB24;
3168
3169 cam->vw.x = 0;
3170 cam->vw.y = 0;
3171 set_vw_size(cam);
3172 cam->vw.chromakey = 0;
3173
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
3185static void init_camera_struct(struct cam_data *cam,
3186 struct cpia_camera_ops *ops )
3187{
3188 int i;
3189
3190
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
3217struct 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
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
3235
3236
3237 if (camera->ops->open(camera->lowlevel_data))
3238 return camera;
3239
3240
3241 if (reset_camera(camera) != 0) {
3242 camera->ops->close(camera->lowlevel_data);
3243 return camera;
3244 }
3245
3246
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
3270void 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
3290static 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
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
3317static void __exit cpia_exit(void)
3318{
3319#ifdef CONFIG_PROC_FS
3320 proc_cpia_destroy();
3321#endif
3322}
3323
3324module_init(cpia_init);
3325module_exit(cpia_exit);
3326
3327
3328
3329EXPORT_SYMBOL(cpia_register_camera);
3330EXPORT_SYMBOL(cpia_unregister_camera);
3331