GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / media / video / gspca / cpia1.c
blob4cd31606bd996fb78aff73d40f928353aed4b14d
1 /*
2 * cpia CPiA (1) gspca driver
4 * Copyright (C) 2010 Hans de Goede <hdgoede@redhat.com>
6 * This module is adapted from the in kernel v4l1 cpia driver which is :
8 * (C) Copyright 1999-2000 Peter Pregler
9 * (C) Copyright 1999-2000 Scott J. Bertin
10 * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
11 * (C) Copyright 2000 STMicroelectronics
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define MODULE_NAME "cpia1"
31 #include "gspca.h"
33 MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>");
34 MODULE_DESCRIPTION("Vision CPiA");
35 MODULE_LICENSE("GPL");
37 /* constant value's */
38 #define MAGIC_0 0x19
39 #define MAGIC_1 0x68
40 #define DATA_IN 0xC0
41 #define DATA_OUT 0x40
42 #define VIDEOSIZE_QCIF 0 /* 176x144 */
43 #define VIDEOSIZE_CIF 1 /* 352x288 */
44 #define SUBSAMPLE_420 0
45 #define SUBSAMPLE_422 1
46 #define YUVORDER_YUYV 0
47 #define YUVORDER_UYVY 1
48 #define NOT_COMPRESSED 0
49 #define COMPRESSED 1
50 #define NO_DECIMATION 0
51 #define DECIMATION_ENAB 1
52 #define EOI 0xff /* End Of Image */
53 #define EOL 0xfd /* End Of Line */
54 #define FRAME_HEADER_SIZE 64
56 /* Image grab modes */
57 #define CPIA_GRAB_SINGLE 0
58 #define CPIA_GRAB_CONTINEOUS 1
60 /* Compression parameters */
61 #define CPIA_COMPRESSION_NONE 0
62 #define CPIA_COMPRESSION_AUTO 1
63 #define CPIA_COMPRESSION_MANUAL 2
64 #define CPIA_COMPRESSION_TARGET_QUALITY 0
65 #define CPIA_COMPRESSION_TARGET_FRAMERATE 1
67 /* Return offsets for GetCameraState */
68 #define SYSTEMSTATE 0
69 #define GRABSTATE 1
70 #define STREAMSTATE 2
71 #define FATALERROR 3
72 #define CMDERROR 4
73 #define DEBUGFLAGS 5
74 #define VPSTATUS 6
75 #define ERRORCODE 7
77 /* SystemState */
78 #define UNINITIALISED_STATE 0
79 #define PASS_THROUGH_STATE 1
80 #define LO_POWER_STATE 2
81 #define HI_POWER_STATE 3
82 #define WARM_BOOT_STATE 4
84 /* GrabState */
85 #define GRAB_IDLE 0
86 #define GRAB_ACTIVE 1
87 #define GRAB_DONE 2
89 /* StreamState */
90 #define STREAM_NOT_READY 0
91 #define STREAM_READY 1
92 #define STREAM_OPEN 2
93 #define STREAM_PAUSED 3
94 #define STREAM_FINISHED 4
96 /* Fatal Error, CmdError, and DebugFlags */
97 #define CPIA_FLAG 1
98 #define SYSTEM_FLAG 2
99 #define INT_CTRL_FLAG 4
100 #define PROCESS_FLAG 8
101 #define COM_FLAG 16
102 #define VP_CTRL_FLAG 32
103 #define CAPTURE_FLAG 64
104 #define DEBUG_FLAG 128
106 /* VPStatus */
107 #define VP_STATE_OK 0x00
109 #define VP_STATE_FAILED_VIDEOINIT 0x01
110 #define VP_STATE_FAILED_AECACBINIT 0x02
111 #define VP_STATE_AEC_MAX 0x04
112 #define VP_STATE_ACB_BMAX 0x08
114 #define VP_STATE_ACB_RMIN 0x10
115 #define VP_STATE_ACB_GMIN 0x20
116 #define VP_STATE_ACB_RMAX 0x40
117 #define VP_STATE_ACB_GMAX 0x80
119 /* default (minimum) compensation values */
120 #define COMP_RED 220
121 #define COMP_GREEN1 214
122 #define COMP_GREEN2 COMP_GREEN1
123 #define COMP_BLUE 230
125 /* exposure status */
126 #define EXPOSURE_VERY_LIGHT 0
127 #define EXPOSURE_LIGHT 1
128 #define EXPOSURE_NORMAL 2
129 #define EXPOSURE_DARK 3
130 #define EXPOSURE_VERY_DARK 4
132 #define CPIA_MODULE_CPIA (0 << 5)
133 #define CPIA_MODULE_SYSTEM (1 << 5)
134 #define CPIA_MODULE_VP_CTRL (5 << 5)
135 #define CPIA_MODULE_CAPTURE (6 << 5)
136 #define CPIA_MODULE_DEBUG (7 << 5)
138 #define INPUT (DATA_IN << 8)
139 #define OUTPUT (DATA_OUT << 8)
141 #define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1)
142 #define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2)
143 #define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3)
144 #define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4)
145 #define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5)
146 #define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7)
147 #define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8)
148 #define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10)
150 #define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1)
151 #define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2)
152 #define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3)
153 #define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4)
154 #define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5)
155 #define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6)
156 #define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7)
157 #define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8)
158 #define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9)
159 #define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10)
160 #define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11)
161 #define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12)
162 #define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13)
164 #define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1)
165 #define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
166 #define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
167 #define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
168 #define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
169 #define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
170 #define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
171 #define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
172 #define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
173 #define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
174 #define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16)
175 #define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17)
176 #define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18)
177 #define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
178 #define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
179 #define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30)
180 #define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
182 #define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1)
183 #define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2)
184 #define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3)
185 #define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4)
186 #define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5)
187 #define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6)
188 #define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7)
189 #define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8)
190 #define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9)
191 #define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10)
192 #define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
193 #define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12)
194 #define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
195 #define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14)
196 #define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15)
198 #define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1)
199 #define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4)
200 #define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5)
201 #define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6)
202 #define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8)
203 #define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9)
204 #define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10)
205 #define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11)
207 #define ROUND_UP_EXP_FOR_FLICKER 15
209 /* Constants for automatic frame rate adjustment */
210 #define MAX_EXP 302
211 #define MAX_EXP_102 255
212 #define LOW_EXP 140
213 #define VERY_LOW_EXP 70
214 #define TC 94
215 #define EXP_ACC_DARK 50
216 #define EXP_ACC_LIGHT 90
217 #define HIGH_COMP_102 160
218 #define MAX_COMP 239
219 #define DARK_TIME 3
220 #define LIGHT_TIME 3
222 #define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
223 sd->params.version.firmwareRevision == (y))
225 /* Developer's Guide Table 5 p 3-34
226 * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
227 static u8 flicker_jumps[2][2][4] =
228 { { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
229 { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
232 struct 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;
351 /* specific webcam descriptor */
352 struct sd {
353 struct gspca_dev gspca_dev; /* !! must be the first item */
354 struct cam_params params; /* camera settings */
356 atomic_t cam_exposure;
357 atomic_t fps;
358 int exposure_count;
359 u8 exposure_status;
360 u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */
361 u8 first_frame;
362 u8 freq;
365 /* V4L2 controls supported by the driver */
366 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
367 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
368 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
369 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
370 static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
371 static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
372 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
373 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
374 static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val);
375 static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val);
377 static const struct ctrl sd_ctrls[] = {
380 .id = V4L2_CID_BRIGHTNESS,
381 .type = V4L2_CTRL_TYPE_INTEGER,
382 .name = "Brightness",
383 .minimum = 0,
384 .maximum = 100,
385 .step = 1,
386 #define BRIGHTNESS_DEF 50
387 .default_value = BRIGHTNESS_DEF,
388 .flags = 0,
390 .set = sd_setbrightness,
391 .get = sd_getbrightness,
395 .id = V4L2_CID_CONTRAST,
396 .type = V4L2_CTRL_TYPE_INTEGER,
397 .name = "Contrast",
398 .minimum = 0,
399 .maximum = 96,
400 .step = 8,
401 #define CONTRAST_DEF 48
402 .default_value = CONTRAST_DEF,
404 .set = sd_setcontrast,
405 .get = sd_getcontrast,
409 .id = V4L2_CID_SATURATION,
410 .type = V4L2_CTRL_TYPE_INTEGER,
411 .name = "Saturation",
412 .minimum = 0,
413 .maximum = 100,
414 .step = 1,
415 #define SATURATION_DEF 50
416 .default_value = SATURATION_DEF,
418 .set = sd_setsaturation,
419 .get = sd_getsaturation,
423 .id = V4L2_CID_POWER_LINE_FREQUENCY,
424 .type = V4L2_CTRL_TYPE_MENU,
425 .name = "Light frequency filter",
426 .minimum = 0,
427 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
428 .step = 1,
429 #define FREQ_DEF 1
430 .default_value = FREQ_DEF,
432 .set = sd_setfreq,
433 .get = sd_getfreq,
437 #define V4L2_CID_COMP_TARGET V4L2_CID_PRIVATE_BASE
438 .id = V4L2_CID_COMP_TARGET,
439 .type = V4L2_CTRL_TYPE_MENU,
440 .name = "Compression Target",
441 .minimum = 0,
442 .maximum = 1,
443 .step = 1,
444 #define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
445 .default_value = COMP_TARGET_DEF,
447 .set = sd_setcomptarget,
448 .get = sd_getcomptarget,
452 static const struct v4l2_pix_format mode[] = {
453 {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
454 /* The sizeimage is trial and error, as with low framerates
455 the camera will pad out usb frames, making the image
456 data larger then strictly necessary */
457 .bytesperline = 160,
458 .sizeimage = 65536,
459 .colorspace = V4L2_COLORSPACE_SRGB,
460 .priv = 3},
461 {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
462 .bytesperline = 172,
463 .sizeimage = 65536,
464 .colorspace = V4L2_COLORSPACE_SRGB,
465 .priv = 2},
466 {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
467 .bytesperline = 320,
468 .sizeimage = 262144,
469 .colorspace = V4L2_COLORSPACE_SRGB,
470 .priv = 1},
471 {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
472 .bytesperline = 352,
473 .sizeimage = 262144,
474 .colorspace = V4L2_COLORSPACE_SRGB,
475 .priv = 0},
478 /**********************************************************************
480 * General functions
482 **********************************************************************/
484 static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
486 u8 requesttype;
487 unsigned int pipe;
488 int ret, databytes = command[6] | (command[7] << 8);
489 /* Sometimes we see spurious EPIPE errors */
490 int retries = 3;
492 if (command[0] == DATA_IN) {
493 pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
494 requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
495 } else if (command[0] == DATA_OUT) {
496 pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
497 requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
498 } else {
499 PDEBUG(D_ERR, "Unexpected first byte of command: %x",
500 command[0]);
501 return -EINVAL;
504 retry:
505 ret = usb_control_msg(gspca_dev->dev, pipe,
506 command[1],
507 requesttype,
508 command[2] | (command[3] << 8),
509 command[4] | (command[5] << 8),
510 gspca_dev->usb_buf, databytes, 1000);
512 if (ret < 0)
513 PDEBUG(D_ERR, "usb_control_msg %02x, error %d", command[1],
514 ret);
516 if (ret == -EPIPE && retries > 0) {
517 retries--;
518 goto retry;
521 return (ret < 0) ? ret : 0;
524 /* send an arbitrary command to the camera */
525 static int do_command(struct gspca_dev *gspca_dev, u16 command,
526 u8 a, u8 b, u8 c, u8 d)
528 struct sd *sd = (struct sd *) gspca_dev;
529 int ret, datasize;
530 u8 cmd[8];
532 switch (command) {
533 case CPIA_COMMAND_GetCPIAVersion:
534 case CPIA_COMMAND_GetPnPID:
535 case CPIA_COMMAND_GetCameraStatus:
536 case CPIA_COMMAND_GetVPVersion:
537 case CPIA_COMMAND_GetColourParams:
538 case CPIA_COMMAND_GetColourBalance:
539 case CPIA_COMMAND_GetExposure:
540 datasize = 8;
541 break;
542 case CPIA_COMMAND_ReadMCPorts:
543 case CPIA_COMMAND_ReadVCRegs:
544 datasize = 4;
545 break;
546 default:
547 datasize = 0;
548 break;
551 cmd[0] = command >> 8;
552 cmd[1] = command & 0xff;
553 cmd[2] = a;
554 cmd[3] = b;
555 cmd[4] = c;
556 cmd[5] = d;
557 cmd[6] = datasize;
558 cmd[7] = 0;
560 ret = cpia_usb_transferCmd(gspca_dev, cmd);
561 if (ret)
562 return ret;
564 switch (command) {
565 case CPIA_COMMAND_GetCPIAVersion:
566 sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
567 sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
568 sd->params.version.vcVersion = gspca_dev->usb_buf[2];
569 sd->params.version.vcRevision = gspca_dev->usb_buf[3];
570 break;
571 case CPIA_COMMAND_GetPnPID:
572 sd->params.pnpID.vendor =
573 gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
574 sd->params.pnpID.product =
575 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
576 sd->params.pnpID.deviceRevision =
577 gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
578 break;
579 case CPIA_COMMAND_GetCameraStatus:
580 sd->params.status.systemState = gspca_dev->usb_buf[0];
581 sd->params.status.grabState = gspca_dev->usb_buf[1];
582 sd->params.status.streamState = gspca_dev->usb_buf[2];
583 sd->params.status.fatalError = gspca_dev->usb_buf[3];
584 sd->params.status.cmdError = gspca_dev->usb_buf[4];
585 sd->params.status.debugFlags = gspca_dev->usb_buf[5];
586 sd->params.status.vpStatus = gspca_dev->usb_buf[6];
587 sd->params.status.errorCode = gspca_dev->usb_buf[7];
588 break;
589 case CPIA_COMMAND_GetVPVersion:
590 sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
591 sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
592 sd->params.vpVersion.cameraHeadID =
593 gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
594 break;
595 case CPIA_COMMAND_GetColourParams:
596 sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
597 sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
598 sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
599 break;
600 case CPIA_COMMAND_GetColourBalance:
601 sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
602 sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
603 sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
604 break;
605 case CPIA_COMMAND_GetExposure:
606 sd->params.exposure.gain = gspca_dev->usb_buf[0];
607 sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
608 sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
609 sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
610 sd->params.exposure.redComp = gspca_dev->usb_buf[4];
611 sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
612 sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
613 sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
614 break;
616 case CPIA_COMMAND_ReadMCPorts:
617 if (!sd->params.qx3.qx3_detected)
618 break;
619 /* test button press */
620 sd->params.qx3.button = ((gspca_dev->usb_buf[1] & 0x02) == 0);
621 if (sd->params.qx3.button) {
622 /* button pressed - unlock the latch */
623 do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
624 3, 0xDF, 0xDF, 0);
625 do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
626 3, 0xFF, 0xFF, 0);
629 /* test whether microscope is cradled */
630 sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
631 break;
634 return 0;
637 /* send a command to the camera with an additional data transaction */
638 static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
639 u8 a, u8 b, u8 c, u8 d,
640 u8 e, u8 f, u8 g, u8 h,
641 u8 i, u8 j, u8 k, u8 l)
643 u8 cmd[8];
645 cmd[0] = command >> 8;
646 cmd[1] = command & 0xff;
647 cmd[2] = a;
648 cmd[3] = b;
649 cmd[4] = c;
650 cmd[5] = d;
651 cmd[6] = 8;
652 cmd[7] = 0;
653 gspca_dev->usb_buf[0] = e;
654 gspca_dev->usb_buf[1] = f;
655 gspca_dev->usb_buf[2] = g;
656 gspca_dev->usb_buf[3] = h;
657 gspca_dev->usb_buf[4] = i;
658 gspca_dev->usb_buf[5] = j;
659 gspca_dev->usb_buf[6] = k;
660 gspca_dev->usb_buf[7] = l;
662 return cpia_usb_transferCmd(gspca_dev, cmd);
665 /* find_over_exposure
666 * Finds a suitable value of OverExposure for use with SetFlickerCtrl
667 * Some calculation is required because this value changes with the brightness
668 * set with SetColourParameters
670 * Parameters: Brightness - last brightness value set with SetColourParameters
672 * Returns: OverExposure value to use with SetFlickerCtrl
674 #define FLICKER_MAX_EXPOSURE 250
675 #define FLICKER_ALLOWABLE_OVER_EXPOSURE 146
676 #define FLICKER_BRIGHTNESS_CONSTANT 59
677 static int find_over_exposure(int brightness)
679 int MaxAllowableOverExposure, OverExposure;
681 MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
682 FLICKER_BRIGHTNESS_CONSTANT;
684 if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
685 OverExposure = MaxAllowableOverExposure;
686 else
687 OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
689 return OverExposure;
691 #undef FLICKER_MAX_EXPOSURE
692 #undef FLICKER_ALLOWABLE_OVER_EXPOSURE
693 #undef FLICKER_BRIGHTNESS_CONSTANT
695 /* initialise cam_data structure */
696 static void reset_camera_params(struct gspca_dev *gspca_dev)
698 struct sd *sd = (struct sd *) gspca_dev;
699 struct cam_params *params = &sd->params;
701 /* The following parameter values are the defaults from
702 * "Software Developer's Guide for CPiA Cameras". Any changes
703 * to the defaults are noted in comments. */
704 params->colourParams.brightness = BRIGHTNESS_DEF;
705 params->colourParams.contrast = CONTRAST_DEF;
706 params->colourParams.saturation = SATURATION_DEF;
707 params->exposure.gainMode = 4;
708 params->exposure.expMode = 2; /* AEC */
709 params->exposure.compMode = 1;
710 params->exposure.centreWeight = 1;
711 params->exposure.gain = 0;
712 params->exposure.fineExp = 0;
713 params->exposure.coarseExpLo = 185;
714 params->exposure.coarseExpHi = 0;
715 params->exposure.redComp = COMP_RED;
716 params->exposure.green1Comp = COMP_GREEN1;
717 params->exposure.green2Comp = COMP_GREEN2;
718 params->exposure.blueComp = COMP_BLUE;
719 params->colourBalance.balanceMode = 2; /* ACB */
720 params->colourBalance.redGain = 32;
721 params->colourBalance.greenGain = 6;
722 params->colourBalance.blueGain = 92;
723 params->apcor.gain1 = 0x18;
724 params->apcor.gain2 = 0x16;
725 params->apcor.gain4 = 0x24;
726 params->apcor.gain8 = 0x34;
727 params->flickerControl.flickerMode = 0;
728 params->flickerControl.disabled = 1;
730 params->flickerControl.coarseJump =
731 flicker_jumps[sd->mainsFreq]
732 [params->sensorFps.baserate]
733 [params->sensorFps.divisor];
734 params->flickerControl.allowableOverExposure =
735 find_over_exposure(params->colourParams.brightness);
736 params->vlOffset.gain1 = 20;
737 params->vlOffset.gain2 = 24;
738 params->vlOffset.gain4 = 26;
739 params->vlOffset.gain8 = 26;
740 params->compressionParams.hysteresis = 3;
741 params->compressionParams.threshMax = 11;
742 params->compressionParams.smallStep = 1;
743 params->compressionParams.largeStep = 3;
744 params->compressionParams.decimationHysteresis = 2;
745 params->compressionParams.frDiffStepThresh = 5;
746 params->compressionParams.qDiffStepThresh = 3;
747 params->compressionParams.decimationThreshMod = 2;
748 /* End of default values from Software Developer's Guide */
750 /* Set Sensor FPS to 15fps. This seems better than 30fps
751 * for indoor lighting. */
752 params->sensorFps.divisor = 1;
753 params->sensorFps.baserate = 1;
755 params->yuvThreshold.yThreshold = 6; /* From windows driver */
756 params->yuvThreshold.uvThreshold = 6; /* From windows driver */
758 params->format.subSample = SUBSAMPLE_420;
759 params->format.yuvOrder = YUVORDER_YUYV;
761 params->compression.mode = CPIA_COMPRESSION_AUTO;
762 params->compression.decimation = NO_DECIMATION;
764 params->compressionTarget.frTargeting = COMP_TARGET_DEF;
765 params->compressionTarget.targetFR = 15; /* From windows driver */
766 params->compressionTarget.targetQ = 5; /* From windows driver */
768 params->qx3.qx3_detected = 0;
769 params->qx3.toplight = 0;
770 params->qx3.bottomlight = 0;
771 params->qx3.button = 0;
772 params->qx3.cradled = 0;
775 static void printstatus(struct cam_params *params)
777 PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
778 params->status.systemState, params->status.grabState,
779 params->status.streamState, params->status.fatalError,
780 params->status.cmdError, params->status.debugFlags,
781 params->status.vpStatus, params->status.errorCode);
784 static int goto_low_power(struct gspca_dev *gspca_dev)
786 struct sd *sd = (struct sd *) gspca_dev;
787 int ret;
789 ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
790 if (ret)
791 return ret;
793 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
794 if (ret)
795 return ret;
797 if (sd->params.status.systemState != LO_POWER_STATE) {
798 if (sd->params.status.systemState != WARM_BOOT_STATE) {
799 PDEBUG(D_ERR,
800 "unexpected state after lo power cmd: %02x",
801 sd->params.status.systemState);
802 printstatus(&sd->params);
804 return -EIO;
807 PDEBUG(D_CONF, "camera now in LOW power state");
808 return 0;
811 static int goto_high_power(struct gspca_dev *gspca_dev)
813 struct sd *sd = (struct sd *) gspca_dev;
814 int ret;
816 ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
817 if (ret)
818 return ret;
820 msleep_interruptible(40); /* windows driver does it too */
822 if (signal_pending(current))
823 return -EINTR;
825 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
826 if (ret)
827 return ret;
829 if (sd->params.status.systemState != HI_POWER_STATE) {
830 PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
831 sd->params.status.systemState);
832 printstatus(&sd->params);
833 return -EIO;
836 PDEBUG(D_CONF, "camera now in HIGH power state");
837 return 0;
840 static int get_version_information(struct gspca_dev *gspca_dev)
842 int ret;
844 /* GetCPIAVersion */
845 ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
846 if (ret)
847 return ret;
849 /* GetPnPID */
850 return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
853 static int save_camera_state(struct gspca_dev *gspca_dev)
855 int ret;
857 ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
858 if (ret)
859 return ret;
861 return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
864 static int command_setformat(struct gspca_dev *gspca_dev)
866 struct sd *sd = (struct sd *) gspca_dev;
867 int ret;
869 ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
870 sd->params.format.videoSize,
871 sd->params.format.subSample,
872 sd->params.format.yuvOrder, 0);
873 if (ret)
874 return ret;
876 return do_command(gspca_dev, CPIA_COMMAND_SetROI,
877 sd->params.roi.colStart, sd->params.roi.colEnd,
878 sd->params.roi.rowStart, sd->params.roi.rowEnd);
881 static int command_setcolourparams(struct gspca_dev *gspca_dev)
883 struct sd *sd = (struct sd *) gspca_dev;
884 return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
885 sd->params.colourParams.brightness,
886 sd->params.colourParams.contrast,
887 sd->params.colourParams.saturation, 0);
890 static int command_setapcor(struct gspca_dev *gspca_dev)
892 struct sd *sd = (struct sd *) gspca_dev;
893 return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
894 sd->params.apcor.gain1,
895 sd->params.apcor.gain2,
896 sd->params.apcor.gain4,
897 sd->params.apcor.gain8);
900 static int command_setvloffset(struct gspca_dev *gspca_dev)
902 struct sd *sd = (struct sd *) gspca_dev;
903 return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
904 sd->params.vlOffset.gain1,
905 sd->params.vlOffset.gain2,
906 sd->params.vlOffset.gain4,
907 sd->params.vlOffset.gain8);
910 static int command_setexposure(struct gspca_dev *gspca_dev)
912 struct sd *sd = (struct sd *) gspca_dev;
913 int ret;
915 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
916 sd->params.exposure.gainMode,
918 sd->params.exposure.compMode,
919 sd->params.exposure.centreWeight,
920 sd->params.exposure.gain,
921 sd->params.exposure.fineExp,
922 sd->params.exposure.coarseExpLo,
923 sd->params.exposure.coarseExpHi,
924 sd->params.exposure.redComp,
925 sd->params.exposure.green1Comp,
926 sd->params.exposure.green2Comp,
927 sd->params.exposure.blueComp);
928 if (ret)
929 return ret;
931 if (sd->params.exposure.expMode != 1) {
932 ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
934 sd->params.exposure.expMode,
935 0, 0,
936 sd->params.exposure.gain,
937 sd->params.exposure.fineExp,
938 sd->params.exposure.coarseExpLo,
939 sd->params.exposure.coarseExpHi,
940 0, 0, 0, 0);
943 return ret;
946 static int command_setcolourbalance(struct gspca_dev *gspca_dev)
948 struct sd *sd = (struct sd *) gspca_dev;
950 if (sd->params.colourBalance.balanceMode == 1) {
951 int ret;
953 ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
955 sd->params.colourBalance.redGain,
956 sd->params.colourBalance.greenGain,
957 sd->params.colourBalance.blueGain);
958 if (ret)
959 return ret;
961 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
962 3, 0, 0, 0);
964 if (sd->params.colourBalance.balanceMode == 2) {
965 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
966 2, 0, 0, 0);
968 if (sd->params.colourBalance.balanceMode == 3) {
969 return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
970 3, 0, 0, 0);
973 return -EINVAL;
976 static int command_setcompressiontarget(struct gspca_dev *gspca_dev)
978 struct sd *sd = (struct sd *) gspca_dev;
980 return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
981 sd->params.compressionTarget.frTargeting,
982 sd->params.compressionTarget.targetFR,
983 sd->params.compressionTarget.targetQ, 0);
986 static int command_setyuvtresh(struct gspca_dev *gspca_dev)
988 struct sd *sd = (struct sd *) gspca_dev;
990 return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
991 sd->params.yuvThreshold.yThreshold,
992 sd->params.yuvThreshold.uvThreshold, 0, 0);
995 static int command_setcompressionparams(struct gspca_dev *gspca_dev)
997 struct sd *sd = (struct sd *) gspca_dev;
999 return do_command_extended(gspca_dev,
1000 CPIA_COMMAND_SetCompressionParams,
1001 0, 0, 0, 0,
1002 sd->params.compressionParams.hysteresis,
1003 sd->params.compressionParams.threshMax,
1004 sd->params.compressionParams.smallStep,
1005 sd->params.compressionParams.largeStep,
1006 sd->params.compressionParams.decimationHysteresis,
1007 sd->params.compressionParams.frDiffStepThresh,
1008 sd->params.compressionParams.qDiffStepThresh,
1009 sd->params.compressionParams.decimationThreshMod);
1012 static int command_setcompression(struct gspca_dev *gspca_dev)
1014 struct sd *sd = (struct sd *) gspca_dev;
1016 return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
1017 sd->params.compression.mode,
1018 sd->params.compression.decimation, 0, 0);
1021 static int command_setsensorfps(struct gspca_dev *gspca_dev)
1023 struct sd *sd = (struct sd *) gspca_dev;
1025 return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
1026 sd->params.sensorFps.divisor,
1027 sd->params.sensorFps.baserate, 0, 0);
1030 static int command_setflickerctrl(struct gspca_dev *gspca_dev)
1032 struct sd *sd = (struct sd *) gspca_dev;
1034 return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
1035 sd->params.flickerControl.flickerMode,
1036 sd->params.flickerControl.coarseJump,
1037 sd->params.flickerControl.allowableOverExposure,
1041 static int command_setecptiming(struct gspca_dev *gspca_dev)
1043 struct sd *sd = (struct sd *) gspca_dev;
1045 return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
1046 sd->params.ecpTiming, 0, 0, 0);
1049 static int command_pause(struct gspca_dev *gspca_dev)
1051 return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
1054 static int command_resume(struct gspca_dev *gspca_dev)
1056 struct sd *sd = (struct sd *) gspca_dev;
1058 return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
1059 0, sd->params.streamStartLine, 0, 0);
1063 static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
1065 /* Everything in here is from the Windows driver */
1066 /* define for compgain calculation */
1067 /* equivalent functions without floating point math */
1068 #define COMPGAIN(base, curexp, newexp) \
1069 (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
1070 #define EXP_FROM_COMP(basecomp, curcomp, curexp) \
1071 (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
1073 struct sd *sd = (struct sd *) gspca_dev;
1074 int currentexp = sd->params.exposure.coarseExpLo +
1075 sd->params.exposure.coarseExpHi * 256;
1076 int ret, startexp;
1078 if (on) {
1079 int cj = sd->params.flickerControl.coarseJump;
1080 sd->params.flickerControl.flickerMode = 1;
1081 sd->params.flickerControl.disabled = 0;
1082 if (sd->params.exposure.expMode != 2) {
1083 sd->params.exposure.expMode = 2;
1084 sd->exposure_status = EXPOSURE_NORMAL;
1086 currentexp = currentexp << sd->params.exposure.gain;
1087 sd->params.exposure.gain = 0;
1088 /* round down current exposure to nearest value */
1089 startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
1090 if (startexp < 1)
1091 startexp = 1;
1092 startexp = (startexp * cj) - 1;
1093 if (FIRMWARE_VERSION(1, 2))
1094 while (startexp > MAX_EXP_102)
1095 startexp -= cj;
1096 else
1097 while (startexp > MAX_EXP)
1098 startexp -= cj;
1099 sd->params.exposure.coarseExpLo = startexp & 0xff;
1100 sd->params.exposure.coarseExpHi = startexp >> 8;
1101 if (currentexp > startexp) {
1102 if (currentexp > (2 * startexp))
1103 currentexp = 2 * startexp;
1104 sd->params.exposure.redComp =
1105 COMPGAIN(COMP_RED, currentexp, startexp);
1106 sd->params.exposure.green1Comp =
1107 COMPGAIN(COMP_GREEN1, currentexp, startexp);
1108 sd->params.exposure.green2Comp =
1109 COMPGAIN(COMP_GREEN2, currentexp, startexp);
1110 sd->params.exposure.blueComp =
1111 COMPGAIN(COMP_BLUE, currentexp, startexp);
1112 } else {
1113 sd->params.exposure.redComp = COMP_RED;
1114 sd->params.exposure.green1Comp = COMP_GREEN1;
1115 sd->params.exposure.green2Comp = COMP_GREEN2;
1116 sd->params.exposure.blueComp = COMP_BLUE;
1118 if (FIRMWARE_VERSION(1, 2))
1119 sd->params.exposure.compMode = 0;
1120 else
1121 sd->params.exposure.compMode = 1;
1123 sd->params.apcor.gain1 = 0x18;
1124 sd->params.apcor.gain2 = 0x18;
1125 sd->params.apcor.gain4 = 0x16;
1126 sd->params.apcor.gain8 = 0x14;
1127 } else {
1128 sd->params.flickerControl.flickerMode = 0;
1129 sd->params.flickerControl.disabled = 1;
1130 /* Average equivalent coarse for each comp channel */
1131 startexp = EXP_FROM_COMP(COMP_RED,
1132 sd->params.exposure.redComp, currentexp);
1133 startexp += EXP_FROM_COMP(COMP_GREEN1,
1134 sd->params.exposure.green1Comp, currentexp);
1135 startexp += EXP_FROM_COMP(COMP_GREEN2,
1136 sd->params.exposure.green2Comp, currentexp);
1137 startexp += EXP_FROM_COMP(COMP_BLUE,
1138 sd->params.exposure.blueComp, currentexp);
1139 startexp = startexp >> 2;
1140 while (startexp > MAX_EXP && sd->params.exposure.gain <
1141 sd->params.exposure.gainMode - 1) {
1142 startexp = startexp >> 1;
1143 ++sd->params.exposure.gain;
1145 if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
1146 startexp = MAX_EXP_102;
1147 if (startexp > MAX_EXP)
1148 startexp = MAX_EXP;
1149 sd->params.exposure.coarseExpLo = startexp & 0xff;
1150 sd->params.exposure.coarseExpHi = startexp >> 8;
1151 sd->params.exposure.redComp = COMP_RED;
1152 sd->params.exposure.green1Comp = COMP_GREEN1;
1153 sd->params.exposure.green2Comp = COMP_GREEN2;
1154 sd->params.exposure.blueComp = COMP_BLUE;
1155 sd->params.exposure.compMode = 1;
1156 sd->params.apcor.gain1 = 0x18;
1157 sd->params.apcor.gain2 = 0x16;
1158 sd->params.apcor.gain4 = 0x24;
1159 sd->params.apcor.gain8 = 0x34;
1161 sd->params.vlOffset.gain1 = 20;
1162 sd->params.vlOffset.gain2 = 24;
1163 sd->params.vlOffset.gain4 = 26;
1164 sd->params.vlOffset.gain8 = 26;
1166 if (apply) {
1167 ret = command_setexposure(gspca_dev);
1168 if (ret)
1169 return ret;
1171 ret = command_setapcor(gspca_dev);
1172 if (ret)
1173 return ret;
1175 ret = command_setvloffset(gspca_dev);
1176 if (ret)
1177 return ret;
1179 ret = command_setflickerctrl(gspca_dev);
1180 if (ret)
1181 return ret;
1184 return 0;
1185 #undef EXP_FROM_COMP
1186 #undef COMPGAIN
1189 /* monitor the exposure and adjust the sensor frame rate if needed */
1190 static void monitor_exposure(struct gspca_dev *gspca_dev)
1192 struct sd *sd = (struct sd *) gspca_dev;
1193 u8 exp_acc, bcomp, gain, coarseL, cmd[8];
1194 int ret, light_exp, dark_exp, very_dark_exp;
1195 int old_exposure, new_exposure, framerate;
1196 int setfps = 0, setexp = 0, setflicker = 0;
1198 /* get necessary stats and register settings from camera */
1199 /* do_command can't handle this, so do it ourselves */
1200 cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
1201 cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
1202 cmd[2] = 30;
1203 cmd[3] = 4;
1204 cmd[4] = 9;
1205 cmd[5] = 8;
1206 cmd[6] = 8;
1207 cmd[7] = 0;
1208 ret = cpia_usb_transferCmd(gspca_dev, cmd);
1209 if (ret) {
1210 PDEBUG(D_ERR, "ReadVPRegs(30,4,9,8) - failed: %d", ret);
1211 return;
1213 exp_acc = gspca_dev->usb_buf[0];
1214 bcomp = gspca_dev->usb_buf[1];
1215 gain = gspca_dev->usb_buf[2];
1216 coarseL = gspca_dev->usb_buf[3];
1218 light_exp = sd->params.colourParams.brightness +
1219 TC - 50 + EXP_ACC_LIGHT;
1220 if (light_exp > 255)
1221 light_exp = 255;
1222 dark_exp = sd->params.colourParams.brightness +
1223 TC - 50 - EXP_ACC_DARK;
1224 if (dark_exp < 0)
1225 dark_exp = 0;
1226 very_dark_exp = dark_exp / 2;
1228 old_exposure = sd->params.exposure.coarseExpHi * 256 +
1229 sd->params.exposure.coarseExpLo;
1231 if (!sd->params.flickerControl.disabled) {
1232 /* Flicker control on */
1233 int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
1234 HIGH_COMP_102;
1235 bcomp += 128; /* decode */
1236 if (bcomp >= max_comp && exp_acc < dark_exp) {
1237 /* dark */
1238 if (exp_acc < very_dark_exp) {
1239 /* very dark */
1240 if (sd->exposure_status == EXPOSURE_VERY_DARK)
1241 ++sd->exposure_count;
1242 else {
1243 sd->exposure_status =
1244 EXPOSURE_VERY_DARK;
1245 sd->exposure_count = 1;
1247 } else {
1248 /* just dark */
1249 if (sd->exposure_status == EXPOSURE_DARK)
1250 ++sd->exposure_count;
1251 else {
1252 sd->exposure_status = EXPOSURE_DARK;
1253 sd->exposure_count = 1;
1256 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
1257 /* light */
1258 if (old_exposure <= VERY_LOW_EXP) {
1259 /* very light */
1260 if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
1261 ++sd->exposure_count;
1262 else {
1263 sd->exposure_status =
1264 EXPOSURE_VERY_LIGHT;
1265 sd->exposure_count = 1;
1267 } else {
1268 /* just light */
1269 if (sd->exposure_status == EXPOSURE_LIGHT)
1270 ++sd->exposure_count;
1271 else {
1272 sd->exposure_status = EXPOSURE_LIGHT;
1273 sd->exposure_count = 1;
1276 } else {
1277 /* not dark or light */
1278 sd->exposure_status = EXPOSURE_NORMAL;
1280 } else {
1281 /* Flicker control off */
1282 if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
1283 /* dark */
1284 if (exp_acc < very_dark_exp) {
1285 /* very dark */
1286 if (sd->exposure_status == EXPOSURE_VERY_DARK)
1287 ++sd->exposure_count;
1288 else {
1289 sd->exposure_status =
1290 EXPOSURE_VERY_DARK;
1291 sd->exposure_count = 1;
1293 } else {
1294 /* just dark */
1295 if (sd->exposure_status == EXPOSURE_DARK)
1296 ++sd->exposure_count;
1297 else {
1298 sd->exposure_status = EXPOSURE_DARK;
1299 sd->exposure_count = 1;
1302 } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
1303 /* light */
1304 if (old_exposure <= VERY_LOW_EXP) {
1305 /* very light */
1306 if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
1307 ++sd->exposure_count;
1308 else {
1309 sd->exposure_status =
1310 EXPOSURE_VERY_LIGHT;
1311 sd->exposure_count = 1;
1313 } else {
1314 /* just light */
1315 if (sd->exposure_status == EXPOSURE_LIGHT)
1316 ++sd->exposure_count;
1317 else {
1318 sd->exposure_status = EXPOSURE_LIGHT;
1319 sd->exposure_count = 1;
1322 } else {
1323 /* not dark or light */
1324 sd->exposure_status = EXPOSURE_NORMAL;
1328 framerate = atomic_read(&sd->fps);
1329 if (framerate > 30 || framerate < 1)
1330 framerate = 1;
1332 if (!sd->params.flickerControl.disabled) {
1333 /* Flicker control on */
1334 if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
1335 sd->exposure_status == EXPOSURE_DARK) &&
1336 sd->exposure_count >= DARK_TIME * framerate &&
1337 sd->params.sensorFps.divisor < 3) {
1339 /* dark for too long */
1340 ++sd->params.sensorFps.divisor;
1341 setfps = 1;
1343 sd->params.flickerControl.coarseJump =
1344 flicker_jumps[sd->mainsFreq]
1345 [sd->params.sensorFps.baserate]
1346 [sd->params.sensorFps.divisor];
1347 setflicker = 1;
1349 new_exposure = sd->params.flickerControl.coarseJump-1;
1350 while (new_exposure < old_exposure / 2)
1351 new_exposure +=
1352 sd->params.flickerControl.coarseJump;
1353 sd->params.exposure.coarseExpLo = new_exposure & 0xff;
1354 sd->params.exposure.coarseExpHi = new_exposure >> 8;
1355 setexp = 1;
1356 sd->exposure_status = EXPOSURE_NORMAL;
1357 PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
1359 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
1360 sd->exposure_status == EXPOSURE_LIGHT) &&
1361 sd->exposure_count >= LIGHT_TIME * framerate &&
1362 sd->params.sensorFps.divisor > 0) {
1364 /* light for too long */
1365 int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
1366 MAX_EXP;
1367 --sd->params.sensorFps.divisor;
1368 setfps = 1;
1370 sd->params.flickerControl.coarseJump =
1371 flicker_jumps[sd->mainsFreq]
1372 [sd->params.sensorFps.baserate]
1373 [sd->params.sensorFps.divisor];
1374 setflicker = 1;
1376 new_exposure = sd->params.flickerControl.coarseJump-1;
1377 while (new_exposure < 2 * old_exposure &&
1378 new_exposure +
1379 sd->params.flickerControl.coarseJump < max_exp)
1380 new_exposure +=
1381 sd->params.flickerControl.coarseJump;
1382 sd->params.exposure.coarseExpLo = new_exposure & 0xff;
1383 sd->params.exposure.coarseExpHi = new_exposure >> 8;
1384 setexp = 1;
1385 sd->exposure_status = EXPOSURE_NORMAL;
1386 PDEBUG(D_CONF, "Automatically increasing sensor_fps");
1388 } else {
1389 /* Flicker control off */
1390 if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
1391 sd->exposure_status == EXPOSURE_DARK) &&
1392 sd->exposure_count >= DARK_TIME * framerate &&
1393 sd->params.sensorFps.divisor < 3) {
1395 /* dark for too long */
1396 ++sd->params.sensorFps.divisor;
1397 setfps = 1;
1399 if (sd->params.exposure.gain > 0) {
1400 --sd->params.exposure.gain;
1401 setexp = 1;
1403 sd->exposure_status = EXPOSURE_NORMAL;
1404 PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
1406 } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
1407 sd->exposure_status == EXPOSURE_LIGHT) &&
1408 sd->exposure_count >= LIGHT_TIME * framerate &&
1409 sd->params.sensorFps.divisor > 0) {
1411 /* light for too long */
1412 --sd->params.sensorFps.divisor;
1413 setfps = 1;
1415 if (sd->params.exposure.gain <
1416 sd->params.exposure.gainMode - 1) {
1417 ++sd->params.exposure.gain;
1418 setexp = 1;
1420 sd->exposure_status = EXPOSURE_NORMAL;
1421 PDEBUG(D_CONF, "Automatically increasing sensor_fps");
1425 if (setexp)
1426 command_setexposure(gspca_dev);
1428 if (setfps)
1429 command_setsensorfps(gspca_dev);
1431 if (setflicker)
1432 command_setflickerctrl(gspca_dev);
1435 /*-----------------------------------------------------------------*/
1436 /* if flicker is switched off, this function switches it back on.It checks,
1437 however, that conditions are suitable before restarting it.
1438 This should only be called for firmware version 1.2.
1440 It also adjust the colour balance when an exposure step is detected - as
1441 long as flicker is running
1443 static void restart_flicker(struct gspca_dev *gspca_dev)
1445 struct sd *sd = (struct sd *) gspca_dev;
1446 int cam_exposure, old_exp;
1448 if (!FIRMWARE_VERSION(1, 2))
1449 return;
1451 cam_exposure = atomic_read(&sd->cam_exposure);
1453 if (sd->params.flickerControl.flickerMode == 0 ||
1454 cam_exposure == 0)
1455 return;
1457 old_exp = sd->params.exposure.coarseExpLo +
1458 sd->params.exposure.coarseExpHi*256;
1460 see how far away camera exposure is from a valid
1461 flicker exposure value
1463 cam_exposure %= sd->params.flickerControl.coarseJump;
1464 if (!sd->params.flickerControl.disabled &&
1465 cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
1466 /* Flicker control auto-disabled */
1467 sd->params.flickerControl.disabled = 1;
1470 if (sd->params.flickerControl.disabled &&
1471 old_exp > sd->params.flickerControl.coarseJump +
1472 ROUND_UP_EXP_FOR_FLICKER) {
1473 /* exposure is now high enough to switch
1474 flicker control back on */
1475 set_flicker(gspca_dev, 1, 1);
1479 /* this function is called at probe time */
1480 static int sd_config(struct gspca_dev *gspca_dev,
1481 const struct usb_device_id *id)
1483 struct cam *cam;
1485 reset_camera_params(gspca_dev);
1487 PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)",
1488 id->idVendor, id->idProduct);
1490 cam = &gspca_dev->cam;
1491 cam->cam_mode = mode;
1492 cam->nmodes = ARRAY_SIZE(mode);
1494 sd_setfreq(gspca_dev, FREQ_DEF);
1496 return 0;
1499 /* -- start the camera -- */
1500 static int sd_start(struct gspca_dev *gspca_dev)
1502 struct sd *sd = (struct sd *) gspca_dev;
1503 int priv, ret;
1505 /* Start the camera in low power mode */
1506 if (goto_low_power(gspca_dev)) {
1507 if (sd->params.status.systemState != WARM_BOOT_STATE) {
1508 PDEBUG(D_ERR, "unexpected systemstate: %02x",
1509 sd->params.status.systemState);
1510 printstatus(&sd->params);
1511 return -ENODEV;
1514 ret = goto_high_power(gspca_dev);
1515 if (ret)
1516 return ret;
1518 ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
1519 0, 0, 0, 0);
1520 if (ret)
1521 return ret;
1523 ret = goto_low_power(gspca_dev);
1524 if (ret)
1525 return ret;
1528 /* procedure described in developer's guide p3-28 */
1530 /* Check the firmware version. */
1531 sd->params.version.firmwareVersion = 0;
1532 get_version_information(gspca_dev);
1533 if (sd->params.version.firmwareVersion != 1) {
1534 PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
1535 sd->params.version.firmwareVersion);
1536 return -ENODEV;
1539 /* A bug in firmware 1-02 limits gainMode to 2 */
1540 if (sd->params.version.firmwareRevision <= 2 &&
1541 sd->params.exposure.gainMode > 2) {
1542 sd->params.exposure.gainMode = 2;
1545 /* set QX3 detected flag */
1546 sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
1547 sd->params.pnpID.product == 0x0001);
1549 /* The fatal error checking should be done after
1550 * the camera powers up (developer's guide p 3-38) */
1552 /* Set streamState before transition to high power to avoid bug
1553 * in firmware 1-02 */
1554 ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
1555 STREAMSTATE, 0, STREAM_NOT_READY, 0);
1556 if (ret)
1557 return ret;
1559 /* GotoHiPower */
1560 ret = goto_high_power(gspca_dev);
1561 if (ret)
1562 return ret;
1564 /* Check the camera status */
1565 ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
1566 if (ret)
1567 return ret;
1569 if (sd->params.status.fatalError) {
1570 PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
1571 sd->params.status.fatalError,
1572 sd->params.status.vpStatus);
1573 return -EIO;
1576 /* VPVersion can't be retrieved before the camera is in HiPower,
1577 * so get it here instead of in get_version_information. */
1578 ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
1579 if (ret)
1580 return ret;
1582 /* Determine video mode settings */
1583 sd->params.streamStartLine = 120;
1585 priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1586 if (priv & 0x01) { /* crop */
1587 sd->params.roi.colStart = 2;
1588 sd->params.roi.rowStart = 6;
1589 } else {
1590 sd->params.roi.colStart = 0;
1591 sd->params.roi.rowStart = 0;
1594 if (priv & 0x02) { /* quarter */
1595 sd->params.format.videoSize = VIDEOSIZE_QCIF;
1596 sd->params.roi.colStart /= 2;
1597 sd->params.roi.rowStart /= 2;
1598 sd->params.streamStartLine /= 2;
1599 } else
1600 sd->params.format.videoSize = VIDEOSIZE_CIF;
1602 sd->params.roi.colEnd = sd->params.roi.colStart +
1603 (gspca_dev->width >> 3);
1604 sd->params.roi.rowEnd = sd->params.roi.rowStart +
1605 (gspca_dev->height >> 2);
1607 /* And now set the camera to a known state */
1608 ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
1609 CPIA_GRAB_CONTINEOUS, 0, 0, 0);
1610 if (ret)
1611 return ret;
1612 /* We start with compression disabled, as we need one uncompressed
1613 frame to handle later compressed frames */
1614 ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
1615 CPIA_COMPRESSION_NONE,
1616 NO_DECIMATION, 0, 0);
1617 if (ret)
1618 return ret;
1619 ret = command_setcompressiontarget(gspca_dev);
1620 if (ret)
1621 return ret;
1622 ret = command_setcolourparams(gspca_dev);
1623 if (ret)
1624 return ret;
1625 ret = command_setformat(gspca_dev);
1626 if (ret)
1627 return ret;
1628 ret = command_setyuvtresh(gspca_dev);
1629 if (ret)
1630 return ret;
1631 ret = command_setecptiming(gspca_dev);
1632 if (ret)
1633 return ret;
1634 ret = command_setcompressionparams(gspca_dev);
1635 if (ret)
1636 return ret;
1637 ret = command_setexposure(gspca_dev);
1638 if (ret)
1639 return ret;
1640 ret = command_setcolourbalance(gspca_dev);
1641 if (ret)
1642 return ret;
1643 ret = command_setsensorfps(gspca_dev);
1644 if (ret)
1645 return ret;
1646 ret = command_setapcor(gspca_dev);
1647 if (ret)
1648 return ret;
1649 ret = command_setflickerctrl(gspca_dev);
1650 if (ret)
1651 return ret;
1652 ret = command_setvloffset(gspca_dev);
1653 if (ret)
1654 return ret;
1656 /* Start stream */
1657 ret = command_resume(gspca_dev);
1658 if (ret)
1659 return ret;
1661 /* Wait 6 frames before turning compression on for the sensor to get
1662 all settings and AEC/ACB to settle */
1663 sd->first_frame = 6;
1664 sd->exposure_status = EXPOSURE_NORMAL;
1665 sd->exposure_count = 0;
1666 atomic_set(&sd->cam_exposure, 0);
1667 atomic_set(&sd->fps, 0);
1669 return 0;
1672 static void sd_stopN(struct gspca_dev *gspca_dev)
1674 command_pause(gspca_dev);
1676 /* save camera state for later open (developers guide ch 3.5.3) */
1677 save_camera_state(gspca_dev);
1679 /* GotoLoPower */
1680 goto_low_power(gspca_dev);
1682 /* Update the camera status */
1683 do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
1686 /* this function is called at probe and resume time */
1687 static int sd_init(struct gspca_dev *gspca_dev)
1689 struct sd *sd = (struct sd *) gspca_dev;
1690 int ret;
1692 /* Start / Stop the camera to make sure we are talking to
1693 a supported camera, and to get some information from it
1694 to print. */
1695 ret = sd_start(gspca_dev);
1696 if (ret)
1697 return ret;
1699 sd_stopN(gspca_dev);
1701 PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)",
1702 sd->params.version.firmwareVersion,
1703 sd->params.version.firmwareRevision,
1704 sd->params.version.vcVersion,
1705 sd->params.version.vcRevision);
1706 PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x",
1707 sd->params.pnpID.vendor, sd->params.pnpID.product,
1708 sd->params.pnpID.deviceRevision);
1709 PDEBUG(D_PROBE, "VP-Version: %d.%d %04x",
1710 sd->params.vpVersion.vpVersion,
1711 sd->params.vpVersion.vpRevision,
1712 sd->params.vpVersion.cameraHeadID);
1714 return 0;
1717 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1718 u8 *data,
1719 int len)
1721 struct sd *sd = (struct sd *) gspca_dev;
1723 /* Check for SOF */
1724 if (len >= 64 &&
1725 data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
1726 data[16] == sd->params.format.videoSize &&
1727 data[17] == sd->params.format.subSample &&
1728 data[18] == sd->params.format.yuvOrder &&
1729 data[24] == sd->params.roi.colStart &&
1730 data[25] == sd->params.roi.colEnd &&
1731 data[26] == sd->params.roi.rowStart &&
1732 data[27] == sd->params.roi.rowEnd) {
1733 u8 *image;
1735 atomic_set(&sd->cam_exposure, data[39] * 2);
1736 atomic_set(&sd->fps, data[41]);
1738 /* Check for proper EOF for last frame */
1739 image = gspca_dev->image;
1740 if (image != NULL &&
1741 gspca_dev->image_len > 4 &&
1742 image[gspca_dev->image_len - 4] == 0xff &&
1743 image[gspca_dev->image_len - 3] == 0xff &&
1744 image[gspca_dev->image_len - 2] == 0xff &&
1745 image[gspca_dev->image_len - 1] == 0xff)
1746 gspca_frame_add(gspca_dev, LAST_PACKET,
1747 NULL, 0);
1749 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
1750 return;
1753 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1756 static void sd_dq_callback(struct gspca_dev *gspca_dev)
1758 struct sd *sd = (struct sd *) gspca_dev;
1760 /* Set the normal compression settings once we have captured a
1761 few uncompressed frames (and AEC has hopefully settled) */
1762 if (sd->first_frame) {
1763 sd->first_frame--;
1764 if (sd->first_frame == 0)
1765 command_setcompression(gspca_dev);
1768 /* Switch flicker control back on if it got turned off */
1769 restart_flicker(gspca_dev);
1771 /* If AEC is enabled, monitor the exposure and
1772 adjust the sensor frame rate if needed */
1773 if (sd->params.exposure.expMode == 2)
1774 monitor_exposure(gspca_dev);
1776 /* Update our knowledge of the camera state */
1777 do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
1778 if (sd->params.qx3.qx3_detected)
1779 do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
1782 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1784 struct sd *sd = (struct sd *) gspca_dev;
1785 int ret;
1787 sd->params.colourParams.brightness = val;
1788 sd->params.flickerControl.allowableOverExposure =
1789 find_over_exposure(sd->params.colourParams.brightness);
1790 if (gspca_dev->streaming) {
1791 ret = command_setcolourparams(gspca_dev);
1792 if (ret)
1793 return ret;
1794 return command_setflickerctrl(gspca_dev);
1796 return 0;
1799 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1801 struct sd *sd = (struct sd *) gspca_dev;
1803 *val = sd->params.colourParams.brightness;
1804 return 0;
1807 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1809 struct sd *sd = (struct sd *) gspca_dev;
1811 sd->params.colourParams.contrast = val;
1812 if (gspca_dev->streaming)
1813 return command_setcolourparams(gspca_dev);
1815 return 0;
1818 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1820 struct sd *sd = (struct sd *) gspca_dev;
1822 *val = sd->params.colourParams.contrast;
1823 return 0;
1826 static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
1828 struct sd *sd = (struct sd *) gspca_dev;
1830 sd->params.colourParams.saturation = val;
1831 if (gspca_dev->streaming)
1832 return command_setcolourparams(gspca_dev);
1834 return 0;
1837 static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
1839 struct sd *sd = (struct sd *) gspca_dev;
1841 *val = sd->params.colourParams.saturation;
1842 return 0;
1845 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1847 struct sd *sd = (struct sd *) gspca_dev;
1848 int on;
1850 switch (val) {
1851 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1852 on = 0;
1853 break;
1854 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1855 on = 1;
1856 sd->mainsFreq = 0;
1857 break;
1858 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1859 on = 1;
1860 sd->mainsFreq = 1;
1861 break;
1862 default:
1863 return -EINVAL;
1866 sd->freq = val;
1867 sd->params.flickerControl.coarseJump =
1868 flicker_jumps[sd->mainsFreq]
1869 [sd->params.sensorFps.baserate]
1870 [sd->params.sensorFps.divisor];
1872 return set_flicker(gspca_dev, on, gspca_dev->streaming);
1875 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1877 struct sd *sd = (struct sd *) gspca_dev;
1879 *val = sd->freq;
1880 return 0;
1883 static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val)
1885 struct sd *sd = (struct sd *) gspca_dev;
1887 sd->params.compressionTarget.frTargeting = val;
1888 if (gspca_dev->streaming)
1889 return command_setcompressiontarget(gspca_dev);
1891 return 0;
1894 static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val)
1896 struct sd *sd = (struct sd *) gspca_dev;
1898 *val = sd->params.compressionTarget.frTargeting;
1899 return 0;
1902 static int sd_querymenu(struct gspca_dev *gspca_dev,
1903 struct v4l2_querymenu *menu)
1905 switch (menu->id) {
1906 case V4L2_CID_POWER_LINE_FREQUENCY:
1907 switch (menu->index) {
1908 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1909 strcpy((char *) menu->name, "NoFliker");
1910 return 0;
1911 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1912 strcpy((char *) menu->name, "50 Hz");
1913 return 0;
1914 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1915 strcpy((char *) menu->name, "60 Hz");
1916 return 0;
1918 break;
1919 case V4L2_CID_COMP_TARGET:
1920 switch (menu->index) {
1921 case CPIA_COMPRESSION_TARGET_QUALITY:
1922 strcpy((char *) menu->name, "Quality");
1923 return 0;
1924 case CPIA_COMPRESSION_TARGET_FRAMERATE:
1925 strcpy((char *) menu->name, "Framerate");
1926 return 0;
1928 break;
1930 return -EINVAL;
1933 /* sub-driver description */
1934 static const struct sd_desc sd_desc = {
1935 .name = MODULE_NAME,
1936 .ctrls = sd_ctrls,
1937 .nctrls = ARRAY_SIZE(sd_ctrls),
1938 .config = sd_config,
1939 .init = sd_init,
1940 .start = sd_start,
1941 .stopN = sd_stopN,
1942 .dq_callback = sd_dq_callback,
1943 .pkt_scan = sd_pkt_scan,
1944 .querymenu = sd_querymenu,
1947 /* -- module initialisation -- */
1948 static const __devinitdata struct usb_device_id device_table[] = {
1949 {USB_DEVICE(0x0553, 0x0002)},
1950 {USB_DEVICE(0x0813, 0x0001)},
1953 MODULE_DEVICE_TABLE(usb, device_table);
1955 /* -- device connect -- */
1956 static int sd_probe(struct usb_interface *intf,
1957 const struct usb_device_id *id)
1959 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1960 THIS_MODULE);
1963 static struct usb_driver sd_driver = {
1964 .name = MODULE_NAME,
1965 .id_table = device_table,
1966 .probe = sd_probe,
1967 .disconnect = gspca_disconnect,
1968 #ifdef CONFIG_PM
1969 .suspend = gspca_suspend,
1970 .resume = gspca_resume,
1971 #endif
1974 /* -- module insert / remove -- */
1975 static int __init sd_mod_init(void)
1977 int ret;
1978 ret = usb_register(&sd_driver);
1979 if (ret < 0)
1980 return ret;
1981 PDEBUG(D_PROBE, "registered");
1982 return 0;
1984 static void __exit sd_mod_exit(void)
1986 usb_deregister(&sd_driver);
1987 PDEBUG(D_PROBE, "deregistered");
1990 module_init(sd_mod_init);
1991 module_exit(sd_mod_exit);