blob: a2a42f61d3c03561b115f7e35e466cab84f65ad4 [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
Hans de Goede895d4642012-04-28 10:31:17 -030026/*
27 * Some documentation about various registers as determined by trial and error.
28 *
29 * Register page 1:
30 *
31 * Address Description
32 * 0x78 Global control, bit 6 controls the LED (inverted)
Hans de Goede48bb7312012-04-27 13:00:57 -030033 * 0x80 Compression balance, 2 interesting settings:
34 * 0x0f Default
35 * 0x50 Values >= this switch the camera to a lower compression,
36 * using the same table for both luminance and chrominance.
37 * This gives a sharper picture. Only usable when running
38 * at < 15 fps! Note currently the driver does not use this
39 * as the quality gain is small and the generated JPG-s are
40 * only understood by v4l-utils >= 0.8.9
Hans de Goede895d4642012-04-28 10:31:17 -030041 *
42 * Register page 3:
43 *
44 * Address Description
45 * 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
46 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
47 * 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
48 * 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
49 * 63 -> ~27 fps, the 2 msb's must always be 1 !!
50 * 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
51 * 1 -> ~30 fps, 2 -> ~20 fps
52 * 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
53 * 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
Hans de Goede48bb7312012-04-27 13:00:57 -030054 * 0x10 Gain 0-31
55 * 0x12 Another gain 0-31, unlike 0x10 this one seems to start with an
56 * amplification value of 1 rather then 0 at its lowest setting
Hans de Goede895d4642012-04-28 10:31:17 -030057 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
Hans de Goede48bb7312012-04-27 13:00:57 -030058 * 0x80 Another framerate control, best left at 1, moving it from 1 to
59 * 2 causes the framerate to become 3/4th of what it was, and
60 * also seems to cause pixel averaging, resulting in an effective
61 * resolution of 320x240 and thus a much blockier image
Hans de Goede895d4642012-04-28 10:31:17 -030062 *
63 * The registers are accessed in the following functions:
64 *
65 * Page | Register | Function
66 * -----+------------+---------------------------------------------------
67 * 0 | 0x0f..0x20 | setcolors()
68 * 0 | 0xa2..0xab | setbrightcont()
69 * 0 | 0xc5 | setredbalance()
70 * 0 | 0xc6 | setwhitebalance()
71 * 0 | 0xc7 | setbluebalance()
72 * 0 | 0xdc | setbrightcont(), setcolors()
73 * 3 | 0x02 | setexposure()
74 * 3 | 0x10 | setgain()
75 * 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
76 * 3 | 0x21 | sethvflip()
77 */
Marton Nemeth1408b842009-11-02 08:13:21 -030078
Joe Perches133a9fe2011-08-21 19:56:57 -030079#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
80
Márton Némethaed6f1b2010-01-28 16:33:38 -030081#include <linux/input.h>
Márton Németh6763cc02009-11-09 07:10:46 -030082#include <media/v4l2-chip-ident.h>
Marton Nemeth1408b842009-11-02 08:13:21 -030083#include "gspca.h"
Jean-François Moineac399cd2012-02-27 05:40:47 -030084/* Include pac common sof detection functions */
85#include "pac_common.h"
Marton Nemeth1408b842009-11-02 08:13:21 -030086
Jean-François Moineae251e62012-02-27 05:15:12 -030087MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
88 "Thomas Kaiser thomas@kaiser-linux.li");
Marton Nemeth1408b842009-11-02 08:13:21 -030089MODULE_DESCRIPTION("Pixart PAC7302");
90MODULE_LICENSE("GPL");
91
Jean-François Moineaa5b7922012-02-27 05:38:09 -030092enum e_ctrl {
93 BRIGHTNESS,
94 CONTRAST,
95 COLORS,
96 WHITE_BALANCE,
97 RED_BALANCE,
98 BLUE_BALANCE,
99 GAIN,
100 AUTOGAIN,
101 EXPOSURE,
102 VFLIP,
103 HFLIP,
104 NCTRLS /* number of controls */
105};
106
Marton Nemeth1408b842009-11-02 08:13:21 -0300107struct sd {
108 struct gspca_dev gspca_dev; /* !! must be the first item */
109
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300110 struct gspca_ctrl ctrls[NCTRLS];
111
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300112 u8 flags;
113#define FL_HFLIP 0x01 /* mirrored by default */
114#define FL_VFLIP 0x02 /* vertical flipped by default */
Marton Nemeth1408b842009-11-02 08:13:21 -0300115
116 u8 sof_read;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300117 s8 autogain_ignore_frames;
Marton Nemeth1408b842009-11-02 08:13:21 -0300118
119 atomic_t avg_lum;
120};
121
122/* V4L2 controls supported by the driver */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300123static void setbrightcont(struct gspca_dev *gspca_dev);
124static void setcolors(struct gspca_dev *gspca_dev);
125static void setwhitebalance(struct gspca_dev *gspca_dev);
126static void setredbalance(struct gspca_dev *gspca_dev);
127static void setbluebalance(struct gspca_dev *gspca_dev);
128static void setgain(struct gspca_dev *gspca_dev);
129static void setexposure(struct gspca_dev *gspca_dev);
Jean-François Moineac399cd2012-02-27 05:40:47 -0300130static void setautogain(struct gspca_dev *gspca_dev);
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300131static void sethvflip(struct gspca_dev *gspca_dev);
Marton Nemeth1408b842009-11-02 08:13:21 -0300132
Marton Nemeth7e64dc42009-12-30 09:12:41 -0300133static const struct ctrl sd_ctrls[] = {
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300134[BRIGHTNESS] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300135 {
136 .id = V4L2_CID_BRIGHTNESS,
137 .type = V4L2_CTRL_TYPE_INTEGER,
138 .name = "Brightness",
139 .minimum = 0,
140#define BRIGHTNESS_MAX 0x20
141 .maximum = BRIGHTNESS_MAX,
142 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300143 .default_value = 0x10,
Marton Nemeth1408b842009-11-02 08:13:21 -0300144 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300145 .set_control = setbrightcont
Marton Nemeth1408b842009-11-02 08:13:21 -0300146 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300147[CONTRAST] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300148 {
149 .id = V4L2_CID_CONTRAST,
150 .type = V4L2_CTRL_TYPE_INTEGER,
151 .name = "Contrast",
152 .minimum = 0,
153#define CONTRAST_MAX 255
154 .maximum = CONTRAST_MAX,
155 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300156 .default_value = 127,
Marton Nemeth1408b842009-11-02 08:13:21 -0300157 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300158 .set_control = setbrightcont
Marton Nemeth1408b842009-11-02 08:13:21 -0300159 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300160[COLORS] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300161 {
162 .id = V4L2_CID_SATURATION,
163 .type = V4L2_CTRL_TYPE_INTEGER,
164 .name = "Saturation",
165 .minimum = 0,
166#define COLOR_MAX 255
167 .maximum = COLOR_MAX,
168 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300169 .default_value = 127
Marton Nemeth1408b842009-11-02 08:13:21 -0300170 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300171 .set_control = setcolors
Marton Nemeth1408b842009-11-02 08:13:21 -0300172 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300173[WHITE_BALANCE] = {
Márton Németh265a8092009-11-07 15:15:56 -0300174 {
Marton Nemeth23fbee62009-11-08 04:35:12 -0300175 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
176 .type = V4L2_CTRL_TYPE_INTEGER,
177 .name = "White Balance",
178 .minimum = 0,
179 .maximum = 255,
180 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300181 .default_value = 4,
Marton Nemeth23fbee62009-11-08 04:35:12 -0300182 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300183 .set_control = setwhitebalance
Marton Nemeth23fbee62009-11-08 04:35:12 -0300184 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300185[RED_BALANCE] = {
Marton Nemeth23fbee62009-11-08 04:35:12 -0300186 {
Márton Németh265a8092009-11-07 15:15:56 -0300187 .id = V4L2_CID_RED_BALANCE,
188 .type = V4L2_CTRL_TYPE_INTEGER,
189 .name = "Red",
190 .minimum = 0,
191 .maximum = 3,
192 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300193 .default_value = 1,
Márton Németh265a8092009-11-07 15:15:56 -0300194 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300195 .set_control = setredbalance
Márton Németh265a8092009-11-07 15:15:56 -0300196 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300197[BLUE_BALANCE] = {
Márton Németh265a8092009-11-07 15:15:56 -0300198 {
199 .id = V4L2_CID_BLUE_BALANCE,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Blue",
202 .minimum = 0,
203 .maximum = 3,
204 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300205 .default_value = 1,
Márton Németh265a8092009-11-07 15:15:56 -0300206 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300207 .set_control = setbluebalance
Márton Németh265a8092009-11-07 15:15:56 -0300208 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300209[GAIN] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300210 {
211 .id = V4L2_CID_GAIN,
212 .type = V4L2_CTRL_TYPE_INTEGER,
213 .name = "Gain",
214 .minimum = 0,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300215 .maximum = 255,
Marton Nemeth1408b842009-11-02 08:13:21 -0300216 .step = 1,
217#define GAIN_DEF 127
218#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
219 .default_value = GAIN_DEF,
220 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300221 .set_control = setgain
Marton Nemeth1408b842009-11-02 08:13:21 -0300222 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300223[EXPOSURE] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300224 {
225 .id = V4L2_CID_EXPOSURE,
226 .type = V4L2_CTRL_TYPE_INTEGER,
227 .name = "Exposure",
228 .minimum = 0,
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300229 .maximum = 1023,
Marton Nemeth1408b842009-11-02 08:13:21 -0300230 .step = 1,
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300231#define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
232#define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
Marton Nemeth1408b842009-11-02 08:13:21 -0300233 .default_value = EXPOSURE_DEF,
234 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300235 .set_control = setexposure
Marton Nemeth1408b842009-11-02 08:13:21 -0300236 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300237[AUTOGAIN] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300238 {
239 .id = V4L2_CID_AUTOGAIN,
240 .type = V4L2_CTRL_TYPE_BOOLEAN,
241 .name = "Auto Gain",
242 .minimum = 0,
243 .maximum = 1,
244 .step = 1,
245#define AUTOGAIN_DEF 1
246 .default_value = AUTOGAIN_DEF,
247 },
Jean-François Moineac399cd2012-02-27 05:40:47 -0300248 .set_control = setautogain,
Marton Nemeth1408b842009-11-02 08:13:21 -0300249 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300250[HFLIP] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300251 {
252 .id = V4L2_CID_HFLIP,
253 .type = V4L2_CTRL_TYPE_BOOLEAN,
254 .name = "Mirror",
255 .minimum = 0,
256 .maximum = 1,
257 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300258 .default_value = 0,
Marton Nemeth1408b842009-11-02 08:13:21 -0300259 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300260 .set_control = sethvflip,
Marton Nemeth1408b842009-11-02 08:13:21 -0300261 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300262[VFLIP] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300263 {
264 .id = V4L2_CID_VFLIP,
265 .type = V4L2_CTRL_TYPE_BOOLEAN,
266 .name = "Vflip",
267 .minimum = 0,
268 .maximum = 1,
269 .step = 1,
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300270 .default_value = 0,
Marton Nemeth1408b842009-11-02 08:13:21 -0300271 },
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300272 .set_control = sethvflip
Marton Nemeth1408b842009-11-02 08:13:21 -0300273 },
274};
275
276static const struct v4l2_pix_format vga_mode[] = {
277 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
278 .bytesperline = 640,
279 .sizeimage = 640 * 480 * 3 / 8 + 590,
280 .colorspace = V4L2_COLORSPACE_JPEG,
Jean-François Moineae251e62012-02-27 05:15:12 -0300281 },
Marton Nemeth1408b842009-11-02 08:13:21 -0300282};
283
284#define LOAD_PAGE3 255
Marton Nemeth1408b842009-11-02 08:13:21 -0300285#define END_OF_SEQUENCE 0
286
Jean-François Moineae251e62012-02-27 05:15:12 -0300287static const u8 init_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300288/* index,value */
289 0xff, 0x01, /* page 1 */
290 0x78, 0x00, /* deactivate */
291 0xff, 0x01,
292 0x78, 0x40, /* led off */
293};
Jean-François Moineae251e62012-02-27 05:15:12 -0300294static const u8 start_7302[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300295/* index, len, [value]* */
296 0xff, 1, 0x00, /* page 0 */
297 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
298 0x00, 0x00, 0x00, 0x00,
299 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
300 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
301 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
302 0x26, 2, 0xaa, 0xaa,
303 0x2e, 1, 0x31,
304 0x38, 1, 0x01,
305 0x3a, 3, 0x14, 0xff, 0x5a,
306 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
307 0x00, 0x54, 0x11,
308 0x55, 1, 0x00,
Jean-François Moineae251e62012-02-27 05:15:12 -0300309 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
Marton Nemeth1408b842009-11-02 08:13:21 -0300310 0x6b, 1, 0x00,
311 0x6e, 3, 0x08, 0x06, 0x00,
312 0x72, 3, 0x00, 0xff, 0x00,
313 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
314 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
315 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
316 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
317 0xd2, 0xeb,
318 0xaf, 1, 0x02,
319 0xb5, 2, 0x08, 0x08,
320 0xb8, 2, 0x08, 0x88,
321 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
322 0xcc, 1, 0x00,
323 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
324 0xc1, 0xd7, 0xec,
325 0xdc, 1, 0x01,
326 0xff, 1, 0x01, /* page 1 */
327 0x12, 3, 0x02, 0x00, 0x01,
328 0x3e, 2, 0x00, 0x00,
329 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
330 0x7c, 1, 0x00,
331 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
332 0x02, 0x00,
333 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
334 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
335 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
336 0xd8, 1, 0x01,
337 0xdb, 2, 0x00, 0x01,
338 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
339 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
340 0xeb, 1, 0x00,
341 0xff, 1, 0x02, /* page 2 */
342 0x22, 1, 0x00,
343 0xff, 1, 0x03, /* page 3 */
344 0, LOAD_PAGE3, /* load the page 3 */
345 0x11, 1, 0x01,
346 0xff, 1, 0x02, /* page 2 */
347 0x13, 1, 0x00,
348 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
349 0x27, 2, 0x14, 0x0c,
350 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
351 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
352 0x6e, 1, 0x08,
353 0xff, 1, 0x01, /* page 1 */
354 0x78, 1, 0x00,
355 0, END_OF_SEQUENCE /* end of sequence */
356};
357
358#define SKIP 0xaa
359/* page 3 - the value SKIP says skip the index - see reg_w_page() */
Jean-François Moineae251e62012-02-27 05:15:12 -0300360static const u8 page3_7302[] = {
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300361 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
Marton Nemeth1408b842009-11-02 08:13:21 -0300362 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
363 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
365 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
366 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
367 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
368 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
Jean-Francois Moinecdf955c2010-01-11 15:06:12 -0300370 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
Marton Nemeth1408b842009-11-02 08:13:21 -0300371 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
375 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
376 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
377 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
380 0x00
381};
382
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300383static void reg_w_buf(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300384 u8 index,
Jean-François Moine0aeb5ec2010-12-28 06:59:04 -0300385 const u8 *buffer, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300386{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300387 int ret;
388
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300389 if (gspca_dev->usb_err < 0)
390 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300391 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300392 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300393 usb_sndctrlpipe(gspca_dev->dev, 0),
Jean-François Moinea1317132010-06-24 04:50:26 -0300394 0, /* request */
Marton Nemeth1408b842009-11-02 08:13:21 -0300395 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
396 0, /* value */
397 index, gspca_dev->usb_buf, len,
398 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300399 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300400 pr_err("reg_w_buf failed i: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300401 index, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300402 gspca_dev->usb_err = ret;
403 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300404}
405
406
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300407static void reg_w(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300408 u8 index,
409 u8 value)
Marton Nemeth1408b842009-11-02 08:13:21 -0300410{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300411 int ret;
412
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300413 if (gspca_dev->usb_err < 0)
414 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300415 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300416 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300417 usb_sndctrlpipe(gspca_dev->dev, 0),
418 0, /* request */
419 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
420 0, index, gspca_dev->usb_buf, 1,
421 500);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300422 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300423 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300424 index, value, ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300425 gspca_dev->usb_err = ret;
426 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300427}
428
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300429static void reg_w_seq(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300430 const u8 *seq, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300431{
432 while (--len >= 0) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300433 reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300434 seq += 2;
435 }
436}
437
438/* load the beginning of a page */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300439static void reg_w_page(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300440 const u8 *page, int len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300441{
442 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300443 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300444
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300445 if (gspca_dev->usb_err < 0)
446 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300447 for (index = 0; index < len; index++) {
448 if (page[index] == SKIP) /* skip this index */
449 continue;
450 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300451 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300452 usb_sndctrlpipe(gspca_dev->dev, 0),
453 0, /* request */
454 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
455 0, index, gspca_dev->usb_buf, 1,
456 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300457 if (ret < 0) {
Jean-François Moineae251e62012-02-27 05:15:12 -0300458 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
Joe Perches133a9fe2011-08-21 19:56:57 -0300459 index, page[index], ret);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300460 gspca_dev->usb_err = ret;
Márton Némethb1784b32009-11-07 05:52:02 -0300461 break;
462 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300463 }
464}
465
466/* output a variable sequence */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300467static void reg_w_var(struct gspca_dev *gspca_dev,
Jean-François Moineae251e62012-02-27 05:15:12 -0300468 const u8 *seq,
469 const u8 *page3, unsigned int page3_len)
Marton Nemeth1408b842009-11-02 08:13:21 -0300470{
471 int index, len;
472
473 for (;;) {
474 index = *seq++;
475 len = *seq++;
476 switch (len) {
477 case END_OF_SEQUENCE:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300478 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300479 case LOAD_PAGE3:
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300480 reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300481 break;
482 default:
Jean-François Moineae251e62012-02-27 05:15:12 -0300483#ifdef GSPCA_DEBUG
Marton Nemeth1408b842009-11-02 08:13:21 -0300484 if (len > USB_BUF_SZ) {
485 PDEBUG(D_ERR|D_STREAM,
486 "Incorrect variable sequence");
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300487 return;
Marton Nemeth1408b842009-11-02 08:13:21 -0300488 }
Jean-François Moineae251e62012-02-27 05:15:12 -0300489#endif
Marton Nemeth1408b842009-11-02 08:13:21 -0300490 while (len > 0) {
491 if (len < 8) {
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300492 reg_w_buf(gspca_dev,
Márton Némethb1784b32009-11-07 05:52:02 -0300493 index, seq, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300494 seq += len;
495 break;
496 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300497 reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300498 seq += 8;
499 index += 8;
500 len -= 8;
501 }
502 }
503 }
504 /* not reached */
505}
506
507/* this function is called at probe time for pac7302 */
508static int sd_config(struct gspca_dev *gspca_dev,
509 const struct usb_device_id *id)
510{
511 struct sd *sd = (struct sd *) gspca_dev;
512 struct cam *cam;
513
514 cam = &gspca_dev->cam;
515
Marton Nemeth1408b842009-11-02 08:13:21 -0300516 cam->cam_mode = vga_mode; /* only 640x480 */
517 cam->nmodes = ARRAY_SIZE(vga_mode);
518
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300519 gspca_dev->cam.ctrls = sd->ctrls;
520
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300521 sd->flags = id->driver_info;
Marton Nemeth1408b842009-11-02 08:13:21 -0300522 return 0;
523}
524
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300525static void setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300526{
527 struct sd *sd = (struct sd *) gspca_dev;
528 int i, v;
Jean-François Moineae251e62012-02-27 05:15:12 -0300529 static const u8 max[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300530 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
531 0xd4, 0xec};
Jean-François Moineae251e62012-02-27 05:15:12 -0300532 static const u8 delta[10] =
Marton Nemeth1408b842009-11-02 08:13:21 -0300533 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
534 0x11, 0x0b};
535
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300536 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300537 for (i = 0; i < 10; i++) {
538 v = max[i];
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300539 v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX)
Marton Nemeth1408b842009-11-02 08:13:21 -0300540 * 150 / BRIGHTNESS_MAX; /* 200 ? */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300541 v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX;
Marton Nemeth1408b842009-11-02 08:13:21 -0300542 if (v < 0)
543 v = 0;
544 else if (v > 0xff)
545 v = 0xff;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300546 reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300547 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300548 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300549}
550
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300551static void setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300552{
553 struct sd *sd = (struct sd *) gspca_dev;
554 int i, v;
555 static const int a[9] =
556 {217, -212, 0, -101, 170, -67, -38, -315, 355};
557 static const int b[9] =
558 {19, 106, 0, 19, 106, 1, 19, 106, 1};
559
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300560 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
561 reg_w(gspca_dev, 0x11, 0x01);
562 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300563 for (i = 0; i < 9; i++) {
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300564 v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i];
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300565 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
566 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300567 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300568 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300569}
570
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300571static void setwhitebalance(struct gspca_dev *gspca_dev)
Marton Nemeth23fbee62009-11-08 04:35:12 -0300572{
573 struct sd *sd = (struct sd *) gspca_dev;
Marton Nemeth23fbee62009-11-08 04:35:12 -0300574
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300575 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300576 reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300577
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300578 reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth23fbee62009-11-08 04:35:12 -0300579}
580
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300581static void setredbalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300582{
583 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300584
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300585 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300586 reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val);
Márton Németh265a8092009-11-07 15:15:56 -0300587
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300588 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300589}
590
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300591static void setbluebalance(struct gspca_dev *gspca_dev)
Márton Németh265a8092009-11-07 15:15:56 -0300592{
593 struct sd *sd = (struct sd *) gspca_dev;
Márton Németh265a8092009-11-07 15:15:56 -0300594
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300595 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300596 reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val);
Márton Németh265a8092009-11-07 15:15:56 -0300597
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300598 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh265a8092009-11-07 15:15:56 -0300599}
600
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300601static void setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300602{
603 struct sd *sd = (struct sd *) gspca_dev;
604
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300605 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300606 reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3);
Marton Nemeth1408b842009-11-02 08:13:21 -0300607
608 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300609 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300610}
611
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300612static void setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300613{
614 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineae251e62012-02-27 05:15:12 -0300615 u8 clockdiv;
616 u16 exposure;
Marton Nemeth1408b842009-11-02 08:13:21 -0300617
Hans de Goede895d4642012-04-28 10:31:17 -0300618 /*
619 * Register 2 of frame 3 contains the clock divider configuring the
620 * no fps according to the formula: 90 / reg. sd->exposure is the
621 * desired exposure time in 0.5 ms.
622 */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300623 clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000;
Marton Nemeth1408b842009-11-02 08:13:21 -0300624
Hans de Goede895d4642012-04-28 10:31:17 -0300625 /*
626 * Note clockdiv = 3 also works, but when running at 30 fps, depending
627 * on the scene being recorded, the camera switches to another
628 * quantization table for certain JPEG blocks, and we don't know how
629 * to decompress these blocks. So we cap the framerate at 15 fps.
630 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300631 if (clockdiv < 6)
632 clockdiv = 6;
633 else if (clockdiv > 63)
634 clockdiv = 63;
635
Hans de Goede895d4642012-04-28 10:31:17 -0300636 /*
637 * Register 2 MUST be a multiple of 3, except when between 6 and 12?
638 * Always round up, otherwise we cannot get the desired frametime
639 * using the partial frame time exposure control.
640 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300641 if (clockdiv < 6 || clockdiv > 12)
642 clockdiv = ((clockdiv + 2) / 3) * 3;
643
Hans de Goede895d4642012-04-28 10:31:17 -0300644 /*
645 * frame exposure time in ms = 1000 * clockdiv / 90 ->
646 * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
647 */
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300648 exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300649 /* 0 = use full frametime, 448 = no exposure, reverse it */
650 exposure = 448 - exposure;
651
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300652 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300653 reg_w(gspca_dev, 0x02, clockdiv);
654 reg_w(gspca_dev, 0x0e, exposure & 0xff);
655 reg_w(gspca_dev, 0x0f, exposure >> 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300656
657 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300658 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300659}
660
Jean-François Moineac399cd2012-02-27 05:40:47 -0300661static void setautogain(struct gspca_dev *gspca_dev)
662{
663 struct sd *sd = (struct sd *) gspca_dev;
664
Hans de Goede895d4642012-04-28 10:31:17 -0300665 /*
666 * When switching to autogain set defaults to make sure
667 * we are on a valid point of the autogain gain /
668 * exposure knee graph, and give this change time to
669 * take effect before doing autogain.
670 */
Jean-François Moineac399cd2012-02-27 05:40:47 -0300671 if (sd->ctrls[AUTOGAIN].val) {
672 sd->ctrls[EXPOSURE].val = EXPOSURE_DEF;
673 sd->ctrls[GAIN].val = GAIN_DEF;
674 sd->autogain_ignore_frames =
675 PAC_AUTOGAIN_IGNORE_FRAMES;
676 } else {
677 sd->autogain_ignore_frames = -1;
678 }
679 setexposure(gspca_dev);
680 setgain(gspca_dev);
681}
682
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300683static void sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300684{
685 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300686 u8 data, hflip, vflip;
687
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300688 hflip = sd->ctrls[HFLIP].val;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300689 if (sd->flags & FL_HFLIP)
690 hflip = !hflip;
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300691 vflip = sd->ctrls[VFLIP].val;
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300692 if (sd->flags & FL_VFLIP)
693 vflip = !vflip;
Marton Nemeth1408b842009-11-02 08:13:21 -0300694
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300695 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300696 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300697 reg_w(gspca_dev, 0x21, data);
698
Marton Nemeth1408b842009-11-02 08:13:21 -0300699 /* load registers to sensor (Bit 0, auto clear) */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300700 reg_w(gspca_dev, 0x11, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300701}
702
703/* this function is called at probe and resume time for pac7302 */
704static int sd_init(struct gspca_dev *gspca_dev)
705{
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300706 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
707 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300708}
709
710static int sd_start(struct gspca_dev *gspca_dev)
711{
712 struct sd *sd = (struct sd *) gspca_dev;
713
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300714 reg_w_var(gspca_dev, start_7302,
Jean-Francois Moine23a5de22010-01-13 08:30:30 -0300715 page3_7302, sizeof(page3_7302));
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300716 setbrightcont(gspca_dev);
717 setcolors(gspca_dev);
718 setwhitebalance(gspca_dev);
719 setredbalance(gspca_dev);
720 setbluebalance(gspca_dev);
Jean-François Moineac399cd2012-02-27 05:40:47 -0300721 setautogain(gspca_dev);
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300722 sethvflip(gspca_dev);
Marton Nemeth1408b842009-11-02 08:13:21 -0300723
Marton Nemeth1408b842009-11-02 08:13:21 -0300724 sd->sof_read = 0;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300725 atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val);
Marton Nemeth1408b842009-11-02 08:13:21 -0300726
727 /* start stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300728 reg_w(gspca_dev, 0xff, 0x01);
729 reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300730
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300731 return gspca_dev->usb_err;
Marton Nemeth1408b842009-11-02 08:13:21 -0300732}
733
734static void sd_stopN(struct gspca_dev *gspca_dev)
735{
Márton Némethb1784b32009-11-07 05:52:02 -0300736
Márton Németh67c98f72009-11-07 05:45:33 -0300737 /* stop stream */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300738 reg_w(gspca_dev, 0xff, 0x01);
739 reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300740}
741
742/* called on streamoff with alt 0 and on disconnect for pac7302 */
743static void sd_stop0(struct gspca_dev *gspca_dev)
744{
745 if (!gspca_dev->present)
746 return;
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300747 reg_w(gspca_dev, 0xff, 0x01);
748 reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300749}
750
Hans de Goedea648e312012-04-27 11:32:24 -0300751#define WANT_REGULAR_AUTOGAIN
Jean-François Moineaa5b7922012-02-27 05:38:09 -0300752#include "autogain_functions.h"
753
Marton Nemeth1408b842009-11-02 08:13:21 -0300754static void do_autogain(struct gspca_dev *gspca_dev)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757 int avg_lum = atomic_read(&sd->avg_lum);
Hans de Goede5fb2dde2010-02-17 11:59:19 -0300758 int desired_lum;
759 const int deadzone = 30;
Marton Nemeth1408b842009-11-02 08:13:21 -0300760
Jean-François Moineac399cd2012-02-27 05:40:47 -0300761 if (sd->autogain_ignore_frames < 0)
Marton Nemeth1408b842009-11-02 08:13:21 -0300762 return;
763
Jean-François Moineac399cd2012-02-27 05:40:47 -0300764 if (sd->autogain_ignore_frames > 0) {
Marton Nemeth1408b842009-11-02 08:13:21 -0300765 sd->autogain_ignore_frames--;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300766 } else {
767 desired_lum = 270 + sd->ctrls[BRIGHTNESS].val;
768
769 auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
770 deadzone, GAIN_KNEE, EXPOSURE_KNEE);
Marton Nemeth1408b842009-11-02 08:13:21 -0300771 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
Jean-François Moineac399cd2012-02-27 05:40:47 -0300772 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300773}
774
Jean-François Moine7532e812012-02-27 05:21:57 -0300775/* JPEG header */
776static const u8 jpeg_header[] = {
777 0xff, 0xd8, /* SOI: Start of Image */
Marton Nemeth1408b842009-11-02 08:13:21 -0300778
Jean-François Moine7532e812012-02-27 05:21:57 -0300779 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
780 0x00, 0x11, /* length = 17 bytes (including this length field) */
781 0x08, /* Precision: 8 */
782 0x02, 0x80, /* height = 640 (image rotated) */
783 0x01, 0xe0, /* width = 480 */
784 0x03, /* Number of image components: 3 */
785 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
786 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
787 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
788
789 0xff, 0xda, /* SOS: Start Of Scan */
790 0x00, 0x0c, /* length = 12 bytes (including this length field) */
791 0x03, /* number of components: 3 */
792 0x01, 0x00, /* selector 1, table 0x00 */
793 0x02, 0x11, /* selector 2, table 0x11 */
794 0x03, 0x11, /* selector 3, table 0x11 */
795 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
796 0x00 /* Successive approximation: 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300797};
798
Marton Nemeth1408b842009-11-02 08:13:21 -0300799/* this function is run at interrupt level */
800static void sd_pkt_scan(struct gspca_dev *gspca_dev,
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300801 u8 *data, /* isoc packet */
Marton Nemeth1408b842009-11-02 08:13:21 -0300802 int len) /* iso packet length */
803{
804 struct sd *sd = (struct sd *) gspca_dev;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300805 u8 *image;
Jean-François Moineae251e62012-02-27 05:15:12 -0300806 u8 *sof;
Marton Nemeth1408b842009-11-02 08:13:21 -0300807
808 sof = pac_find_sof(&sd->sof_read, data, len);
809 if (sof) {
810 int n, lum_offset, footer_length;
811
Hans de Goede895d4642012-04-28 10:31:17 -0300812 /*
813 * 6 bytes after the FF D9 EOF marker a number of lumination
814 * bytes are send corresponding to different parts of the
815 * image, the 14th and 15th byte after the EOF seem to
816 * correspond to the center of the image.
817 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300818 lum_offset = 61 + sizeof pac_sof_marker;
819 footer_length = 74;
820
821 /* Finish decoding current frame */
822 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
823 if (n < 0) {
Jean-François Moineb192ca92010-06-27 03:08:19 -0300824 gspca_dev->image_len += n;
Marton Nemeth1408b842009-11-02 08:13:21 -0300825 n = 0;
Jean-François Moineb192ca92010-06-27 03:08:19 -0300826 } else {
827 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
Marton Nemeth1408b842009-11-02 08:13:21 -0300828 }
Jean-François Moinef7059ea2010-07-06 04:32:27 -0300829
830 image = gspca_dev->image;
831 if (image != NULL
Jean-François Moineb192ca92010-06-27 03:08:19 -0300832 && image[gspca_dev->image_len - 2] == 0xff
833 && image[gspca_dev->image_len - 1] == 0xd9)
834 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
Marton Nemeth1408b842009-11-02 08:13:21 -0300835
836 n = sof - data;
837 len -= n;
838 data = sof;
839
840 /* Get average lumination */
841 if (gspca_dev->last_packet_type == LAST_PACKET &&
842 n >= lum_offset)
843 atomic_set(&sd->avg_lum, data[-lum_offset] +
844 data[-lum_offset + 1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300845
846 /* Start the new frame with the jpeg header */
847 /* The PAC7302 has the image rotated 90 degrees */
Jean-François Moine7532e812012-02-27 05:21:57 -0300848 gspca_frame_add(gspca_dev, FIRST_PACKET,
849 jpeg_header, sizeof jpeg_header);
Marton Nemeth1408b842009-11-02 08:13:21 -0300850 }
Jean-Francois Moine76dd2722009-11-13 09:21:03 -0300851 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300852}
853
Márton Németh6763cc02009-11-09 07:10:46 -0300854#ifdef CONFIG_VIDEO_ADV_DEBUG
855static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
856 struct v4l2_dbg_register *reg)
857{
Jean-François Moineae251e62012-02-27 05:15:12 -0300858 u8 index;
859 u8 value;
Márton Németh6763cc02009-11-09 07:10:46 -0300860
Hans de Goede895d4642012-04-28 10:31:17 -0300861 /*
862 * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
863 * long on the USB bus)
864 */
Márton Németh6763cc02009-11-09 07:10:46 -0300865 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
866 reg->match.addr == 0 &&
867 (reg->reg < 0x000000ff) &&
868 (reg->val <= 0x000000ff)
869 ) {
870 /* Currently writing to page 0 is only supported. */
871 /* reg_w() only supports 8bit index */
Jean-François Moineae251e62012-02-27 05:15:12 -0300872 index = reg->reg;
873 value = reg->val;
Márton Németh6763cc02009-11-09 07:10:46 -0300874
Hans de Goede895d4642012-04-28 10:31:17 -0300875 /*
876 * Note that there shall be no access to other page
877 * by any other function between the page switch and
878 * the actual register write.
879 */
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300880 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
881 reg_w(gspca_dev, index, value);
Márton Németh6763cc02009-11-09 07:10:46 -0300882
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300883 reg_w(gspca_dev, 0xdc, 0x01);
Márton Németh6763cc02009-11-09 07:10:46 -0300884 }
Jean-Francois Moinebe927be2010-01-13 15:09:14 -0300885 return gspca_dev->usb_err;
Márton Németh6763cc02009-11-09 07:10:46 -0300886}
887
888static int sd_chip_ident(struct gspca_dev *gspca_dev,
889 struct v4l2_dbg_chip_ident *chip)
890{
891 int ret = -EINVAL;
892
893 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
894 chip->match.addr == 0) {
895 chip->revision = 0;
896 chip->ident = V4L2_IDENT_UNKNOWN;
897 ret = 0;
898 }
899 return ret;
900}
901#endif
902
Jean-François Moine28566432010-10-01 07:33:26 -0300903#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -0300904static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
905 u8 *data, /* interrupt packet data */
906 int len) /* interrput packet length */
907{
908 int ret = -EINVAL;
909 u8 data0, data1;
910
911 if (len == 2) {
912 data0 = data[0];
913 data1 = data[1];
914 if ((data0 == 0x00 && data1 == 0x11) ||
915 (data0 == 0x22 && data1 == 0x33) ||
916 (data0 == 0x44 && data1 == 0x55) ||
917 (data0 == 0x66 && data1 == 0x77) ||
918 (data0 == 0x88 && data1 == 0x99) ||
919 (data0 == 0xaa && data1 == 0xbb) ||
920 (data0 == 0xcc && data1 == 0xdd) ||
921 (data0 == 0xee && data1 == 0xff)) {
922 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
923 input_sync(gspca_dev->input_dev);
924 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
925 input_sync(gspca_dev->input_dev);
926 ret = 0;
927 }
928 }
929
930 return ret;
931}
932#endif
933
Marton Nemeth1408b842009-11-02 08:13:21 -0300934/* sub-driver description for pac7302 */
Márton Némethaabcdfb2010-01-05 12:39:02 -0300935static const struct sd_desc sd_desc = {
Jean-François Moineae251e62012-02-27 05:15:12 -0300936 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -0300937 .ctrls = sd_ctrls,
938 .nctrls = ARRAY_SIZE(sd_ctrls),
939 .config = sd_config,
940 .init = sd_init,
941 .start = sd_start,
942 .stopN = sd_stopN,
943 .stop0 = sd_stop0,
944 .pkt_scan = sd_pkt_scan,
945 .dq_callback = do_autogain,
Márton Németh6763cc02009-11-09 07:10:46 -0300946#ifdef CONFIG_VIDEO_ADV_DEBUG
947 .set_register = sd_dbg_s_register,
948 .get_chip_ident = sd_chip_ident,
949#endif
Jean-François Moine28566432010-10-01 07:33:26 -0300950#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
Márton Némethaed6f1b2010-01-28 16:33:38 -0300951 .int_pkt_scan = sd_int_pkt_scan,
952#endif
Marton Nemeth1408b842009-11-02 08:13:21 -0300953};
954
955/* -- module initialisation -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300956static const struct usb_device_id device_table[] = {
Marton Nemeth1408b842009-11-02 08:13:21 -0300957 {USB_DEVICE(0x06f8, 0x3009)},
Jean-François Moinedd32f982012-02-27 04:58:59 -0300958 {USB_DEVICE(0x06f8, 0x301b)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300959 {USB_DEVICE(0x093a, 0x2620)},
960 {USB_DEVICE(0x093a, 0x2621)},
Jean-Francois Moinefe2b60322009-11-26 14:28:48 -0300961 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
962 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
Márton Németh4e6aeef2010-06-14 17:21:37 -0300963 {USB_DEVICE(0x093a, 0x2625)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300964 {USB_DEVICE(0x093a, 0x2626)},
965 {USB_DEVICE(0x093a, 0x2628)},
Jean-Francois Moinec4322bf2009-12-02 07:04:35 -0300966 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
Marton Nemeth1408b842009-11-02 08:13:21 -0300967 {USB_DEVICE(0x093a, 0x262a)},
968 {USB_DEVICE(0x093a, 0x262c)},
Hans de Goede4d6454d2011-12-30 19:15:53 -0300969 {USB_DEVICE(0x145f, 0x013c)},
Marton Nemeth1408b842009-11-02 08:13:21 -0300970 {}
971};
972MODULE_DEVICE_TABLE(usb, device_table);
973
974/* -- device connect -- */
Jean-François Moine95c967c2011-01-13 05:20:29 -0300975static int sd_probe(struct usb_interface *intf,
Marton Nemeth1408b842009-11-02 08:13:21 -0300976 const struct usb_device_id *id)
977{
978 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
979 THIS_MODULE);
980}
981
982static struct usb_driver sd_driver = {
Jean-François Moineae251e62012-02-27 05:15:12 -0300983 .name = KBUILD_MODNAME,
Marton Nemeth1408b842009-11-02 08:13:21 -0300984 .id_table = device_table,
985 .probe = sd_probe,
986 .disconnect = gspca_disconnect,
987#ifdef CONFIG_PM
988 .suspend = gspca_suspend,
989 .resume = gspca_resume,
990#endif
991};
992
Greg Kroah-Hartmanecb3b2b2011-11-18 09:46:12 -0800993module_usb_driver(sd_driver);