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