cpia1.c (55533B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * cpia CPiA (1) gspca driver 4 * 5 * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> 6 * 7 * This module is adapted from the in kernel v4l1 cpia driver which is : 8 * 9 * (C) Copyright 1999-2000 Peter Pregler 10 * (C) Copyright 1999-2000 Scott J. Bertin 11 * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com> 12 * (C) Copyright 2000 STMicroelectronics 13 */ 14 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 17#define MODULE_NAME "cpia1" 18 19#include <linux/input.h> 20#include <linux/sched/signal.h> 21 22#include "gspca.h" 23 24MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 25MODULE_DESCRIPTION("Vision CPiA"); 26MODULE_LICENSE("GPL"); 27 28/* constant value's */ 29#define MAGIC_0 0x19 30#define MAGIC_1 0x68 31#define DATA_IN 0xc0 32#define DATA_OUT 0x40 33#define VIDEOSIZE_QCIF 0 /* 176x144 */ 34#define VIDEOSIZE_CIF 1 /* 352x288 */ 35#define SUBSAMPLE_420 0 36#define SUBSAMPLE_422 1 37#define YUVORDER_YUYV 0 38#define YUVORDER_UYVY 1 39#define NOT_COMPRESSED 0 40#define COMPRESSED 1 41#define NO_DECIMATION 0 42#define DECIMATION_ENAB 1 43#define EOI 0xff /* End Of Image */ 44#define EOL 0xfd /* End Of Line */ 45#define FRAME_HEADER_SIZE 64 46 47/* Image grab modes */ 48#define CPIA_GRAB_SINGLE 0 49#define CPIA_GRAB_CONTINEOUS 1 50 51/* Compression parameters */ 52#define CPIA_COMPRESSION_NONE 0 53#define CPIA_COMPRESSION_AUTO 1 54#define CPIA_COMPRESSION_MANUAL 2 55#define CPIA_COMPRESSION_TARGET_QUALITY 0 56#define CPIA_COMPRESSION_TARGET_FRAMERATE 1 57 58/* Return offsets for GetCameraState */ 59#define SYSTEMSTATE 0 60#define GRABSTATE 1 61#define STREAMSTATE 2 62#define FATALERROR 3 63#define CMDERROR 4 64#define DEBUGFLAGS 5 65#define VPSTATUS 6 66#define ERRORCODE 7 67 68/* SystemState */ 69#define UNINITIALISED_STATE 0 70#define PASS_THROUGH_STATE 1 71#define LO_POWER_STATE 2 72#define HI_POWER_STATE 3 73#define WARM_BOOT_STATE 4 74 75/* GrabState */ 76#define GRAB_IDLE 0 77#define GRAB_ACTIVE 1 78#define GRAB_DONE 2 79 80/* StreamState */ 81#define STREAM_NOT_READY 0 82#define STREAM_READY 1 83#define STREAM_OPEN 2 84#define STREAM_PAUSED 3 85#define STREAM_FINISHED 4 86 87/* Fatal Error, CmdError, and DebugFlags */ 88#define CPIA_FLAG 1 89#define SYSTEM_FLAG 2 90#define INT_CTRL_FLAG 4 91#define PROCESS_FLAG 8 92#define COM_FLAG 16 93#define VP_CTRL_FLAG 32 94#define CAPTURE_FLAG 64 95#define DEBUG_FLAG 128 96 97/* VPStatus */ 98#define VP_STATE_OK 0x00 99 100#define VP_STATE_FAILED_VIDEOINIT 0x01 101#define VP_STATE_FAILED_AECACBINIT 0x02 102#define VP_STATE_AEC_MAX 0x04 103#define VP_STATE_ACB_BMAX 0x08 104 105#define VP_STATE_ACB_RMIN 0x10 106#define VP_STATE_ACB_GMIN 0x20 107#define VP_STATE_ACB_RMAX 0x40 108#define VP_STATE_ACB_GMAX 0x80 109 110/* default (minimum) compensation values */ 111#define COMP_RED 220 112#define COMP_GREEN1 214 113#define COMP_GREEN2 COMP_GREEN1 114#define COMP_BLUE 230 115 116/* exposure status */ 117#define EXPOSURE_VERY_LIGHT 0 118#define EXPOSURE_LIGHT 1 119#define EXPOSURE_NORMAL 2 120#define EXPOSURE_DARK 3 121#define EXPOSURE_VERY_DARK 4 122 123#define CPIA_MODULE_CPIA (0 << 5) 124#define CPIA_MODULE_SYSTEM (1 << 5) 125#define CPIA_MODULE_VP_CTRL (5 << 5) 126#define CPIA_MODULE_CAPTURE (6 << 5) 127#define CPIA_MODULE_DEBUG (7 << 5) 128 129#define INPUT (DATA_IN << 8) 130#define OUTPUT (DATA_OUT << 8) 131 132#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) 133#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) 134#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) 135#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) 136#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) 137#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) 138#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) 139#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) 140 141#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) 142#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) 143#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) 144#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) 145#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) 146#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) 147#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) 148#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) 149#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) 150#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) 151#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) 152#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) 153#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) 154 155#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) 156#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2) 157#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) 158#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) 159#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) 160#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) 161#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) 162#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) 163#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) 164#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) 165#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) 166#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) 167#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) 168#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) 169#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) 170#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) 171#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) 172 173#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) 174#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) 175#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) 176#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) 177#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) 178#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) 179#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) 180#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) 181#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) 182#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) 183#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) 184#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) 185#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) 186#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) 187#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15) 188 189#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) 190#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) 191#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) 192#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) 193#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) 194#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) 195#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) 196#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11) 197 198#define ROUND_UP_EXP_FOR_FLICKER 15 199 200/* Constants for automatic frame rate adjustment */ 201#define MAX_EXP 302 202#define MAX_EXP_102 255 203#define LOW_EXP 140 204#define VERY_LOW_EXP 70 205#define TC 94 206#define EXP_ACC_DARK 50 207#define EXP_ACC_LIGHT 90 208#define HIGH_COMP_102 160 209#define MAX_COMP 239 210#define DARK_TIME 3 211#define LIGHT_TIME 3 212 213#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \ 214 sd->params.version.firmwareRevision == (y)) 215 216#define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000) 217#define BRIGHTNESS_DEF 50 218#define CONTRAST_DEF 48 219#define SATURATION_DEF 50 220#define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ 221#define ILLUMINATORS_1_DEF 0 222#define ILLUMINATORS_2_DEF 0 223#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY 224 225/* Developer's Guide Table 5 p 3-34 226 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ 227static u8 flicker_jumps[2][2][4] = 228{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, 229 { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } 230}; 231 232struct cam_params { 233 struct { 234 u8 firmwareVersion; 235 u8 firmwareRevision; 236 u8 vcVersion; 237 u8 vcRevision; 238 } version; 239 struct { 240 u16 vendor; 241 u16 product; 242 u16 deviceRevision; 243 } pnpID; 244 struct { 245 u8 vpVersion; 246 u8 vpRevision; 247 u16 cameraHeadID; 248 } vpVersion; 249 struct { 250 u8 systemState; 251 u8 grabState; 252 u8 streamState; 253 u8 fatalError; 254 u8 cmdError; 255 u8 debugFlags; 256 u8 vpStatus; 257 u8 errorCode; 258 } status; 259 struct { 260 u8 brightness; 261 u8 contrast; 262 u8 saturation; 263 } colourParams; 264 struct { 265 u8 gainMode; 266 u8 expMode; 267 u8 compMode; 268 u8 centreWeight; 269 u8 gain; 270 u8 fineExp; 271 u8 coarseExpLo; 272 u8 coarseExpHi; 273 u8 redComp; 274 u8 green1Comp; 275 u8 green2Comp; 276 u8 blueComp; 277 } exposure; 278 struct { 279 u8 balanceMode; 280 u8 redGain; 281 u8 greenGain; 282 u8 blueGain; 283 } colourBalance; 284 struct { 285 u8 divisor; 286 u8 baserate; 287 } sensorFps; 288 struct { 289 u8 gain1; 290 u8 gain2; 291 u8 gain4; 292 u8 gain8; 293 } apcor; 294 struct { 295 u8 disabled; 296 u8 flickerMode; 297 u8 coarseJump; 298 u8 allowableOverExposure; 299 } flickerControl; 300 struct { 301 u8 gain1; 302 u8 gain2; 303 u8 gain4; 304 u8 gain8; 305 } vlOffset; 306 struct { 307 u8 mode; 308 u8 decimation; 309 } compression; 310 struct { 311 u8 frTargeting; 312 u8 targetFR; 313 u8 targetQ; 314 } compressionTarget; 315 struct { 316 u8 yThreshold; 317 u8 uvThreshold; 318 } yuvThreshold; 319 struct { 320 u8 hysteresis; 321 u8 threshMax; 322 u8 smallStep; 323 u8 largeStep; 324 u8 decimationHysteresis; 325 u8 frDiffStepThresh; 326 u8 qDiffStepThresh; 327 u8 decimationThreshMod; 328 } compressionParams; 329 struct { 330 u8 videoSize; /* CIF/QCIF */ 331 u8 subSample; 332 u8 yuvOrder; 333 } format; 334 struct { /* Intel QX3 specific data */ 335 u8 qx3_detected; /* a QX3 is present */ 336 u8 toplight; /* top light lit , R/W */ 337 u8 bottomlight; /* bottom light lit, R/W */ 338 u8 button; /* snapshot button pressed (R/O) */ 339 u8 cradled; /* microscope is in cradle (R/O) */ 340 } qx3; 341 struct { 342 u8 colStart; /* skip first 8*colStart pixels */ 343 u8 colEnd; /* finish at 8*colEnd pixels */ 344 u8 rowStart; /* skip first 4*rowStart lines */ 345 u8 rowEnd; /* finish at 4*rowEnd lines */ 346 } roi; 347 u8 ecpTiming; 348 u8 streamStartLine; 349}; 350 351/* specific webcam descriptor */ 352struct sd { 353 struct gspca_dev gspca_dev; /* !! must be the first item */ 354 struct cam_params params; /* camera settings */ 355 356 atomic_t cam_exposure; 357 atomic_t fps; 358 int exposure_count; 359 u8 exposure_status; 360 struct v4l2_ctrl *freq; 361 u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */ 362 u8 first_frame; 363}; 364 365static const struct v4l2_pix_format mode[] = { 366 {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, 367 /* The sizeimage is trial and error, as with low framerates 368 * the camera will pad out usb frames, making the image 369 * data larger than strictly necessary 370 */ 371 .bytesperline = 160, 372 .sizeimage = 65536, 373 .colorspace = V4L2_COLORSPACE_SRGB, 374 .priv = 3}, 375 {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, 376 .bytesperline = 172, 377 .sizeimage = 65536, 378 .colorspace = V4L2_COLORSPACE_SRGB, 379 .priv = 2}, 380 {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, 381 .bytesperline = 320, 382 .sizeimage = 262144, 383 .colorspace = V4L2_COLORSPACE_SRGB, 384 .priv = 1}, 385 {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, 386 .bytesperline = 352, 387 .sizeimage = 262144, 388 .colorspace = V4L2_COLORSPACE_SRGB, 389 .priv = 0}, 390}; 391 392/********************************************************************** 393 * 394 * General functions 395 * 396 **********************************************************************/ 397 398static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command) 399{ 400 u8 requesttype; 401 unsigned int pipe; 402 int ret, databytes = command[6] | (command[7] << 8); 403 /* Sometimes we see spurious EPIPE errors */ 404 int retries = 3; 405 406 if (command[0] == DATA_IN) { 407 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); 408 requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; 409 } else if (command[0] == DATA_OUT) { 410 pipe = usb_sndctrlpipe(gspca_dev->dev, 0); 411 requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE; 412 } else { 413 gspca_err(gspca_dev, "Unexpected first byte of command: %x\n", 414 command[0]); 415 return -EINVAL; 416 } 417 418retry: 419 ret = usb_control_msg(gspca_dev->dev, pipe, 420 command[1], 421 requesttype, 422 command[2] | (command[3] << 8), 423 command[4] | (command[5] << 8), 424 gspca_dev->usb_buf, databytes, 1000); 425 426 if (ret < 0) 427 pr_err("usb_control_msg %02x, error %d\n", command[1], ret); 428 429 if (ret == -EPIPE && retries > 0) { 430 retries--; 431 goto retry; 432 } 433 434 return (ret < 0) ? ret : 0; 435} 436 437/* send an arbitrary command to the camera */ 438static int do_command(struct gspca_dev *gspca_dev, u16 command, 439 u8 a, u8 b, u8 c, u8 d) 440{ 441 struct sd *sd = (struct sd *) gspca_dev; 442 int ret, datasize; 443 u8 cmd[8]; 444 445 switch (command) { 446 case CPIA_COMMAND_GetCPIAVersion: 447 case CPIA_COMMAND_GetPnPID: 448 case CPIA_COMMAND_GetCameraStatus: 449 case CPIA_COMMAND_GetVPVersion: 450 case CPIA_COMMAND_GetColourParams: 451 case CPIA_COMMAND_GetColourBalance: 452 case CPIA_COMMAND_GetExposure: 453 datasize = 8; 454 break; 455 case CPIA_COMMAND_ReadMCPorts: 456 case CPIA_COMMAND_ReadVCRegs: 457 datasize = 4; 458 break; 459 default: 460 datasize = 0; 461 break; 462 } 463 464 cmd[0] = command >> 8; 465 cmd[1] = command & 0xff; 466 cmd[2] = a; 467 cmd[3] = b; 468 cmd[4] = c; 469 cmd[5] = d; 470 cmd[6] = datasize; 471 cmd[7] = 0; 472 473 ret = cpia_usb_transferCmd(gspca_dev, cmd); 474 if (ret) 475 return ret; 476 477 switch (command) { 478 case CPIA_COMMAND_GetCPIAVersion: 479 sd->params.version.firmwareVersion = gspca_dev->usb_buf[0]; 480 sd->params.version.firmwareRevision = gspca_dev->usb_buf[1]; 481 sd->params.version.vcVersion = gspca_dev->usb_buf[2]; 482 sd->params.version.vcRevision = gspca_dev->usb_buf[3]; 483 break; 484 case CPIA_COMMAND_GetPnPID: 485 sd->params.pnpID.vendor = 486 gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); 487 sd->params.pnpID.product = 488 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); 489 sd->params.pnpID.deviceRevision = 490 gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8); 491 break; 492 case CPIA_COMMAND_GetCameraStatus: 493 sd->params.status.systemState = gspca_dev->usb_buf[0]; 494 sd->params.status.grabState = gspca_dev->usb_buf[1]; 495 sd->params.status.streamState = gspca_dev->usb_buf[2]; 496 sd->params.status.fatalError = gspca_dev->usb_buf[3]; 497 sd->params.status.cmdError = gspca_dev->usb_buf[4]; 498 sd->params.status.debugFlags = gspca_dev->usb_buf[5]; 499 sd->params.status.vpStatus = gspca_dev->usb_buf[6]; 500 sd->params.status.errorCode = gspca_dev->usb_buf[7]; 501 break; 502 case CPIA_COMMAND_GetVPVersion: 503 sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0]; 504 sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1]; 505 sd->params.vpVersion.cameraHeadID = 506 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); 507 break; 508 case CPIA_COMMAND_GetColourParams: 509 sd->params.colourParams.brightness = gspca_dev->usb_buf[0]; 510 sd->params.colourParams.contrast = gspca_dev->usb_buf[1]; 511 sd->params.colourParams.saturation = gspca_dev->usb_buf[2]; 512 break; 513 case CPIA_COMMAND_GetColourBalance: 514 sd->params.colourBalance.redGain = gspca_dev->usb_buf[0]; 515 sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1]; 516 sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2]; 517 break; 518 case CPIA_COMMAND_GetExposure: 519 sd->params.exposure.gain = gspca_dev->usb_buf[0]; 520 sd->params.exposure.fineExp = gspca_dev->usb_buf[1]; 521 sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2]; 522 sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3]; 523 sd->params.exposure.redComp = gspca_dev->usb_buf[4]; 524 sd->params.exposure.green1Comp = gspca_dev->usb_buf[5]; 525 sd->params.exposure.green2Comp = gspca_dev->usb_buf[6]; 526 sd->params.exposure.blueComp = gspca_dev->usb_buf[7]; 527 break; 528 529 case CPIA_COMMAND_ReadMCPorts: 530 /* test button press */ 531 a = ((gspca_dev->usb_buf[1] & 0x02) == 0); 532 if (a != sd->params.qx3.button) { 533#if IS_ENABLED(CONFIG_INPUT) 534 input_report_key(gspca_dev->input_dev, KEY_CAMERA, a); 535 input_sync(gspca_dev->input_dev); 536#endif 537 sd->params.qx3.button = a; 538 } 539 if (sd->params.qx3.button) { 540 /* button pressed - unlock the latch */ 541 ret = do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 542 3, 0xdf, 0xdf, 0); 543 if (ret) 544 return ret; 545 ret = do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 546 3, 0xff, 0xff, 0); 547 if (ret) 548 return ret; 549 } 550 551 /* test whether microscope is cradled */ 552 sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0); 553 break; 554 } 555 556 return 0; 557} 558 559/* send a command to the camera with an additional data transaction */ 560static int do_command_extended(struct gspca_dev *gspca_dev, u16 command, 561 u8 a, u8 b, u8 c, u8 d, 562 u8 e, u8 f, u8 g, u8 h, 563 u8 i, u8 j, u8 k, u8 l) 564{ 565 u8 cmd[8]; 566 567 cmd[0] = command >> 8; 568 cmd[1] = command & 0xff; 569 cmd[2] = a; 570 cmd[3] = b; 571 cmd[4] = c; 572 cmd[5] = d; 573 cmd[6] = 8; 574 cmd[7] = 0; 575 gspca_dev->usb_buf[0] = e; 576 gspca_dev->usb_buf[1] = f; 577 gspca_dev->usb_buf[2] = g; 578 gspca_dev->usb_buf[3] = h; 579 gspca_dev->usb_buf[4] = i; 580 gspca_dev->usb_buf[5] = j; 581 gspca_dev->usb_buf[6] = k; 582 gspca_dev->usb_buf[7] = l; 583 584 return cpia_usb_transferCmd(gspca_dev, cmd); 585} 586 587/* find_over_exposure 588 * Finds a suitable value of OverExposure for use with SetFlickerCtrl 589 * Some calculation is required because this value changes with the brightness 590 * set with SetColourParameters 591 * 592 * Parameters: Brightness - last brightness value set with SetColourParameters 593 * 594 * Returns: OverExposure value to use with SetFlickerCtrl 595 */ 596#define FLICKER_MAX_EXPOSURE 250 597#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146 598#define FLICKER_BRIGHTNESS_CONSTANT 59 599static int find_over_exposure(int brightness) 600{ 601 int MaxAllowableOverExposure, OverExposure; 602 603 MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - 604 FLICKER_BRIGHTNESS_CONSTANT; 605 606 if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) 607 OverExposure = MaxAllowableOverExposure; 608 else 609 OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE; 610 611 return OverExposure; 612} 613#undef FLICKER_MAX_EXPOSURE 614#undef FLICKER_ALLOWABLE_OVER_EXPOSURE 615#undef FLICKER_BRIGHTNESS_CONSTANT 616 617/* initialise cam_data structure */ 618static void reset_camera_params(struct gspca_dev *gspca_dev) 619{ 620 struct sd *sd = (struct sd *) gspca_dev; 621 struct cam_params *params = &sd->params; 622 623 /* The following parameter values are the defaults from 624 * "Software Developer's Guide for CPiA Cameras". Any changes 625 * to the defaults are noted in comments. */ 626 params->colourParams.brightness = BRIGHTNESS_DEF; 627 params->colourParams.contrast = CONTRAST_DEF; 628 params->colourParams.saturation = SATURATION_DEF; 629 params->exposure.gainMode = 4; 630 params->exposure.expMode = 2; /* AEC */ 631 params->exposure.compMode = 1; 632 params->exposure.centreWeight = 1; 633 params->exposure.gain = 0; 634 params->exposure.fineExp = 0; 635 params->exposure.coarseExpLo = 185; 636 params->exposure.coarseExpHi = 0; 637 params->exposure.redComp = COMP_RED; 638 params->exposure.green1Comp = COMP_GREEN1; 639 params->exposure.green2Comp = COMP_GREEN2; 640 params->exposure.blueComp = COMP_BLUE; 641 params->colourBalance.balanceMode = 2; /* ACB */ 642 params->colourBalance.redGain = 32; 643 params->colourBalance.greenGain = 6; 644 params->colourBalance.blueGain = 92; 645 params->apcor.gain1 = 0x18; 646 params->apcor.gain2 = 0x16; 647 params->apcor.gain4 = 0x24; 648 params->apcor.gain8 = 0x34; 649 params->vlOffset.gain1 = 20; 650 params->vlOffset.gain2 = 24; 651 params->vlOffset.gain4 = 26; 652 params->vlOffset.gain8 = 26; 653 params->compressionParams.hysteresis = 3; 654 params->compressionParams.threshMax = 11; 655 params->compressionParams.smallStep = 1; 656 params->compressionParams.largeStep = 3; 657 params->compressionParams.decimationHysteresis = 2; 658 params->compressionParams.frDiffStepThresh = 5; 659 params->compressionParams.qDiffStepThresh = 3; 660 params->compressionParams.decimationThreshMod = 2; 661 /* End of default values from Software Developer's Guide */ 662 663 /* Set Sensor FPS to 15fps. This seems better than 30fps 664 * for indoor lighting. */ 665 params->sensorFps.divisor = 1; 666 params->sensorFps.baserate = 1; 667 668 params->flickerControl.flickerMode = 0; 669 params->flickerControl.disabled = 1; 670 params->flickerControl.coarseJump = 671 flicker_jumps[sd->mainsFreq] 672 [params->sensorFps.baserate] 673 [params->sensorFps.divisor]; 674 params->flickerControl.allowableOverExposure = 675 find_over_exposure(params->colourParams.brightness); 676 677 params->yuvThreshold.yThreshold = 6; /* From windows driver */ 678 params->yuvThreshold.uvThreshold = 6; /* From windows driver */ 679 680 params->format.subSample = SUBSAMPLE_420; 681 params->format.yuvOrder = YUVORDER_YUYV; 682 683 params->compression.mode = CPIA_COMPRESSION_AUTO; 684 params->compression.decimation = NO_DECIMATION; 685 686 params->compressionTarget.frTargeting = COMP_TARGET_DEF; 687 params->compressionTarget.targetFR = 15; /* From windows driver */ 688 params->compressionTarget.targetQ = 5; /* From windows driver */ 689 690 params->qx3.qx3_detected = 0; 691 params->qx3.toplight = 0; 692 params->qx3.bottomlight = 0; 693 params->qx3.button = 0; 694 params->qx3.cradled = 0; 695} 696 697static void printstatus(struct gspca_dev *gspca_dev, struct cam_params *params) 698{ 699 gspca_dbg(gspca_dev, D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x\n", 700 params->status.systemState, params->status.grabState, 701 params->status.streamState, params->status.fatalError, 702 params->status.cmdError, params->status.debugFlags, 703 params->status.vpStatus, params->status.errorCode); 704} 705 706static int goto_low_power(struct gspca_dev *gspca_dev) 707{ 708 struct sd *sd = (struct sd *) gspca_dev; 709 int ret; 710 711 ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0); 712 if (ret) 713 return ret; 714 715 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); 716 if (ret) 717 return ret; 718 719 if (sd->params.status.systemState != LO_POWER_STATE) { 720 if (sd->params.status.systemState != WARM_BOOT_STATE) { 721 gspca_err(gspca_dev, "unexpected state after lo power cmd: %02x\n", 722 sd->params.status.systemState); 723 printstatus(gspca_dev, &sd->params); 724 } 725 return -EIO; 726 } 727 728 gspca_dbg(gspca_dev, D_CONF, "camera now in LOW power state\n"); 729 return 0; 730} 731 732static int goto_high_power(struct gspca_dev *gspca_dev) 733{ 734 struct sd *sd = (struct sd *) gspca_dev; 735 int ret; 736 737 ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0); 738 if (ret) 739 return ret; 740 741 msleep_interruptible(40); /* windows driver does it too */ 742 743 if (signal_pending(current)) 744 return -EINTR; 745 746 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); 747 if (ret) 748 return ret; 749 750 if (sd->params.status.systemState != HI_POWER_STATE) { 751 gspca_err(gspca_dev, "unexpected state after hi power cmd: %02x\n", 752 sd->params.status.systemState); 753 printstatus(gspca_dev, &sd->params); 754 return -EIO; 755 } 756 757 gspca_dbg(gspca_dev, D_CONF, "camera now in HIGH power state\n"); 758 return 0; 759} 760 761static int get_version_information(struct gspca_dev *gspca_dev) 762{ 763 int ret; 764 765 /* GetCPIAVersion */ 766 ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); 767 if (ret) 768 return ret; 769 770 /* GetPnPID */ 771 return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); 772} 773 774static int save_camera_state(struct gspca_dev *gspca_dev) 775{ 776 int ret; 777 778 ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); 779 if (ret) 780 return ret; 781 782 return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); 783} 784 785static int command_setformat(struct gspca_dev *gspca_dev) 786{ 787 struct sd *sd = (struct sd *) gspca_dev; 788 int ret; 789 790 ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat, 791 sd->params.format.videoSize, 792 sd->params.format.subSample, 793 sd->params.format.yuvOrder, 0); 794 if (ret) 795 return ret; 796 797 return do_command(gspca_dev, CPIA_COMMAND_SetROI, 798 sd->params.roi.colStart, sd->params.roi.colEnd, 799 sd->params.roi.rowStart, sd->params.roi.rowEnd); 800} 801 802static int command_setcolourparams(struct gspca_dev *gspca_dev) 803{ 804 struct sd *sd = (struct sd *) gspca_dev; 805 return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, 806 sd->params.colourParams.brightness, 807 sd->params.colourParams.contrast, 808 sd->params.colourParams.saturation, 0); 809} 810 811static int command_setapcor(struct gspca_dev *gspca_dev) 812{ 813 struct sd *sd = (struct sd *) gspca_dev; 814 return do_command(gspca_dev, CPIA_COMMAND_SetApcor, 815 sd->params.apcor.gain1, 816 sd->params.apcor.gain2, 817 sd->params.apcor.gain4, 818 sd->params.apcor.gain8); 819} 820 821static int command_setvloffset(struct gspca_dev *gspca_dev) 822{ 823 struct sd *sd = (struct sd *) gspca_dev; 824 return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, 825 sd->params.vlOffset.gain1, 826 sd->params.vlOffset.gain2, 827 sd->params.vlOffset.gain4, 828 sd->params.vlOffset.gain8); 829} 830 831static int command_setexposure(struct gspca_dev *gspca_dev) 832{ 833 struct sd *sd = (struct sd *) gspca_dev; 834 int ret; 835 836 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, 837 sd->params.exposure.gainMode, 838 1, 839 sd->params.exposure.compMode, 840 sd->params.exposure.centreWeight, 841 sd->params.exposure.gain, 842 sd->params.exposure.fineExp, 843 sd->params.exposure.coarseExpLo, 844 sd->params.exposure.coarseExpHi, 845 sd->params.exposure.redComp, 846 sd->params.exposure.green1Comp, 847 sd->params.exposure.green2Comp, 848 sd->params.exposure.blueComp); 849 if (ret) 850 return ret; 851 852 if (sd->params.exposure.expMode != 1) { 853 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, 854 0, 855 sd->params.exposure.expMode, 856 0, 0, 857 sd->params.exposure.gain, 858 sd->params.exposure.fineExp, 859 sd->params.exposure.coarseExpLo, 860 sd->params.exposure.coarseExpHi, 861 0, 0, 0, 0); 862 } 863 864 return ret; 865} 866 867static int command_setcolourbalance(struct gspca_dev *gspca_dev) 868{ 869 struct sd *sd = (struct sd *) gspca_dev; 870 871 if (sd->params.colourBalance.balanceMode == 1) { 872 int ret; 873 874 ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, 875 1, 876 sd->params.colourBalance.redGain, 877 sd->params.colourBalance.greenGain, 878 sd->params.colourBalance.blueGain); 879 if (ret) 880 return ret; 881 882 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, 883 3, 0, 0, 0); 884 } 885 if (sd->params.colourBalance.balanceMode == 2) { 886 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, 887 2, 0, 0, 0); 888 } 889 if (sd->params.colourBalance.balanceMode == 3) { 890 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, 891 3, 0, 0, 0); 892 } 893 894 return -EINVAL; 895} 896 897static int command_setcompressiontarget(struct gspca_dev *gspca_dev) 898{ 899 struct sd *sd = (struct sd *) gspca_dev; 900 901 return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget, 902 sd->params.compressionTarget.frTargeting, 903 sd->params.compressionTarget.targetFR, 904 sd->params.compressionTarget.targetQ, 0); 905} 906 907static int command_setyuvtresh(struct gspca_dev *gspca_dev) 908{ 909 struct sd *sd = (struct sd *) gspca_dev; 910 911 return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh, 912 sd->params.yuvThreshold.yThreshold, 913 sd->params.yuvThreshold.uvThreshold, 0, 0); 914} 915 916static int command_setcompressionparams(struct gspca_dev *gspca_dev) 917{ 918 struct sd *sd = (struct sd *) gspca_dev; 919 920 return do_command_extended(gspca_dev, 921 CPIA_COMMAND_SetCompressionParams, 922 0, 0, 0, 0, 923 sd->params.compressionParams.hysteresis, 924 sd->params.compressionParams.threshMax, 925 sd->params.compressionParams.smallStep, 926 sd->params.compressionParams.largeStep, 927 sd->params.compressionParams.decimationHysteresis, 928 sd->params.compressionParams.frDiffStepThresh, 929 sd->params.compressionParams.qDiffStepThresh, 930 sd->params.compressionParams.decimationThreshMod); 931} 932 933static int command_setcompression(struct gspca_dev *gspca_dev) 934{ 935 struct sd *sd = (struct sd *) gspca_dev; 936 937 return do_command(gspca_dev, CPIA_COMMAND_SetCompression, 938 sd->params.compression.mode, 939 sd->params.compression.decimation, 0, 0); 940} 941 942static int command_setsensorfps(struct gspca_dev *gspca_dev) 943{ 944 struct sd *sd = (struct sd *) gspca_dev; 945 946 return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS, 947 sd->params.sensorFps.divisor, 948 sd->params.sensorFps.baserate, 0, 0); 949} 950 951static int command_setflickerctrl(struct gspca_dev *gspca_dev) 952{ 953 struct sd *sd = (struct sd *) gspca_dev; 954 955 return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl, 956 sd->params.flickerControl.flickerMode, 957 sd->params.flickerControl.coarseJump, 958 sd->params.flickerControl.allowableOverExposure, 959 0); 960} 961 962static int command_setecptiming(struct gspca_dev *gspca_dev) 963{ 964 struct sd *sd = (struct sd *) gspca_dev; 965 966 return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming, 967 sd->params.ecpTiming, 0, 0, 0); 968} 969 970static int command_pause(struct gspca_dev *gspca_dev) 971{ 972 return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); 973} 974 975static int command_resume(struct gspca_dev *gspca_dev) 976{ 977 struct sd *sd = (struct sd *) gspca_dev; 978 979 return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap, 980 0, sd->params.streamStartLine, 0, 0); 981} 982 983static int command_setlights(struct gspca_dev *gspca_dev) 984{ 985 struct sd *sd = (struct sd *) gspca_dev; 986 int ret, p1, p2; 987 988 p1 = (sd->params.qx3.bottomlight == 0) << 1; 989 p2 = (sd->params.qx3.toplight == 0) << 3; 990 991 ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, 992 0x90, 0x8f, 0x50, 0); 993 if (ret) 994 return ret; 995 996 return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, 997 p1 | p2 | 0xe0, 0); 998} 999 1000static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) 1001{ 1002 /* Everything in here is from the Windows driver */ 1003/* define for compgain calculation */ 1004#if 0 1005#define COMPGAIN(base, curexp, newexp) \ 1006 (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5) 1007#define EXP_FROM_COMP(basecomp, curcomp, curexp) \ 1008 (u16)((float)curexp * (float)(u8)(curcomp + 128) / \ 1009 (float)(u8)(basecomp - 128)) 1010#else 1011 /* equivalent functions without floating point math */ 1012#define COMPGAIN(base, curexp, newexp) \ 1013 (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp))) 1014#define EXP_FROM_COMP(basecomp, curcomp, curexp) \ 1015 (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128))) 1016#endif 1017 1018 struct sd *sd = (struct sd *) gspca_dev; 1019 int currentexp = sd->params.exposure.coarseExpLo + 1020 sd->params.exposure.coarseExpHi * 256; 1021 int ret, startexp; 1022 1023 if (on) { 1024 int cj = sd->params.flickerControl.coarseJump; 1025 sd->params.flickerControl.flickerMode = 1; 1026 sd->params.flickerControl.disabled = 0; 1027 if (sd->params.exposure.expMode != 2) { 1028 sd->params.exposure.expMode = 2; 1029 sd->exposure_status = EXPOSURE_NORMAL; 1030 } 1031 currentexp = currentexp << sd->params.exposure.gain; 1032 sd->params.exposure.gain = 0; 1033 /* round down current exposure to nearest value */ 1034 startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj; 1035 if (startexp < 1) 1036 startexp = 1; 1037 startexp = (startexp * cj) - 1; 1038 if (FIRMWARE_VERSION(1, 2)) 1039 while (startexp > MAX_EXP_102) 1040 startexp -= cj; 1041 else 1042 while (startexp > MAX_EXP) 1043 startexp -= cj; 1044 sd->params.exposure.coarseExpLo = startexp & 0xff; 1045 sd->params.exposure.coarseExpHi = startexp >> 8; 1046 if (currentexp > startexp) { 1047 if (currentexp > (2 * startexp)) 1048 currentexp = 2 * startexp; 1049 sd->params.exposure.redComp = 1050 COMPGAIN(COMP_RED, currentexp, startexp); 1051 sd->params.exposure.green1Comp = 1052 COMPGAIN(COMP_GREEN1, currentexp, startexp); 1053 sd->params.exposure.green2Comp = 1054 COMPGAIN(COMP_GREEN2, currentexp, startexp); 1055 sd->params.exposure.blueComp = 1056 COMPGAIN(COMP_BLUE, currentexp, startexp); 1057 } else { 1058 sd->params.exposure.redComp = COMP_RED; 1059 sd->params.exposure.green1Comp = COMP_GREEN1; 1060 sd->params.exposure.green2Comp = COMP_GREEN2; 1061 sd->params.exposure.blueComp = COMP_BLUE; 1062 } 1063 if (FIRMWARE_VERSION(1, 2)) 1064 sd->params.exposure.compMode = 0; 1065 else 1066 sd->params.exposure.compMode = 1; 1067 1068 sd->params.apcor.gain1 = 0x18; 1069 sd->params.apcor.gain2 = 0x18; 1070 sd->params.apcor.gain4 = 0x16; 1071 sd->params.apcor.gain8 = 0x14; 1072 } else { 1073 sd->params.flickerControl.flickerMode = 0; 1074 sd->params.flickerControl.disabled = 1; 1075 /* Average equivalent coarse for each comp channel */ 1076 startexp = EXP_FROM_COMP(COMP_RED, 1077 sd->params.exposure.redComp, currentexp); 1078 startexp += EXP_FROM_COMP(COMP_GREEN1, 1079 sd->params.exposure.green1Comp, currentexp); 1080 startexp += EXP_FROM_COMP(COMP_GREEN2, 1081 sd->params.exposure.green2Comp, currentexp); 1082 startexp += EXP_FROM_COMP(COMP_BLUE, 1083 sd->params.exposure.blueComp, currentexp); 1084 startexp = startexp >> 2; 1085 while (startexp > MAX_EXP && sd->params.exposure.gain < 1086 sd->params.exposure.gainMode - 1) { 1087 startexp = startexp >> 1; 1088 ++sd->params.exposure.gain; 1089 } 1090 if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102) 1091 startexp = MAX_EXP_102; 1092 if (startexp > MAX_EXP) 1093 startexp = MAX_EXP; 1094 sd->params.exposure.coarseExpLo = startexp & 0xff; 1095 sd->params.exposure.coarseExpHi = startexp >> 8; 1096 sd->params.exposure.redComp = COMP_RED; 1097 sd->params.exposure.green1Comp = COMP_GREEN1; 1098 sd->params.exposure.green2Comp = COMP_GREEN2; 1099 sd->params.exposure.blueComp = COMP_BLUE; 1100 sd->params.exposure.compMode = 1; 1101 sd->params.apcor.gain1 = 0x18; 1102 sd->params.apcor.gain2 = 0x16; 1103 sd->params.apcor.gain4 = 0x24; 1104 sd->params.apcor.gain8 = 0x34; 1105 } 1106 sd->params.vlOffset.gain1 = 20; 1107 sd->params.vlOffset.gain2 = 24; 1108 sd->params.vlOffset.gain4 = 26; 1109 sd->params.vlOffset.gain8 = 26; 1110 1111 if (apply) { 1112 ret = command_setexposure(gspca_dev); 1113 if (ret) 1114 return ret; 1115 1116 ret = command_setapcor(gspca_dev); 1117 if (ret) 1118 return ret; 1119 1120 ret = command_setvloffset(gspca_dev); 1121 if (ret) 1122 return ret; 1123 1124 ret = command_setflickerctrl(gspca_dev); 1125 if (ret) 1126 return ret; 1127 } 1128 1129 return 0; 1130#undef EXP_FROM_COMP 1131#undef COMPGAIN 1132} 1133 1134/* monitor the exposure and adjust the sensor frame rate if needed */ 1135static void monitor_exposure(struct gspca_dev *gspca_dev) 1136{ 1137 struct sd *sd = (struct sd *) gspca_dev; 1138 u8 exp_acc, bcomp, cmd[8]; 1139 int ret, light_exp, dark_exp, very_dark_exp; 1140 int old_exposure, new_exposure, framerate; 1141 int setfps = 0, setexp = 0, setflicker = 0; 1142 1143 /* get necessary stats and register settings from camera */ 1144 /* do_command can't handle this, so do it ourselves */ 1145 cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8; 1146 cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff; 1147 cmd[2] = 30; 1148 cmd[3] = 4; 1149 cmd[4] = 9; 1150 cmd[5] = 8; 1151 cmd[6] = 8; 1152 cmd[7] = 0; 1153 ret = cpia_usb_transferCmd(gspca_dev, cmd); 1154 if (ret) { 1155 pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret); 1156 return; 1157 } 1158 exp_acc = gspca_dev->usb_buf[0]; 1159 bcomp = gspca_dev->usb_buf[1]; 1160 1161 light_exp = sd->params.colourParams.brightness + 1162 TC - 50 + EXP_ACC_LIGHT; 1163 if (light_exp > 255) 1164 light_exp = 255; 1165 dark_exp = sd->params.colourParams.brightness + 1166 TC - 50 - EXP_ACC_DARK; 1167 if (dark_exp < 0) 1168 dark_exp = 0; 1169 very_dark_exp = dark_exp / 2; 1170 1171 old_exposure = sd->params.exposure.coarseExpHi * 256 + 1172 sd->params.exposure.coarseExpLo; 1173 1174 if (!sd->params.flickerControl.disabled) { 1175 /* Flicker control on */ 1176 int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP : 1177 HIGH_COMP_102; 1178 bcomp += 128; /* decode */ 1179 if (bcomp >= max_comp && exp_acc < dark_exp) { 1180 /* dark */ 1181 if (exp_acc < very_dark_exp) { 1182 /* very dark */ 1183 if (sd->exposure_status == EXPOSURE_VERY_DARK) 1184 ++sd->exposure_count; 1185 else { 1186 sd->exposure_status = 1187 EXPOSURE_VERY_DARK; 1188 sd->exposure_count = 1; 1189 } 1190 } else { 1191 /* just dark */ 1192 if (sd->exposure_status == EXPOSURE_DARK) 1193 ++sd->exposure_count; 1194 else { 1195 sd->exposure_status = EXPOSURE_DARK; 1196 sd->exposure_count = 1; 1197 } 1198 } 1199 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { 1200 /* light */ 1201 if (old_exposure <= VERY_LOW_EXP) { 1202 /* very light */ 1203 if (sd->exposure_status == EXPOSURE_VERY_LIGHT) 1204 ++sd->exposure_count; 1205 else { 1206 sd->exposure_status = 1207 EXPOSURE_VERY_LIGHT; 1208 sd->exposure_count = 1; 1209 } 1210 } else { 1211 /* just light */ 1212 if (sd->exposure_status == EXPOSURE_LIGHT) 1213 ++sd->exposure_count; 1214 else { 1215 sd->exposure_status = EXPOSURE_LIGHT; 1216 sd->exposure_count = 1; 1217 } 1218 } 1219 } else { 1220 /* not dark or light */ 1221 sd->exposure_status = EXPOSURE_NORMAL; 1222 } 1223 } else { 1224 /* Flicker control off */ 1225 if (old_exposure >= MAX_EXP && exp_acc < dark_exp) { 1226 /* dark */ 1227 if (exp_acc < very_dark_exp) { 1228 /* very dark */ 1229 if (sd->exposure_status == EXPOSURE_VERY_DARK) 1230 ++sd->exposure_count; 1231 else { 1232 sd->exposure_status = 1233 EXPOSURE_VERY_DARK; 1234 sd->exposure_count = 1; 1235 } 1236 } else { 1237 /* just dark */ 1238 if (sd->exposure_status == EXPOSURE_DARK) 1239 ++sd->exposure_count; 1240 else { 1241 sd->exposure_status = EXPOSURE_DARK; 1242 sd->exposure_count = 1; 1243 } 1244 } 1245 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { 1246 /* light */ 1247 if (old_exposure <= VERY_LOW_EXP) { 1248 /* very light */ 1249 if (sd->exposure_status == EXPOSURE_VERY_LIGHT) 1250 ++sd->exposure_count; 1251 else { 1252 sd->exposure_status = 1253 EXPOSURE_VERY_LIGHT; 1254 sd->exposure_count = 1; 1255 } 1256 } else { 1257 /* just light */ 1258 if (sd->exposure_status == EXPOSURE_LIGHT) 1259 ++sd->exposure_count; 1260 else { 1261 sd->exposure_status = EXPOSURE_LIGHT; 1262 sd->exposure_count = 1; 1263 } 1264 } 1265 } else { 1266 /* not dark or light */ 1267 sd->exposure_status = EXPOSURE_NORMAL; 1268 } 1269 } 1270 1271 framerate = atomic_read(&sd->fps); 1272 if (framerate > 30 || framerate < 1) 1273 framerate = 1; 1274 1275 if (!sd->params.flickerControl.disabled) { 1276 /* Flicker control on */ 1277 if ((sd->exposure_status == EXPOSURE_VERY_DARK || 1278 sd->exposure_status == EXPOSURE_DARK) && 1279 sd->exposure_count >= DARK_TIME * framerate && 1280 sd->params.sensorFps.divisor < 2) { 1281 1282 /* dark for too long */ 1283 ++sd->params.sensorFps.divisor; 1284 setfps = 1; 1285 1286 sd->params.flickerControl.coarseJump = 1287 flicker_jumps[sd->mainsFreq] 1288 [sd->params.sensorFps.baserate] 1289 [sd->params.sensorFps.divisor]; 1290 setflicker = 1; 1291 1292 new_exposure = sd->params.flickerControl.coarseJump-1; 1293 while (new_exposure < old_exposure / 2) 1294 new_exposure += 1295 sd->params.flickerControl.coarseJump; 1296 sd->params.exposure.coarseExpLo = new_exposure & 0xff; 1297 sd->params.exposure.coarseExpHi = new_exposure >> 8; 1298 setexp = 1; 1299 sd->exposure_status = EXPOSURE_NORMAL; 1300 gspca_dbg(gspca_dev, D_CONF, "Automatically decreasing sensor_fps\n"); 1301 1302 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || 1303 sd->exposure_status == EXPOSURE_LIGHT) && 1304 sd->exposure_count >= LIGHT_TIME * framerate && 1305 sd->params.sensorFps.divisor > 0) { 1306 1307 /* light for too long */ 1308 int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 : 1309 MAX_EXP; 1310 --sd->params.sensorFps.divisor; 1311 setfps = 1; 1312 1313 sd->params.flickerControl.coarseJump = 1314 flicker_jumps[sd->mainsFreq] 1315 [sd->params.sensorFps.baserate] 1316 [sd->params.sensorFps.divisor]; 1317 setflicker = 1; 1318 1319 new_exposure = sd->params.flickerControl.coarseJump-1; 1320 while (new_exposure < 2 * old_exposure && 1321 new_exposure + 1322 sd->params.flickerControl.coarseJump < max_exp) 1323 new_exposure += 1324 sd->params.flickerControl.coarseJump; 1325 sd->params.exposure.coarseExpLo = new_exposure & 0xff; 1326 sd->params.exposure.coarseExpHi = new_exposure >> 8; 1327 setexp = 1; 1328 sd->exposure_status = EXPOSURE_NORMAL; 1329 gspca_dbg(gspca_dev, D_CONF, "Automatically increasing sensor_fps\n"); 1330 } 1331 } else { 1332 /* Flicker control off */ 1333 if ((sd->exposure_status == EXPOSURE_VERY_DARK || 1334 sd->exposure_status == EXPOSURE_DARK) && 1335 sd->exposure_count >= DARK_TIME * framerate && 1336 sd->params.sensorFps.divisor < 2) { 1337 1338 /* dark for too long */ 1339 ++sd->params.sensorFps.divisor; 1340 setfps = 1; 1341 1342 if (sd->params.exposure.gain > 0) { 1343 --sd->params.exposure.gain; 1344 setexp = 1; 1345 } 1346 sd->exposure_status = EXPOSURE_NORMAL; 1347 gspca_dbg(gspca_dev, D_CONF, "Automatically decreasing sensor_fps\n"); 1348 1349 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || 1350 sd->exposure_status == EXPOSURE_LIGHT) && 1351 sd->exposure_count >= LIGHT_TIME * framerate && 1352 sd->params.sensorFps.divisor > 0) { 1353 1354 /* light for too long */ 1355 --sd->params.sensorFps.divisor; 1356 setfps = 1; 1357 1358 if (sd->params.exposure.gain < 1359 sd->params.exposure.gainMode - 1) { 1360 ++sd->params.exposure.gain; 1361 setexp = 1; 1362 } 1363 sd->exposure_status = EXPOSURE_NORMAL; 1364 gspca_dbg(gspca_dev, D_CONF, "Automatically increasing sensor_fps\n"); 1365 } 1366 } 1367 1368 if (setexp) 1369 command_setexposure(gspca_dev); 1370 1371 if (setfps) 1372 command_setsensorfps(gspca_dev); 1373 1374 if (setflicker) 1375 command_setflickerctrl(gspca_dev); 1376} 1377 1378/*-----------------------------------------------------------------*/ 1379/* if flicker is switched off, this function switches it back on.It checks, 1380 however, that conditions are suitable before restarting it. 1381 This should only be called for firmware version 1.2. 1382 1383 It also adjust the colour balance when an exposure step is detected - as 1384 long as flicker is running 1385*/ 1386static void restart_flicker(struct gspca_dev *gspca_dev) 1387{ 1388 struct sd *sd = (struct sd *) gspca_dev; 1389 int cam_exposure, old_exp; 1390 1391 if (!FIRMWARE_VERSION(1, 2)) 1392 return; 1393 1394 cam_exposure = atomic_read(&sd->cam_exposure); 1395 1396 if (sd->params.flickerControl.flickerMode == 0 || 1397 cam_exposure == 0) 1398 return; 1399 1400 old_exp = sd->params.exposure.coarseExpLo + 1401 sd->params.exposure.coarseExpHi*256; 1402 /* 1403 see how far away camera exposure is from a valid 1404 flicker exposure value 1405 */ 1406 cam_exposure %= sd->params.flickerControl.coarseJump; 1407 if (!sd->params.flickerControl.disabled && 1408 cam_exposure <= sd->params.flickerControl.coarseJump - 3) { 1409 /* Flicker control auto-disabled */ 1410 sd->params.flickerControl.disabled = 1; 1411 } 1412 1413 if (sd->params.flickerControl.disabled && 1414 old_exp > sd->params.flickerControl.coarseJump + 1415 ROUND_UP_EXP_FOR_FLICKER) { 1416 /* exposure is now high enough to switch 1417 flicker control back on */ 1418 set_flicker(gspca_dev, 1, 1); 1419 } 1420} 1421 1422/* this function is called at probe time */ 1423static int sd_config(struct gspca_dev *gspca_dev, 1424 const struct usb_device_id *id) 1425{ 1426 struct sd *sd = (struct sd *) gspca_dev; 1427 struct cam *cam; 1428 1429 sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ; 1430 reset_camera_params(gspca_dev); 1431 1432 gspca_dbg(gspca_dev, D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)\n", 1433 id->idVendor, id->idProduct); 1434 1435 cam = &gspca_dev->cam; 1436 cam->cam_mode = mode; 1437 cam->nmodes = ARRAY_SIZE(mode); 1438 1439 goto_low_power(gspca_dev); 1440 /* Check the firmware version. */ 1441 sd->params.version.firmwareVersion = 0; 1442 get_version_information(gspca_dev); 1443 if (sd->params.version.firmwareVersion != 1) { 1444 gspca_err(gspca_dev, "only firmware version 1 is supported (got: %d)\n", 1445 sd->params.version.firmwareVersion); 1446 return -ENODEV; 1447 } 1448 1449 /* A bug in firmware 1-02 limits gainMode to 2 */ 1450 if (sd->params.version.firmwareRevision <= 2 && 1451 sd->params.exposure.gainMode > 2) { 1452 sd->params.exposure.gainMode = 2; 1453 } 1454 1455 /* set QX3 detected flag */ 1456 sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 && 1457 sd->params.pnpID.product == 0x0001); 1458 return 0; 1459} 1460 1461/* -- start the camera -- */ 1462static int sd_start(struct gspca_dev *gspca_dev) 1463{ 1464 struct sd *sd = (struct sd *) gspca_dev; 1465 int priv, ret; 1466 1467 /* Start the camera in low power mode */ 1468 if (goto_low_power(gspca_dev)) { 1469 if (sd->params.status.systemState != WARM_BOOT_STATE) { 1470 gspca_err(gspca_dev, "unexpected systemstate: %02x\n", 1471 sd->params.status.systemState); 1472 printstatus(gspca_dev, &sd->params); 1473 return -ENODEV; 1474 } 1475 1476 /* FIXME: this is just dirty trial and error */ 1477 ret = goto_high_power(gspca_dev); 1478 if (ret) 1479 return ret; 1480 1481 ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame, 1482 0, 0, 0, 0); 1483 if (ret) 1484 return ret; 1485 1486 ret = goto_low_power(gspca_dev); 1487 if (ret) 1488 return ret; 1489 } 1490 1491 /* procedure described in developer's guide p3-28 */ 1492 1493 /* Check the firmware version. */ 1494 sd->params.version.firmwareVersion = 0; 1495 get_version_information(gspca_dev); 1496 1497 /* The fatal error checking should be done after 1498 * the camera powers up (developer's guide p 3-38) */ 1499 1500 /* Set streamState before transition to high power to avoid bug 1501 * in firmware 1-02 */ 1502 ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus, 1503 STREAMSTATE, 0, STREAM_NOT_READY, 0); 1504 if (ret) 1505 return ret; 1506 1507 /* GotoHiPower */ 1508 ret = goto_high_power(gspca_dev); 1509 if (ret) 1510 return ret; 1511 1512 /* Check the camera status */ 1513 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); 1514 if (ret) 1515 return ret; 1516 1517 if (sd->params.status.fatalError) { 1518 gspca_err(gspca_dev, "fatal_error: %04x, vp_status: %04x\n", 1519 sd->params.status.fatalError, 1520 sd->params.status.vpStatus); 1521 return -EIO; 1522 } 1523 1524 /* VPVersion can't be retrieved before the camera is in HiPower, 1525 * so get it here instead of in get_version_information. */ 1526 ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); 1527 if (ret) 1528 return ret; 1529 1530 /* Determine video mode settings */ 1531 sd->params.streamStartLine = 120; 1532 1533 priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 1534 if (priv & 0x01) { /* crop */ 1535 sd->params.roi.colStart = 2; 1536 sd->params.roi.rowStart = 6; 1537 } else { 1538 sd->params.roi.colStart = 0; 1539 sd->params.roi.rowStart = 0; 1540 } 1541 1542 if (priv & 0x02) { /* quarter */ 1543 sd->params.format.videoSize = VIDEOSIZE_QCIF; 1544 sd->params.roi.colStart /= 2; 1545 sd->params.roi.rowStart /= 2; 1546 sd->params.streamStartLine /= 2; 1547 } else 1548 sd->params.format.videoSize = VIDEOSIZE_CIF; 1549 1550 sd->params.roi.colEnd = sd->params.roi.colStart + 1551 (gspca_dev->pixfmt.width >> 3); 1552 sd->params.roi.rowEnd = sd->params.roi.rowStart + 1553 (gspca_dev->pixfmt.height >> 2); 1554 1555 /* And now set the camera to a known state */ 1556 ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode, 1557 CPIA_GRAB_CONTINEOUS, 0, 0, 0); 1558 if (ret) 1559 return ret; 1560 /* We start with compression disabled, as we need one uncompressed 1561 frame to handle later compressed frames */ 1562 ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression, 1563 CPIA_COMPRESSION_NONE, 1564 NO_DECIMATION, 0, 0); 1565 if (ret) 1566 return ret; 1567 ret = command_setcompressiontarget(gspca_dev); 1568 if (ret) 1569 return ret; 1570 ret = command_setcolourparams(gspca_dev); 1571 if (ret) 1572 return ret; 1573 ret = command_setformat(gspca_dev); 1574 if (ret) 1575 return ret; 1576 ret = command_setyuvtresh(gspca_dev); 1577 if (ret) 1578 return ret; 1579 ret = command_setecptiming(gspca_dev); 1580 if (ret) 1581 return ret; 1582 ret = command_setcompressionparams(gspca_dev); 1583 if (ret) 1584 return ret; 1585 ret = command_setexposure(gspca_dev); 1586 if (ret) 1587 return ret; 1588 ret = command_setcolourbalance(gspca_dev); 1589 if (ret) 1590 return ret; 1591 ret = command_setsensorfps(gspca_dev); 1592 if (ret) 1593 return ret; 1594 ret = command_setapcor(gspca_dev); 1595 if (ret) 1596 return ret; 1597 ret = command_setflickerctrl(gspca_dev); 1598 if (ret) 1599 return ret; 1600 ret = command_setvloffset(gspca_dev); 1601 if (ret) 1602 return ret; 1603 1604 /* Start stream */ 1605 ret = command_resume(gspca_dev); 1606 if (ret) 1607 return ret; 1608 1609 /* Wait 6 frames before turning compression on for the sensor to get 1610 all settings and AEC/ACB to settle */ 1611 sd->first_frame = 6; 1612 sd->exposure_status = EXPOSURE_NORMAL; 1613 sd->exposure_count = 0; 1614 atomic_set(&sd->cam_exposure, 0); 1615 atomic_set(&sd->fps, 0); 1616 1617 return 0; 1618} 1619 1620static void sd_stopN(struct gspca_dev *gspca_dev) 1621{ 1622 struct sd *sd __maybe_unused = (struct sd *) gspca_dev; 1623 1624 command_pause(gspca_dev); 1625 1626 /* save camera state for later open (developers guide ch 3.5.3) */ 1627 save_camera_state(gspca_dev); 1628 1629 /* GotoLoPower */ 1630 goto_low_power(gspca_dev); 1631 1632 /* Update the camera status */ 1633 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); 1634 1635#if IS_ENABLED(CONFIG_INPUT) 1636 /* If the last button state is pressed, release it now! */ 1637 if (sd->params.qx3.button) { 1638 /* The camera latch will hold the pressed state until we reset 1639 the latch, so we do not reset sd->params.qx3.button now, to 1640 avoid a false keypress being reported the next sd_start */ 1641 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 1642 input_sync(gspca_dev->input_dev); 1643 } 1644#endif 1645} 1646 1647/* this function is called at probe and resume time */ 1648static int sd_init(struct gspca_dev *gspca_dev) 1649{ 1650 struct sd *sd = (struct sd *) gspca_dev; 1651 int ret; 1652 1653 /* Start / Stop the camera to make sure we are talking to 1654 a supported camera, and to get some information from it 1655 to print. */ 1656 ret = sd_start(gspca_dev); 1657 if (ret) 1658 return ret; 1659 1660 /* Ensure the QX3 illuminators' states are restored upon resume, 1661 or disable the illuminator controls, if this isn't a QX3 */ 1662 if (sd->params.qx3.qx3_detected) 1663 command_setlights(gspca_dev); 1664 1665 sd_stopN(gspca_dev); 1666 1667 gspca_dbg(gspca_dev, D_PROBE, "CPIA Version: %d.%02d (%d.%d)\n", 1668 sd->params.version.firmwareVersion, 1669 sd->params.version.firmwareRevision, 1670 sd->params.version.vcVersion, 1671 sd->params.version.vcRevision); 1672 gspca_dbg(gspca_dev, D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x", 1673 sd->params.pnpID.vendor, sd->params.pnpID.product, 1674 sd->params.pnpID.deviceRevision); 1675 gspca_dbg(gspca_dev, D_PROBE, "VP-Version: %d.%d %04x", 1676 sd->params.vpVersion.vpVersion, 1677 sd->params.vpVersion.vpRevision, 1678 sd->params.vpVersion.cameraHeadID); 1679 1680 return 0; 1681} 1682 1683static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1684 u8 *data, 1685 int len) 1686{ 1687 struct sd *sd = (struct sd *) gspca_dev; 1688 1689 /* Check for SOF */ 1690 if (len >= 64 && 1691 data[0] == MAGIC_0 && data[1] == MAGIC_1 && 1692 data[16] == sd->params.format.videoSize && 1693 data[17] == sd->params.format.subSample && 1694 data[18] == sd->params.format.yuvOrder && 1695 data[24] == sd->params.roi.colStart && 1696 data[25] == sd->params.roi.colEnd && 1697 data[26] == sd->params.roi.rowStart && 1698 data[27] == sd->params.roi.rowEnd) { 1699 u8 *image; 1700 1701 atomic_set(&sd->cam_exposure, data[39] * 2); 1702 atomic_set(&sd->fps, data[41]); 1703 1704 /* Check for proper EOF for last frame */ 1705 image = gspca_dev->image; 1706 if (image != NULL && 1707 gspca_dev->image_len > 4 && 1708 image[gspca_dev->image_len - 4] == 0xff && 1709 image[gspca_dev->image_len - 3] == 0xff && 1710 image[gspca_dev->image_len - 2] == 0xff && 1711 image[gspca_dev->image_len - 1] == 0xff) 1712 gspca_frame_add(gspca_dev, LAST_PACKET, 1713 NULL, 0); 1714 1715 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); 1716 return; 1717 } 1718 1719 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 1720} 1721 1722static void sd_dq_callback(struct gspca_dev *gspca_dev) 1723{ 1724 struct sd *sd = (struct sd *) gspca_dev; 1725 1726 /* Set the normal compression settings once we have captured a 1727 few uncompressed frames (and AEC has hopefully settled) */ 1728 if (sd->first_frame) { 1729 sd->first_frame--; 1730 if (sd->first_frame == 0) 1731 command_setcompression(gspca_dev); 1732 } 1733 1734 /* Switch flicker control back on if it got turned off */ 1735 restart_flicker(gspca_dev); 1736 1737 /* If AEC is enabled, monitor the exposure and 1738 adjust the sensor frame rate if needed */ 1739 if (sd->params.exposure.expMode == 2) 1740 monitor_exposure(gspca_dev); 1741 1742 /* Update our knowledge of the camera state */ 1743 do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); 1744 do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); 1745} 1746 1747static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 1748{ 1749 struct gspca_dev *gspca_dev = 1750 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 1751 struct sd *sd = (struct sd *)gspca_dev; 1752 1753 gspca_dev->usb_err = 0; 1754 1755 if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY) 1756 return 0; 1757 1758 switch (ctrl->id) { 1759 case V4L2_CID_BRIGHTNESS: 1760 sd->params.colourParams.brightness = ctrl->val; 1761 sd->params.flickerControl.allowableOverExposure = 1762 find_over_exposure(sd->params.colourParams.brightness); 1763 gspca_dev->usb_err = command_setcolourparams(gspca_dev); 1764 if (!gspca_dev->usb_err) 1765 gspca_dev->usb_err = command_setflickerctrl(gspca_dev); 1766 break; 1767 case V4L2_CID_CONTRAST: 1768 sd->params.colourParams.contrast = ctrl->val; 1769 gspca_dev->usb_err = command_setcolourparams(gspca_dev); 1770 break; 1771 case V4L2_CID_SATURATION: 1772 sd->params.colourParams.saturation = ctrl->val; 1773 gspca_dev->usb_err = command_setcolourparams(gspca_dev); 1774 break; 1775 case V4L2_CID_POWER_LINE_FREQUENCY: 1776 sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ; 1777 sd->params.flickerControl.coarseJump = 1778 flicker_jumps[sd->mainsFreq] 1779 [sd->params.sensorFps.baserate] 1780 [sd->params.sensorFps.divisor]; 1781 1782 gspca_dev->usb_err = set_flicker(gspca_dev, 1783 ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, 1784 gspca_dev->streaming); 1785 break; 1786 case V4L2_CID_ILLUMINATORS_1: 1787 sd->params.qx3.bottomlight = ctrl->val; 1788 gspca_dev->usb_err = command_setlights(gspca_dev); 1789 break; 1790 case V4L2_CID_ILLUMINATORS_2: 1791 sd->params.qx3.toplight = ctrl->val; 1792 gspca_dev->usb_err = command_setlights(gspca_dev); 1793 break; 1794 case CPIA1_CID_COMP_TARGET: 1795 sd->params.compressionTarget.frTargeting = ctrl->val; 1796 gspca_dev->usb_err = command_setcompressiontarget(gspca_dev); 1797 break; 1798 } 1799 return gspca_dev->usb_err; 1800} 1801 1802static const struct v4l2_ctrl_ops sd_ctrl_ops = { 1803 .s_ctrl = sd_s_ctrl, 1804}; 1805 1806static int sd_init_controls(struct gspca_dev *gspca_dev) 1807{ 1808 struct sd *sd = (struct sd *)gspca_dev; 1809 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 1810 static const char * const comp_target_menu[] = { 1811 "Quality", 1812 "Framerate", 1813 NULL 1814 }; 1815 static const struct v4l2_ctrl_config comp_target = { 1816 .ops = &sd_ctrl_ops, 1817 .id = CPIA1_CID_COMP_TARGET, 1818 .type = V4L2_CTRL_TYPE_MENU, 1819 .name = "Compression Target", 1820 .qmenu = comp_target_menu, 1821 .max = 1, 1822 .def = COMP_TARGET_DEF, 1823 }; 1824 1825 gspca_dev->vdev.ctrl_handler = hdl; 1826 v4l2_ctrl_handler_init(hdl, 7); 1827 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1828 V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF); 1829 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1830 V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF); 1831 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1832 V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF); 1833 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 1834 V4L2_CID_POWER_LINE_FREQUENCY, 1835 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 1836 FREQ_DEF); 1837 if (sd->params.qx3.qx3_detected) { 1838 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1839 V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 1840 ILLUMINATORS_1_DEF); 1841 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 1842 V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 1843 ILLUMINATORS_2_DEF); 1844 } 1845 v4l2_ctrl_new_custom(hdl, &comp_target, NULL); 1846 1847 if (hdl->error) { 1848 pr_err("Could not initialize controls\n"); 1849 return hdl->error; 1850 } 1851 return 0; 1852} 1853 1854/* sub-driver description */ 1855static const struct sd_desc sd_desc = { 1856 .name = MODULE_NAME, 1857 .config = sd_config, 1858 .init = sd_init, 1859 .init_controls = sd_init_controls, 1860 .start = sd_start, 1861 .stopN = sd_stopN, 1862 .dq_callback = sd_dq_callback, 1863 .pkt_scan = sd_pkt_scan, 1864#if IS_ENABLED(CONFIG_INPUT) 1865 .other_input = 1, 1866#endif 1867}; 1868 1869/* -- module initialisation -- */ 1870static const struct usb_device_id device_table[] = { 1871 {USB_DEVICE(0x0553, 0x0002)}, 1872 {USB_DEVICE(0x0813, 0x0001)}, 1873 {} 1874}; 1875MODULE_DEVICE_TABLE(usb, device_table); 1876 1877/* -- device connect -- */ 1878static int sd_probe(struct usb_interface *intf, 1879 const struct usb_device_id *id) 1880{ 1881 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1882 THIS_MODULE); 1883} 1884 1885static struct usb_driver sd_driver = { 1886 .name = MODULE_NAME, 1887 .id_table = device_table, 1888 .probe = sd_probe, 1889 .disconnect = gspca_disconnect, 1890#ifdef CONFIG_PM 1891 .suspend = gspca_suspend, 1892 .resume = gspca_resume, 1893 .reset_resume = gspca_resume, 1894#endif 1895}; 1896 1897module_usb_driver(sd_driver);