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