blob: a8f4995a8f102c64039c989e222d99fe630c7ec0 [file] [log] [blame]
Marton Nemeth1408b842009-11-02 08:13:21 -03001/*
Jean-François Moineae251e62012-02-27 05:15:12 -03002 * Pixart PAC7302 driver
Marton Nemeth1408b842009-11-02 08:13:21 -03003 *
Jean-François Moineae251e62012-02-27 05:15:12 -03004 * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
Marton Nemeth1408b842009-11-02 08:13:21 -03006 *
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
Joe Perches133a9fe2011-08-21 19:56:57 -030064#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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
Jean-François Moineae251e62012-02-27 05:15:12 -030070MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
71 "Thomas Kaiser thomas@kaiser-linux.li");
Marton Nemeth1408b842009-11-02 08:13:21 -030072MODULE_DESCRIPTION("Pixart PAC7302");
73MODULE_LICENSE("GPL");
74
75/* specific webcam descriptor for pac7302 */
76struct sd {
77 struct gspca_dev gspca_dev; /* !! must be the first item */
78
79 unsigned char brightness;
80 unsigned char contrast;
81 unsigned char colors;
Marton Nemeth23fbee62009-11-08 04:35:12 -030082 unsigned char white_balance;
Márton Németh265a8092009-11-07 15:15:56 -030083 unsigned char red_balance;
84 unsigned char blue_balance;
Marton Nemeth1408b842009-11-02 08:13:21 -030085 unsigned char gain;
Marton Nemeth1408b842009-11-02 08:13:21 -030086 unsigned char autogain;
Hans de Goede5fb2dde2010-02-17 11:59:19 -030087 unsigned short exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -030088 __u8 hflip;
89 __u8 vflip;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -030090 u8 flags;
91#define FL_HFLIP 0x01 /* mirrored by default */
92#define FL_VFLIP 0x02 /* vertical flipped by default */
Marton Nemeth1408b842009-11-02 08:13:21 -030093
94 u8 sof_read;
95 u8 autogain_ignore_frames;
96
97 atomic_t avg_lum;
98};
99
100/* V4L2 controls supported by the driver */
101static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
102static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
103static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
104static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
105static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
106static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300107static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
108static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
Márton Németh265a8092009-11-07 15:15:56 -0300109static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
110static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
111static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
112static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
Marton Nemeth1408b842009-11-02 08:13:21 -0300113static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
114static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
115static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
116static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
117static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
118static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
119static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
120static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
121static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
122static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
123
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300124static const struct ctrl sd_ctrls[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300125 {
126 {
127 .id = V4L2_CID_BRIGHTNESS,
128 .type = V4L2_CTRL_TYPE_INTEGER,
129 .name = "Brightness",
130 .minimum = 0,
131#define BRIGHTNESS_MAX 0x20
132 .maximum = BRIGHTNESS_MAX,
133 .step = 1,
134#define BRIGHTNESS_DEF 0x10
135 .default_value = BRIGHTNESS_DEF,
136 },
137 .set = sd_setbrightness,
138 .get = sd_getbrightness,
139 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300140 {
141 {
142 .id = V4L2_CID_CONTRAST,
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Contrast",
145 .minimum = 0,
146#define CONTRAST_MAX 255
147 .maximum = CONTRAST_MAX,
148 .step = 1,
149#define CONTRAST_DEF 127
150 .default_value = CONTRAST_DEF,
151 },
152 .set = sd_setcontrast,
153 .get = sd_getcontrast,
154 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300155 {
156 {
157 .id = V4L2_CID_SATURATION,
158 .type = V4L2_CTRL_TYPE_INTEGER,
159 .name = "Saturation",
160 .minimum = 0,
161#define COLOR_MAX 255
162 .maximum = COLOR_MAX,
163 .step = 1,
164#define COLOR_DEF 127
165 .default_value = COLOR_DEF,
166 },
167 .set = sd_setcolors,
168 .get = sd_getcolors,
169 },
Márton Németh265a8092009-11-07 15:15:56 -0300170 {
171 {
Marton Nemeth23fbee62009-11-08 04:35:12 -0300172 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
173 .type = V4L2_CTRL_TYPE_INTEGER,
174 .name = "White Balance",
175 .minimum = 0,
176 .maximum = 255,
177 .step = 1,
178#define WHITEBALANCE_DEF 4
179 .default_value = WHITEBALANCE_DEF,
180 },
181 .set = sd_setwhitebalance,
182 .get = sd_getwhitebalance,
183 },
184 {
185 {
Márton Németh265a8092009-11-07 15:15:56 -0300186 .id = V4L2_CID_RED_BALANCE,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 .name = "Red",
189 .minimum = 0,
190 .maximum = 3,
191 .step = 1,
192#define REDBALANCE_DEF 1
193 .default_value = REDBALANCE_DEF,
194 },
195 .set = sd_setredbalance,
196 .get = sd_getredbalance,
197 },
198 {
199 {
200 .id = V4L2_CID_BLUE_BALANCE,
201 .type = V4L2_CTRL_TYPE_INTEGER,
202 .name = "Blue",
203 .minimum = 0,
204 .maximum = 3,
205 .step = 1,
206#define BLUEBALANCE_DEF 1
207 .default_value = BLUEBALANCE_DEF,
208 },
209 .set = sd_setbluebalance,
210 .get = sd_getbluebalance,
211 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300212 {
213 {
214 .id = V4L2_CID_GAIN,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .name = "Gain",
217 .minimum = 0,
218#define GAIN_MAX 255
219 .maximum = GAIN_MAX,
220 .step = 1,
221#define GAIN_DEF 127
222#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
223 .default_value = GAIN_DEF,
224 },
225 .set = sd_setgain,
226 .get = sd_getgain,
227 },
228 {
229 {
230 .id = V4L2_CID_EXPOSURE,
231 .type = V4L2_CTRL_TYPE_INTEGER,
232 .name = "Exposure",
233 .minimum = 0,
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300234 .maximum = 1023,
Marton Nemeth1408b842009-11-02 08:13:21 -0300235 .step = 1,
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300236#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
237#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
Marton Nemeth1408b842009-11-02 08:13:21 -0300238 .default_value = EXPOSURE_DEF,
239 },
240 .set = sd_setexposure,
241 .get = sd_getexposure,
242 },
243 {
244 {
245 .id = V4L2_CID_AUTOGAIN,
246 .type = V4L2_CTRL_TYPE_BOOLEAN,
247 .name = "Auto Gain",
248 .minimum = 0,
249 .maximum = 1,
250 .step = 1,
251#define AUTOGAIN_DEF 1
252 .default_value = AUTOGAIN_DEF,
253 },
254 .set = sd_setautogain,
255 .get = sd_getautogain,
256 },
257 {
258 {
259 .id = V4L2_CID_HFLIP,
260 .type = V4L2_CTRL_TYPE_BOOLEAN,
261 .name = "Mirror",
262 .minimum = 0,
263 .maximum = 1,
264 .step = 1,
265#define HFLIP_DEF 0
266 .default_value = HFLIP_DEF,
267 },
268 .set = sd_sethflip,
269 .get = sd_gethflip,
270 },
271 {
272 {
273 .id = V4L2_CID_VFLIP,
274 .type = V4L2_CTRL_TYPE_BOOLEAN,
275 .name = "Vflip",
276 .minimum = 0,
277 .maximum = 1,
278 .step = 1,
279#define VFLIP_DEF 0
280 .default_value = VFLIP_DEF,
281 },
282 .set = sd_setvflip,
283 .get = sd_getvflip,
284 },
285};
286
287static const struct v4l2_pix_format vga_mode[] = {
288 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
289 .bytesperline = 640,
290 .sizeimage = 640 * 480 * 3 / 8 + 590,
291 .colorspace = V4L2_COLORSPACE_JPEG,
Jean-François Moineae251e62012-02-27 05:15:12 -0300292 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300293};
294
295#define LOAD_PAGE3 255
Marton Nemeth1408b842009-11-02 08:13:21 -0300296#define END_OF_SEQUENCE 0
297
298/* pac 7302 */
Jean-François Moineae251e62012-02-27 05:15:12 -0300299static const u8 init_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300300/* index,value */
301 0xff, 0x01, /* page 1 */
302 0x78, 0x00, /* deactivate */
303 0xff, 0x01,
304 0x78, 0x40, /* led off */
305};
Jean-François Moineae251e62012-02-27 05:15:12 -0300306static const u8 start_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300307/* index, len, [value]* */
308 0xff, 1, 0x00, /* page 0 */
309 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
310 0x00, 0x00, 0x00, 0x00,
311 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
312 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
313 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
314 0x26, 2, 0xaa, 0xaa,
315 0x2e, 1, 0x31,
316 0x38, 1, 0x01,
317 0x3a, 3, 0x14, 0xff, 0x5a,
318 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
319 0x00, 0x54, 0x11,
320 0x55, 1, 0x00,
Jean-François Moineae251e62012-02-27 05:15:12 -0300321 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
Marton Nemeth1408b842009-11-02 08:13:21 -0300322 0x6b, 1, 0x00,
323 0x6e, 3, 0x08, 0x06, 0x00,
324 0x72, 3, 0x00, 0xff, 0x00,
325 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
326 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
327 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
328 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
329 0xd2, 0xeb,
330 0xaf, 1, 0x02,
331 0xb5, 2, 0x08, 0x08,
332 0xb8, 2, 0x08, 0x88,
333 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
334 0xcc, 1, 0x00,
335 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
336 0xc1, 0xd7, 0xec,
337 0xdc, 1, 0x01,
338 0xff, 1, 0x01, /* page 1 */
339 0x12, 3, 0x02, 0x00, 0x01,
340 0x3e, 2, 0x00, 0x00,
341 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
342 0x7c, 1, 0x00,
343 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
344 0x02, 0x00,
345 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
346 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
347 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
348 0xd8, 1, 0x01,
349 0xdb, 2, 0x00, 0x01,
350 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
351 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
352 0xeb, 1, 0x00,
353 0xff, 1, 0x02, /* page 2 */
354 0x22, 1, 0x00,
355 0xff, 1, 0x03, /* page 3 */
356 0, LOAD_PAGE3, /* load the page 3 */
357 0x11, 1, 0x01,
358 0xff, 1, 0x02, /* page 2 */
359 0x13, 1, 0x00,
360 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
361 0x27, 2, 0x14, 0x0c,
362 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
363 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
364 0x6e, 1, 0x08,
365 0xff, 1, 0x01, /* page 1 */
366 0x78, 1, 0x00,
367 0, END_OF_SEQUENCE /* end of sequence */
368};
369
370#define SKIP 0xaa
371/* page 3 - the value SKIP says skip the index - see reg_w_page() */
Jean-François Moineae251e62012-02-27 05:15:12 -0300372static const u8 page3_7302[] = {
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300373 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
Marton Nemeth1408b842009-11-02 08:13:21 -0300374 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
375 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
377 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
378 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
379 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
380 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
Jean-Francois Moinecdf955c2010-01-11 15:06:12 -0300382 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
Marton Nemeth1408b842009-11-02 08:13:21 -0300383 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
387 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
388 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
389 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
392 0x00
393};
394
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300395static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300396 u8 index,
Jean-François Moine0aeb5ec2010-12-28 06:59:04 -0300397 const u8 *buffer, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300398{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300399 int ret;
400
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300401 if (gspca_dev->usb_err < 0)
402 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300403 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300404 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300405 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-François Moinea1317132010-06-24 04:50:26 -0300406 0, /* request */
Marton Nemeth1408b842009-11-02 08:13:21 -0300407 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
408 0, /* value */
409 index, gspca_dev->usb_buf, len,
410 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300411 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300412 pr_err("reg_w_buf failed i: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300413 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,
Jean-François Moineae251e62012-02-27 05:15:12 -0300420 u8 index,
421 u8 value)
Marton Nemeth1408b842009-11-02 08:13:21 -0300422{
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) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300435 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300436 index, value, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300437 gspca_dev->usb_err = ret;
438 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300439}
440
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300441static void reg_w_seq(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300442 const u8 *seq, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300443{
444 while (--len >= 0) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300445 reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300446 seq += 2;
447 }
448}
449
450/* load the beginning of a page */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300451static void reg_w_page(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300452 const u8 *page, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300453{
454 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300455 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300456
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300457 if (gspca_dev->usb_err < 0)
458 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300459 for (index = 0; index < len; index++) {
460 if (page[index] == SKIP) /* skip this index */
461 continue;
462 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300463 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300464 usb_sndctrlpipe(gspca_dev->dev, 0),
465 0, /* request */
466 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
467 0, index, gspca_dev->usb_buf, 1,
468 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300469 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300470 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300471 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,
Jean-François Moineae251e62012-02-27 05:15:12 -0300480 const u8 *seq,
481 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:
Jean-François Moineae251e62012-02-27 05:15:12 -0300495#ifdef GSPCA_DEBUG
Marton Nemeth1408b842009-11-02 08:13:21 -0300496 if (len > USB_BUF_SZ) {
497 PDEBUG(D_ERR|D_STREAM,
498 "Incorrect variable sequence");
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300499 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300500 }
Jean-François Moineae251e62012-02-27 05:15:12 -0300501#endif
Marton Nemeth1408b842009-11-02 08:13:21 -0300502 while (len > 0) {
503 if (len < 8) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300504 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300505 index, seq, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300506 seq += len;
507 break;
508 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300509 reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300510 seq += 8;
511 index += 8;
512 len -= 8;
513 }
514 }
515 }
516 /* not reached */
517}
518
519/* this function is called at probe time for pac7302 */
520static int sd_config(struct gspca_dev *gspca_dev,
521 const struct usb_device_id *id)
522{
523 struct sd *sd = (struct sd *) gspca_dev;
524 struct cam *cam;
525
526 cam = &gspca_dev->cam;
527
Marton Nemeth1408b842009-11-02 08:13:21 -0300528 cam->cam_mode = vga_mode; /* only 640x480 */
529 cam->nmodes = ARRAY_SIZE(vga_mode);
530
531 sd->brightness = BRIGHTNESS_DEF;
532 sd->contrast = CONTRAST_DEF;
533 sd->colors = COLOR_DEF;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300534 sd->white_balance = WHITEBALANCE_DEF;
Márton Németh265a8092009-11-07 15:15:56 -0300535 sd->red_balance = REDBALANCE_DEF;
536 sd->blue_balance = BLUEBALANCE_DEF;
Marton Nemeth1408b842009-11-02 08:13:21 -0300537 sd->gain = GAIN_DEF;
538 sd->exposure = EXPOSURE_DEF;
539 sd->autogain = AUTOGAIN_DEF;
540 sd->hflip = HFLIP_DEF;
541 sd->vflip = VFLIP_DEF;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300542 sd->flags = id->driver_info;
Marton Nemeth1408b842009-11-02 08:13:21 -0300543 return 0;
544}
545
546/* This function is used by pac7302 only */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300547static void setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300548{
549 struct sd *sd = (struct sd *) gspca_dev;
550 int i, v;
Jean-François Moineae251e62012-02-27 05:15:12 -0300551 static const u8 max[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300552 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
553 0xd4, 0xec};
Jean-François Moineae251e62012-02-27 05:15:12 -0300554 static const u8 delta[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300555 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
556 0x11, 0x0b};
557
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300558 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300559 for (i = 0; i < 10; i++) {
560 v = max[i];
561 v += (sd->brightness - BRIGHTNESS_MAX)
562 * 150 / BRIGHTNESS_MAX; /* 200 ? */
563 v -= delta[i] * sd->contrast / CONTRAST_MAX;
564 if (v < 0)
565 v = 0;
566 else if (v > 0xff)
567 v = 0xff;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300568 reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300569 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300570 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300571}
572
573/* This function is used by pac7302 only */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300574static void setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300575{
576 struct sd *sd = (struct sd *) gspca_dev;
577 int i, v;
578 static const int a[9] =
579 {217, -212, 0, -101, 170, -67, -38, -315, 355};
580 static const int b[9] =
581 {19, 106, 0, 19, 106, 1, 19, 106, 1};
582
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300583 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
584 reg_w(gspca_dev, 0x11, 0x01);
585 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300586 for (i = 0; i < 9; i++) {
587 v = a[i] * sd->colors / COLOR_MAX + b[i];
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300588 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
589 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300590 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300591 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300592}
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}
603
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300604static void setredbalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300605{
606 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300607
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300608 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
609 reg_w(gspca_dev, 0xc5, sd->red_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300610
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300611 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300612}
613
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300614static void setbluebalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300615{
616 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300617
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300618 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
619 reg_w(gspca_dev, 0xc7, sd->blue_balance);
Márton Németh265a8092009-11-07 15:15:56 -0300620
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300621 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300622}
623
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300624static void setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300625{
626 struct sd *sd = (struct sd *) gspca_dev;
627
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300628 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
629 reg_w(gspca_dev, 0x10, sd->gain >> 3);
Marton Nemeth1408b842009-11-02 08:13:21 -0300630
631 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300632 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300633}
634
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300635static void setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300636{
637 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineae251e62012-02-27 05:15:12 -0300638 u8 clockdiv;
639 u16 exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -0300640
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300641 /* register 2 of frame 3 contains the clock divider configuring the
642 no fps according to the formula: 90 / reg. sd->exposure is the
643 desired exposure time in 0.5 ms. */
644 clockdiv = (90 * sd->exposure + 1999) / 2000;
Marton Nemeth1408b842009-11-02 08:13:21 -0300645
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300646 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
647 on the scene being recorded, the camera switches to another
648 quantization table for certain JPEG blocks, and we don't know how
649 to decompress these blocks. So we cap the framerate at 15 fps */
650 if (clockdiv < 6)
651 clockdiv = 6;
652 else if (clockdiv > 63)
653 clockdiv = 63;
654
655 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
656 Always round up, otherwise we cannot get the desired frametime
657 using the partial frame time exposure control */
658 if (clockdiv < 6 || clockdiv > 12)
659 clockdiv = ((clockdiv + 2) / 3) * 3;
660
661 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
662 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
663 exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv);
664 /* 0 = use full frametime, 448 = no exposure, reverse it */
665 exposure = 448 - exposure;
666
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300667 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300668 reg_w(gspca_dev, 0x02, clockdiv);
669 reg_w(gspca_dev, 0x0e, exposure & 0xff);
670 reg_w(gspca_dev, 0x0f, exposure >> 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300671
672 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300673 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300674}
675
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300676static void sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300677{
678 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300679 u8 data, hflip, vflip;
680
681 hflip = sd->hflip;
682 if (sd->flags & FL_HFLIP)
683 hflip = !hflip;
684 vflip = sd->vflip;
685 if (sd->flags & FL_VFLIP)
686 vflip = !vflip;
Marton Nemeth1408b842009-11-02 08:13:21 -0300687
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300688 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300689 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300690 reg_w(gspca_dev, 0x21, data);
691
Marton Nemeth1408b842009-11-02 08:13:21 -0300692 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300693 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300694}
695
696/* this function is called at probe and resume time for pac7302 */
697static int sd_init(struct gspca_dev *gspca_dev)
698{
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300699 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
700 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300701}
702
703static int sd_start(struct gspca_dev *gspca_dev)
704{
705 struct sd *sd = (struct sd *) gspca_dev;
706
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300707 reg_w_var(gspca_dev, start_7302,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300708 page3_7302, sizeof(page3_7302));
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300709 setbrightcont(gspca_dev);
710 setcolors(gspca_dev);
711 setwhitebalance(gspca_dev);
712 setredbalance(gspca_dev);
713 setbluebalance(gspca_dev);
714 setgain(gspca_dev);
715 setexposure(gspca_dev);
716 sethvflip(gspca_dev);
Marton Nemeth1408b842009-11-02 08:13:21 -0300717
718 /* only resolution 640x480 is supported for pac7302 */
719
720 sd->sof_read = 0;
721 sd->autogain_ignore_frames = 0;
722 atomic_set(&sd->avg_lum, -1);
723
724 /* start stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300725 reg_w(gspca_dev, 0xff, 0x01);
726 reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300727
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300728 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300729}
730
731static void sd_stopN(struct gspca_dev *gspca_dev)
732{
Márton Némethb1784b32009-11-07 05:52:02 -0300733
Márton Németh67c98f72009-11-07 05:45:33 -0300734 /* stop stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300735 reg_w(gspca_dev, 0xff, 0x01);
736 reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300737}
738
739/* called on streamoff with alt 0 and on disconnect for pac7302 */
740static void sd_stop0(struct gspca_dev *gspca_dev)
741{
742 if (!gspca_dev->present)
743 return;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300744 reg_w(gspca_dev, 0xff, 0x01);
745 reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300746}
747
748/* Include pac common sof detection functions */
749#include "pac_common.h"
750
751static void do_autogain(struct gspca_dev *gspca_dev)
752{
753 struct sd *sd = (struct sd *) gspca_dev;
754 int avg_lum = atomic_read(&sd->avg_lum);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300755 int desired_lum;
756 const int deadzone = 30;
Marton Nemeth1408b842009-11-02 08:13:21 -0300757
758 if (avg_lum == -1)
759 return;
760
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300761 desired_lum = 270 + sd->brightness;
Marton Nemeth1408b842009-11-02 08:13:21 -0300762
763 if (sd->autogain_ignore_frames > 0)
764 sd->autogain_ignore_frames--;
765 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
766 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
767 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
768}
769
Jean-François Moine7532e812012-02-27 05:21:57 -0300770/* JPEG header */
771static const u8 jpeg_header[] = {
772 0xff, 0xd8, /* SOI: Start of Image */
Marton Nemeth1408b842009-11-02 08:13:21 -0300773
Jean-François Moine7532e812012-02-27 05:21:57 -0300774 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
775 0x00, 0x11, /* length = 17 bytes (including this length field) */
776 0x08, /* Precision: 8 */
777 0x02, 0x80, /* height = 640 (image rotated) */
778 0x01, 0xe0, /* width = 480 */
779 0x03, /* Number of image components: 3 */
780 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
781 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
782 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
783
784 0xff, 0xda, /* SOS: Start Of Scan */
785 0x00, 0x0c, /* length = 12 bytes (including this length field) */
786 0x03, /* number of components: 3 */
787 0x01, 0x00, /* selector 1, table 0x00 */
788 0x02, 0x11, /* selector 2, table 0x11 */
789 0x03, 0x11, /* selector 3, table 0x11 */
790 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
791 0x00 /* Successive approximation: 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300792};
793
Marton Nemeth1408b842009-11-02 08:13:21 -0300794/* this function is run at interrupt level */
795static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300796 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300797 int len) /* iso packet length */
798{
799 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300800 u8 *image;
Jean-François Moineae251e62012-02-27 05:15:12 -0300801 u8 *sof;
Marton Nemeth1408b842009-11-02 08:13:21 -0300802
803 sof = pac_find_sof(&sd->sof_read, data, len);
804 if (sof) {
805 int n, lum_offset, footer_length;
806
807 /* 6 bytes after the FF D9 EOF marker a number of lumination
808 bytes are send corresponding to different parts of the
809 image, the 14th and 15th byte after the EOF seem to
810 correspond to the center of the image */
811 lum_offset = 61 + sizeof pac_sof_marker;
812 footer_length = 74;
813
814 /* Finish decoding current frame */
815 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
816 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300817 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300818 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300819 } else {
820 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300821 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300822
823 image = gspca_dev->image;
824 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300825 && image[gspca_dev->image_len - 2] == 0xff
826 && image[gspca_dev->image_len - 1] == 0xd9)
827 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Marton Nemeth1408b842009-11-02 08:13:21 -0300828
829 n = sof - data;
830 len -= n;
831 data = sof;
832
833 /* Get average lumination */
834 if (gspca_dev->last_packet_type == LAST_PACKET &&
835 n >= lum_offset)
836 atomic_set(&sd->avg_lum, data[-lum_offset] +
837 data[-lum_offset + 1]);
838 else
839 atomic_set(&sd->avg_lum, -1);
840
841 /* Start the new frame with the jpeg header */
842 /* The PAC7302 has the image rotated 90 degrees */
Jean-François Moine7532e812012-02-27 05:21:57 -0300843 gspca_frame_add(gspca_dev, FIRST_PACKET,
844 jpeg_header, sizeof jpeg_header);
Marton Nemeth1408b842009-11-02 08:13:21 -0300845 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300846 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300847}
848
849static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
850{
851 struct sd *sd = (struct sd *) gspca_dev;
852
853 sd->brightness = val;
854 if (gspca_dev->streaming)
855 setbrightcont(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300856 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300857}
858
859static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
860{
861 struct sd *sd = (struct sd *) gspca_dev;
862
863 *val = sd->brightness;
864 return 0;
865}
866
867static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
868{
869 struct sd *sd = (struct sd *) gspca_dev;
870
871 sd->contrast = val;
Jean-François Moine780e3122010-10-19 04:29:10 -0300872 if (gspca_dev->streaming)
Marton Nemeth1408b842009-11-02 08:13:21 -0300873 setbrightcont(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300874 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300875}
876
877static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
878{
879 struct sd *sd = (struct sd *) gspca_dev;
880
881 *val = sd->contrast;
882 return 0;
883}
884
885static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
886{
887 struct sd *sd = (struct sd *) gspca_dev;
888
889 sd->colors = val;
890 if (gspca_dev->streaming)
891 setcolors(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300892 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300893}
894
895static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898
899 *val = sd->colors;
900 return 0;
901}
902
Marton Nemeth23fbee62009-11-08 04:35:12 -0300903static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300906
907 sd->white_balance = val;
908 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300909 setwhitebalance(gspca_dev);
910 return gspca_dev->usb_err;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300911}
912
913static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
914{
915 struct sd *sd = (struct sd *) gspca_dev;
916
917 *val = sd->white_balance;
918 return 0;
919}
920
Márton Németh265a8092009-11-07 15:15:56 -0300921static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
922{
923 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300924
925 sd->red_balance = val;
926 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300927 setredbalance(gspca_dev);
928 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300929}
930
931static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
932{
933 struct sd *sd = (struct sd *) gspca_dev;
934
935 *val = sd->red_balance;
936 return 0;
937}
938
939static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
940{
941 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300942
943 sd->blue_balance = val;
944 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300945 setbluebalance(gspca_dev);
946 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300947}
948
949static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
950{
951 struct sd *sd = (struct sd *) gspca_dev;
952
953 *val = sd->blue_balance;
954 return 0;
955}
956
Marton Nemeth1408b842009-11-02 08:13:21 -0300957static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
958{
959 struct sd *sd = (struct sd *) gspca_dev;
960
961 sd->gain = val;
962 if (gspca_dev->streaming)
963 setgain(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300964 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300965}
966
967static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
968{
969 struct sd *sd = (struct sd *) gspca_dev;
970
971 *val = sd->gain;
972 return 0;
973}
974
975static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
976{
977 struct sd *sd = (struct sd *) gspca_dev;
978
979 sd->exposure = val;
980 if (gspca_dev->streaming)
981 setexposure(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300982 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300983}
984
985static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
986{
987 struct sd *sd = (struct sd *) gspca_dev;
988
989 *val = sd->exposure;
990 return 0;
991}
992
993static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
994{
995 struct sd *sd = (struct sd *) gspca_dev;
996
997 sd->autogain = val;
998 /* when switching to autogain set defaults to make sure
999 we are on a valid point of the autogain gain /
1000 exposure knee graph, and give this change time to
1001 take effect before doing autogain. */
1002 if (sd->autogain) {
1003 sd->exposure = EXPOSURE_DEF;
1004 sd->gain = GAIN_DEF;
1005 if (gspca_dev->streaming) {
1006 sd->autogain_ignore_frames =
1007 PAC_AUTOGAIN_IGNORE_FRAMES;
1008 setexposure(gspca_dev);
1009 setgain(gspca_dev);
1010 }
1011 }
1012
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001013 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001014}
1015
1016static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1017{
1018 struct sd *sd = (struct sd *) gspca_dev;
1019
1020 *val = sd->autogain;
1021 return 0;
1022}
1023
1024static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1025{
1026 struct sd *sd = (struct sd *) gspca_dev;
1027
1028 sd->hflip = val;
1029 if (gspca_dev->streaming)
1030 sethvflip(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001031 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001032}
1033
1034static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1035{
1036 struct sd *sd = (struct sd *) gspca_dev;
1037
1038 *val = sd->hflip;
1039 return 0;
1040}
1041
1042static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1043{
1044 struct sd *sd = (struct sd *) gspca_dev;
1045
1046 sd->vflip = val;
1047 if (gspca_dev->streaming)
1048 sethvflip(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001049 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001050}
1051
1052static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1053{
1054 struct sd *sd = (struct sd *) gspca_dev;
1055
1056 *val = sd->vflip;
1057 return 0;
1058}
1059
Márton Németh6763cc02009-11-09 07:10:46 -03001060#ifdef CONFIG_VIDEO_ADV_DEBUG
1061static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1062 struct v4l2_dbg_register *reg)
1063{
Jean-François Moineae251e62012-02-27 05:15:12 -03001064 u8 index;
1065 u8 value;
Márton Németh6763cc02009-11-09 07:10:46 -03001066
1067 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
1068 long on the USB bus)
1069 */
1070 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
1071 reg->match.addr == 0 &&
1072 (reg->reg < 0x000000ff) &&
1073 (reg->val <= 0x000000ff)
1074 ) {
1075 /* Currently writing to page 0 is only supported. */
1076 /* reg_w() only supports 8bit index */
Jean-François Moineae251e62012-02-27 05:15:12 -03001077 index = reg->reg;
1078 value = reg->val;
Márton Németh6763cc02009-11-09 07:10:46 -03001079
1080 /* Note that there shall be no access to other page
1081 by any other function between the page swith and
1082 the actual register write */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001083 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1084 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -03001085
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001086 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -03001087 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001088 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -03001089}
1090
1091static int sd_chip_ident(struct gspca_dev *gspca_dev,
1092 struct v4l2_dbg_chip_ident *chip)
1093{
1094 int ret = -EINVAL;
1095
1096 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1097 chip->match.addr == 0) {
1098 chip->revision = 0;
1099 chip->ident = V4L2_IDENT_UNKNOWN;
1100 ret = 0;
1101 }
1102 return ret;
1103}
1104#endif
1105
Jean-François Moine28566432010-10-01 07:33:26 -03001106#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -03001107static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1108 u8 *data, /* interrupt packet data */
1109 int len) /* interrput packet length */
1110{
1111 int ret = -EINVAL;
1112 u8 data0, data1;
1113
1114 if (len == 2) {
1115 data0 = data[0];
1116 data1 = data[1];
1117 if ((data0 == 0x00 && data1 == 0x11) ||
1118 (data0 == 0x22 && data1 == 0x33) ||
1119 (data0 == 0x44 && data1 == 0x55) ||
1120 (data0 == 0x66 && data1 == 0x77) ||
1121 (data0 == 0x88 && data1 == 0x99) ||
1122 (data0 == 0xaa && data1 == 0xbb) ||
1123 (data0 == 0xcc && data1 == 0xdd) ||
1124 (data0 == 0xee && data1 == 0xff)) {
1125 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1126 input_sync(gspca_dev->input_dev);
1127 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1128 input_sync(gspca_dev->input_dev);
1129 ret = 0;
1130 }
1131 }
1132
1133 return ret;
1134}
1135#endif
1136
Marton Nemeth1408b842009-11-02 08:13:21 -03001137/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -03001138static const struct sd_desc sd_desc = {
Jean-François Moineae251e62012-02-27 05:15:12 -03001139 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -03001140 .ctrls = sd_ctrls,
1141 .nctrls = ARRAY_SIZE(sd_ctrls),
1142 .config = sd_config,
1143 .init = sd_init,
1144 .start = sd_start,
1145 .stopN = sd_stopN,
1146 .stop0 = sd_stop0,
1147 .pkt_scan = sd_pkt_scan,
1148 .dq_callback = do_autogain,
Márton Németh6763cc02009-11-09 07:10:46 -03001149#ifdef CONFIG_VIDEO_ADV_DEBUG
1150 .set_register = sd_dbg_s_register,
1151 .get_chip_ident = sd_chip_ident,
1152#endif
Jean-François Moine28566432010-10-01 07:33:26 -03001153#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -03001154 .int_pkt_scan = sd_int_pkt_scan,
1155#endif
Marton Nemeth1408b842009-11-02 08:13:21 -03001156};
1157
1158/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001159static const struct usb_device_id device_table[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -03001160 {USB_DEVICE(0x06f8, 0x3009)},
Jean-François Moinedd32f982012-02-27 04:58:59 -03001161 {USB_DEVICE(0x06f8, 0x301b)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001162 {USB_DEVICE(0x093a, 0x2620)},
1163 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -03001164 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1165 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -03001166 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001167 {USB_DEVICE(0x093a, 0x2626)},
1168 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -03001169 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -03001170 {USB_DEVICE(0x093a, 0x262a)},
1171 {USB_DEVICE(0x093a, 0x262c)},
Hans de Goede4d6454d2011-12-30 19:15:53 -03001172 {USB_DEVICE(0x145f, 0x013c)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001173 {}
1174};
1175MODULE_DEVICE_TABLE(usb, device_table);
1176
1177/* -- device connect -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001178static int sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -03001179 const struct usb_device_id *id)
1180{
1181 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1182 THIS_MODULE);
1183}
1184
1185static struct usb_driver sd_driver = {
Jean-François Moineae251e62012-02-27 05:15:12 -03001186 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -03001187 .id_table = device_table,
1188 .probe = sd_probe,
1189 .disconnect = gspca_disconnect,
1190#ifdef CONFIG_PM
1191 .suspend = gspca_suspend,
1192 .resume = gspca_resume,
1193#endif
1194};
1195
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001196module_usb_driver(sd_driver);