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

source code of linux/drivers/media/usb/gspca/cpia1.c