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