[media] gspca_pac7311: Properly set the compression balance
[deliverable/linux.git] / drivers / media / video / gspca / pac7302.c
CommitLineData
1408b847 1/*
ae251e6b 2 * Pixart PAC7302 driver
1408b847 3 *
ae251e6b
JFM
4 * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
1408b847 6 *
cc2f82c2 7 * Separated from Pixart PAC7311 library by Márton Németh
aed6f1b5
MN
8 * Camera button input handling by Márton Németh <nm127@freemail.hu>
9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
1408b847
MN
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26/* Some documentation about various registers as determined by trial and error.
1408b847
MN
27
28 Register page 1:
29
30 Address Description
1408b847 31 0x78 Global control, bit 6 controls the LED (inverted)
1408b847 32
5fb2dde2 33 Register page 3:
1408b847
MN
34
35 Address Description
5fb2dde2 36 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
1408b847 37 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
5fb2dde2
HG
38 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
39 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
40 63 -> ~27 fps, the 2 msb's must always be 1 !!
41 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
42 1 -> ~30 fps, 2 -> ~20 fps
43 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
44 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
45 0x10 Master gain 0-31
1408b847 46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
265a8098
MN
47
48 The registers are accessed in the following functions:
49
50 Page | Register | Function
51 -----+------------+---------------------------------------------------
52 0 | 0x0f..0x20 | setcolors()
53 0 | 0xa2..0xab | setbrightcont()
54 0 | 0xc5 | setredbalance()
23fbee6f 55 0 | 0xc6 | setwhitebalance()
265a8098
MN
56 0 | 0xc7 | setbluebalance()
57 0 | 0xdc | setbrightcont(), setcolors()
58 3 | 0x02 | setexposure()
59 3 | 0x10 | setgain()
60 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
61 3 | 0x21 | sethvflip()
1408b847
MN
62*/
63
133a9fe9
JP
64#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
65
aed6f1b5 66#include <linux/input.h>
6763cc0e 67#include <media/v4l2-chip-ident.h>
1408b847 68#include "gspca.h"
ac399cd3
JFM
69/* Include pac common sof detection functions */
70#include "pac_common.h"
1408b847 71
ae251e6b
JFM
72MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
73 "Thomas Kaiser thomas@kaiser-linux.li");
1408b847
MN
74MODULE_DESCRIPTION("Pixart PAC7302");
75MODULE_LICENSE("GPL");
76
aa5b7925
JFM
77enum e_ctrl {
78 BRIGHTNESS,
79 CONTRAST,
80 COLORS,
81 WHITE_BALANCE,
82 RED_BALANCE,
83 BLUE_BALANCE,
84 GAIN,
85 AUTOGAIN,
86 EXPOSURE,
87 VFLIP,
88 HFLIP,
89 NCTRLS /* number of controls */
90};
91
1408b847
MN
92struct sd {
93 struct gspca_dev gspca_dev; /* !! must be the first item */
94
aa5b7925
JFM
95 struct gspca_ctrl ctrls[NCTRLS];
96
fe2b6032
JFM
97 u8 flags;
98#define FL_HFLIP 0x01 /* mirrored by default */
99#define FL_VFLIP 0x02 /* vertical flipped by default */
1408b847
MN
100
101 u8 sof_read;
ac399cd3 102 s8 autogain_ignore_frames;
1408b847
MN
103
104 atomic_t avg_lum;
105};
106
107/* V4L2 controls supported by the driver */
aa5b7925
JFM
108static void setbrightcont(struct gspca_dev *gspca_dev);
109static void setcolors(struct gspca_dev *gspca_dev);
110static void setwhitebalance(struct gspca_dev *gspca_dev);
111static void setredbalance(struct gspca_dev *gspca_dev);
112static void setbluebalance(struct gspca_dev *gspca_dev);
113static void setgain(struct gspca_dev *gspca_dev);
114static void setexposure(struct gspca_dev *gspca_dev);
ac399cd3 115static void setautogain(struct gspca_dev *gspca_dev);
aa5b7925 116static void sethvflip(struct gspca_dev *gspca_dev);
1408b847 117
7e64dc4c 118static const struct ctrl sd_ctrls[] = {
aa5b7925 119[BRIGHTNESS] = {
1408b847
MN
120 {
121 .id = V4L2_CID_BRIGHTNESS,
122 .type = V4L2_CTRL_TYPE_INTEGER,
123 .name = "Brightness",
124 .minimum = 0,
125#define BRIGHTNESS_MAX 0x20
126 .maximum = BRIGHTNESS_MAX,
127 .step = 1,
aa5b7925 128 .default_value = 0x10,
1408b847 129 },
aa5b7925 130 .set_control = setbrightcont
1408b847 131 },
aa5b7925 132[CONTRAST] = {
1408b847
MN
133 {
134 .id = V4L2_CID_CONTRAST,
135 .type = V4L2_CTRL_TYPE_INTEGER,
136 .name = "Contrast",
137 .minimum = 0,
138#define CONTRAST_MAX 255
139 .maximum = CONTRAST_MAX,
140 .step = 1,
aa5b7925 141 .default_value = 127,
1408b847 142 },
aa5b7925 143 .set_control = setbrightcont
1408b847 144 },
aa5b7925 145[COLORS] = {
1408b847
MN
146 {
147 .id = V4L2_CID_SATURATION,
148 .type = V4L2_CTRL_TYPE_INTEGER,
149 .name = "Saturation",
150 .minimum = 0,
151#define COLOR_MAX 255
152 .maximum = COLOR_MAX,
153 .step = 1,
aa5b7925 154 .default_value = 127
1408b847 155 },
aa5b7925 156 .set_control = setcolors
1408b847 157 },
aa5b7925 158[WHITE_BALANCE] = {
23fbee6f
MN
159 {
160 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
161 .type = V4L2_CTRL_TYPE_INTEGER,
162 .name = "White Balance",
163 .minimum = 0,
164 .maximum = 255,
165 .step = 1,
aa5b7925 166 .default_value = 4,
23fbee6f 167 },
aa5b7925 168 .set_control = setwhitebalance
23fbee6f 169 },
aa5b7925 170[RED_BALANCE] = {
265a8098
MN
171 {
172 .id = V4L2_CID_RED_BALANCE,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 .name = "Red",
175 .minimum = 0,
176 .maximum = 3,
177 .step = 1,
aa5b7925 178 .default_value = 1,
265a8098 179 },
aa5b7925 180 .set_control = setredbalance
265a8098 181 },
aa5b7925 182[BLUE_BALANCE] = {
265a8098
MN
183 {
184 .id = V4L2_CID_BLUE_BALANCE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "Blue",
187 .minimum = 0,
188 .maximum = 3,
189 .step = 1,
aa5b7925 190 .default_value = 1,
265a8098 191 },
aa5b7925 192 .set_control = setbluebalance
265a8098 193 },
aa5b7925 194[GAIN] = {
1408b847
MN
195 {
196 .id = V4L2_CID_GAIN,
197 .type = V4L2_CTRL_TYPE_INTEGER,
198 .name = "Gain",
199 .minimum = 0,
aa5b7925 200 .maximum = 255,
1408b847
MN
201 .step = 1,
202#define GAIN_DEF 127
203#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
204 .default_value = GAIN_DEF,
205 },
aa5b7925 206 .set_control = setgain
1408b847 207 },
aa5b7925 208[EXPOSURE] = {
1408b847
MN
209 {
210 .id = V4L2_CID_EXPOSURE,
211 .type = V4L2_CTRL_TYPE_INTEGER,
212 .name = "Exposure",
213 .minimum = 0,
5fb2dde2 214 .maximum = 1023,
1408b847 215 .step = 1,
5fb2dde2
HG
216#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
217#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
1408b847
MN
218 .default_value = EXPOSURE_DEF,
219 },
aa5b7925 220 .set_control = setexposure
1408b847 221 },
aa5b7925 222[AUTOGAIN] = {
1408b847
MN
223 {
224 .id = V4L2_CID_AUTOGAIN,
225 .type = V4L2_CTRL_TYPE_BOOLEAN,
226 .name = "Auto Gain",
227 .minimum = 0,
228 .maximum = 1,
229 .step = 1,
230#define AUTOGAIN_DEF 1
231 .default_value = AUTOGAIN_DEF,
232 },
ac399cd3 233 .set_control = setautogain,
1408b847 234 },
aa5b7925 235[HFLIP] = {
1408b847
MN
236 {
237 .id = V4L2_CID_HFLIP,
238 .type = V4L2_CTRL_TYPE_BOOLEAN,
239 .name = "Mirror",
240 .minimum = 0,
241 .maximum = 1,
242 .step = 1,
aa5b7925 243 .default_value = 0,
1408b847 244 },
aa5b7925 245 .set_control = sethvflip,
1408b847 246 },
aa5b7925 247[VFLIP] = {
1408b847
MN
248 {
249 .id = V4L2_CID_VFLIP,
250 .type = V4L2_CTRL_TYPE_BOOLEAN,
251 .name = "Vflip",
252 .minimum = 0,
253 .maximum = 1,
254 .step = 1,
aa5b7925 255 .default_value = 0,
1408b847 256 },
aa5b7925 257 .set_control = sethvflip
1408b847
MN
258 },
259};
260
261static const struct v4l2_pix_format vga_mode[] = {
262 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
263 .bytesperline = 640,
264 .sizeimage = 640 * 480 * 3 / 8 + 590,
265 .colorspace = V4L2_COLORSPACE_JPEG,
ae251e6b 266 },
1408b847
MN
267};
268
269#define LOAD_PAGE3 255
1408b847
MN
270#define END_OF_SEQUENCE 0
271
ae251e6b 272static const u8 init_7302[] = {
1408b847
MN
273/* index,value */
274 0xff, 0x01, /* page 1 */
275 0x78, 0x00, /* deactivate */
276 0xff, 0x01,
277 0x78, 0x40, /* led off */
278};
ae251e6b 279static const u8 start_7302[] = {
1408b847
MN
280/* index, len, [value]* */
281 0xff, 1, 0x00, /* page 0 */
282 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
283 0x00, 0x00, 0x00, 0x00,
284 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
285 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
286 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
287 0x26, 2, 0xaa, 0xaa,
288 0x2e, 1, 0x31,
289 0x38, 1, 0x01,
290 0x3a, 3, 0x14, 0xff, 0x5a,
291 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
292 0x00, 0x54, 0x11,
293 0x55, 1, 0x00,
ae251e6b 294 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
1408b847
MN
295 0x6b, 1, 0x00,
296 0x6e, 3, 0x08, 0x06, 0x00,
297 0x72, 3, 0x00, 0xff, 0x00,
298 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
299 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
300 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
301 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
302 0xd2, 0xeb,
303 0xaf, 1, 0x02,
304 0xb5, 2, 0x08, 0x08,
305 0xb8, 2, 0x08, 0x88,
306 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
307 0xcc, 1, 0x00,
308 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
309 0xc1, 0xd7, 0xec,
310 0xdc, 1, 0x01,
311 0xff, 1, 0x01, /* page 1 */
312 0x12, 3, 0x02, 0x00, 0x01,
313 0x3e, 2, 0x00, 0x00,
314 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
315 0x7c, 1, 0x00,
316 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
317 0x02, 0x00,
318 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
319 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
320 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
321 0xd8, 1, 0x01,
322 0xdb, 2, 0x00, 0x01,
323 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
324 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
325 0xeb, 1, 0x00,
326 0xff, 1, 0x02, /* page 2 */
327 0x22, 1, 0x00,
328 0xff, 1, 0x03, /* page 3 */
329 0, LOAD_PAGE3, /* load the page 3 */
330 0x11, 1, 0x01,
331 0xff, 1, 0x02, /* page 2 */
332 0x13, 1, 0x00,
333 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
334 0x27, 2, 0x14, 0x0c,
335 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
336 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
337 0x6e, 1, 0x08,
338 0xff, 1, 0x01, /* page 1 */
339 0x78, 1, 0x00,
340 0, END_OF_SEQUENCE /* end of sequence */
341};
342
343#define SKIP 0xaa
344/* page 3 - the value SKIP says skip the index - see reg_w_page() */
ae251e6b 345static const u8 page3_7302[] = {
5fb2dde2 346 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
1408b847
MN
347 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
348 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
350 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
351 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
352 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
353 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
cdf955cd 355 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
1408b847
MN
356 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
360 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
361 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
362 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
365 0x00
366};
367
be927bef 368static void reg_w_buf(struct gspca_dev *gspca_dev,
ae251e6b 369 u8 index,
0aeb5ec7 370 const u8 *buffer, int len)
1408b847 371{
4f7309e2
MN
372 int ret;
373
be927bef
JFM
374 if (gspca_dev->usb_err < 0)
375 return;
1408b847 376 memcpy(gspca_dev->usb_buf, buffer, len);
4f7309e2 377 ret = usb_control_msg(gspca_dev->dev,
1408b847 378 usb_sndctrlpipe(gspca_dev->dev, 0),
a1317135 379 0, /* request */
1408b847
MN
380 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
381 0, /* value */
382 index, gspca_dev->usb_buf, len,
383 500);
be927bef 384 if (ret < 0) {
ae251e6b 385 pr_err("reg_w_buf failed i: %02x error %d\n",
133a9fe9 386 index, ret);
be927bef
JFM
387 gspca_dev->usb_err = ret;
388 }
1408b847
MN
389}
390
391
be927bef 392static void reg_w(struct gspca_dev *gspca_dev,
ae251e6b
JFM
393 u8 index,
394 u8 value)
1408b847 395{
4f7309e2
MN
396 int ret;
397
be927bef
JFM
398 if (gspca_dev->usb_err < 0)
399 return;
1408b847 400 gspca_dev->usb_buf[0] = value;
4f7309e2 401 ret = usb_control_msg(gspca_dev->dev,
1408b847
MN
402 usb_sndctrlpipe(gspca_dev->dev, 0),
403 0, /* request */
404 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
405 0, index, gspca_dev->usb_buf, 1,
406 500);
be927bef 407 if (ret < 0) {
ae251e6b 408 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
133a9fe9 409 index, value, ret);
be927bef
JFM
410 gspca_dev->usb_err = ret;
411 }
1408b847
MN
412}
413
be927bef 414static void reg_w_seq(struct gspca_dev *gspca_dev,
ae251e6b 415 const u8 *seq, int len)
1408b847
MN
416{
417 while (--len >= 0) {
be927bef 418 reg_w(gspca_dev, seq[0], seq[1]);
1408b847
MN
419 seq += 2;
420 }
421}
422
423/* load the beginning of a page */
be927bef 424static void reg_w_page(struct gspca_dev *gspca_dev,
ae251e6b 425 const u8 *page, int len)
1408b847
MN
426{
427 int index;
b1784b33 428 int ret = 0;
1408b847 429
be927bef
JFM
430 if (gspca_dev->usb_err < 0)
431 return;
1408b847
MN
432 for (index = 0; index < len; index++) {
433 if (page[index] == SKIP) /* skip this index */
434 continue;
435 gspca_dev->usb_buf[0] = page[index];
4f7309e2 436 ret = usb_control_msg(gspca_dev->dev,
1408b847
MN
437 usb_sndctrlpipe(gspca_dev->dev, 0),
438 0, /* request */
439 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
440 0, index, gspca_dev->usb_buf, 1,
441 500);
b1784b33 442 if (ret < 0) {
ae251e6b 443 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
133a9fe9 444 index, page[index], ret);
be927bef 445 gspca_dev->usb_err = ret;
b1784b33
MN
446 break;
447 }
1408b847
MN
448 }
449}
450
451/* output a variable sequence */
be927bef 452static void reg_w_var(struct gspca_dev *gspca_dev,
ae251e6b
JFM
453 const u8 *seq,
454 const u8 *page3, unsigned int page3_len)
1408b847
MN
455{
456 int index, len;
457
458 for (;;) {
459 index = *seq++;
460 len = *seq++;
461 switch (len) {
462 case END_OF_SEQUENCE:
be927bef 463 return;
1408b847 464 case LOAD_PAGE3:
be927bef 465 reg_w_page(gspca_dev, page3, page3_len);
1408b847
MN
466 break;
467 default:
ae251e6b 468#ifdef GSPCA_DEBUG
1408b847
MN
469 if (len > USB_BUF_SZ) {
470 PDEBUG(D_ERR|D_STREAM,
471 "Incorrect variable sequence");
be927bef 472 return;
1408b847 473 }
ae251e6b 474#endif
1408b847
MN
475 while (len > 0) {
476 if (len < 8) {
be927bef 477 reg_w_buf(gspca_dev,
b1784b33 478 index, seq, len);
1408b847
MN
479 seq += len;
480 break;
481 }
be927bef 482 reg_w_buf(gspca_dev, index, seq, 8);
1408b847
MN
483 seq += 8;
484 index += 8;
485 len -= 8;
486 }
487 }
488 }
489 /* not reached */
490}
491
492/* this function is called at probe time for pac7302 */
493static int sd_config(struct gspca_dev *gspca_dev,
494 const struct usb_device_id *id)
495{
496 struct sd *sd = (struct sd *) gspca_dev;
497 struct cam *cam;
498
499 cam = &gspca_dev->cam;
500
1408b847
MN
501 cam->cam_mode = vga_mode; /* only 640x480 */
502 cam->nmodes = ARRAY_SIZE(vga_mode);
503
aa5b7925
JFM
504 gspca_dev->cam.ctrls = sd->ctrls;
505
fe2b6032 506 sd->flags = id->driver_info;
1408b847
MN
507 return 0;
508}
509
be927bef 510static void setbrightcont(struct gspca_dev *gspca_dev)
1408b847
MN
511{
512 struct sd *sd = (struct sd *) gspca_dev;
513 int i, v;
ae251e6b 514 static const u8 max[10] =
1408b847
MN
515 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
516 0xd4, 0xec};
ae251e6b 517 static const u8 delta[10] =
1408b847
MN
518 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
519 0x11, 0x0b};
520
be927bef 521 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1408b847
MN
522 for (i = 0; i < 10; i++) {
523 v = max[i];
aa5b7925 524 v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX)
1408b847 525 * 150 / BRIGHTNESS_MAX; /* 200 ? */
aa5b7925 526 v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX;
1408b847
MN
527 if (v < 0)
528 v = 0;
529 else if (v > 0xff)
530 v = 0xff;
be927bef 531 reg_w(gspca_dev, 0xa2 + i, v);
1408b847 532 }
be927bef 533 reg_w(gspca_dev, 0xdc, 0x01);
1408b847
MN
534}
535
be927bef 536static void setcolors(struct gspca_dev *gspca_dev)
1408b847
MN
537{
538 struct sd *sd = (struct sd *) gspca_dev;
539 int i, v;
540 static const int a[9] =
541 {217, -212, 0, -101, 170, -67, -38, -315, 355};
542 static const int b[9] =
543 {19, 106, 0, 19, 106, 1, 19, 106, 1};
544
be927bef
JFM
545 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
546 reg_w(gspca_dev, 0x11, 0x01);
547 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1408b847 548 for (i = 0; i < 9; i++) {
aa5b7925 549 v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i];
be927bef
JFM
550 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
551 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
1408b847 552 }
be927bef 553 reg_w(gspca_dev, 0xdc, 0x01);
1408b847
MN
554}
555
be927bef 556static void setwhitebalance(struct gspca_dev *gspca_dev)
23fbee6f
MN
557{
558 struct sd *sd = (struct sd *) gspca_dev;
23fbee6f 559
be927bef 560 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
aa5b7925 561 reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val);
23fbee6f 562
be927bef 563 reg_w(gspca_dev, 0xdc, 0x01);
23fbee6f
MN
564}
565
be927bef 566static void setredbalance(struct gspca_dev *gspca_dev)
265a8098
MN
567{
568 struct sd *sd = (struct sd *) gspca_dev;
265a8098 569
be927bef 570 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
aa5b7925 571 reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val);
265a8098 572
be927bef 573 reg_w(gspca_dev, 0xdc, 0x01);
265a8098
MN
574}
575
be927bef 576static void setbluebalance(struct gspca_dev *gspca_dev)
265a8098
MN
577{
578 struct sd *sd = (struct sd *) gspca_dev;
265a8098 579
be927bef 580 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
aa5b7925 581 reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val);
265a8098 582
be927bef 583 reg_w(gspca_dev, 0xdc, 0x01);
265a8098
MN
584}
585
be927bef 586static void setgain(struct gspca_dev *gspca_dev)
1408b847
MN
587{
588 struct sd *sd = (struct sd *) gspca_dev;
589
be927bef 590 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
aa5b7925 591 reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3);
1408b847
MN
592
593 /* load registers to sensor (Bit 0, auto clear) */
be927bef 594 reg_w(gspca_dev, 0x11, 0x01);
1408b847
MN
595}
596
be927bef 597static void setexposure(struct gspca_dev *gspca_dev)
1408b847
MN
598{
599 struct sd *sd = (struct sd *) gspca_dev;
ae251e6b
JFM
600 u8 clockdiv;
601 u16 exposure;
5fb2dde2
HG
602
603 /* register 2 of frame 3 contains the clock divider configuring the
604 no fps according to the formula: 90 / reg. sd->exposure is the
605 desired exposure time in 0.5 ms. */
aa5b7925 606 clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000;
5fb2dde2
HG
607
608 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
609 on the scene being recorded, the camera switches to another
610 quantization table for certain JPEG blocks, and we don't know how
611 to decompress these blocks. So we cap the framerate at 15 fps */
612 if (clockdiv < 6)
613 clockdiv = 6;
614 else if (clockdiv > 63)
615 clockdiv = 63;
616
617 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
618 Always round up, otherwise we cannot get the desired frametime
619 using the partial frame time exposure control */
620 if (clockdiv < 6 || clockdiv > 12)
621 clockdiv = ((clockdiv + 2) / 3) * 3;
622
623 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
624 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
aa5b7925 625 exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv);
5fb2dde2
HG
626 /* 0 = use full frametime, 448 = no exposure, reverse it */
627 exposure = 448 - exposure;
628
be927bef 629 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
5fb2dde2
HG
630 reg_w(gspca_dev, 0x02, clockdiv);
631 reg_w(gspca_dev, 0x0e, exposure & 0xff);
632 reg_w(gspca_dev, 0x0f, exposure >> 8);
1408b847
MN
633
634 /* load registers to sensor (Bit 0, auto clear) */
be927bef 635 reg_w(gspca_dev, 0x11, 0x01);
1408b847
MN
636}
637
ac399cd3
JFM
638static void setautogain(struct gspca_dev *gspca_dev)
639{
640 struct sd *sd = (struct sd *) gspca_dev;
641
642 /* when switching to autogain set defaults to make sure
643 we are on a valid point of the autogain gain /
644 exposure knee graph, and give this change time to
645 take effect before doing autogain. */
646 if (sd->ctrls[AUTOGAIN].val) {
647 sd->ctrls[EXPOSURE].val = EXPOSURE_DEF;
648 sd->ctrls[GAIN].val = GAIN_DEF;
649 sd->autogain_ignore_frames =
650 PAC_AUTOGAIN_IGNORE_FRAMES;
651 } else {
652 sd->autogain_ignore_frames = -1;
653 }
654 setexposure(gspca_dev);
655 setgain(gspca_dev);
656}
657
be927bef 658static void sethvflip(struct gspca_dev *gspca_dev)
1408b847
MN
659{
660 struct sd *sd = (struct sd *) gspca_dev;
fe2b6032
JFM
661 u8 data, hflip, vflip;
662
aa5b7925 663 hflip = sd->ctrls[HFLIP].val;
fe2b6032
JFM
664 if (sd->flags & FL_HFLIP)
665 hflip = !hflip;
aa5b7925 666 vflip = sd->ctrls[VFLIP].val;
fe2b6032
JFM
667 if (sd->flags & FL_VFLIP)
668 vflip = !vflip;
1408b847 669
be927bef 670 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
fe2b6032 671 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
be927bef
JFM
672 reg_w(gspca_dev, 0x21, data);
673
1408b847 674 /* load registers to sensor (Bit 0, auto clear) */
be927bef 675 reg_w(gspca_dev, 0x11, 0x01);
1408b847
MN
676}
677
678/* this function is called at probe and resume time for pac7302 */
679static int sd_init(struct gspca_dev *gspca_dev)
680{
be927bef
JFM
681 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
682 return gspca_dev->usb_err;
1408b847
MN
683}
684
685static int sd_start(struct gspca_dev *gspca_dev)
686{
687 struct sd *sd = (struct sd *) gspca_dev;
688
be927bef 689 reg_w_var(gspca_dev, start_7302,
23a5de20 690 page3_7302, sizeof(page3_7302));
be927bef
JFM
691 setbrightcont(gspca_dev);
692 setcolors(gspca_dev);
693 setwhitebalance(gspca_dev);
694 setredbalance(gspca_dev);
695 setbluebalance(gspca_dev);
ac399cd3 696 setautogain(gspca_dev);
be927bef 697 sethvflip(gspca_dev);
1408b847 698
1408b847 699 sd->sof_read = 0;
ac399cd3 700 atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val);
1408b847
MN
701
702 /* start stream */
be927bef
JFM
703 reg_w(gspca_dev, 0xff, 0x01);
704 reg_w(gspca_dev, 0x78, 0x01);
1408b847 705
be927bef 706 return gspca_dev->usb_err;
1408b847
MN
707}
708
709static void sd_stopN(struct gspca_dev *gspca_dev)
710{
b1784b33 711
67c98f72 712 /* stop stream */
be927bef
JFM
713 reg_w(gspca_dev, 0xff, 0x01);
714 reg_w(gspca_dev, 0x78, 0x00);
1408b847
MN
715}
716
717/* called on streamoff with alt 0 and on disconnect for pac7302 */
718static void sd_stop0(struct gspca_dev *gspca_dev)
719{
720 if (!gspca_dev->present)
721 return;
be927bef
JFM
722 reg_w(gspca_dev, 0xff, 0x01);
723 reg_w(gspca_dev, 0x78, 0x40);
1408b847
MN
724}
725
a648e310 726#define WANT_REGULAR_AUTOGAIN
aa5b7925
JFM
727#include "autogain_functions.h"
728
1408b847
MN
729static void do_autogain(struct gspca_dev *gspca_dev)
730{
731 struct sd *sd = (struct sd *) gspca_dev;
732 int avg_lum = atomic_read(&sd->avg_lum);
5fb2dde2
HG
733 int desired_lum;
734 const int deadzone = 30;
1408b847 735
ac399cd3 736 if (sd->autogain_ignore_frames < 0)
1408b847
MN
737 return;
738
ac399cd3 739 if (sd->autogain_ignore_frames > 0) {
1408b847 740 sd->autogain_ignore_frames--;
ac399cd3
JFM
741 } else {
742 desired_lum = 270 + sd->ctrls[BRIGHTNESS].val;
743
744 auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
745 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
1408b847 746 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
ac399cd3 747 }
1408b847
MN
748}
749
7532e815
JFM
750/* JPEG header */
751static const u8 jpeg_header[] = {
752 0xff, 0xd8, /* SOI: Start of Image */
753
754 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
755 0x00, 0x11, /* length = 17 bytes (including this length field) */
756 0x08, /* Precision: 8 */
757 0x02, 0x80, /* height = 640 (image rotated) */
758 0x01, 0xe0, /* width = 480 */
759 0x03, /* Number of image components: 3 */
760 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
761 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
762 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
763
764 0xff, 0xda, /* SOS: Start Of Scan */
765 0x00, 0x0c, /* length = 12 bytes (including this length field) */
766 0x03, /* number of components: 3 */
767 0x01, 0x00, /* selector 1, table 0x00 */
768 0x02, 0x11, /* selector 2, table 0x11 */
769 0x03, 0x11, /* selector 3, table 0x11 */
770 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
771 0x00 /* Successive approximation: 0 */
1408b847
MN
772};
773
1408b847
MN
774/* this function is run at interrupt level */
775static void sd_pkt_scan(struct gspca_dev *gspca_dev,
76dd272b 776 u8 *data, /* isoc packet */
1408b847
MN
777 int len) /* iso packet length */
778{
779 struct sd *sd = (struct sd *) gspca_dev;
b192ca98 780 u8 *image;
ae251e6b 781 u8 *sof;
1408b847
MN
782
783 sof = pac_find_sof(&sd->sof_read, data, len);
784 if (sof) {
785 int n, lum_offset, footer_length;
786
787 /* 6 bytes after the FF D9 EOF marker a number of lumination
788 bytes are send corresponding to different parts of the
789 image, the 14th and 15th byte after the EOF seem to
790 correspond to the center of the image */
791 lum_offset = 61 + sizeof pac_sof_marker;
792 footer_length = 74;
793
794 /* Finish decoding current frame */
795 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
796 if (n < 0) {
b192ca98 797 gspca_dev->image_len += n;
1408b847 798 n = 0;
b192ca98
JFM
799 } else {
800 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
1408b847 801 }
f7059eaa
JFM
802
803 image = gspca_dev->image;
804 if (image != NULL
b192ca98
JFM
805 && image[gspca_dev->image_len - 2] == 0xff
806 && image[gspca_dev->image_len - 1] == 0xd9)
807 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1408b847
MN
808
809 n = sof - data;
810 len -= n;
811 data = sof;
812
813 /* Get average lumination */
814 if (gspca_dev->last_packet_type == LAST_PACKET &&
815 n >= lum_offset)
816 atomic_set(&sd->avg_lum, data[-lum_offset] +
817 data[-lum_offset + 1]);
1408b847
MN
818
819 /* Start the new frame with the jpeg header */
820 /* The PAC7302 has the image rotated 90 degrees */
7532e815
JFM
821 gspca_frame_add(gspca_dev, FIRST_PACKET,
822 jpeg_header, sizeof jpeg_header);
1408b847 823 }
76dd272b 824 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1408b847
MN
825}
826
6763cc0e
MN
827#ifdef CONFIG_VIDEO_ADV_DEBUG
828static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
829 struct v4l2_dbg_register *reg)
830{
ae251e6b
JFM
831 u8 index;
832 u8 value;
6763cc0e
MN
833
834 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
835 long on the USB bus)
836 */
837 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
838 reg->match.addr == 0 &&
839 (reg->reg < 0x000000ff) &&
840 (reg->val <= 0x000000ff)
841 ) {
842 /* Currently writing to page 0 is only supported. */
843 /* reg_w() only supports 8bit index */
ae251e6b
JFM
844 index = reg->reg;
845 value = reg->val;
6763cc0e
MN
846
847 /* Note that there shall be no access to other page
848 by any other function between the page swith and
849 the actual register write */
be927bef
JFM
850 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
851 reg_w(gspca_dev, index, value);
6763cc0e 852
be927bef 853 reg_w(gspca_dev, 0xdc, 0x01);
6763cc0e 854 }
be927bef 855 return gspca_dev->usb_err;
6763cc0e
MN
856}
857
858static int sd_chip_ident(struct gspca_dev *gspca_dev,
859 struct v4l2_dbg_chip_ident *chip)
860{
861 int ret = -EINVAL;
862
863 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
864 chip->match.addr == 0) {
865 chip->revision = 0;
866 chip->ident = V4L2_IDENT_UNKNOWN;
867 ret = 0;
868 }
869 return ret;
870}
871#endif
872
2856643e 873#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
aed6f1b5
MN
874static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
875 u8 *data, /* interrupt packet data */
876 int len) /* interrput packet length */
877{
878 int ret = -EINVAL;
879 u8 data0, data1;
880
881 if (len == 2) {
882 data0 = data[0];
883 data1 = data[1];
884 if ((data0 == 0x00 && data1 == 0x11) ||
885 (data0 == 0x22 && data1 == 0x33) ||
886 (data0 == 0x44 && data1 == 0x55) ||
887 (data0 == 0x66 && data1 == 0x77) ||
888 (data0 == 0x88 && data1 == 0x99) ||
889 (data0 == 0xaa && data1 == 0xbb) ||
890 (data0 == 0xcc && data1 == 0xdd) ||
891 (data0 == 0xee && data1 == 0xff)) {
892 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
893 input_sync(gspca_dev->input_dev);
894 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
895 input_sync(gspca_dev->input_dev);
896 ret = 0;
897 }
898 }
899
900 return ret;
901}
902#endif
903
1408b847 904/* sub-driver description for pac7302 */
aabcdfb6 905static const struct sd_desc sd_desc = {
ae251e6b 906 .name = KBUILD_MODNAME,
1408b847
MN
907 .ctrls = sd_ctrls,
908 .nctrls = ARRAY_SIZE(sd_ctrls),
909 .config = sd_config,
910 .init = sd_init,
911 .start = sd_start,
912 .stopN = sd_stopN,
913 .stop0 = sd_stop0,
914 .pkt_scan = sd_pkt_scan,
915 .dq_callback = do_autogain,
6763cc0e
MN
916#ifdef CONFIG_VIDEO_ADV_DEBUG
917 .set_register = sd_dbg_s_register,
918 .get_chip_ident = sd_chip_ident,
919#endif
2856643e 920#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
aed6f1b5
MN
921 .int_pkt_scan = sd_int_pkt_scan,
922#endif
1408b847
MN
923};
924
925/* -- module initialisation -- */
95c967c1 926static const struct usb_device_id device_table[] = {
1408b847 927 {USB_DEVICE(0x06f8, 0x3009)},
dd32f981 928 {USB_DEVICE(0x06f8, 0x301b)},
1408b847
MN
929 {USB_DEVICE(0x093a, 0x2620)},
930 {USB_DEVICE(0x093a, 0x2621)},
fe2b6032
JFM
931 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
932 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
4e6aeefe 933 {USB_DEVICE(0x093a, 0x2625)},
1408b847
MN
934 {USB_DEVICE(0x093a, 0x2626)},
935 {USB_DEVICE(0x093a, 0x2628)},
c4322bfc 936 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
1408b847
MN
937 {USB_DEVICE(0x093a, 0x262a)},
938 {USB_DEVICE(0x093a, 0x262c)},
4d6454db 939 {USB_DEVICE(0x145f, 0x013c)},
1408b847
MN
940 {}
941};
942MODULE_DEVICE_TABLE(usb, device_table);
943
944/* -- device connect -- */
95c967c1 945static int sd_probe(struct usb_interface *intf,
1408b847
MN
946 const struct usb_device_id *id)
947{
948 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
949 THIS_MODULE);
950}
951
952static struct usb_driver sd_driver = {
ae251e6b 953 .name = KBUILD_MODNAME,
1408b847
MN
954 .id_table = device_table,
955 .probe = sd_probe,
956 .disconnect = gspca_disconnect,
957#ifdef CONFIG_PM
958 .suspend = gspca_suspend,
959 .resume = gspca_resume,
960#endif
961};
962
ecb3b2b3 963module_usb_driver(sd_driver);
This page took 0.265476 seconds and 5 git commands to generate.