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