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