cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cpia1.c (55533B)


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