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