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