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