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