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 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);
1898