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