File Index
Files and directories
Sign in
FILE

cpia1.c

File preview with syntax highlighting.

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