Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-block.git] / drivers / media / video / gspca / pac7302.c
CommitLineData
1408b847
MN
1/*
2 * Pixart PAC7302 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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
64#define MODULE_NAME "pac7302"
65
aed6f1b5 66#include <linux/input.h>
6763cc0e 67#include <media/v4l2-chip-ident.h>
1408b847
MN
68#include "gspca.h"
69
70MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
71MODULE_DESCRIPTION("Pixart PAC7302");
72MODULE_LICENSE("GPL");
73
74/* specific webcam descriptor for pac7302 */
75struct sd {
76 struct gspca_dev gspca_dev; /* !! must be the first item */
77
78 unsigned char brightness;
79 unsigned char contrast;
80 unsigned char colors;
23fbee6f 81 unsigned char white_balance;
265a8098
MN
82 unsigned char red_balance;
83 unsigned char blue_balance;
1408b847 84 unsigned char gain;
1408b847 85 unsigned char autogain;
5fb2dde2 86 unsigned short exposure;
1408b847
MN
87 __u8 hflip;
88 __u8 vflip;
fe2b6032
JFM
89 u8 flags;
90#define FL_HFLIP 0x01 /* mirrored by default */
91#define FL_VFLIP 0x02 /* vertical flipped by default */
1408b847
MN
92
93 u8 sof_read;
94 u8 autogain_ignore_frames;
95
96 atomic_t avg_lum;
97};
98
99/* V4L2 controls supported by the driver */
100static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
101static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
102static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
103static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
104static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
105static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
23fbee6f
MN
106static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
265a8098
MN
108static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
110static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
111static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
1408b847
MN
112static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
113static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
114static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
115static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
116static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
117static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
118static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
119static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
120static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
121static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
122
7e64dc4c 123static const struct ctrl sd_ctrls[] = {
1408b847
MN
124 {
125 {
126 .id = V4L2_CID_BRIGHTNESS,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Brightness",
129 .minimum = 0,
130#define BRIGHTNESS_MAX 0x20
131 .maximum = BRIGHTNESS_MAX,
132 .step = 1,
133#define BRIGHTNESS_DEF 0x10
134 .default_value = BRIGHTNESS_DEF,
135 },
136 .set = sd_setbrightness,
137 .get = sd_getbrightness,
138 },
1408b847
MN
139 {
140 {
141 .id = V4L2_CID_CONTRAST,
142 .type = V4L2_CTRL_TYPE_INTEGER,
143 .name = "Contrast",
144 .minimum = 0,
145#define CONTRAST_MAX 255
146 .maximum = CONTRAST_MAX,
147 .step = 1,
148#define CONTRAST_DEF 127
149 .default_value = CONTRAST_DEF,
150 },
151 .set = sd_setcontrast,
152 .get = sd_getcontrast,
153 },
1408b847
MN
154 {
155 {
156 .id = V4L2_CID_SATURATION,
157 .type = V4L2_CTRL_TYPE_INTEGER,
158 .name = "Saturation",
159 .minimum = 0,
160#define COLOR_MAX 255
161 .maximum = COLOR_MAX,
162 .step = 1,
163#define COLOR_DEF 127
164 .default_value = COLOR_DEF,
165 },
166 .set = sd_setcolors,
167 .get = sd_getcolors,
168 },
23fbee6f
MN
169 {
170 {
171 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
172 .type = V4L2_CTRL_TYPE_INTEGER,
173 .name = "White Balance",
174 .minimum = 0,
175 .maximum = 255,
176 .step = 1,
177#define WHITEBALANCE_DEF 4
178 .default_value = WHITEBALANCE_DEF,
179 },
180 .set = sd_setwhitebalance,
181 .get = sd_getwhitebalance,
182 },
265a8098
MN
183 {
184 {
185 .id = V4L2_CID_RED_BALANCE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Red",
188 .minimum = 0,
189 .maximum = 3,
190 .step = 1,
191#define REDBALANCE_DEF 1
192 .default_value = REDBALANCE_DEF,
193 },
194 .set = sd_setredbalance,
195 .get = sd_getredbalance,
196 },
197 {
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,
205#define BLUEBALANCE_DEF 1
206 .default_value = BLUEBALANCE_DEF,
207 },
208 .set = sd_setbluebalance,
209 .get = sd_getbluebalance,
210 },
1408b847
MN
211 {
212 {
213 .id = V4L2_CID_GAIN,
214 .type = V4L2_CTRL_TYPE_INTEGER,
215 .name = "Gain",
216 .minimum = 0,
217#define GAIN_MAX 255
218 .maximum = GAIN_MAX,
219 .step = 1,
220#define GAIN_DEF 127
221#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
222 .default_value = GAIN_DEF,
223 },
224 .set = sd_setgain,
225 .get = sd_getgain,
226 },
227 {
228 {
229 .id = V4L2_CID_EXPOSURE,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Exposure",
232 .minimum = 0,
5fb2dde2 233 .maximum = 1023,
1408b847 234 .step = 1,
5fb2dde2
HG
235#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
236#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
1408b847
MN
237 .default_value = EXPOSURE_DEF,
238 },
239 .set = sd_setexposure,
240 .get = sd_getexposure,
241 },
242 {
243 {
244 .id = V4L2_CID_AUTOGAIN,
245 .type = V4L2_CTRL_TYPE_BOOLEAN,
246 .name = "Auto Gain",
247 .minimum = 0,
248 .maximum = 1,
249 .step = 1,
250#define AUTOGAIN_DEF 1
251 .default_value = AUTOGAIN_DEF,
252 },
253 .set = sd_setautogain,
254 .get = sd_getautogain,
255 },
256 {
257 {
258 .id = V4L2_CID_HFLIP,
259 .type = V4L2_CTRL_TYPE_BOOLEAN,
260 .name = "Mirror",
261 .minimum = 0,
262 .maximum = 1,
263 .step = 1,
264#define HFLIP_DEF 0
265 .default_value = HFLIP_DEF,
266 },
267 .set = sd_sethflip,
268 .get = sd_gethflip,
269 },
270 {
271 {
272 .id = V4L2_CID_VFLIP,
273 .type = V4L2_CTRL_TYPE_BOOLEAN,
274 .name = "Vflip",
275 .minimum = 0,
276 .maximum = 1,
277 .step = 1,
278#define VFLIP_DEF 0
279 .default_value = VFLIP_DEF,
280 },
281 .set = sd_setvflip,
282 .get = sd_getvflip,
283 },
284};
285
286static const struct v4l2_pix_format vga_mode[] = {
287 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
288 .bytesperline = 640,
289 .sizeimage = 640 * 480 * 3 / 8 + 590,
290 .colorspace = V4L2_COLORSPACE_JPEG,
291 .priv = 0},
292};
293
294#define LOAD_PAGE3 255
1408b847
MN
295#define END_OF_SEQUENCE 0
296
297/* pac 7302 */
298static const __u8 init_7302[] = {
299/* index,value */
300 0xff, 0x01, /* page 1 */
301 0x78, 0x00, /* deactivate */
302 0xff, 0x01,
303 0x78, 0x40, /* led off */
304};
305static const __u8 start_7302[] = {
306/* index, len, [value]* */
307 0xff, 1, 0x00, /* page 0 */
308 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
309 0x00, 0x00, 0x00, 0x00,
310 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
311 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
312 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
313 0x26, 2, 0xaa, 0xaa,
314 0x2e, 1, 0x31,
315 0x38, 1, 0x01,
316 0x3a, 3, 0x14, 0xff, 0x5a,
317 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
318 0x00, 0x54, 0x11,
319 0x55, 1, 0x00,
320 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
321 0x6b, 1, 0x00,
322 0x6e, 3, 0x08, 0x06, 0x00,
323 0x72, 3, 0x00, 0xff, 0x00,
324 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
325 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
326 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
327 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
328 0xd2, 0xeb,
329 0xaf, 1, 0x02,
330 0xb5, 2, 0x08, 0x08,
331 0xb8, 2, 0x08, 0x88,
332 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
333 0xcc, 1, 0x00,
334 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
335 0xc1, 0xd7, 0xec,
336 0xdc, 1, 0x01,
337 0xff, 1, 0x01, /* page 1 */
338 0x12, 3, 0x02, 0x00, 0x01,
339 0x3e, 2, 0x00, 0x00,
340 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
341 0x7c, 1, 0x00,
342 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
343 0x02, 0x00,
344 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
345 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
346 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
347 0xd8, 1, 0x01,
348 0xdb, 2, 0x00, 0x01,
349 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
350 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
351 0xeb, 1, 0x00,
352 0xff, 1, 0x02, /* page 2 */
353 0x22, 1, 0x00,
354 0xff, 1, 0x03, /* page 3 */
355 0, LOAD_PAGE3, /* load the page 3 */
356 0x11, 1, 0x01,
357 0xff, 1, 0x02, /* page 2 */
358 0x13, 1, 0x00,
359 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
360 0x27, 2, 0x14, 0x0c,
361 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
362 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
363 0x6e, 1, 0x08,
364 0xff, 1, 0x01, /* page 1 */
365 0x78, 1, 0x00,
366 0, END_OF_SEQUENCE /* end of sequence */
367};
368
369#define SKIP 0xaa
370/* page 3 - the value SKIP says skip the index - see reg_w_page() */
371static const __u8 page3_7302[] = {
5fb2dde2 372 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
1408b847
MN
373 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
374 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
376 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
377 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
378 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
379 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
cdf955cd 381 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
1408b847
MN
382 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
386 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
387 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
388 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
391 0x00
392};
393
be927bef 394static void reg_w_buf(struct gspca_dev *gspca_dev,
1408b847 395 __u8 index,
0aeb5ec7 396 const u8 *buffer, int len)
1408b847 397{
4f7309e2
MN
398 int ret;
399
be927bef
JFM
400 if (gspca_dev->usb_err < 0)
401 return;
1408b847 402 memcpy(gspca_dev->usb_buf, buffer, len);
4f7309e2 403 ret = usb_control_msg(gspca_dev->dev,
1408b847 404 usb_sndctrlpipe(gspca_dev->dev, 0),
a1317135 405 0, /* request */
1408b847
MN
406 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
407 0, /* value */
408 index, gspca_dev->usb_buf, len,
409 500);
be927bef 410 if (ret < 0) {
0b656321
JFM
411 err("reg_w_buf failed index 0x%02x, error %d",
412 index, ret);
be927bef
JFM
413 gspca_dev->usb_err = ret;
414 }
1408b847
MN
415}
416
417
be927bef 418static void reg_w(struct gspca_dev *gspca_dev,
1408b847
MN
419 __u8 index,
420 __u8 value)
421{
4f7309e2
MN
422 int ret;
423
be927bef
JFM
424 if (gspca_dev->usb_err < 0)
425 return;
1408b847 426 gspca_dev->usb_buf[0] = value;
4f7309e2 427 ret = usb_control_msg(gspca_dev->dev,
1408b847
MN
428 usb_sndctrlpipe(gspca_dev->dev, 0),
429 0, /* request */
430 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
431 0, index, gspca_dev->usb_buf, 1,
432 500);
be927bef 433 if (ret < 0) {
0b656321
JFM
434 err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
435 index, value, ret);
be927bef
JFM
436 gspca_dev->usb_err = ret;
437 }
1408b847
MN
438}
439
be927bef 440static void reg_w_seq(struct gspca_dev *gspca_dev,
1408b847
MN
441 const __u8 *seq, int len)
442{
443 while (--len >= 0) {
be927bef 444 reg_w(gspca_dev, seq[0], seq[1]);
1408b847
MN
445 seq += 2;
446 }
447}
448
449/* load the beginning of a page */
be927bef 450static void reg_w_page(struct gspca_dev *gspca_dev,
1408b847
MN
451 const __u8 *page, int len)
452{
453 int index;
b1784b33 454 int ret = 0;
1408b847 455
be927bef
JFM
456 if (gspca_dev->usb_err < 0)
457 return;
1408b847
MN
458 for (index = 0; index < len; index++) {
459 if (page[index] == SKIP) /* skip this index */
460 continue;
461 gspca_dev->usb_buf[0] = page[index];
4f7309e2 462 ret = usb_control_msg(gspca_dev->dev,
1408b847
MN
463 usb_sndctrlpipe(gspca_dev->dev, 0),
464 0, /* request */
465 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
466 0, index, gspca_dev->usb_buf, 1,
467 500);
b1784b33 468 if (ret < 0) {
0b656321
JFM
469 err("reg_w_page() failed index 0x%02x, "
470 "value 0x%02x, error %d",
471 index, page[index], ret);
be927bef 472 gspca_dev->usb_err = ret;
b1784b33
MN
473 break;
474 }
1408b847
MN
475 }
476}
477
478/* output a variable sequence */
be927bef 479static void reg_w_var(struct gspca_dev *gspca_dev,
1408b847 480 const __u8 *seq,
23a5de20 481 const __u8 *page3, unsigned int page3_len)
1408b847
MN
482{
483 int index, len;
484
485 for (;;) {
486 index = *seq++;
487 len = *seq++;
488 switch (len) {
489 case END_OF_SEQUENCE:
be927bef 490 return;
1408b847 491 case LOAD_PAGE3:
be927bef 492 reg_w_page(gspca_dev, page3, page3_len);
1408b847
MN
493 break;
494 default:
495 if (len > USB_BUF_SZ) {
496 PDEBUG(D_ERR|D_STREAM,
497 "Incorrect variable sequence");
be927bef 498 return;
1408b847
MN
499 }
500 while (len > 0) {
501 if (len < 8) {
be927bef 502 reg_w_buf(gspca_dev,
b1784b33 503 index, seq, len);
1408b847
MN
504 seq += len;
505 break;
506 }
be927bef 507 reg_w_buf(gspca_dev, index, seq, 8);
1408b847
MN
508 seq += 8;
509 index += 8;
510 len -= 8;
511 }
512 }
513 }
514 /* not reached */
515}
516
517/* this function is called at probe time for pac7302 */
518static int sd_config(struct gspca_dev *gspca_dev,
519 const struct usb_device_id *id)
520{
521 struct sd *sd = (struct sd *) gspca_dev;
522 struct cam *cam;
523
524 cam = &gspca_dev->cam;
525
526 PDEBUG(D_CONF, "Find Sensor PAC7302");
527 cam->cam_mode = vga_mode; /* only 640x480 */
528 cam->nmodes = ARRAY_SIZE(vga_mode);
529
530 sd->brightness = BRIGHTNESS_DEF;
531 sd->contrast = CONTRAST_DEF;
532 sd->colors = COLOR_DEF;
23fbee6f 533 sd->white_balance = WHITEBALANCE_DEF;
265a8098
MN
534 sd->red_balance = REDBALANCE_DEF;
535 sd->blue_balance = BLUEBALANCE_DEF;
1408b847
MN
536 sd->gain = GAIN_DEF;
537 sd->exposure = EXPOSURE_DEF;
538 sd->autogain = AUTOGAIN_DEF;
539 sd->hflip = HFLIP_DEF;
540 sd->vflip = VFLIP_DEF;
fe2b6032 541 sd->flags = id->driver_info;
1408b847
MN
542 return 0;
543}
544
545/* This function is used by pac7302 only */
be927bef 546static void setbrightcont(struct gspca_dev *gspca_dev)
1408b847
MN
547{
548 struct sd *sd = (struct sd *) gspca_dev;
549 int i, v;
550 static const __u8 max[10] =
551 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
552 0xd4, 0xec};
553 static const __u8 delta[10] =
554 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
555 0x11, 0x0b};
556
be927bef 557 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1408b847
MN
558 for (i = 0; i < 10; i++) {
559 v = max[i];
560 v += (sd->brightness - BRIGHTNESS_MAX)
561 * 150 / BRIGHTNESS_MAX; /* 200 ? */
562 v -= delta[i] * sd->contrast / CONTRAST_MAX;
563 if (v < 0)
564 v = 0;
565 else if (v > 0xff)
566 v = 0xff;
be927bef 567 reg_w(gspca_dev, 0xa2 + i, v);
1408b847 568 }
be927bef 569 reg_w(gspca_dev, 0xdc, 0x01);
1408b847
MN
570}
571
572/* This function is used by pac7302 only */
be927bef 573static void setcolors(struct gspca_dev *gspca_dev)
1408b847
MN
574{
575 struct sd *sd = (struct sd *) gspca_dev;
576 int i, v;
577 static const int a[9] =
578 {217, -212, 0, -101, 170, -67, -38, -315, 355};
579 static const int b[9] =
580 {19, 106, 0, 19, 106, 1, 19, 106, 1};
581
be927bef
JFM
582 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
583 reg_w(gspca_dev, 0x11, 0x01);
584 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1408b847
MN
585 for (i = 0; i < 9; i++) {
586 v = a[i] * sd->colors / COLOR_MAX + b[i];
be927bef
JFM
587 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
588 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
1408b847 589 }
be927bef 590 reg_w(gspca_dev, 0xdc, 0x01);
1408b847
MN
591 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
592}
593
be927bef 594static void setwhitebalance(struct gspca_dev *gspca_dev)
23fbee6f
MN
595{
596 struct sd *sd = (struct sd *) gspca_dev;
23fbee6f 597
be927bef
JFM
598 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
599 reg_w(gspca_dev, 0xc6, sd->white_balance);
23fbee6f 600
be927bef 601 reg_w(gspca_dev, 0xdc, 0x01);
23fbee6f 602 PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
23fbee6f
MN
603}
604
be927bef 605static void setredbalance(struct gspca_dev *gspca_dev)
265a8098
MN
606{
607 struct sd *sd = (struct sd *) gspca_dev;
265a8098 608
be927bef
JFM
609 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
610 reg_w(gspca_dev, 0xc5, sd->red_balance);
265a8098 611
be927bef 612 reg_w(gspca_dev, 0xdc, 0x01);
265a8098 613 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
265a8098
MN
614}
615
be927bef 616static void setbluebalance(struct gspca_dev *gspca_dev)
265a8098
MN
617{
618 struct sd *sd = (struct sd *) gspca_dev;
265a8098 619
be927bef
JFM
620 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
621 reg_w(gspca_dev, 0xc7, sd->blue_balance);
265a8098 622
be927bef 623 reg_w(gspca_dev, 0xdc, 0x01);
265a8098 624 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
265a8098
MN
625}
626
be927bef 627static void setgain(struct gspca_dev *gspca_dev)
1408b847
MN
628{
629 struct sd *sd = (struct sd *) gspca_dev;
630
be927bef
JFM
631 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
632 reg_w(gspca_dev, 0x10, sd->gain >> 3);
1408b847
MN
633
634 /* load registers to sensor (Bit 0, auto clear) */
be927bef 635 reg_w(gspca_dev, 0x11, 0x01);
1408b847
MN
636}
637
be927bef 638static void setexposure(struct gspca_dev *gspca_dev)
1408b847
MN
639{
640 struct sd *sd = (struct sd *) gspca_dev;
5fb2dde2
HG
641 __u8 clockdiv;
642 __u16 exposure;
643
644 /* register 2 of frame 3 contains the clock divider configuring the
645 no fps according to the formula: 90 / reg. sd->exposure is the
646 desired exposure time in 0.5 ms. */
647 clockdiv = (90 * sd->exposure + 1999) / 2000;
648
649 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
650 on the scene being recorded, the camera switches to another
651 quantization table for certain JPEG blocks, and we don't know how
652 to decompress these blocks. So we cap the framerate at 15 fps */
653 if (clockdiv < 6)
654 clockdiv = 6;
655 else if (clockdiv > 63)
656 clockdiv = 63;
657
658 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
659 Always round up, otherwise we cannot get the desired frametime
660 using the partial frame time exposure control */
661 if (clockdiv < 6 || clockdiv > 12)
662 clockdiv = ((clockdiv + 2) / 3) * 3;
663
664 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
665 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
666 exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv);
667 /* 0 = use full frametime, 448 = no exposure, reverse it */
668 exposure = 448 - exposure;
669
be927bef 670 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
5fb2dde2
HG
671 reg_w(gspca_dev, 0x02, clockdiv);
672 reg_w(gspca_dev, 0x0e, exposure & 0xff);
673 reg_w(gspca_dev, 0x0f, exposure >> 8);
1408b847
MN
674
675 /* load registers to sensor (Bit 0, auto clear) */
be927bef 676 reg_w(gspca_dev, 0x11, 0x01);
1408b847
MN
677}
678
be927bef 679static void sethvflip(struct gspca_dev *gspca_dev)
1408b847
MN
680{
681 struct sd *sd = (struct sd *) gspca_dev;
fe2b6032
JFM
682 u8 data, hflip, vflip;
683
684 hflip = sd->hflip;
685 if (sd->flags & FL_HFLIP)
686 hflip = !hflip;
687 vflip = sd->vflip;
688 if (sd->flags & FL_VFLIP)
689 vflip = !vflip;
1408b847 690
be927bef 691 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
fe2b6032 692 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
be927bef
JFM
693 reg_w(gspca_dev, 0x21, data);
694
1408b847 695 /* load registers to sensor (Bit 0, auto clear) */
be927bef 696 reg_w(gspca_dev, 0x11, 0x01);
1408b847
MN
697}
698
699/* this function is called at probe and resume time for pac7302 */
700static int sd_init(struct gspca_dev *gspca_dev)
701{
be927bef
JFM
702 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
703 return gspca_dev->usb_err;
1408b847
MN
704}
705
706static int sd_start(struct gspca_dev *gspca_dev)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
709
710 sd->sof_read = 0;
711
be927bef 712 reg_w_var(gspca_dev, start_7302,
23a5de20 713 page3_7302, sizeof(page3_7302));
be927bef
JFM
714 setbrightcont(gspca_dev);
715 setcolors(gspca_dev);
716 setwhitebalance(gspca_dev);
717 setredbalance(gspca_dev);
718 setbluebalance(gspca_dev);
719 setgain(gspca_dev);
720 setexposure(gspca_dev);
721 sethvflip(gspca_dev);
1408b847
MN
722
723 /* only resolution 640x480 is supported for pac7302 */
724
725 sd->sof_read = 0;
726 sd->autogain_ignore_frames = 0;
727 atomic_set(&sd->avg_lum, -1);
728
729 /* start stream */
be927bef
JFM
730 reg_w(gspca_dev, 0xff, 0x01);
731 reg_w(gspca_dev, 0x78, 0x01);
1408b847 732
be927bef 733 return gspca_dev->usb_err;
1408b847
MN
734}
735
736static void sd_stopN(struct gspca_dev *gspca_dev)
737{
b1784b33 738
67c98f72 739 /* stop stream */
be927bef
JFM
740 reg_w(gspca_dev, 0xff, 0x01);
741 reg_w(gspca_dev, 0x78, 0x00);
1408b847
MN
742}
743
744/* called on streamoff with alt 0 and on disconnect for pac7302 */
745static void sd_stop0(struct gspca_dev *gspca_dev)
746{
747 if (!gspca_dev->present)
748 return;
be927bef
JFM
749 reg_w(gspca_dev, 0xff, 0x01);
750 reg_w(gspca_dev, 0x78, 0x40);
1408b847
MN
751}
752
753/* Include pac common sof detection functions */
754#include "pac_common.h"
755
756static void do_autogain(struct gspca_dev *gspca_dev)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759 int avg_lum = atomic_read(&sd->avg_lum);
5fb2dde2
HG
760 int desired_lum;
761 const int deadzone = 30;
1408b847
MN
762
763 if (avg_lum == -1)
764 return;
765
5fb2dde2 766 desired_lum = 270 + sd->brightness;
1408b847
MN
767
768 if (sd->autogain_ignore_frames > 0)
769 sd->autogain_ignore_frames--;
770 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
771 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
772 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
773}
774
775/* JPEG header, part 1 */
776static const unsigned char pac_jpeg_header1[] = {
777 0xff, 0xd8, /* SOI: Start of Image */
778
779 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
780 0x00, 0x11, /* length = 17 bytes (including this length field) */
781 0x08 /* Precision: 8 */
782 /* 2 bytes is placed here: number of image lines */
783 /* 2 bytes is placed here: samples per line */
784};
785
786/* JPEG header, continued */
787static const unsigned char pac_jpeg_header2[] = {
788 0x03, /* Number of image components: 3 */
789 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
790 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
791 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
792
793 0xff, 0xda, /* SOS: Start Of Scan */
794 0x00, 0x0c, /* length = 12 bytes (including this length field) */
795 0x03, /* number of components: 3 */
796 0x01, 0x00, /* selector 1, table 0x00 */
797 0x02, 0x11, /* selector 2, table 0x11 */
798 0x03, 0x11, /* selector 3, table 0x11 */
799 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
800 0x00 /* Successive approximation: 0 */
801};
802
803static void pac_start_frame(struct gspca_dev *gspca_dev,
1408b847
MN
804 __u16 lines, __u16 samples_per_line)
805{
806 unsigned char tmpbuf[4];
807
76dd272b 808 gspca_frame_add(gspca_dev, FIRST_PACKET,
1408b847
MN
809 pac_jpeg_header1, sizeof(pac_jpeg_header1));
810
811 tmpbuf[0] = lines >> 8;
812 tmpbuf[1] = lines & 0xff;
813 tmpbuf[2] = samples_per_line >> 8;
814 tmpbuf[3] = samples_per_line & 0xff;
815
76dd272b 816 gspca_frame_add(gspca_dev, INTER_PACKET,
1408b847 817 tmpbuf, sizeof(tmpbuf));
76dd272b 818 gspca_frame_add(gspca_dev, INTER_PACKET,
1408b847
MN
819 pac_jpeg_header2, sizeof(pac_jpeg_header2));
820}
821
822/* this function is run at interrupt level */
823static void sd_pkt_scan(struct gspca_dev *gspca_dev,
76dd272b 824 u8 *data, /* isoc packet */
1408b847
MN
825 int len) /* iso packet length */
826{
827 struct sd *sd = (struct sd *) gspca_dev;
b192ca98 828 u8 *image;
1408b847
MN
829 unsigned char *sof;
830
831 sof = pac_find_sof(&sd->sof_read, data, len);
832 if (sof) {
833 int n, lum_offset, footer_length;
834
835 /* 6 bytes after the FF D9 EOF marker a number of lumination
836 bytes are send corresponding to different parts of the
837 image, the 14th and 15th byte after the EOF seem to
838 correspond to the center of the image */
839 lum_offset = 61 + sizeof pac_sof_marker;
840 footer_length = 74;
841
842 /* Finish decoding current frame */
843 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
844 if (n < 0) {
b192ca98 845 gspca_dev->image_len += n;
1408b847 846 n = 0;
b192ca98
JFM
847 } else {
848 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
1408b847 849 }
f7059eaa
JFM
850
851 image = gspca_dev->image;
852 if (image != NULL
b192ca98
JFM
853 && image[gspca_dev->image_len - 2] == 0xff
854 && image[gspca_dev->image_len - 1] == 0xd9)
855 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1408b847
MN
856
857 n = sof - data;
858 len -= n;
859 data = sof;
860
861 /* Get average lumination */
862 if (gspca_dev->last_packet_type == LAST_PACKET &&
863 n >= lum_offset)
864 atomic_set(&sd->avg_lum, data[-lum_offset] +
865 data[-lum_offset + 1]);
866 else
867 atomic_set(&sd->avg_lum, -1);
868
869 /* Start the new frame with the jpeg header */
870 /* The PAC7302 has the image rotated 90 degrees */
b192ca98 871 pac_start_frame(gspca_dev,
1408b847
MN
872 gspca_dev->width, gspca_dev->height);
873 }
76dd272b 874 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1408b847
MN
875}
876
877static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
878{
879 struct sd *sd = (struct sd *) gspca_dev;
880
881 sd->brightness = val;
882 if (gspca_dev->streaming)
883 setbrightcont(gspca_dev);
be927bef 884 return gspca_dev->usb_err;
1408b847
MN
885}
886
887static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
888{
889 struct sd *sd = (struct sd *) gspca_dev;
890
891 *val = sd->brightness;
892 return 0;
893}
894
895static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 sd->contrast = val;
780e3121 900 if (gspca_dev->streaming)
1408b847 901 setbrightcont(gspca_dev);
be927bef 902 return gspca_dev->usb_err;
1408b847
MN
903}
904
905static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
906{
907 struct sd *sd = (struct sd *) gspca_dev;
908
909 *val = sd->contrast;
910 return 0;
911}
912
913static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
914{
915 struct sd *sd = (struct sd *) gspca_dev;
916
917 sd->colors = val;
918 if (gspca_dev->streaming)
919 setcolors(gspca_dev);
be927bef 920 return gspca_dev->usb_err;
1408b847
MN
921}
922
923static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926
927 *val = sd->colors;
928 return 0;
929}
930
23fbee6f
MN
931static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
932{
933 struct sd *sd = (struct sd *) gspca_dev;
23fbee6f
MN
934
935 sd->white_balance = val;
936 if (gspca_dev->streaming)
be927bef
JFM
937 setwhitebalance(gspca_dev);
938 return gspca_dev->usb_err;
23fbee6f
MN
939}
940
941static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
944
945 *val = sd->white_balance;
946 return 0;
947}
948
265a8098
MN
949static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
950{
951 struct sd *sd = (struct sd *) gspca_dev;
265a8098
MN
952
953 sd->red_balance = val;
954 if (gspca_dev->streaming)
be927bef
JFM
955 setredbalance(gspca_dev);
956 return gspca_dev->usb_err;
265a8098
MN
957}
958
959static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 *val = sd->red_balance;
964 return 0;
965}
966
967static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
265a8098
MN
970
971 sd->blue_balance = val;
972 if (gspca_dev->streaming)
be927bef
JFM
973 setbluebalance(gspca_dev);
974 return gspca_dev->usb_err;
265a8098
MN
975}
976
977static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 *val = sd->blue_balance;
982 return 0;
983}
984
1408b847
MN
985static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 sd->gain = val;
990 if (gspca_dev->streaming)
991 setgain(gspca_dev);
be927bef 992 return gspca_dev->usb_err;
1408b847
MN
993}
994
995static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
998
999 *val = sd->gain;
1000 return 0;
1001}
1002
1003static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1004{
1005 struct sd *sd = (struct sd *) gspca_dev;
1006
1007 sd->exposure = val;
1008 if (gspca_dev->streaming)
1009 setexposure(gspca_dev);
be927bef 1010 return gspca_dev->usb_err;
1408b847
MN
1011}
1012
1013static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1014{
1015 struct sd *sd = (struct sd *) gspca_dev;
1016
1017 *val = sd->exposure;
1018 return 0;
1019}
1020
1021static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1022{
1023 struct sd *sd = (struct sd *) gspca_dev;
1024
1025 sd->autogain = val;
1026 /* when switching to autogain set defaults to make sure
1027 we are on a valid point of the autogain gain /
1028 exposure knee graph, and give this change time to
1029 take effect before doing autogain. */
1030 if (sd->autogain) {
1031 sd->exposure = EXPOSURE_DEF;
1032 sd->gain = GAIN_DEF;
1033 if (gspca_dev->streaming) {
1034 sd->autogain_ignore_frames =
1035 PAC_AUTOGAIN_IGNORE_FRAMES;
1036 setexposure(gspca_dev);
1037 setgain(gspca_dev);
1038 }
1039 }
1040
be927bef 1041 return gspca_dev->usb_err;
1408b847
MN
1042}
1043
1044static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1045{
1046 struct sd *sd = (struct sd *) gspca_dev;
1047
1048 *val = sd->autogain;
1049 return 0;
1050}
1051
1052static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1053{
1054 struct sd *sd = (struct sd *) gspca_dev;
1055
1056 sd->hflip = val;
1057 if (gspca_dev->streaming)
1058 sethvflip(gspca_dev);
be927bef 1059 return gspca_dev->usb_err;
1408b847
MN
1060}
1061
1062static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1063{
1064 struct sd *sd = (struct sd *) gspca_dev;
1065
1066 *val = sd->hflip;
1067 return 0;
1068}
1069
1070static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1071{
1072 struct sd *sd = (struct sd *) gspca_dev;
1073
1074 sd->vflip = val;
1075 if (gspca_dev->streaming)
1076 sethvflip(gspca_dev);
be927bef 1077 return gspca_dev->usb_err;
1408b847
MN
1078}
1079
1080static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1081{
1082 struct sd *sd = (struct sd *) gspca_dev;
1083
1084 *val = sd->vflip;
1085 return 0;
1086}
1087
6763cc0e
MN
1088#ifdef CONFIG_VIDEO_ADV_DEBUG
1089static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1090 struct v4l2_dbg_register *reg)
1091{
6763cc0e
MN
1092 __u8 index;
1093 __u8 value;
1094
1095 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
1096 long on the USB bus)
1097 */
1098 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
1099 reg->match.addr == 0 &&
1100 (reg->reg < 0x000000ff) &&
1101 (reg->val <= 0x000000ff)
1102 ) {
1103 /* Currently writing to page 0 is only supported. */
1104 /* reg_w() only supports 8bit index */
1105 index = reg->reg & 0x000000ff;
1106 value = reg->val & 0x000000ff;
1107
1108 /* Note that there shall be no access to other page
1109 by any other function between the page swith and
1110 the actual register write */
be927bef
JFM
1111 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1112 reg_w(gspca_dev, index, value);
6763cc0e 1113
be927bef 1114 reg_w(gspca_dev, 0xdc, 0x01);
6763cc0e 1115 }
be927bef 1116 return gspca_dev->usb_err;
6763cc0e
MN
1117}
1118
1119static int sd_chip_ident(struct gspca_dev *gspca_dev,
1120 struct v4l2_dbg_chip_ident *chip)
1121{
1122 int ret = -EINVAL;
1123
1124 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1125 chip->match.addr == 0) {
1126 chip->revision = 0;
1127 chip->ident = V4L2_IDENT_UNKNOWN;
1128 ret = 0;
1129 }
1130 return ret;
1131}
1132#endif
1133
2856643e 1134#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
aed6f1b5
MN
1135static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1136 u8 *data, /* interrupt packet data */
1137 int len) /* interrput packet length */
1138{
1139 int ret = -EINVAL;
1140 u8 data0, data1;
1141
1142 if (len == 2) {
1143 data0 = data[0];
1144 data1 = data[1];
1145 if ((data0 == 0x00 && data1 == 0x11) ||
1146 (data0 == 0x22 && data1 == 0x33) ||
1147 (data0 == 0x44 && data1 == 0x55) ||
1148 (data0 == 0x66 && data1 == 0x77) ||
1149 (data0 == 0x88 && data1 == 0x99) ||
1150 (data0 == 0xaa && data1 == 0xbb) ||
1151 (data0 == 0xcc && data1 == 0xdd) ||
1152 (data0 == 0xee && data1 == 0xff)) {
1153 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1154 input_sync(gspca_dev->input_dev);
1155 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1156 input_sync(gspca_dev->input_dev);
1157 ret = 0;
1158 }
1159 }
1160
1161 return ret;
1162}
1163#endif
1164
1408b847 1165/* sub-driver description for pac7302 */
aabcdfb6 1166static const struct sd_desc sd_desc = {
1408b847
MN
1167 .name = MODULE_NAME,
1168 .ctrls = sd_ctrls,
1169 .nctrls = ARRAY_SIZE(sd_ctrls),
1170 .config = sd_config,
1171 .init = sd_init,
1172 .start = sd_start,
1173 .stopN = sd_stopN,
1174 .stop0 = sd_stop0,
1175 .pkt_scan = sd_pkt_scan,
1176 .dq_callback = do_autogain,
6763cc0e
MN
1177#ifdef CONFIG_VIDEO_ADV_DEBUG
1178 .set_register = sd_dbg_s_register,
1179 .get_chip_ident = sd_chip_ident,
1180#endif
2856643e 1181#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
aed6f1b5
MN
1182 .int_pkt_scan = sd_int_pkt_scan,
1183#endif
1408b847
MN
1184};
1185
1186/* -- module initialisation -- */
37b372e5 1187static const struct usb_device_id device_table[] __devinitconst = {
1408b847
MN
1188 {USB_DEVICE(0x06f8, 0x3009)},
1189 {USB_DEVICE(0x093a, 0x2620)},
1190 {USB_DEVICE(0x093a, 0x2621)},
fe2b6032
JFM
1191 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1192 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
4e6aeefe 1193 {USB_DEVICE(0x093a, 0x2625)},
1408b847
MN
1194 {USB_DEVICE(0x093a, 0x2626)},
1195 {USB_DEVICE(0x093a, 0x2628)},
c4322bfc 1196 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
1408b847
MN
1197 {USB_DEVICE(0x093a, 0x262a)},
1198 {USB_DEVICE(0x093a, 0x262c)},
1199 {}
1200};
1201MODULE_DEVICE_TABLE(usb, device_table);
1202
1203/* -- device connect -- */
37b372e5 1204static int __devinit sd_probe(struct usb_interface *intf,
1408b847
MN
1205 const struct usb_device_id *id)
1206{
1207 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1208 THIS_MODULE);
1209}
1210
1211static struct usb_driver sd_driver = {
1212 .name = MODULE_NAME,
1213 .id_table = device_table,
1214 .probe = sd_probe,
1215 .disconnect = gspca_disconnect,
1216#ifdef CONFIG_PM
1217 .suspend = gspca_suspend,
1218 .resume = gspca_resume,
1219#endif
1220};
1221
1222/* -- module insert / remove -- */
1223static int __init sd_mod_init(void)
1224{
54826437 1225 return usb_register(&sd_driver);
1408b847
MN
1226}
1227static void __exit sd_mod_exit(void)
1228{
1229 usb_deregister(&sd_driver);
1408b847
MN
1230}
1231
1232module_init(sd_mod_init);
1233module_exit(sd_mod_exit);