blob: 7b1a32d1e15b02f01ec73aa4d720d0786e7201e6 [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 Moinefe2b6032009-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 Moinefe2b6032009-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 Moinefe2b6032009-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 Moinefe2b6032009-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
770/* JPEG header, part 1 */
771static const unsigned char pac_jpeg_header1[] = {
772 0xff, 0xd8, /* SOI: Start of Image */
773
774 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
775 0x00, 0x11, /* length = 17 bytes (including this length field) */
776 0x08 /* Precision: 8 */
777 /* 2 bytes is placed here: number of image lines */
778 /* 2 bytes is placed here: samples per line */
779};
780
781/* JPEG header, continued */
782static const unsigned char pac_jpeg_header2[] = {
783 0x03, /* Number of image components: 3 */
784 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
785 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
786 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
787
788 0xff, 0xda, /* SOS: Start Of Scan */
789 0x00, 0x0c, /* length = 12 bytes (including this length field) */
790 0x03, /* number of components: 3 */
791 0x01, 0x00, /* selector 1, table 0x00 */
792 0x02, 0x11, /* selector 2, table 0x11 */
793 0x03, 0x11, /* selector 3, table 0x11 */
794 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
795 0x00 /* Successive approximation: 0 */
796};
797
798static void pac_start_frame(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300799 __u16 lines, __u16 samples_per_line)
800{
801 unsigned char tmpbuf[4];
802
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300803 gspca_frame_add(gspca_dev, FIRST_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300804 pac_jpeg_header1, sizeof(pac_jpeg_header1));
805
806 tmpbuf[0] = lines >> 8;
807 tmpbuf[1] = lines & 0xff;
808 tmpbuf[2] = samples_per_line >> 8;
809 tmpbuf[3] = samples_per_line & 0xff;
810
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300811 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300812 tmpbuf, sizeof(tmpbuf));
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300813 gspca_frame_add(gspca_dev, INTER_PACKET,
Marton Nemeth1408b842009-11-02 08:13:21 -0300814 pac_jpeg_header2, sizeof(pac_jpeg_header2));
815}
816
817/* this function is run at interrupt level */
818static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300819 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300820 int len) /* iso packet length */
821{
822 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300823 u8 *image;
Jean-François Moineae251e62012-02-27 05:15:12 -0300824 u8 *sof;
Marton Nemeth1408b842009-11-02 08:13:21 -0300825
826 sof = pac_find_sof(&sd->sof_read, data, len);
827 if (sof) {
828 int n, lum_offset, footer_length;
829
830 /* 6 bytes after the FF D9 EOF marker a number of lumination
831 bytes are send corresponding to different parts of the
832 image, the 14th and 15th byte after the EOF seem to
833 correspond to the center of the image */
834 lum_offset = 61 + sizeof pac_sof_marker;
835 footer_length = 74;
836
837 /* Finish decoding current frame */
838 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
839 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300840 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300841 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300842 } else {
843 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300844 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300845
846 image = gspca_dev->image;
847 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300848 && image[gspca_dev->image_len - 2] == 0xff
849 && image[gspca_dev->image_len - 1] == 0xd9)
850 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Marton Nemeth1408b842009-11-02 08:13:21 -0300851
852 n = sof - data;
853 len -= n;
854 data = sof;
855
856 /* Get average lumination */
857 if (gspca_dev->last_packet_type == LAST_PACKET &&
858 n >= lum_offset)
859 atomic_set(&sd->avg_lum, data[-lum_offset] +
860 data[-lum_offset + 1]);
861 else
862 atomic_set(&sd->avg_lum, -1);
863
864 /* Start the new frame with the jpeg header */
865 /* The PAC7302 has the image rotated 90 degrees */
Jean-François Moineb192ca92010-06-27 03:08:19 -0300866 pac_start_frame(gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300867 gspca_dev->width, gspca_dev->height);
868 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300869 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300870}
871
872static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
873{
874 struct sd *sd = (struct sd *) gspca_dev;
875
876 sd->brightness = val;
877 if (gspca_dev->streaming)
878 setbrightcont(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300879 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300880}
881
882static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
883{
884 struct sd *sd = (struct sd *) gspca_dev;
885
886 *val = sd->brightness;
887 return 0;
888}
889
890static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
891{
892 struct sd *sd = (struct sd *) gspca_dev;
893
894 sd->contrast = val;
Jean-François Moine780e3122010-10-19 04:29:10 -0300895 if (gspca_dev->streaming)
Marton Nemeth1408b842009-11-02 08:13:21 -0300896 setbrightcont(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300897 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300898}
899
900static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
901{
902 struct sd *sd = (struct sd *) gspca_dev;
903
904 *val = sd->contrast;
905 return 0;
906}
907
908static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
909{
910 struct sd *sd = (struct sd *) gspca_dev;
911
912 sd->colors = val;
913 if (gspca_dev->streaming)
914 setcolors(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300915 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300916}
917
918static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
919{
920 struct sd *sd = (struct sd *) gspca_dev;
921
922 *val = sd->colors;
923 return 0;
924}
925
Marton Nemeth23fbee62009-11-08 04:35:12 -0300926static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300929
930 sd->white_balance = val;
931 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300932 setwhitebalance(gspca_dev);
933 return gspca_dev->usb_err;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300934}
935
936static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
937{
938 struct sd *sd = (struct sd *) gspca_dev;
939
940 *val = sd->white_balance;
941 return 0;
942}
943
Márton Németh265a8092009-11-07 15:15:56 -0300944static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
945{
946 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300947
948 sd->red_balance = val;
949 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300950 setredbalance(gspca_dev);
951 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300952}
953
954static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
955{
956 struct sd *sd = (struct sd *) gspca_dev;
957
958 *val = sd->red_balance;
959 return 0;
960}
961
962static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
963{
964 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300965
966 sd->blue_balance = val;
967 if (gspca_dev->streaming)
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300968 setbluebalance(gspca_dev);
969 return gspca_dev->usb_err;
Márton Németh265a8092009-11-07 15:15:56 -0300970}
971
972static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
973{
974 struct sd *sd = (struct sd *) gspca_dev;
975
976 *val = sd->blue_balance;
977 return 0;
978}
979
Marton Nemeth1408b842009-11-02 08:13:21 -0300980static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
981{
982 struct sd *sd = (struct sd *) gspca_dev;
983
984 sd->gain = val;
985 if (gspca_dev->streaming)
986 setgain(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300987 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300988}
989
990static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
991{
992 struct sd *sd = (struct sd *) gspca_dev;
993
994 *val = sd->gain;
995 return 0;
996}
997
998static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
999{
1000 struct sd *sd = (struct sd *) gspca_dev;
1001
1002 sd->exposure = val;
1003 if (gspca_dev->streaming)
1004 setexposure(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001005 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001006}
1007
1008static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1009{
1010 struct sd *sd = (struct sd *) gspca_dev;
1011
1012 *val = sd->exposure;
1013 return 0;
1014}
1015
1016static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1017{
1018 struct sd *sd = (struct sd *) gspca_dev;
1019
1020 sd->autogain = val;
1021 /* when switching to autogain set defaults to make sure
1022 we are on a valid point of the autogain gain /
1023 exposure knee graph, and give this change time to
1024 take effect before doing autogain. */
1025 if (sd->autogain) {
1026 sd->exposure = EXPOSURE_DEF;
1027 sd->gain = GAIN_DEF;
1028 if (gspca_dev->streaming) {
1029 sd->autogain_ignore_frames =
1030 PAC_AUTOGAIN_IGNORE_FRAMES;
1031 setexposure(gspca_dev);
1032 setgain(gspca_dev);
1033 }
1034 }
1035
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001036 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001037}
1038
1039static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1040{
1041 struct sd *sd = (struct sd *) gspca_dev;
1042
1043 *val = sd->autogain;
1044 return 0;
1045}
1046
1047static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1048{
1049 struct sd *sd = (struct sd *) gspca_dev;
1050
1051 sd->hflip = val;
1052 if (gspca_dev->streaming)
1053 sethvflip(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001054 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001055}
1056
1057static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1058{
1059 struct sd *sd = (struct sd *) gspca_dev;
1060
1061 *val = sd->hflip;
1062 return 0;
1063}
1064
1065static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1066{
1067 struct sd *sd = (struct sd *) gspca_dev;
1068
1069 sd->vflip = val;
1070 if (gspca_dev->streaming)
1071 sethvflip(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001072 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -03001073}
1074
1075static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1076{
1077 struct sd *sd = (struct sd *) gspca_dev;
1078
1079 *val = sd->vflip;
1080 return 0;
1081}
1082
Márton Németh6763cc02009-11-09 07:10:46 -03001083#ifdef CONFIG_VIDEO_ADV_DEBUG
1084static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1085 struct v4l2_dbg_register *reg)
1086{
Jean-François Moineae251e62012-02-27 05:15:12 -03001087 u8 index;
1088 u8 value;
Márton Németh6763cc02009-11-09 07:10:46 -03001089
1090 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
1091 long on the USB bus)
1092 */
1093 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
1094 reg->match.addr == 0 &&
1095 (reg->reg < 0x000000ff) &&
1096 (reg->val <= 0x000000ff)
1097 ) {
1098 /* Currently writing to page 0 is only supported. */
1099 /* reg_w() only supports 8bit index */
Jean-François Moineae251e62012-02-27 05:15:12 -03001100 index = reg->reg;
1101 value = reg->val;
Márton Németh6763cc02009-11-09 07:10:46 -03001102
1103 /* Note that there shall be no access to other page
1104 by any other function between the page swith and
1105 the actual register write */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001106 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1107 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -03001108
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001109 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -03001110 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -03001111 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -03001112}
1113
1114static int sd_chip_ident(struct gspca_dev *gspca_dev,
1115 struct v4l2_dbg_chip_ident *chip)
1116{
1117 int ret = -EINVAL;
1118
1119 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1120 chip->match.addr == 0) {
1121 chip->revision = 0;
1122 chip->ident = V4L2_IDENT_UNKNOWN;
1123 ret = 0;
1124 }
1125 return ret;
1126}
1127#endif
1128
Jean-François Moine28566432010-10-01 07:33:26 -03001129#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -03001130static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1131 u8 *data, /* interrupt packet data */
1132 int len) /* interrput packet length */
1133{
1134 int ret = -EINVAL;
1135 u8 data0, data1;
1136
1137 if (len == 2) {
1138 data0 = data[0];
1139 data1 = data[1];
1140 if ((data0 == 0x00 && data1 == 0x11) ||
1141 (data0 == 0x22 && data1 == 0x33) ||
1142 (data0 == 0x44 && data1 == 0x55) ||
1143 (data0 == 0x66 && data1 == 0x77) ||
1144 (data0 == 0x88 && data1 == 0x99) ||
1145 (data0 == 0xaa && data1 == 0xbb) ||
1146 (data0 == 0xcc && data1 == 0xdd) ||
1147 (data0 == 0xee && data1 == 0xff)) {
1148 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1149 input_sync(gspca_dev->input_dev);
1150 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1151 input_sync(gspca_dev->input_dev);
1152 ret = 0;
1153 }
1154 }
1155
1156 return ret;
1157}
1158#endif
1159
Marton Nemeth1408b842009-11-02 08:13:21 -03001160/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -03001161static const struct sd_desc sd_desc = {
Jean-François Moineae251e62012-02-27 05:15:12 -03001162 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -03001163 .ctrls = sd_ctrls,
1164 .nctrls = ARRAY_SIZE(sd_ctrls),
1165 .config = sd_config,
1166 .init = sd_init,
1167 .start = sd_start,
1168 .stopN = sd_stopN,
1169 .stop0 = sd_stop0,
1170 .pkt_scan = sd_pkt_scan,
1171 .dq_callback = do_autogain,
Márton Németh6763cc02009-11-09 07:10:46 -03001172#ifdef CONFIG_VIDEO_ADV_DEBUG
1173 .set_register = sd_dbg_s_register,
1174 .get_chip_ident = sd_chip_ident,
1175#endif
Jean-François Moine28566432010-10-01 07:33:26 -03001176#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -03001177 .int_pkt_scan = sd_int_pkt_scan,
1178#endif
Marton Nemeth1408b842009-11-02 08:13:21 -03001179};
1180
1181/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001182static const struct usb_device_id device_table[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -03001183 {USB_DEVICE(0x06f8, 0x3009)},
Jean-François Moinedd32f982012-02-27 04:58:59 -03001184 {USB_DEVICE(0x06f8, 0x301b)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001185 {USB_DEVICE(0x093a, 0x2620)},
1186 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b6032009-11-26 14:28:48 -03001187 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1188 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -03001189 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001190 {USB_DEVICE(0x093a, 0x2626)},
1191 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -03001192 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -03001193 {USB_DEVICE(0x093a, 0x262a)},
1194 {USB_DEVICE(0x093a, 0x262c)},
Hans de Goede4d6454d2011-12-30 19:15:53 -03001195 {USB_DEVICE(0x145f, 0x013c)},
Marton Nemeth1408b842009-11-02 08:13:21 -03001196 {}
1197};
1198MODULE_DEVICE_TABLE(usb, device_table);
1199
1200/* -- device connect -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -03001201static int sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -03001202 const struct usb_device_id *id)
1203{
1204 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1205 THIS_MODULE);
1206}
1207
1208static struct usb_driver sd_driver = {
Jean-François Moineae251e62012-02-27 05:15:12 -03001209 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -03001210 .id_table = device_table,
1211 .probe = sd_probe,
1212 .disconnect = gspca_disconnect,
1213#ifdef CONFIG_PM
1214 .suspend = gspca_suspend,
1215 .resume = gspca_resume,
1216#endif
1217};
1218
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -08001219module_usb_driver(sd_driver);