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