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