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