blob: 2700975abce5e277103830ef419485054d05976a [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,
Jean-François Moine0aeb5ec2010-12-28 06:59:04 -0300396 const u8 *buffer, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300397{
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) {
Jean-François Moine0b656322010-09-13 05:19:58 -0300411 err("reg_w_buf failed index 0x%02x, error %d",
412 index, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300413 gspca_dev->usb_err = ret;
414 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300415}
416
417
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300418static void reg_w(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300419 __u8 index,
420 __u8 value)
421{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300422 int ret;
423
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300424 if (gspca_dev->usb_err < 0)
425 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300426 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300427 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300428 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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300433 if (ret < 0) {
Jean-François Moine0b656322010-09-13 05:19:58 -0300434 err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
435 index, value, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300436 gspca_dev->usb_err = ret;
437 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300438}
439
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300440static void reg_w_seq(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300441 const __u8 *seq, int len)
442{
443 while (--len >= 0) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300444 reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300445 seq += 2;
446 }
447}
448
449/* load the beginning of a page */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300450static void reg_w_page(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300451 const __u8 *page, int len)
452{
453 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300454 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300455
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300456 if (gspca_dev->usb_err < 0)
457 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300458 for (index = 0; index < len; index++) {
459 if (page[index] == SKIP) /* skip this index */
460 continue;
461 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300462 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300463 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);
Márton Némethb1784b32009-11-07 05:52:02 -0300468 if (ret < 0) {
Jean-François Moine0b656322010-09-13 05:19:58 -0300469 err("reg_w_page() failed index 0x%02x, "
470 "value 0x%02x, error %d",
471 index, page[index], ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300472 gspca_dev->usb_err = ret;
Márton Némethb1784b32009-11-07 05:52:02 -0300473 break;
474 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300475 }
476}
477
478/* output a variable sequence */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300479static void reg_w_var(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300480 const __u8 *seq,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300481 const __u8 *page3, unsigned int page3_len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300482{
483 int index, len;
484
485 for (;;) {
486 index = *seq++;
487 len = *seq++;
488 switch (len) {
489 case END_OF_SEQUENCE:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300490 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300491 case LOAD_PAGE3:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300492 reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300493 break;
494 default:
495 if (len > USB_BUF_SZ) {
496 PDEBUG(D_ERR|D_STREAM,
497 "Incorrect variable sequence");
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300498 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300499 }
500 while (len > 0) {
501 if (len < 8) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300502 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300503 index, seq, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300504 seq += len;
505 break;
506 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300507 reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300508 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;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300533 sd->white_balance = WHITEBALANCE_DEF;
Márton Németh265a8092009-11-07 15:15:56 -0300534 sd->red_balance = REDBALANCE_DEF;
535 sd->blue_balance = BLUEBALANCE_DEF;
Marton Nemeth1408b842009-11-02 08:13:21 -0300536 sd->gain = GAIN_DEF;
537 sd->exposure = EXPOSURE_DEF;
538 sd->autogain = AUTOGAIN_DEF;
539 sd->hflip = HFLIP_DEF;
540 sd->vflip = VFLIP_DEF;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300541 sd->flags = id->driver_info;
Marton Nemeth1408b842009-11-02 08:13:21 -0300542 return 0;
543}
544
545/* This function is used by pac7302 only */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300546static void setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300547{
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
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300557 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300558 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;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300567 reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300568 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300569 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300570}
571
572/* This function is used by pac7302 only */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300573static void setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300574{
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
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300582 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
583 reg_w(gspca_dev, 0x11, 0x01);
584 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];
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300587 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
588 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300589 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300590 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300591 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
592}
593
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300594static void setwhitebalance(struct gspca_dev *gspca_dev)
Marton Nemeth23fbee62009-11-08 04:35:12 -0300595{
596 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300597
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300598 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
599 reg_w(gspca_dev, 0xc6, sd->white_balance);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300600
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300601 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300602 PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300603}
604
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300605static void setredbalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300606{
607 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300608
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300609 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
610 reg_w(gspca_dev, 0xc5, sd->red_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300611
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300612 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300613 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300614}
615
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300616static void setbluebalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300617{
618 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300619
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300620 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
621 reg_w(gspca_dev, 0xc7, sd->blue_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300622
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300623 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300624 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300625}
626
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300627static void setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300628{
629 struct sd *sd = (struct sd *) gspca_dev;
630
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300631 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
632 reg_w(gspca_dev, 0x10, sd->gain >> 3);
Marton Nemeth1408b842009-11-02 08:13:21 -0300633
634 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300635 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300636}
637
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300638static void setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300639{
640 struct sd *sd = (struct sd *) gspca_dev;
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300641 __u8 clockdiv;
642 __u16 exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -0300643
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300644 /* 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;
Marton Nemeth1408b842009-11-02 08:13:21 -0300648
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300649 /* 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
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300670 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300671 reg_w(gspca_dev, 0x02, clockdiv);
672 reg_w(gspca_dev, 0x0e, exposure & 0xff);
673 reg_w(gspca_dev, 0x0f, exposure >> 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300674
675 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300676 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300677}
678
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300679static void sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300680{
681 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300682 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;
Marton Nemeth1408b842009-11-02 08:13:21 -0300690
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300691 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300692 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300693 reg_w(gspca_dev, 0x21, data);
694
Marton Nemeth1408b842009-11-02 08:13:21 -0300695 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300696 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300697}
698
699/* this function is called at probe and resume time for pac7302 */
700static int sd_init(struct gspca_dev *gspca_dev)
701{
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300702 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
703 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300704}
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
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300712 reg_w_var(gspca_dev, start_7302,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300713 page3_7302, sizeof(page3_7302));
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300714 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);
Marton Nemeth1408b842009-11-02 08:13:21 -0300722
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 */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300730 reg_w(gspca_dev, 0xff, 0x01);
731 reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300732
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300733 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300734}
735
736static void sd_stopN(struct gspca_dev *gspca_dev)
737{
Márton Némethb1784b32009-11-07 05:52:02 -0300738
Márton Németh67c98f72009-11-07 05:45:33 -0300739 /* stop stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300740 reg_w(gspca_dev, 0xff, 0x01);
741 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{
747 if (!gspca_dev->present)
748 return;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300749 reg_w(gspca_dev, 0xff, 0x01);
750 reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300751}
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);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300760 int desired_lum;
761 const int deadzone = 30;
Marton Nemeth1408b842009-11-02 08:13:21 -0300762
763 if (avg_lum == -1)
764 return;
765
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300766 desired_lum = 270 + sd->brightness;
Marton Nemeth1408b842009-11-02 08:13:21 -0300767
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,
Marton Nemeth1408b842009-11-02 08:13:21 -0300804 __u16 lines, __u16 samples_per_line)
805{
806 unsigned char tmpbuf[4];
807
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300808 gspca_frame_add(gspca_dev, FIRST_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300809 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
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300816 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300817 tmpbuf, sizeof(tmpbuf));
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300818 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300819 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,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300824 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300825 int len) /* iso packet length */
826{
827 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300828 u8 *image;
Marton Nemeth1408b842009-11-02 08:13:21 -0300829 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) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300845 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300846 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300847 } else {
848 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300849 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300850
851 image = gspca_dev->image;
852 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300853 && 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);
Marton Nemeth1408b842009-11-02 08:13:21 -0300856
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 */
Jean-François Moineb192ca92010-06-27 03:08:19 -0300871 pac_start_frame(gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300872 gspca_dev->width, gspca_dev->height);
873 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300874 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300875}
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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300884 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300885}
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;
Jean-François Moine780e3122010-10-19 04:29:10 -0300900 if (gspca_dev->streaming)
Marton Nemeth1408b842009-11-02 08:13:21 -0300901 setbrightcont(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300902 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300903}
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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300920 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300921}
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
Marton Nemeth23fbee62009-11-08 04:35:12 -0300931static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
932{
933 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300934
935 sd->white_balance = val;
936 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300937 setwhitebalance(gspca_dev);
938 return gspca_dev->usb_err;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300939}
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
Márton Németh265a8092009-11-07 15:15:56 -0300949static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
950{
951 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300952
953 sd->red_balance = val;
954 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300955 setredbalance(gspca_dev);
956 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300957}
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;
Márton Németh265a8092009-11-07 15:15:56 -0300970
971 sd->blue_balance = val;
972 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300973 setbluebalance(gspca_dev);
974 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300975}
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
Marton Nemeth1408b842009-11-02 08:13:21 -0300985static 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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300992 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300993}
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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001010 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001011}
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
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001041 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001042}
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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001059 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001060}
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);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001077 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001078}
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
Márton Németh6763cc02009-11-09 07:10:46 -03001088#ifdef CONFIG_VIDEO_ADV_DEBUG
1089static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1090 struct v4l2_dbg_register *reg)
1091{
Márton Németh6763cc02009-11-09 07:10:46 -03001092 __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 */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001111 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1112 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -03001113
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001114 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -03001115 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001116 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -03001117}
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
Jean-François Moine28566432010-10-01 07:33:26 -03001134#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -03001135static 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
Marton Nemeth1408b842009-11-02 08:13:21 -03001165/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -03001166static const struct sd_desc sd_desc = {
Marton Nemeth1408b842009-11-02 08:13:21 -03001167 .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,
Márton Németh6763cc02009-11-09 07:10:46 -03001177#ifdef CONFIG_VIDEO_ADV_DEBUG
1178 .set_register = sd_dbg_s_register,
1179 .get_chip_ident = sd_chip_ident,
1180#endif
Jean-François Moine28566432010-10-01 07:33:26 -03001181#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -03001182 .int_pkt_scan = sd_int_pkt_scan,
1183#endif
Marton Nemeth1408b842009-11-02 08:13:21 -03001184};
1185
1186/* -- module initialisation -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001187static const struct usb_device_id device_table[] __devinitconst = {
Marton Nemeth1408b842009-11-02 08:13:21 -03001188 {USB_DEVICE(0x06f8, 0x3009)},
1189 {USB_DEVICE(0x093a, 0x2620)},
1190 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -03001191 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1192 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -03001193 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001194 {USB_DEVICE(0x093a, 0x2626)},
1195 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -03001196 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -03001197 {USB_DEVICE(0x093a, 0x262a)},
1198 {USB_DEVICE(0x093a, 0x262c)},
1199 {}
1200};
1201MODULE_DEVICE_TABLE(usb, device_table);
1202
1203/* -- device connect -- */
Márton Németh37b372e2009-12-10 11:31:09 -03001204static int __devinit sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -03001205 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{
Jean-François Moine54826432010-09-13 04:53:03 -03001225 return usb_register(&sd_driver);
Marton Nemeth1408b842009-11-02 08:13:21 -03001226}
1227static void __exit sd_mod_exit(void)
1228{
1229 usb_deregister(&sd_driver);
Marton Nemeth1408b842009-11-02 08:13:21 -03001230}
1231
1232module_init(sd_mod_init);
1233module_exit(sd_mod_exit);