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