blob: a66df07d7625668c485660d807c9dea2549bdee2 [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 *
Jean-Francois Moinecc2f82c2010-01-28 16:35:40 -03007 * Separated from Pixart PAC7311 library by Márton Németh
Márton Némethaed6f1b2010-01-28 16:33:38 -03008 * Camera button input handling by Márton Németh <nm127@freemail.hu>
9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
Marton Nemeth1408b842009-11-02 08:13:21 -030010 *
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.
Marton Nemeth1408b842009-11-02 08:13:21 -030027
28 Register page 1:
29
30 Address Description
Marton Nemeth1408b842009-11-02 08:13:21 -030031 0x78 Global control, bit 6 controls the LED (inverted)
Marton Nemeth1408b842009-11-02 08:13:21 -030032
Hans de Goede5fb2dde2010-02-17 11:59:19 -030033 Register page 3:
Marton Nemeth1408b842009-11-02 08:13:21 -030034
35 Address Description
Hans de Goede5fb2dde2010-02-17 11:59:19 -030036 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
Marton Nemeth1408b842009-11-02 08:13:21 -030037 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
Hans de Goede5fb2dde2010-02-17 11:59:19 -030038 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
Marton Nemeth1408b842009-11-02 08:13:21 -030046 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
Márton Németh265a8092009-11-07 15:15:56 -030047
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()
Marton Nemeth23fbee62009-11-08 04:35:12 -030055 0 | 0xc6 | setwhitebalance()
Márton Németh265a8092009-11-07 15:15:56 -030056 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()
Marton Nemeth1408b842009-11-02 08:13:21 -030062*/
63
64#define MODULE_NAME "pac7302"
65
Márton Némethaed6f1b2010-01-28 16:33:38 -030066#include <linux/input.h>
Márton Németh6763cc02009-11-09 07:10:46 -030067#include <media/v4l2-chip-ident.h>
Marton Nemeth1408b842009-11-02 08:13:21 -030068#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;
Marton Nemeth23fbee62009-11-08 04:35:12 -030081 unsigned char white_balance;
Márton Németh265a8092009-11-07 15:15:56 -030082 unsigned char red_balance;
83 unsigned char blue_balance;
Marton Nemeth1408b842009-11-02 08:13:21 -030084 unsigned char gain;
Marton Nemeth1408b842009-11-02 08:13:21 -030085 unsigned char autogain;
Hans de Goede5fb2dde2010-02-17 11:59:19 -030086 unsigned short exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -030087 __u8 hflip;
88 __u8 vflip;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -030089 u8 flags;
90#define FL_HFLIP 0x01 /* mirrored by default */
91#define FL_VFLIP 0x02 /* vertical flipped by default */
Marton Nemeth1408b842009-11-02 08:13:21 -030092
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);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300106static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
Márton Németh265a8092009-11-07 15:15:56 -0300108static 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);
Marton Nemeth1408b842009-11-02 08:13:21 -0300112static 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
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300123static const struct ctrl sd_ctrls[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300124 {
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 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300139 {
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 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300154 {
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 },
Márton Németh265a8092009-11-07 15:15:56 -0300169 {
170 {
Marton Nemeth23fbee62009-11-08 04:35:12 -0300171 .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 },
183 {
184 {
Márton Németh265a8092009-11-07 15:15:56 -0300185 .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 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300211 {
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,
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300233 .maximum = 1023,
Marton Nemeth1408b842009-11-02 08:13:21 -0300234 .step = 1,
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300235#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
236#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
Marton Nemeth1408b842009-11-02 08:13:21 -0300237 .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
Marton Nemeth1408b842009-11-02 08:13:21 -0300295#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[] = {
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300372 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
Marton Nemeth1408b842009-11-02 08:13:21 -0300373 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,
Jean-Francois Moinecdf955c2010-01-11 15:06:12 -0300381 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
Marton Nemeth1408b842009-11-02 08:13:21 -0300382 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
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300394static void reg_w_buf(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300395 __u8 index,
396 const char *buffer, int len)
397{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300398 int ret;
399
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300400 if (gspca_dev->usb_err < 0)
401 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300402 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300403 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300404 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-François Moinea1317132010-06-24 04:50:26 -0300405 0, /* request */
Marton Nemeth1408b842009-11-02 08:13:21 -0300406 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
407 0, /* value */
408 index, gspca_dev->usb_buf, len,
409 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300410 if (ret < 0) {
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300411 PDEBUG(D_ERR, "reg_w_buf(): "
412 "Failed to write registers to index 0x%x, error %i",
413 index, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300414 gspca_dev->usb_err = ret;
415 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300416}
417
418
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300419static void reg_w(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300420 __u8 index,
421 __u8 value)
422{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300423 int ret;
424
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300425 if (gspca_dev->usb_err < 0)
426 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300427 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300428 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300429 usb_sndctrlpipe(gspca_dev->dev, 0),
430 0, /* request */
431 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
432 0, index, gspca_dev->usb_buf, 1,
433 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300434 if (ret < 0) {
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300435 PDEBUG(D_ERR, "reg_w(): "
436 "Failed to write register to index 0x%x, value 0x%x, error %i",
437 index, value, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300438 gspca_dev->usb_err = ret;
439 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300440}
441
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300442static void reg_w_seq(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300443 const __u8 *seq, int len)
444{
445 while (--len >= 0) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300446 reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300447 seq += 2;
448 }
449}
450
451/* load the beginning of a page */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300452static void reg_w_page(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300453 const __u8 *page, int len)
454{
455 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300456 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300457
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300458 if (gspca_dev->usb_err < 0)
459 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300460 for (index = 0; index < len; index++) {
461 if (page[index] == SKIP) /* skip this index */
462 continue;
463 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300464 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300465 usb_sndctrlpipe(gspca_dev->dev, 0),
466 0, /* request */
467 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
468 0, index, gspca_dev->usb_buf, 1,
469 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300470 if (ret < 0) {
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300471 PDEBUG(D_ERR, "reg_w_page(): "
472 "Failed to write register to index 0x%x, "
473 "value 0x%x, error %i",
474 index, page[index], ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300475 gspca_dev->usb_err = ret;
Márton Némethb1784b32009-11-07 05:52:02 -0300476 break;
477 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300478 }
479}
480
481/* output a variable sequence */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300482static void reg_w_var(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300483 const __u8 *seq,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300484 const __u8 *page3, unsigned int page3_len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300485{
486 int index, len;
487
488 for (;;) {
489 index = *seq++;
490 len = *seq++;
491 switch (len) {
492 case END_OF_SEQUENCE:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300493 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300494 case LOAD_PAGE3:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300495 reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300496 break;
497 default:
498 if (len > USB_BUF_SZ) {
499 PDEBUG(D_ERR|D_STREAM,
500 "Incorrect variable sequence");
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300501 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300502 }
503 while (len > 0) {
504 if (len < 8) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300505 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300506 index, seq, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300507 seq += len;
508 break;
509 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300510 reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300511 seq += 8;
512 index += 8;
513 len -= 8;
514 }
515 }
516 }
517 /* not reached */
518}
519
520/* this function is called at probe time for pac7302 */
521static int sd_config(struct gspca_dev *gspca_dev,
522 const struct usb_device_id *id)
523{
524 struct sd *sd = (struct sd *) gspca_dev;
525 struct cam *cam;
526
527 cam = &gspca_dev->cam;
528
529 PDEBUG(D_CONF, "Find Sensor PAC7302");
530 cam->cam_mode = vga_mode; /* only 640x480 */
531 cam->nmodes = ARRAY_SIZE(vga_mode);
532
533 sd->brightness = BRIGHTNESS_DEF;
534 sd->contrast = CONTRAST_DEF;
535 sd->colors = COLOR_DEF;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300536 sd->white_balance = WHITEBALANCE_DEF;
Márton Németh265a8092009-11-07 15:15:56 -0300537 sd->red_balance = REDBALANCE_DEF;
538 sd->blue_balance = BLUEBALANCE_DEF;
Marton Nemeth1408b842009-11-02 08:13:21 -0300539 sd->gain = GAIN_DEF;
540 sd->exposure = EXPOSURE_DEF;
541 sd->autogain = AUTOGAIN_DEF;
542 sd->hflip = HFLIP_DEF;
543 sd->vflip = VFLIP_DEF;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300544 sd->flags = id->driver_info;
Marton Nemeth1408b842009-11-02 08:13:21 -0300545 return 0;
546}
547
548/* This function is used by pac7302 only */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300549static void setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300550{
551 struct sd *sd = (struct sd *) gspca_dev;
552 int i, v;
553 static const __u8 max[10] =
554 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
555 0xd4, 0xec};
556 static const __u8 delta[10] =
557 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
558 0x11, 0x0b};
559
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300560 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300561 for (i = 0; i < 10; i++) {
562 v = max[i];
563 v += (sd->brightness - BRIGHTNESS_MAX)
564 * 150 / BRIGHTNESS_MAX; /* 200 ? */
565 v -= delta[i] * sd->contrast / CONTRAST_MAX;
566 if (v < 0)
567 v = 0;
568 else if (v > 0xff)
569 v = 0xff;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300570 reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300571 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300572 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300573}
574
575/* This function is used by pac7302 only */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300576static void setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300577{
578 struct sd *sd = (struct sd *) gspca_dev;
579 int i, v;
580 static const int a[9] =
581 {217, -212, 0, -101, 170, -67, -38, -315, 355};
582 static const int b[9] =
583 {19, 106, 0, 19, 106, 1, 19, 106, 1};
584
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300585 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
586 reg_w(gspca_dev, 0x11, 0x01);
587 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300588 for (i = 0; i < 9; i++) {
589 v = a[i] * sd->colors / COLOR_MAX + b[i];
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300590 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
591 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300592 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300593 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300594 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
595}
596
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300597static void setwhitebalance(struct gspca_dev *gspca_dev)
Marton Nemeth23fbee62009-11-08 04:35:12 -0300598{
599 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300600
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300601 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
602 reg_w(gspca_dev, 0xc6, sd->white_balance);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300603
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300604 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300605 PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300606}
607
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300608static void setredbalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300609{
610 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300611
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300612 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
613 reg_w(gspca_dev, 0xc5, sd->red_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300614
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300615 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300616 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300617}
618
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300619static void setbluebalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300620{
621 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300622
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300623 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
624 reg_w(gspca_dev, 0xc7, sd->blue_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300625
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300626 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300627 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300628}
629
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300630static void setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300631{
632 struct sd *sd = (struct sd *) gspca_dev;
633
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300634 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
635 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) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300638 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300639}
640
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300641static void setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300642{
643 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300644 __u8 clockdiv;
645 __u16 exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -0300646
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300647 /* register 2 of frame 3 contains the clock divider configuring the
648 no fps according to the formula: 90 / reg. sd->exposure is the
649 desired exposure time in 0.5 ms. */
650 clockdiv = (90 * sd->exposure + 1999) / 2000;
Marton Nemeth1408b842009-11-02 08:13:21 -0300651
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300652 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
653 on the scene being recorded, the camera switches to another
654 quantization table for certain JPEG blocks, and we don't know how
655 to decompress these blocks. So we cap the framerate at 15 fps */
656 if (clockdiv < 6)
657 clockdiv = 6;
658 else if (clockdiv > 63)
659 clockdiv = 63;
660
661 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
662 Always round up, otherwise we cannot get the desired frametime
663 using the partial frame time exposure control */
664 if (clockdiv < 6 || clockdiv > 12)
665 clockdiv = ((clockdiv + 2) / 3) * 3;
666
667 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
668 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
669 exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv);
670 /* 0 = use full frametime, 448 = no exposure, reverse it */
671 exposure = 448 - exposure;
672
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300673 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300674 reg_w(gspca_dev, 0x02, clockdiv);
675 reg_w(gspca_dev, 0x0e, exposure & 0xff);
676 reg_w(gspca_dev, 0x0f, exposure >> 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300677
678 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300679 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300680}
681
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300682static void sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300683{
684 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300685 u8 data, hflip, vflip;
686
687 hflip = sd->hflip;
688 if (sd->flags & FL_HFLIP)
689 hflip = !hflip;
690 vflip = sd->vflip;
691 if (sd->flags & FL_VFLIP)
692 vflip = !vflip;
Marton Nemeth1408b842009-11-02 08:13:21 -0300693
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300694 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300695 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300696 reg_w(gspca_dev, 0x21, data);
697
Marton Nemeth1408b842009-11-02 08:13:21 -0300698 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300699 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300700}
701
702/* this function is called at probe and resume time for pac7302 */
703static int sd_init(struct gspca_dev *gspca_dev)
704{
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300705 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
706 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300707}
708
709static int sd_start(struct gspca_dev *gspca_dev)
710{
711 struct sd *sd = (struct sd *) gspca_dev;
712
713 sd->sof_read = 0;
714
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300715 reg_w_var(gspca_dev, start_7302,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300716 page3_7302, sizeof(page3_7302));
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300717 setbrightcont(gspca_dev);
718 setcolors(gspca_dev);
719 setwhitebalance(gspca_dev);
720 setredbalance(gspca_dev);
721 setbluebalance(gspca_dev);
722 setgain(gspca_dev);
723 setexposure(gspca_dev);
724 sethvflip(gspca_dev);
Marton Nemeth1408b842009-11-02 08:13:21 -0300725
726 /* only resolution 640x480 is supported for pac7302 */
727
728 sd->sof_read = 0;
729 sd->autogain_ignore_frames = 0;
730 atomic_set(&sd->avg_lum, -1);
731
732 /* start stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300733 reg_w(gspca_dev, 0xff, 0x01);
734 reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300735
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300736 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300737}
738
739static void sd_stopN(struct gspca_dev *gspca_dev)
740{
Márton Némethb1784b32009-11-07 05:52:02 -0300741
Márton Németh67c98f72009-11-07 05:45:33 -0300742 /* stop stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300743 reg_w(gspca_dev, 0xff, 0x01);
744 reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300745}
746
747/* called on streamoff with alt 0 and on disconnect for pac7302 */
748static void sd_stop0(struct gspca_dev *gspca_dev)
749{
750 if (!gspca_dev->present)
751 return;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300752 reg_w(gspca_dev, 0xff, 0x01);
753 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);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300763 int desired_lum;
764 const int deadzone = 30;
Marton Nemeth1408b842009-11-02 08:13:21 -0300765
766 if (avg_lum == -1)
767 return;
768
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300769 desired_lum = 270 + sd->brightness;
Marton Nemeth1408b842009-11-02 08:13:21 -0300770
771 if (sd->autogain_ignore_frames > 0)
772 sd->autogain_ignore_frames--;
773 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
774 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
775 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
776}
777
778/* JPEG header, part 1 */
779static const unsigned char pac_jpeg_header1[] = {
780 0xff, 0xd8, /* SOI: Start of Image */
781
782 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
783 0x00, 0x11, /* length = 17 bytes (including this length field) */
784 0x08 /* Precision: 8 */
785 /* 2 bytes is placed here: number of image lines */
786 /* 2 bytes is placed here: samples per line */
787};
788
789/* JPEG header, continued */
790static const unsigned char pac_jpeg_header2[] = {
791 0x03, /* Number of image components: 3 */
792 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
793 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
794 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
795
796 0xff, 0xda, /* SOS: Start Of Scan */
797 0x00, 0x0c, /* length = 12 bytes (including this length field) */
798 0x03, /* number of components: 3 */
799 0x01, 0x00, /* selector 1, table 0x00 */
800 0x02, 0x11, /* selector 2, table 0x11 */
801 0x03, 0x11, /* selector 3, table 0x11 */
802 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
803 0x00 /* Successive approximation: 0 */
804};
805
806static void pac_start_frame(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300807 __u16 lines, __u16 samples_per_line)
808{
809 unsigned char tmpbuf[4];
810
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300811 gspca_frame_add(gspca_dev, FIRST_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300812 pac_jpeg_header1, sizeof(pac_jpeg_header1));
813
814 tmpbuf[0] = lines >> 8;
815 tmpbuf[1] = lines & 0xff;
816 tmpbuf[2] = samples_per_line >> 8;
817 tmpbuf[3] = samples_per_line & 0xff;
818
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300819 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300820 tmpbuf, sizeof(tmpbuf));
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300821 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300822 pac_jpeg_header2, sizeof(pac_jpeg_header2));
823}
824
825/* this function is run at interrupt level */
826static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300827 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300828 int len) /* iso packet length */
829{
830 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300831 u8 *image;
Marton Nemeth1408b842009-11-02 08:13:21 -0300832 unsigned char *sof;
833
834 sof = pac_find_sof(&sd->sof_read, data, len);
835 if (sof) {
836 int n, lum_offset, footer_length;
837
838 /* 6 bytes after the FF D9 EOF marker a number of lumination
839 bytes are send corresponding to different parts of the
840 image, the 14th and 15th byte after the EOF seem to
841 correspond to the center of the image */
842 lum_offset = 61 + sizeof pac_sof_marker;
843 footer_length = 74;
844
845 /* Finish decoding current frame */
846 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
847 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300848 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300849 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300850 } else {
851 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300852 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300853
854 image = gspca_dev->image;
855 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300856 && image[gspca_dev->image_len - 2] == 0xff
857 && image[gspca_dev->image_len - 1] == 0xd9)
858 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Marton Nemeth1408b842009-11-02 08:13:21 -0300859
860 n = sof - data;
861 len -= n;
862 data = sof;
863
864 /* Get average lumination */
865 if (gspca_dev->last_packet_type == LAST_PACKET &&
866 n >= lum_offset)
867 atomic_set(&sd->avg_lum, data[-lum_offset] +
868 data[-lum_offset + 1]);
869 else
870 atomic_set(&sd->avg_lum, -1);
871
872 /* Start the new frame with the jpeg header */
873 /* The PAC7302 has the image rotated 90 degrees */
Jean-François Moineb192ca92010-06-27 03:08:19 -0300874 pac_start_frame(gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300875 gspca_dev->width, gspca_dev->height);
876 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300877 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300878}
879
880static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
881{
882 struct sd *sd = (struct sd *) gspca_dev;
883
884 sd->brightness = val;
885 if (gspca_dev->streaming)
886 setbrightcont(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300887 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300888}
889
890static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
891{
892 struct sd *sd = (struct sd *) gspca_dev;
893
894 *val = sd->brightness;
895 return 0;
896}
897
898static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
899{
900 struct sd *sd = (struct sd *) gspca_dev;
901
902 sd->contrast = val;
903 if (gspca_dev->streaming) {
904 setbrightcont(gspca_dev);
905 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300906 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300907}
908
909static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
910{
911 struct sd *sd = (struct sd *) gspca_dev;
912
913 *val = sd->contrast;
914 return 0;
915}
916
917static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
918{
919 struct sd *sd = (struct sd *) gspca_dev;
920
921 sd->colors = val;
922 if (gspca_dev->streaming)
923 setcolors(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300924 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300925}
926
927static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
928{
929 struct sd *sd = (struct sd *) gspca_dev;
930
931 *val = sd->colors;
932 return 0;
933}
934
Marton Nemeth23fbee62009-11-08 04:35:12 -0300935static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300938
939 sd->white_balance = val;
940 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300941 setwhitebalance(gspca_dev);
942 return gspca_dev->usb_err;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300943}
944
945static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
946{
947 struct sd *sd = (struct sd *) gspca_dev;
948
949 *val = sd->white_balance;
950 return 0;
951}
952
Márton Németh265a8092009-11-07 15:15:56 -0300953static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
954{
955 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300956
957 sd->red_balance = val;
958 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300959 setredbalance(gspca_dev);
960 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300961}
962
963static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
964{
965 struct sd *sd = (struct sd *) gspca_dev;
966
967 *val = sd->red_balance;
968 return 0;
969}
970
971static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
972{
973 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300974
975 sd->blue_balance = val;
976 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300977 setbluebalance(gspca_dev);
978 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300979}
980
981static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
982{
983 struct sd *sd = (struct sd *) gspca_dev;
984
985 *val = sd->blue_balance;
986 return 0;
987}
988
Marton Nemeth1408b842009-11-02 08:13:21 -0300989static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
990{
991 struct sd *sd = (struct sd *) gspca_dev;
992
993 sd->gain = val;
994 if (gspca_dev->streaming)
995 setgain(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300996 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300997}
998
999static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1000{
1001 struct sd *sd = (struct sd *) gspca_dev;
1002
1003 *val = sd->gain;
1004 return 0;
1005}
1006
1007static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1008{
1009 struct sd *sd = (struct sd *) gspca_dev;
1010
1011 sd->exposure = val;
1012 if (gspca_dev->streaming)
1013 setexposure(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001014 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001015}
1016
1017static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1018{
1019 struct sd *sd = (struct sd *) gspca_dev;
1020
1021 *val = sd->exposure;
1022 return 0;
1023}
1024
1025static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1026{
1027 struct sd *sd = (struct sd *) gspca_dev;
1028
1029 sd->autogain = val;
1030 /* when switching to autogain set defaults to make sure
1031 we are on a valid point of the autogain gain /
1032 exposure knee graph, and give this change time to
1033 take effect before doing autogain. */
1034 if (sd->autogain) {
1035 sd->exposure = EXPOSURE_DEF;
1036 sd->gain = GAIN_DEF;
1037 if (gspca_dev->streaming) {
1038 sd->autogain_ignore_frames =
1039 PAC_AUTOGAIN_IGNORE_FRAMES;
1040 setexposure(gspca_dev);
1041 setgain(gspca_dev);
1042 }
1043 }
1044
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001045 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001046}
1047
1048static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1049{
1050 struct sd *sd = (struct sd *) gspca_dev;
1051
1052 *val = sd->autogain;
1053 return 0;
1054}
1055
1056static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1057{
1058 struct sd *sd = (struct sd *) gspca_dev;
1059
1060 sd->hflip = val;
1061 if (gspca_dev->streaming)
1062 sethvflip(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001063 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001064}
1065
1066static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069
1070 *val = sd->hflip;
1071 return 0;
1072}
1073
1074static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1075{
1076 struct sd *sd = (struct sd *) gspca_dev;
1077
1078 sd->vflip = val;
1079 if (gspca_dev->streaming)
1080 sethvflip(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001081 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001082}
1083
1084static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1085{
1086 struct sd *sd = (struct sd *) gspca_dev;
1087
1088 *val = sd->vflip;
1089 return 0;
1090}
1091
Márton Németh6763cc02009-11-09 07:10:46 -03001092#ifdef CONFIG_VIDEO_ADV_DEBUG
1093static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1094 struct v4l2_dbg_register *reg)
1095{
Márton Németh6763cc02009-11-09 07:10:46 -03001096 __u8 index;
1097 __u8 value;
1098
1099 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
1100 long on the USB bus)
1101 */
1102 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
1103 reg->match.addr == 0 &&
1104 (reg->reg < 0x000000ff) &&
1105 (reg->val <= 0x000000ff)
1106 ) {
1107 /* Currently writing to page 0 is only supported. */
1108 /* reg_w() only supports 8bit index */
1109 index = reg->reg & 0x000000ff;
1110 value = reg->val & 0x000000ff;
1111
1112 /* Note that there shall be no access to other page
1113 by any other function between the page swith and
1114 the actual register write */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001115 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1116 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -03001117
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001118 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -03001119 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001120 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -03001121}
1122
1123static int sd_chip_ident(struct gspca_dev *gspca_dev,
1124 struct v4l2_dbg_chip_ident *chip)
1125{
1126 int ret = -EINVAL;
1127
1128 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1129 chip->match.addr == 0) {
1130 chip->revision = 0;
1131 chip->ident = V4L2_IDENT_UNKNOWN;
1132 ret = 0;
1133 }
1134 return ret;
1135}
1136#endif
1137
Márton Némethaed6f1b2010-01-28 16:33:38 -03001138#ifdef CONFIG_INPUT
1139static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1140 u8 *data, /* interrupt packet data */
1141 int len) /* interrput packet length */
1142{
1143 int ret = -EINVAL;
1144 u8 data0, data1;
1145
1146 if (len == 2) {
1147 data0 = data[0];
1148 data1 = data[1];
1149 if ((data0 == 0x00 && data1 == 0x11) ||
1150 (data0 == 0x22 && data1 == 0x33) ||
1151 (data0 == 0x44 && data1 == 0x55) ||
1152 (data0 == 0x66 && data1 == 0x77) ||
1153 (data0 == 0x88 && data1 == 0x99) ||
1154 (data0 == 0xaa && data1 == 0xbb) ||
1155 (data0 == 0xcc && data1 == 0xdd) ||
1156 (data0 == 0xee && data1 == 0xff)) {
1157 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1158 input_sync(gspca_dev->input_dev);
1159 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1160 input_sync(gspca_dev->input_dev);
1161 ret = 0;
1162 }
1163 }
1164
1165 return ret;
1166}
1167#endif
1168
Marton Nemeth1408b842009-11-02 08:13:21 -03001169/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -03001170static const struct sd_desc sd_desc = {
Marton Nemeth1408b842009-11-02 08:13:21 -03001171 .name = MODULE_NAME,
1172 .ctrls = sd_ctrls,
1173 .nctrls = ARRAY_SIZE(sd_ctrls),
1174 .config = sd_config,
1175 .init = sd_init,
1176 .start = sd_start,
1177 .stopN = sd_stopN,
1178 .stop0 = sd_stop0,
1179 .pkt_scan = sd_pkt_scan,
1180 .dq_callback = do_autogain,
Márton Németh6763cc02009-11-09 07:10:46 -03001181#ifdef CONFIG_VIDEO_ADV_DEBUG
1182 .set_register = sd_dbg_s_register,
1183 .get_chip_ident = sd_chip_ident,
1184#endif
Márton Némethaed6f1b2010-01-28 16:33:38 -03001185#ifdef CONFIG_INPUT
1186 .int_pkt_scan = sd_int_pkt_scan,
1187#endif
Marton Nemeth1408b842009-11-02 08:13:21 -03001188};
1189
1190/* -- module initialisation -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001191static const struct usb_device_id device_table[] __devinitconst = {
Marton Nemeth1408b842009-11-02 08:13:21 -03001192 {USB_DEVICE(0x06f8, 0x3009)},
1193 {USB_DEVICE(0x093a, 0x2620)},
1194 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -03001195 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1196 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -03001197 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001198 {USB_DEVICE(0x093a, 0x2626)},
1199 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -03001200 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -03001201 {USB_DEVICE(0x093a, 0x262a)},
1202 {USB_DEVICE(0x093a, 0x262c)},
1203 {}
1204};
1205MODULE_DEVICE_TABLE(usb, device_table);
1206
1207/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001208static int __devinit sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -03001209 const struct usb_device_id *id)
1210{
1211 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1212 THIS_MODULE);
1213}
1214
1215static struct usb_driver sd_driver = {
1216 .name = MODULE_NAME,
1217 .id_table = device_table,
1218 .probe = sd_probe,
1219 .disconnect = gspca_disconnect,
1220#ifdef CONFIG_PM
1221 .suspend = gspca_suspend,
1222 .resume = gspca_resume,
1223#endif
1224};
1225
1226/* -- module insert / remove -- */
1227static int __init sd_mod_init(void)
1228{
1229 int ret;
1230 ret = usb_register(&sd_driver);
1231 if (ret < 0)
1232 return ret;
1233 PDEBUG(D_PROBE, "registered");
1234 return 0;
1235}
1236static void __exit sd_mod_exit(void)
1237{
1238 usb_deregister(&sd_driver);
1239 PDEBUG(D_PROBE, "deregistered");
1240}
1241
1242module_init(sd_mod_init);
1243module_exit(sd_mod_exit);