Linux Audio

Check our new training course

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