blob: e7a4ced86e9bdabb56eb553a2ae0be818152e522 [file] [log] [blame]
Marton Nemeth1408b842009-11-02 08:13:21 -03001/*
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 *
7 * Separated from Pixart PAC7311 library by Márton Németh <nm127@freemail.hu>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* Some documentation about various registers as determined by trial and error.
25 When the register addresses differ between the 7202 and the 7311 the 2
26 different addresses are written as 7302addr/7311addr, when one of the 2
27 addresses is a - sign that register description is not valid for the
28 matching IC.
29
30 Register page 1:
31
32 Address Description
33 -/0x08 Unknown compressor related, must always be 8 except when not
34 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
35 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
36 bits 345 seem to toggle per color gains on/off (inverted)
37 0x78 Global control, bit 6 controls the LED (inverted)
38 -/0x80 JPEG compression ratio ? Best not touched
39
40 Register page 3/4:
41
42 Address Description
43 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
44 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
45 -/0x0f Master gain 1-245, low value = high gain
46 0x10/- Master gain 0-31
47 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
48 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
49 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
50 completely disable the analog amplification block. Set to 0x68
51 for max gain, 0x14 for minimal gain.
Márton Németh265a8092009-11-07 15:15:56 -030052
53 The registers are accessed in the following functions:
54
55 Page | Register | Function
56 -----+------------+---------------------------------------------------
57 0 | 0x0f..0x20 | setcolors()
58 0 | 0xa2..0xab | setbrightcont()
59 0 | 0xc5 | setredbalance()
60 0 | 0xc7 | setbluebalance()
61 0 | 0xdc | setbrightcont(), setcolors()
62 3 | 0x02 | setexposure()
63 3 | 0x10 | setgain()
64 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
65 3 | 0x21 | sethvflip()
Marton Nemeth1408b842009-11-02 08:13:21 -030066*/
67
68#define MODULE_NAME "pac7302"
69
70#include "gspca.h"
71
72MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
73MODULE_DESCRIPTION("Pixart PAC7302");
74MODULE_LICENSE("GPL");
75
76/* specific webcam descriptor for pac7302 */
77struct sd {
78 struct gspca_dev gspca_dev; /* !! must be the first item */
79
80 unsigned char brightness;
81 unsigned char contrast;
82 unsigned char colors;
Márton Németh265a8092009-11-07 15:15:56 -030083 unsigned char red_balance;
84 unsigned char blue_balance;
Marton Nemeth1408b842009-11-02 08:13:21 -030085 unsigned char gain;
86 unsigned char exposure;
87 unsigned char autogain;
88 __u8 hflip;
89 __u8 vflip;
90
91 u8 sof_read;
92 u8 autogain_ignore_frames;
93
94 atomic_t avg_lum;
95};
96
97/* V4L2 controls supported by the driver */
98static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
99static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
100static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
101static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
102static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
103static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
Márton Németh265a8092009-11-07 15:15:56 -0300104static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
105static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
106static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
Marton Nemeth1408b842009-11-02 08:13:21 -0300108static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
110static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
111static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
112static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
113static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
114static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
115static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
116static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
117static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
118
119static struct ctrl sd_ctrls[] = {
120/* This control is pac7302 only */
121 {
122 {
123 .id = V4L2_CID_BRIGHTNESS,
124 .type = V4L2_CTRL_TYPE_INTEGER,
125 .name = "Brightness",
126 .minimum = 0,
127#define BRIGHTNESS_MAX 0x20
128 .maximum = BRIGHTNESS_MAX,
129 .step = 1,
130#define BRIGHTNESS_DEF 0x10
131 .default_value = BRIGHTNESS_DEF,
132 },
133 .set = sd_setbrightness,
134 .get = sd_getbrightness,
135 },
136/* This control is for both the 7302 and the 7311 */
137 {
138 {
139 .id = V4L2_CID_CONTRAST,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Contrast",
142 .minimum = 0,
143#define CONTRAST_MAX 255
144 .maximum = CONTRAST_MAX,
145 .step = 1,
146#define CONTRAST_DEF 127
147 .default_value = CONTRAST_DEF,
148 },
149 .set = sd_setcontrast,
150 .get = sd_getcontrast,
151 },
152/* This control is pac7302 only */
153 {
154 {
155 .id = V4L2_CID_SATURATION,
156 .type = V4L2_CTRL_TYPE_INTEGER,
157 .name = "Saturation",
158 .minimum = 0,
159#define COLOR_MAX 255
160 .maximum = COLOR_MAX,
161 .step = 1,
162#define COLOR_DEF 127
163 .default_value = COLOR_DEF,
164 },
165 .set = sd_setcolors,
166 .get = sd_getcolors,
167 },
Márton Németh265a8092009-11-07 15:15:56 -0300168 {
169 {
170 .id = V4L2_CID_RED_BALANCE,
171 .type = V4L2_CTRL_TYPE_INTEGER,
172 .name = "Red",
173 .minimum = 0,
174 .maximum = 3,
175 .step = 1,
176#define REDBALANCE_DEF 1
177 .default_value = REDBALANCE_DEF,
178 },
179 .set = sd_setredbalance,
180 .get = sd_getredbalance,
181 },
182 {
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,
190#define BLUEBALANCE_DEF 1
191 .default_value = BLUEBALANCE_DEF,
192 },
193 .set = sd_setbluebalance,
194 .get = sd_getbluebalance,
195 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300196/* All controls below are for both the 7302 and the 7311 */
197 {
198 {
199 .id = V4L2_CID_GAIN,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Gain",
202 .minimum = 0,
203#define GAIN_MAX 255
204 .maximum = GAIN_MAX,
205 .step = 1,
206#define GAIN_DEF 127
207#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
208 .default_value = GAIN_DEF,
209 },
210 .set = sd_setgain,
211 .get = sd_getgain,
212 },
213 {
214 {
215 .id = V4L2_CID_EXPOSURE,
216 .type = V4L2_CTRL_TYPE_INTEGER,
217 .name = "Exposure",
218 .minimum = 0,
219#define EXPOSURE_MAX 255
220 .maximum = EXPOSURE_MAX,
221 .step = 1,
222#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
223#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
224 .default_value = EXPOSURE_DEF,
225 },
226 .set = sd_setexposure,
227 .get = sd_getexposure,
228 },
229 {
230 {
231 .id = V4L2_CID_AUTOGAIN,
232 .type = V4L2_CTRL_TYPE_BOOLEAN,
233 .name = "Auto Gain",
234 .minimum = 0,
235 .maximum = 1,
236 .step = 1,
237#define AUTOGAIN_DEF 1
238 .default_value = AUTOGAIN_DEF,
239 },
240 .set = sd_setautogain,
241 .get = sd_getautogain,
242 },
243 {
244 {
245 .id = V4L2_CID_HFLIP,
246 .type = V4L2_CTRL_TYPE_BOOLEAN,
247 .name = "Mirror",
248 .minimum = 0,
249 .maximum = 1,
250 .step = 1,
251#define HFLIP_DEF 0
252 .default_value = HFLIP_DEF,
253 },
254 .set = sd_sethflip,
255 .get = sd_gethflip,
256 },
257 {
258 {
259 .id = V4L2_CID_VFLIP,
260 .type = V4L2_CTRL_TYPE_BOOLEAN,
261 .name = "Vflip",
262 .minimum = 0,
263 .maximum = 1,
264 .step = 1,
265#define VFLIP_DEF 0
266 .default_value = VFLIP_DEF,
267 },
268 .set = sd_setvflip,
269 .get = sd_getvflip,
270 },
271};
272
273static const struct v4l2_pix_format vga_mode[] = {
274 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
275 .bytesperline = 640,
276 .sizeimage = 640 * 480 * 3 / 8 + 590,
277 .colorspace = V4L2_COLORSPACE_JPEG,
278 .priv = 0},
279};
280
281#define LOAD_PAGE3 255
282#define LOAD_PAGE4 254
283#define END_OF_SEQUENCE 0
284
285/* pac 7302 */
286static const __u8 init_7302[] = {
287/* index,value */
288 0xff, 0x01, /* page 1 */
289 0x78, 0x00, /* deactivate */
290 0xff, 0x01,
291 0x78, 0x40, /* led off */
292};
293static const __u8 start_7302[] = {
294/* index, len, [value]* */
295 0xff, 1, 0x00, /* page 0 */
296 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
297 0x00, 0x00, 0x00, 0x00,
298 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
299 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
300 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
301 0x26, 2, 0xaa, 0xaa,
302 0x2e, 1, 0x31,
303 0x38, 1, 0x01,
304 0x3a, 3, 0x14, 0xff, 0x5a,
305 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
306 0x00, 0x54, 0x11,
307 0x55, 1, 0x00,
308 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
309 0x6b, 1, 0x00,
310 0x6e, 3, 0x08, 0x06, 0x00,
311 0x72, 3, 0x00, 0xff, 0x00,
312 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
313 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
314 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
315 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
316 0xd2, 0xeb,
317 0xaf, 1, 0x02,
318 0xb5, 2, 0x08, 0x08,
319 0xb8, 2, 0x08, 0x88,
320 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
321 0xcc, 1, 0x00,
322 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
323 0xc1, 0xd7, 0xec,
324 0xdc, 1, 0x01,
325 0xff, 1, 0x01, /* page 1 */
326 0x12, 3, 0x02, 0x00, 0x01,
327 0x3e, 2, 0x00, 0x00,
328 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
329 0x7c, 1, 0x00,
330 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
331 0x02, 0x00,
332 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
333 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
334 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
335 0xd8, 1, 0x01,
336 0xdb, 2, 0x00, 0x01,
337 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
338 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
339 0xeb, 1, 0x00,
340 0xff, 1, 0x02, /* page 2 */
341 0x22, 1, 0x00,
342 0xff, 1, 0x03, /* page 3 */
343 0, LOAD_PAGE3, /* load the page 3 */
344 0x11, 1, 0x01,
345 0xff, 1, 0x02, /* page 2 */
346 0x13, 1, 0x00,
347 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
348 0x27, 2, 0x14, 0x0c,
349 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
350 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
351 0x6e, 1, 0x08,
352 0xff, 1, 0x01, /* page 1 */
353 0x78, 1, 0x00,
354 0, END_OF_SEQUENCE /* end of sequence */
355};
356
357#define SKIP 0xaa
358/* page 3 - the value SKIP says skip the index - see reg_w_page() */
359static const __u8 page3_7302[] = {
360 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
361 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
362 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
364 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
365 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
366 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
367 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
370 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
374 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
375 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
376 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
379 0x00
380};
381
Márton Némethb1784b32009-11-07 05:52:02 -0300382static int reg_w_buf(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300383 __u8 index,
384 const char *buffer, int len)
385{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300386 int ret;
387
Marton Nemeth1408b842009-11-02 08:13:21 -0300388 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300389 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300390 usb_sndctrlpipe(gspca_dev->dev, 0),
391 1, /* request */
392 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
393 0, /* value */
394 index, gspca_dev->usb_buf, len,
395 500);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300396 if (ret < 0)
397 PDEBUG(D_ERR, "reg_w_buf(): "
398 "Failed to write registers to index 0x%x, error %i",
399 index, ret);
Márton Némethb1784b32009-11-07 05:52:02 -0300400 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300401}
402
403
Márton Némethb1784b32009-11-07 05:52:02 -0300404static int reg_w(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300405 __u8 index,
406 __u8 value)
407{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300408 int ret;
409
Marton Nemeth1408b842009-11-02 08:13:21 -0300410 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300411 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300412 usb_sndctrlpipe(gspca_dev->dev, 0),
413 0, /* request */
414 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
415 0, index, gspca_dev->usb_buf, 1,
416 500);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300417 if (ret < 0)
418 PDEBUG(D_ERR, "reg_w(): "
419 "Failed to write register to index 0x%x, value 0x%x, error %i",
420 index, value, ret);
Márton Némethb1784b32009-11-07 05:52:02 -0300421 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300422}
423
Márton Némethb1784b32009-11-07 05:52:02 -0300424static int reg_w_seq(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300425 const __u8 *seq, int len)
426{
Márton Némethb1784b32009-11-07 05:52:02 -0300427 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300428 while (--len >= 0) {
Márton Némethb1784b32009-11-07 05:52:02 -0300429 if (0 <= ret)
430 ret = reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300431 seq += 2;
432 }
Márton Némethb1784b32009-11-07 05:52:02 -0300433 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300434}
435
436/* load the beginning of a page */
Márton Némethb1784b32009-11-07 05:52:02 -0300437static int reg_w_page(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300438 const __u8 *page, int len)
439{
440 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300441 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300442
443 for (index = 0; index < len; index++) {
444 if (page[index] == SKIP) /* skip this index */
445 continue;
446 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300447 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300448 usb_sndctrlpipe(gspca_dev->dev, 0),
449 0, /* request */
450 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
451 0, index, gspca_dev->usb_buf, 1,
452 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300453 if (ret < 0) {
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300454 PDEBUG(D_ERR, "reg_w_page(): "
455 "Failed to write register to index 0x%x, "
456 "value 0x%x, error %i",
457 index, page[index], ret);
Márton Némethb1784b32009-11-07 05:52:02 -0300458 break;
459 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300460 }
Márton Némethb1784b32009-11-07 05:52:02 -0300461 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300462}
463
464/* output a variable sequence */
Márton Némethb1784b32009-11-07 05:52:02 -0300465static int reg_w_var(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300466 const __u8 *seq,
467 const __u8 *page3, unsigned int page3_len,
468 const __u8 *page4, unsigned int page4_len)
469{
470 int index, len;
Márton Némethb1784b32009-11-07 05:52:02 -0300471 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300472
473 for (;;) {
474 index = *seq++;
475 len = *seq++;
476 switch (len) {
477 case END_OF_SEQUENCE:
Márton Némethb1784b32009-11-07 05:52:02 -0300478 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300479 case LOAD_PAGE4:
Márton Némethb1784b32009-11-07 05:52:02 -0300480 ret = reg_w_page(gspca_dev, page4, page4_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300481 break;
482 case LOAD_PAGE3:
Márton Némethb1784b32009-11-07 05:52:02 -0300483 ret = reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300484 break;
485 default:
486 if (len > USB_BUF_SZ) {
487 PDEBUG(D_ERR|D_STREAM,
488 "Incorrect variable sequence");
Márton Némethb1784b32009-11-07 05:52:02 -0300489 return -EINVAL;
Marton Nemeth1408b842009-11-02 08:13:21 -0300490 }
491 while (len > 0) {
492 if (len < 8) {
Márton Némethb1784b32009-11-07 05:52:02 -0300493 ret = reg_w_buf(gspca_dev,
494 index, seq, len);
495 if (ret < 0)
496 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300497 seq += len;
498 break;
499 }
Márton Némethb1784b32009-11-07 05:52:02 -0300500 ret = reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300501 seq += 8;
502 index += 8;
503 len -= 8;
504 }
505 }
Márton Némethb1784b32009-11-07 05:52:02 -0300506 if (ret < 0)
507 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300508 }
509 /* not reached */
510}
511
512/* this function is called at probe time for pac7302 */
513static int sd_config(struct gspca_dev *gspca_dev,
514 const struct usb_device_id *id)
515{
516 struct sd *sd = (struct sd *) gspca_dev;
517 struct cam *cam;
518
519 cam = &gspca_dev->cam;
520
521 PDEBUG(D_CONF, "Find Sensor PAC7302");
522 cam->cam_mode = vga_mode; /* only 640x480 */
523 cam->nmodes = ARRAY_SIZE(vga_mode);
524
525 sd->brightness = BRIGHTNESS_DEF;
526 sd->contrast = CONTRAST_DEF;
527 sd->colors = COLOR_DEF;
Márton Németh265a8092009-11-07 15:15:56 -0300528 sd->red_balance = REDBALANCE_DEF;
529 sd->blue_balance = BLUEBALANCE_DEF;
Marton Nemeth1408b842009-11-02 08:13:21 -0300530 sd->gain = GAIN_DEF;
531 sd->exposure = EXPOSURE_DEF;
532 sd->autogain = AUTOGAIN_DEF;
533 sd->hflip = HFLIP_DEF;
534 sd->vflip = VFLIP_DEF;
535 return 0;
536}
537
538/* This function is used by pac7302 only */
Márton Némethb1784b32009-11-07 05:52:02 -0300539static int setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300540{
541 struct sd *sd = (struct sd *) gspca_dev;
542 int i, v;
Márton Némethb1784b32009-11-07 05:52:02 -0300543 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300544 static const __u8 max[10] =
545 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
546 0xd4, 0xec};
547 static const __u8 delta[10] =
548 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
549 0x11, 0x0b};
550
Márton Némethb1784b32009-11-07 05:52:02 -0300551 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300552 for (i = 0; i < 10; i++) {
553 v = max[i];
554 v += (sd->brightness - BRIGHTNESS_MAX)
555 * 150 / BRIGHTNESS_MAX; /* 200 ? */
556 v -= delta[i] * sd->contrast / CONTRAST_MAX;
557 if (v < 0)
558 v = 0;
559 else if (v > 0xff)
560 v = 0xff;
Márton Némethb1784b32009-11-07 05:52:02 -0300561 if (0 <= ret)
562 ret = reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300563 }
Márton Némethb1784b32009-11-07 05:52:02 -0300564 if (0 <= ret)
565 ret = reg_w(gspca_dev, 0xdc, 0x01);
566 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300567}
568
569/* This function is used by pac7302 only */
Márton Némethb1784b32009-11-07 05:52:02 -0300570static int setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300571{
572 struct sd *sd = (struct sd *) gspca_dev;
573 int i, v;
Márton Némethb1784b32009-11-07 05:52:02 -0300574 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300575 static const int a[9] =
576 {217, -212, 0, -101, 170, -67, -38, -315, 355};
577 static const int b[9] =
578 {19, 106, 0, 19, 106, 1, 19, 106, 1};
579
Márton Némethb1784b32009-11-07 05:52:02 -0300580 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
581 if (0 <= ret)
582 ret = reg_w(gspca_dev, 0x11, 0x01);
583 if (0 <= ret)
584 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300585 for (i = 0; i < 9; i++) {
586 v = a[i] * sd->colors / COLOR_MAX + b[i];
Márton Némethb1784b32009-11-07 05:52:02 -0300587 if (0 <= ret)
588 ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
589 if (0 <= ret)
590 ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300591 }
Márton Némethb1784b32009-11-07 05:52:02 -0300592 if (0 <= ret)
593 ret = reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300594 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
Márton Némethb1784b32009-11-07 05:52:02 -0300595 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300596}
597
Márton Németh265a8092009-11-07 15:15:56 -0300598static int setredbalance(struct gspca_dev *gspca_dev)
599{
600 struct sd *sd = (struct sd *) gspca_dev;
601 int ret;
602
603 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
604 if (0 <= ret)
605 ret = reg_w(gspca_dev, 0xc5, sd->red_balance);
606
607 if (0 <= ret)
608 ret = reg_w(gspca_dev, 0xdc, 0x01);
609 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
610 return ret;
611}
612
613static int setbluebalance(struct gspca_dev *gspca_dev)
614{
615 struct sd *sd = (struct sd *) gspca_dev;
616 int ret;
617
618 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
619 if (0 <= ret)
620 ret = reg_w(gspca_dev, 0xc7, sd->blue_balance);
621
622 if (0 <= ret)
623 ret = reg_w(gspca_dev, 0xdc, 0x01);
624 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
625 return ret;
626}
627
Márton Némethb1784b32009-11-07 05:52:02 -0300628static int setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300629{
630 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300631 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300632
Márton Némethb1784b32009-11-07 05:52:02 -0300633 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
634 if (0 <= ret)
635 ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);
Marton Nemeth1408b842009-11-02 08:13:21 -0300636
637 /* load registers to sensor (Bit 0, auto clear) */
Márton Némethb1784b32009-11-07 05:52:02 -0300638 if (0 <= ret)
639 ret = reg_w(gspca_dev, 0x11, 0x01);
640 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300641}
642
Márton Némethb1784b32009-11-07 05:52:02 -0300643static int setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300644{
645 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300646 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300647 __u8 reg;
648
649 /* register 2 of frame 3/4 contains the clock divider configuring the
650 no fps according to the formula: 60 / reg. sd->exposure is the
651 desired exposure time in ms. */
652 reg = 120 * sd->exposure / 1000;
653 if (reg < 2)
654 reg = 2;
655 else if (reg > 63)
656 reg = 63;
657
658 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
659 the nearest multiple of 3, except when between 6 and 12? */
660 if (reg < 6 || reg > 12)
661 reg = ((reg + 1) / 3) * 3;
Márton Némethb1784b32009-11-07 05:52:02 -0300662 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
663 if (0 <= ret)
664 ret = reg_w(gspca_dev, 0x02, reg);
Marton Nemeth1408b842009-11-02 08:13:21 -0300665
666 /* load registers to sensor (Bit 0, auto clear) */
Márton Némethb1784b32009-11-07 05:52:02 -0300667 if (0 <= ret)
668 ret = reg_w(gspca_dev, 0x11, 0x01);
669 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300670}
671
Márton Némethb1784b32009-11-07 05:52:02 -0300672static int sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300673{
674 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300675 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300676 __u8 data;
677
Márton Némethb1784b32009-11-07 05:52:02 -0300678 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300679 data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
Márton Némethb1784b32009-11-07 05:52:02 -0300680 if (0 <= ret)
681 ret = reg_w(gspca_dev, 0x21, data);
Marton Nemeth1408b842009-11-02 08:13:21 -0300682 /* load registers to sensor (Bit 0, auto clear) */
Márton Némethb1784b32009-11-07 05:52:02 -0300683 if (0 <= ret)
684 ret = reg_w(gspca_dev, 0x11, 0x01);
685 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300686}
687
688/* this function is called at probe and resume time for pac7302 */
689static int sd_init(struct gspca_dev *gspca_dev)
690{
Márton Némethb1784b32009-11-07 05:52:02 -0300691 return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
Marton Nemeth1408b842009-11-02 08:13:21 -0300692}
693
694static int sd_start(struct gspca_dev *gspca_dev)
695{
696 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300697 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300698
699 sd->sof_read = 0;
700
Márton Némethb1784b32009-11-07 05:52:02 -0300701 ret = reg_w_var(gspca_dev, start_7302,
Marton Nemeth1408b842009-11-02 08:13:21 -0300702 page3_7302, sizeof(page3_7302),
703 NULL, 0);
Márton Némethb1784b32009-11-07 05:52:02 -0300704 if (0 <= ret)
705 ret = setbrightcont(gspca_dev);
706 if (0 <= ret)
707 ret = setcolors(gspca_dev);
708 if (0 <= ret)
Márton Németh265a8092009-11-07 15:15:56 -0300709 ret = setredbalance(gspca_dev);
710 if (0 <= ret)
711 ret = setbluebalance(gspca_dev);
712 if (0 <= ret)
Márton Némethb1784b32009-11-07 05:52:02 -0300713 setgain(gspca_dev);
714 if (0 <= ret)
715 setexposure(gspca_dev);
716 if (0 <= ret)
717 sethvflip(gspca_dev);
Marton Nemeth1408b842009-11-02 08:13:21 -0300718
719 /* only resolution 640x480 is supported for pac7302 */
720
721 sd->sof_read = 0;
722 sd->autogain_ignore_frames = 0;
723 atomic_set(&sd->avg_lum, -1);
724
725 /* start stream */
Márton Némethb1784b32009-11-07 05:52:02 -0300726 if (0 <= ret)
727 ret = reg_w(gspca_dev, 0xff, 0x01);
728 if (0 <= ret)
729 ret = reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300730
Márton Némethb1784b32009-11-07 05:52:02 -0300731 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300732}
733
734static void sd_stopN(struct gspca_dev *gspca_dev)
735{
Márton Némethb1784b32009-11-07 05:52:02 -0300736 int ret;
737
Márton Németh67c98f72009-11-07 05:45:33 -0300738 /* stop stream */
Márton Némethb1784b32009-11-07 05:52:02 -0300739 ret = reg_w(gspca_dev, 0xff, 0x01);
740 if (0 <= ret)
741 ret = reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300742}
743
744/* called on streamoff with alt 0 and on disconnect for pac7302 */
745static void sd_stop0(struct gspca_dev *gspca_dev)
746{
Márton Némethb1784b32009-11-07 05:52:02 -0300747 int ret;
748
Marton Nemeth1408b842009-11-02 08:13:21 -0300749 if (!gspca_dev->present)
750 return;
Márton Némethb1784b32009-11-07 05:52:02 -0300751 ret = reg_w(gspca_dev, 0xff, 0x01);
752 if (0 <= ret)
753 ret = reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300754}
755
756/* Include pac common sof detection functions */
757#include "pac_common.h"
758
759static void do_autogain(struct gspca_dev *gspca_dev)
760{
761 struct sd *sd = (struct sd *) gspca_dev;
762 int avg_lum = atomic_read(&sd->avg_lum);
763 int desired_lum, deadzone;
764
765 if (avg_lum == -1)
766 return;
767
768 desired_lum = 270 + sd->brightness * 4;
769 /* Hack hack, with the 7202 the first exposure step is
770 pretty large, so if we're about to make the first
771 exposure increase make the deadzone large to avoid
772 oscilating */
773 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
774 sd->exposure > EXPOSURE_DEF &&
775 sd->exposure < 42)
776 deadzone = 90;
777 else
778 deadzone = 30;
779
780 if (sd->autogain_ignore_frames > 0)
781 sd->autogain_ignore_frames--;
782 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
783 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
784 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
785}
786
787/* JPEG header, part 1 */
788static const unsigned char pac_jpeg_header1[] = {
789 0xff, 0xd8, /* SOI: Start of Image */
790
791 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
792 0x00, 0x11, /* length = 17 bytes (including this length field) */
793 0x08 /* Precision: 8 */
794 /* 2 bytes is placed here: number of image lines */
795 /* 2 bytes is placed here: samples per line */
796};
797
798/* JPEG header, continued */
799static const unsigned char pac_jpeg_header2[] = {
800 0x03, /* Number of image components: 3 */
801 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
802 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
803 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
804
805 0xff, 0xda, /* SOS: Start Of Scan */
806 0x00, 0x0c, /* length = 12 bytes (including this length field) */
807 0x03, /* number of components: 3 */
808 0x01, 0x00, /* selector 1, table 0x00 */
809 0x02, 0x11, /* selector 2, table 0x11 */
810 0x03, 0x11, /* selector 3, table 0x11 */
811 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
812 0x00 /* Successive approximation: 0 */
813};
814
815static void pac_start_frame(struct gspca_dev *gspca_dev,
816 struct gspca_frame *frame,
817 __u16 lines, __u16 samples_per_line)
818{
819 unsigned char tmpbuf[4];
820
821 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
822 pac_jpeg_header1, sizeof(pac_jpeg_header1));
823
824 tmpbuf[0] = lines >> 8;
825 tmpbuf[1] = lines & 0xff;
826 tmpbuf[2] = samples_per_line >> 8;
827 tmpbuf[3] = samples_per_line & 0xff;
828
829 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
830 tmpbuf, sizeof(tmpbuf));
831 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
832 pac_jpeg_header2, sizeof(pac_jpeg_header2));
833}
834
835/* this function is run at interrupt level */
836static void sd_pkt_scan(struct gspca_dev *gspca_dev,
837 struct gspca_frame *frame, /* target */
838 __u8 *data, /* isoc packet */
839 int len) /* iso packet length */
840{
841 struct sd *sd = (struct sd *) gspca_dev;
842 unsigned char *sof;
843
844 sof = pac_find_sof(&sd->sof_read, data, len);
845 if (sof) {
846 int n, lum_offset, footer_length;
847
848 /* 6 bytes after the FF D9 EOF marker a number of lumination
849 bytes are send corresponding to different parts of the
850 image, the 14th and 15th byte after the EOF seem to
851 correspond to the center of the image */
852 lum_offset = 61 + sizeof pac_sof_marker;
853 footer_length = 74;
854
855 /* Finish decoding current frame */
856 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
857 if (n < 0) {
858 frame->data_end += n;
859 n = 0;
860 }
861 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
862 data, n);
863 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
864 frame->data_end[-2] == 0xff &&
865 frame->data_end[-1] == 0xd9)
866 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
867 NULL, 0);
868
869 n = sof - data;
870 len -= n;
871 data = sof;
872
873 /* Get average lumination */
874 if (gspca_dev->last_packet_type == LAST_PACKET &&
875 n >= lum_offset)
876 atomic_set(&sd->avg_lum, data[-lum_offset] +
877 data[-lum_offset + 1]);
878 else
879 atomic_set(&sd->avg_lum, -1);
880
881 /* Start the new frame with the jpeg header */
882 /* The PAC7302 has the image rotated 90 degrees */
883 pac_start_frame(gspca_dev, frame,
884 gspca_dev->width, gspca_dev->height);
885 }
886 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
887}
888
889static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
890{
891 struct sd *sd = (struct sd *) gspca_dev;
892
893 sd->brightness = val;
894 if (gspca_dev->streaming)
895 setbrightcont(gspca_dev);
896 return 0;
897}
898
899static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
900{
901 struct sd *sd = (struct sd *) gspca_dev;
902
903 *val = sd->brightness;
904 return 0;
905}
906
907static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
908{
909 struct sd *sd = (struct sd *) gspca_dev;
910
911 sd->contrast = val;
912 if (gspca_dev->streaming) {
913 setbrightcont(gspca_dev);
914 }
915 return 0;
916}
917
918static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
919{
920 struct sd *sd = (struct sd *) gspca_dev;
921
922 *val = sd->contrast;
923 return 0;
924}
925
926static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929
930 sd->colors = val;
931 if (gspca_dev->streaming)
932 setcolors(gspca_dev);
933 return 0;
934}
935
936static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
937{
938 struct sd *sd = (struct sd *) gspca_dev;
939
940 *val = sd->colors;
941 return 0;
942}
943
Márton Németh265a8092009-11-07 15:15:56 -0300944static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
945{
946 struct sd *sd = (struct sd *) gspca_dev;
947 int ret = 0;
948
949 sd->red_balance = val;
950 if (gspca_dev->streaming)
951 ret = setredbalance(gspca_dev);
952 if (0 <= ret)
953 ret = 0;
954 return ret;
955}
956
957static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
960
961 *val = sd->red_balance;
962 return 0;
963}
964
965static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
966{
967 struct sd *sd = (struct sd *) gspca_dev;
968 int ret = 0;
969
970 sd->blue_balance = val;
971 if (gspca_dev->streaming)
972 ret = setbluebalance(gspca_dev);
973 if (0 <= ret)
974 ret = 0;
975 return ret;
976}
977
978static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
979{
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 *val = sd->blue_balance;
983 return 0;
984}
985
Marton Nemeth1408b842009-11-02 08:13:21 -0300986static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
987{
988 struct sd *sd = (struct sd *) gspca_dev;
989
990 sd->gain = val;
991 if (gspca_dev->streaming)
992 setgain(gspca_dev);
993 return 0;
994}
995
996static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
997{
998 struct sd *sd = (struct sd *) gspca_dev;
999
1000 *val = sd->gain;
1001 return 0;
1002}
1003
1004static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1005{
1006 struct sd *sd = (struct sd *) gspca_dev;
1007
1008 sd->exposure = val;
1009 if (gspca_dev->streaming)
1010 setexposure(gspca_dev);
1011 return 0;
1012}
1013
1014static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1015{
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 *val = sd->exposure;
1019 return 0;
1020}
1021
1022static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1023{
1024 struct sd *sd = (struct sd *) gspca_dev;
1025
1026 sd->autogain = val;
1027 /* when switching to autogain set defaults to make sure
1028 we are on a valid point of the autogain gain /
1029 exposure knee graph, and give this change time to
1030 take effect before doing autogain. */
1031 if (sd->autogain) {
1032 sd->exposure = EXPOSURE_DEF;
1033 sd->gain = GAIN_DEF;
1034 if (gspca_dev->streaming) {
1035 sd->autogain_ignore_frames =
1036 PAC_AUTOGAIN_IGNORE_FRAMES;
1037 setexposure(gspca_dev);
1038 setgain(gspca_dev);
1039 }
1040 }
1041
1042 return 0;
1043}
1044
1045static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1046{
1047 struct sd *sd = (struct sd *) gspca_dev;
1048
1049 *val = sd->autogain;
1050 return 0;
1051}
1052
1053static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1054{
1055 struct sd *sd = (struct sd *) gspca_dev;
1056
1057 sd->hflip = val;
1058 if (gspca_dev->streaming)
1059 sethvflip(gspca_dev);
1060 return 0;
1061}
1062
1063static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1064{
1065 struct sd *sd = (struct sd *) gspca_dev;
1066
1067 *val = sd->hflip;
1068 return 0;
1069}
1070
1071static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1072{
1073 struct sd *sd = (struct sd *) gspca_dev;
1074
1075 sd->vflip = val;
1076 if (gspca_dev->streaming)
1077 sethvflip(gspca_dev);
1078 return 0;
1079}
1080
1081static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1082{
1083 struct sd *sd = (struct sd *) gspca_dev;
1084
1085 *val = sd->vflip;
1086 return 0;
1087}
1088
1089/* sub-driver description for pac7302 */
1090static struct sd_desc sd_desc = {
1091 .name = MODULE_NAME,
1092 .ctrls = sd_ctrls,
1093 .nctrls = ARRAY_SIZE(sd_ctrls),
1094 .config = sd_config,
1095 .init = sd_init,
1096 .start = sd_start,
1097 .stopN = sd_stopN,
1098 .stop0 = sd_stop0,
1099 .pkt_scan = sd_pkt_scan,
1100 .dq_callback = do_autogain,
1101};
1102
1103/* -- module initialisation -- */
1104static __devinitdata struct usb_device_id device_table[] = {
1105 {USB_DEVICE(0x06f8, 0x3009)},
1106 {USB_DEVICE(0x093a, 0x2620)},
1107 {USB_DEVICE(0x093a, 0x2621)},
1108 {USB_DEVICE(0x093a, 0x2622)},
1109 {USB_DEVICE(0x093a, 0x2624)},
1110 {USB_DEVICE(0x093a, 0x2626)},
1111 {USB_DEVICE(0x093a, 0x2628)},
1112 {USB_DEVICE(0x093a, 0x2629)},
1113 {USB_DEVICE(0x093a, 0x262a)},
1114 {USB_DEVICE(0x093a, 0x262c)},
1115 {}
1116};
1117MODULE_DEVICE_TABLE(usb, device_table);
1118
1119/* -- device connect -- */
1120static int sd_probe(struct usb_interface *intf,
1121 const struct usb_device_id *id)
1122{
1123 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1124 THIS_MODULE);
1125}
1126
1127static struct usb_driver sd_driver = {
1128 .name = MODULE_NAME,
1129 .id_table = device_table,
1130 .probe = sd_probe,
1131 .disconnect = gspca_disconnect,
1132#ifdef CONFIG_PM
1133 .suspend = gspca_suspend,
1134 .resume = gspca_resume,
1135#endif
1136};
1137
1138/* -- module insert / remove -- */
1139static int __init sd_mod_init(void)
1140{
1141 int ret;
1142 ret = usb_register(&sd_driver);
1143 if (ret < 0)
1144 return ret;
1145 PDEBUG(D_PROBE, "registered");
1146 return 0;
1147}
1148static void __exit sd_mod_exit(void)
1149{
1150 usb_deregister(&sd_driver);
1151 PDEBUG(D_PROBE, "deregistered");
1152}
1153
1154module_init(sd_mod_init);
1155module_exit(sd_mod_exit);