blob: ec2930871d1fc31e462e661e2b46b9f11178be16 [file] [log] [blame]
Marton Nemeth1408b842009-11-02 08:13:21 -03001/*
2 * Pixart PAC7302 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * Separated from Pixart PAC7311 library by Márton Németh <nm127@freemail.hu>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* Some documentation about various registers as determined by trial and error.
25 When the register addresses differ between the 7202 and the 7311 the 2
26 different addresses are written as 7302addr/7311addr, when one of the 2
27 addresses is a - sign that register description is not valid for the
28 matching IC.
29
30 Register page 1:
31
32 Address Description
33 -/0x08 Unknown compressor related, must always be 8 except when not
34 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
35 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
36 bits 345 seem to toggle per color gains on/off (inverted)
37 0x78 Global control, bit 6 controls the LED (inverted)
38 -/0x80 JPEG compression ratio ? Best not touched
39
40 Register page 3/4:
41
42 Address Description
43 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
44 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
45 -/0x0f Master gain 1-245, low value = high gain
46 0x10/- Master gain 0-31
47 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
48 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
49 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
50 completely disable the analog amplification block. Set to 0x68
51 for max gain, 0x14 for minimal gain.
52*/
53
54#define MODULE_NAME "pac7302"
55
56#include "gspca.h"
57
58MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
59MODULE_DESCRIPTION("Pixart PAC7302");
60MODULE_LICENSE("GPL");
61
62/* specific webcam descriptor for pac7302 */
63struct sd {
64 struct gspca_dev gspca_dev; /* !! must be the first item */
65
66 unsigned char brightness;
67 unsigned char contrast;
68 unsigned char colors;
69 unsigned char gain;
70 unsigned char exposure;
71 unsigned char autogain;
72 __u8 hflip;
73 __u8 vflip;
74
75 u8 sof_read;
76 u8 autogain_ignore_frames;
77
78 atomic_t avg_lum;
79};
80
81/* V4L2 controls supported by the driver */
82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
92static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
96static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
97static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
98
99static struct ctrl sd_ctrls[] = {
100/* This control is pac7302 only */
101 {
102 {
103 .id = V4L2_CID_BRIGHTNESS,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Brightness",
106 .minimum = 0,
107#define BRIGHTNESS_MAX 0x20
108 .maximum = BRIGHTNESS_MAX,
109 .step = 1,
110#define BRIGHTNESS_DEF 0x10
111 .default_value = BRIGHTNESS_DEF,
112 },
113 .set = sd_setbrightness,
114 .get = sd_getbrightness,
115 },
116/* This control is for both the 7302 and the 7311 */
117 {
118 {
119 .id = V4L2_CID_CONTRAST,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Contrast",
122 .minimum = 0,
123#define CONTRAST_MAX 255
124 .maximum = CONTRAST_MAX,
125 .step = 1,
126#define CONTRAST_DEF 127
127 .default_value = CONTRAST_DEF,
128 },
129 .set = sd_setcontrast,
130 .get = sd_getcontrast,
131 },
132/* This control is pac7302 only */
133 {
134 {
135 .id = V4L2_CID_SATURATION,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "Saturation",
138 .minimum = 0,
139#define COLOR_MAX 255
140 .maximum = COLOR_MAX,
141 .step = 1,
142#define COLOR_DEF 127
143 .default_value = COLOR_DEF,
144 },
145 .set = sd_setcolors,
146 .get = sd_getcolors,
147 },
148/* All controls below are for both the 7302 and the 7311 */
149 {
150 {
151 .id = V4L2_CID_GAIN,
152 .type = V4L2_CTRL_TYPE_INTEGER,
153 .name = "Gain",
154 .minimum = 0,
155#define GAIN_MAX 255
156 .maximum = GAIN_MAX,
157 .step = 1,
158#define GAIN_DEF 127
159#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
160 .default_value = GAIN_DEF,
161 },
162 .set = sd_setgain,
163 .get = sd_getgain,
164 },
165 {
166 {
167 .id = V4L2_CID_EXPOSURE,
168 .type = V4L2_CTRL_TYPE_INTEGER,
169 .name = "Exposure",
170 .minimum = 0,
171#define EXPOSURE_MAX 255
172 .maximum = EXPOSURE_MAX,
173 .step = 1,
174#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
175#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
176 .default_value = EXPOSURE_DEF,
177 },
178 .set = sd_setexposure,
179 .get = sd_getexposure,
180 },
181 {
182 {
183 .id = V4L2_CID_AUTOGAIN,
184 .type = V4L2_CTRL_TYPE_BOOLEAN,
185 .name = "Auto Gain",
186 .minimum = 0,
187 .maximum = 1,
188 .step = 1,
189#define AUTOGAIN_DEF 1
190 .default_value = AUTOGAIN_DEF,
191 },
192 .set = sd_setautogain,
193 .get = sd_getautogain,
194 },
195 {
196 {
197 .id = V4L2_CID_HFLIP,
198 .type = V4L2_CTRL_TYPE_BOOLEAN,
199 .name = "Mirror",
200 .minimum = 0,
201 .maximum = 1,
202 .step = 1,
203#define HFLIP_DEF 0
204 .default_value = HFLIP_DEF,
205 },
206 .set = sd_sethflip,
207 .get = sd_gethflip,
208 },
209 {
210 {
211 .id = V4L2_CID_VFLIP,
212 .type = V4L2_CTRL_TYPE_BOOLEAN,
213 .name = "Vflip",
214 .minimum = 0,
215 .maximum = 1,
216 .step = 1,
217#define VFLIP_DEF 0
218 .default_value = VFLIP_DEF,
219 },
220 .set = sd_setvflip,
221 .get = sd_getvflip,
222 },
223};
224
225static const struct v4l2_pix_format vga_mode[] = {
226 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
227 .bytesperline = 640,
228 .sizeimage = 640 * 480 * 3 / 8 + 590,
229 .colorspace = V4L2_COLORSPACE_JPEG,
230 .priv = 0},
231};
232
233#define LOAD_PAGE3 255
234#define LOAD_PAGE4 254
235#define END_OF_SEQUENCE 0
236
237/* pac 7302 */
238static const __u8 init_7302[] = {
239/* index,value */
240 0xff, 0x01, /* page 1 */
241 0x78, 0x00, /* deactivate */
242 0xff, 0x01,
243 0x78, 0x40, /* led off */
244};
245static const __u8 start_7302[] = {
246/* index, len, [value]* */
247 0xff, 1, 0x00, /* page 0 */
248 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
249 0x00, 0x00, 0x00, 0x00,
250 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
251 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
252 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
253 0x26, 2, 0xaa, 0xaa,
254 0x2e, 1, 0x31,
255 0x38, 1, 0x01,
256 0x3a, 3, 0x14, 0xff, 0x5a,
257 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
258 0x00, 0x54, 0x11,
259 0x55, 1, 0x00,
260 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
261 0x6b, 1, 0x00,
262 0x6e, 3, 0x08, 0x06, 0x00,
263 0x72, 3, 0x00, 0xff, 0x00,
264 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
265 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
266 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
267 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
268 0xd2, 0xeb,
269 0xaf, 1, 0x02,
270 0xb5, 2, 0x08, 0x08,
271 0xb8, 2, 0x08, 0x88,
272 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
273 0xcc, 1, 0x00,
274 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
275 0xc1, 0xd7, 0xec,
276 0xdc, 1, 0x01,
277 0xff, 1, 0x01, /* page 1 */
278 0x12, 3, 0x02, 0x00, 0x01,
279 0x3e, 2, 0x00, 0x00,
280 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
281 0x7c, 1, 0x00,
282 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
283 0x02, 0x00,
284 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
285 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
286 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
287 0xd8, 1, 0x01,
288 0xdb, 2, 0x00, 0x01,
289 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
290 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
291 0xeb, 1, 0x00,
292 0xff, 1, 0x02, /* page 2 */
293 0x22, 1, 0x00,
294 0xff, 1, 0x03, /* page 3 */
295 0, LOAD_PAGE3, /* load the page 3 */
296 0x11, 1, 0x01,
297 0xff, 1, 0x02, /* page 2 */
298 0x13, 1, 0x00,
299 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
300 0x27, 2, 0x14, 0x0c,
301 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
302 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
303 0x6e, 1, 0x08,
304 0xff, 1, 0x01, /* page 1 */
305 0x78, 1, 0x00,
306 0, END_OF_SEQUENCE /* end of sequence */
307};
308
309#define SKIP 0xaa
310/* page 3 - the value SKIP says skip the index - see reg_w_page() */
311static const __u8 page3_7302[] = {
312 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
313 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
314 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
316 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
317 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
318 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
319 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
322 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
326 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
327 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
328 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
331 0x00
332};
333
Márton Némethb1784b32009-11-07 05:52:02 -0300334static int reg_w_buf(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300335 __u8 index,
336 const char *buffer, int len)
337{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300338 int ret;
339
Marton Nemeth1408b842009-11-02 08:13:21 -0300340 memcpy(gspca_dev->usb_buf, buffer, len);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300341 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300342 usb_sndctrlpipe(gspca_dev->dev, 0),
343 1, /* request */
344 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
345 0, /* value */
346 index, gspca_dev->usb_buf, len,
347 500);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300348 if (ret < 0)
349 PDEBUG(D_ERR, "reg_w_buf(): "
350 "Failed to write registers to index 0x%x, error %i",
351 index, ret);
Márton Némethb1784b32009-11-07 05:52:02 -0300352 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300353}
354
355
Márton Némethb1784b32009-11-07 05:52:02 -0300356static int reg_w(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300357 __u8 index,
358 __u8 value)
359{
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300360 int ret;
361
Marton Nemeth1408b842009-11-02 08:13:21 -0300362 gspca_dev->usb_buf[0] = value;
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300363 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300364 usb_sndctrlpipe(gspca_dev->dev, 0),
365 0, /* request */
366 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
367 0, index, gspca_dev->usb_buf, 1,
368 500);
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300369 if (ret < 0)
370 PDEBUG(D_ERR, "reg_w(): "
371 "Failed to write register to index 0x%x, value 0x%x, error %i",
372 index, value, ret);
Márton Némethb1784b32009-11-07 05:52:02 -0300373 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300374}
375
Márton Némethb1784b32009-11-07 05:52:02 -0300376static int reg_w_seq(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300377 const __u8 *seq, int len)
378{
Márton Némethb1784b32009-11-07 05:52:02 -0300379 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300380 while (--len >= 0) {
Márton Némethb1784b32009-11-07 05:52:02 -0300381 if (0 <= ret)
382 ret = reg_w(gspca_dev, seq[0], seq[1]);
Marton Nemeth1408b842009-11-02 08:13:21 -0300383 seq += 2;
384 }
Márton Némethb1784b32009-11-07 05:52:02 -0300385 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300386}
387
388/* load the beginning of a page */
Márton Némethb1784b32009-11-07 05:52:02 -0300389static int reg_w_page(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300390 const __u8 *page, int len)
391{
392 int index;
Márton Némethb1784b32009-11-07 05:52:02 -0300393 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300394
395 for (index = 0; index < len; index++) {
396 if (page[index] == SKIP) /* skip this index */
397 continue;
398 gspca_dev->usb_buf[0] = page[index];
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300399 ret = usb_control_msg(gspca_dev->dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300400 usb_sndctrlpipe(gspca_dev->dev, 0),
401 0, /* request */
402 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
403 0, index, gspca_dev->usb_buf, 1,
404 500);
Márton Némethb1784b32009-11-07 05:52:02 -0300405 if (ret < 0) {
Marton Nemeth4f7309e2009-11-05 05:35:08 -0300406 PDEBUG(D_ERR, "reg_w_page(): "
407 "Failed to write register to index 0x%x, "
408 "value 0x%x, error %i",
409 index, page[index], ret);
Márton Némethb1784b32009-11-07 05:52:02 -0300410 break;
411 }
Marton Nemeth1408b842009-11-02 08:13:21 -0300412 }
Márton Némethb1784b32009-11-07 05:52:02 -0300413 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300414}
415
416/* output a variable sequence */
Márton Némethb1784b32009-11-07 05:52:02 -0300417static int reg_w_var(struct gspca_dev *gspca_dev,
Marton Nemeth1408b842009-11-02 08:13:21 -0300418 const __u8 *seq,
419 const __u8 *page3, unsigned int page3_len,
420 const __u8 *page4, unsigned int page4_len)
421{
422 int index, len;
Márton Némethb1784b32009-11-07 05:52:02 -0300423 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300424
425 for (;;) {
426 index = *seq++;
427 len = *seq++;
428 switch (len) {
429 case END_OF_SEQUENCE:
Márton Némethb1784b32009-11-07 05:52:02 -0300430 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300431 case LOAD_PAGE4:
Márton Némethb1784b32009-11-07 05:52:02 -0300432 ret = reg_w_page(gspca_dev, page4, page4_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300433 break;
434 case LOAD_PAGE3:
Márton Némethb1784b32009-11-07 05:52:02 -0300435 ret = reg_w_page(gspca_dev, page3, page3_len);
Marton Nemeth1408b842009-11-02 08:13:21 -0300436 break;
437 default:
438 if (len > USB_BUF_SZ) {
439 PDEBUG(D_ERR|D_STREAM,
440 "Incorrect variable sequence");
Márton Némethb1784b32009-11-07 05:52:02 -0300441 return -EINVAL;
Marton Nemeth1408b842009-11-02 08:13:21 -0300442 }
443 while (len > 0) {
444 if (len < 8) {
Márton Némethb1784b32009-11-07 05:52:02 -0300445 ret = reg_w_buf(gspca_dev,
446 index, seq, len);
447 if (ret < 0)
448 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300449 seq += len;
450 break;
451 }
Márton Némethb1784b32009-11-07 05:52:02 -0300452 ret = reg_w_buf(gspca_dev, index, seq, 8);
Marton Nemeth1408b842009-11-02 08:13:21 -0300453 seq += 8;
454 index += 8;
455 len -= 8;
456 }
457 }
Márton Némethb1784b32009-11-07 05:52:02 -0300458 if (ret < 0)
459 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300460 }
461 /* not reached */
462}
463
464/* this function is called at probe time for pac7302 */
465static int sd_config(struct gspca_dev *gspca_dev,
466 const struct usb_device_id *id)
467{
468 struct sd *sd = (struct sd *) gspca_dev;
469 struct cam *cam;
470
471 cam = &gspca_dev->cam;
472
473 PDEBUG(D_CONF, "Find Sensor PAC7302");
474 cam->cam_mode = vga_mode; /* only 640x480 */
475 cam->nmodes = ARRAY_SIZE(vga_mode);
476
477 sd->brightness = BRIGHTNESS_DEF;
478 sd->contrast = CONTRAST_DEF;
479 sd->colors = COLOR_DEF;
480 sd->gain = GAIN_DEF;
481 sd->exposure = EXPOSURE_DEF;
482 sd->autogain = AUTOGAIN_DEF;
483 sd->hflip = HFLIP_DEF;
484 sd->vflip = VFLIP_DEF;
485 return 0;
486}
487
488/* This function is used by pac7302 only */
Márton Némethb1784b32009-11-07 05:52:02 -0300489static int setbrightcont(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300490{
491 struct sd *sd = (struct sd *) gspca_dev;
492 int i, v;
Márton Némethb1784b32009-11-07 05:52:02 -0300493 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300494 static const __u8 max[10] =
495 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
496 0xd4, 0xec};
497 static const __u8 delta[10] =
498 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
499 0x11, 0x0b};
500
Márton Némethb1784b32009-11-07 05:52:02 -0300501 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300502 for (i = 0; i < 10; i++) {
503 v = max[i];
504 v += (sd->brightness - BRIGHTNESS_MAX)
505 * 150 / BRIGHTNESS_MAX; /* 200 ? */
506 v -= delta[i] * sd->contrast / CONTRAST_MAX;
507 if (v < 0)
508 v = 0;
509 else if (v > 0xff)
510 v = 0xff;
Márton Némethb1784b32009-11-07 05:52:02 -0300511 if (0 <= ret)
512 ret = reg_w(gspca_dev, 0xa2 + i, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300513 }
Márton Némethb1784b32009-11-07 05:52:02 -0300514 if (0 <= ret)
515 ret = reg_w(gspca_dev, 0xdc, 0x01);
516 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300517}
518
519/* This function is used by pac7302 only */
Márton Némethb1784b32009-11-07 05:52:02 -0300520static int setcolors(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300521{
522 struct sd *sd = (struct sd *) gspca_dev;
523 int i, v;
Márton Némethb1784b32009-11-07 05:52:02 -0300524 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300525 static const int a[9] =
526 {217, -212, 0, -101, 170, -67, -38, -315, 355};
527 static const int b[9] =
528 {19, 106, 0, 19, 106, 1, 19, 106, 1};
529
Márton Némethb1784b32009-11-07 05:52:02 -0300530 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
531 if (0 <= ret)
532 ret = reg_w(gspca_dev, 0x11, 0x01);
533 if (0 <= ret)
534 ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300535 for (i = 0; i < 9; i++) {
536 v = a[i] * sd->colors / COLOR_MAX + b[i];
Márton Némethb1784b32009-11-07 05:52:02 -0300537 if (0 <= ret)
538 ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
539 if (0 <= ret)
540 ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
Marton Nemeth1408b842009-11-02 08:13:21 -0300541 }
Márton Némethb1784b32009-11-07 05:52:02 -0300542 if (0 <= ret)
543 ret = reg_w(gspca_dev, 0xdc, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300544 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
Márton Némethb1784b32009-11-07 05:52:02 -0300545 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300546}
547
Márton Némethb1784b32009-11-07 05:52:02 -0300548static int setgain(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300549{
550 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300551 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300552
Márton Némethb1784b32009-11-07 05:52:02 -0300553 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
554 if (0 <= ret)
555 ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);
Marton Nemeth1408b842009-11-02 08:13:21 -0300556
557 /* load registers to sensor (Bit 0, auto clear) */
Márton Némethb1784b32009-11-07 05:52:02 -0300558 if (0 <= ret)
559 ret = reg_w(gspca_dev, 0x11, 0x01);
560 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300561}
562
Márton Némethb1784b32009-11-07 05:52:02 -0300563static int setexposure(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300564{
565 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300566 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300567 __u8 reg;
568
569 /* register 2 of frame 3/4 contains the clock divider configuring the
570 no fps according to the formula: 60 / reg. sd->exposure is the
571 desired exposure time in ms. */
572 reg = 120 * sd->exposure / 1000;
573 if (reg < 2)
574 reg = 2;
575 else if (reg > 63)
576 reg = 63;
577
578 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
579 the nearest multiple of 3, except when between 6 and 12? */
580 if (reg < 6 || reg > 12)
581 reg = ((reg + 1) / 3) * 3;
Márton Némethb1784b32009-11-07 05:52:02 -0300582 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
583 if (0 <= ret)
584 ret = reg_w(gspca_dev, 0x02, reg);
Marton Nemeth1408b842009-11-02 08:13:21 -0300585
586 /* load registers to sensor (Bit 0, auto clear) */
Márton Némethb1784b32009-11-07 05:52:02 -0300587 if (0 <= ret)
588 ret = reg_w(gspca_dev, 0x11, 0x01);
589 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300590}
591
Márton Némethb1784b32009-11-07 05:52:02 -0300592static int sethvflip(struct gspca_dev *gspca_dev)
Marton Nemeth1408b842009-11-02 08:13:21 -0300593{
594 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300595 int ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300596 __u8 data;
597
Márton Némethb1784b32009-11-07 05:52:02 -0300598 ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
Marton Nemeth1408b842009-11-02 08:13:21 -0300599 data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
Márton Némethb1784b32009-11-07 05:52:02 -0300600 if (0 <= ret)
601 ret = reg_w(gspca_dev, 0x21, data);
Marton Nemeth1408b842009-11-02 08:13:21 -0300602 /* load registers to sensor (Bit 0, auto clear) */
Márton Némethb1784b32009-11-07 05:52:02 -0300603 if (0 <= ret)
604 ret = reg_w(gspca_dev, 0x11, 0x01);
605 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300606}
607
608/* this function is called at probe and resume time for pac7302 */
609static int sd_init(struct gspca_dev *gspca_dev)
610{
Márton Némethb1784b32009-11-07 05:52:02 -0300611 return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
Marton Nemeth1408b842009-11-02 08:13:21 -0300612}
613
614static int sd_start(struct gspca_dev *gspca_dev)
615{
616 struct sd *sd = (struct sd *) gspca_dev;
Márton Némethb1784b32009-11-07 05:52:02 -0300617 int ret = 0;
Marton Nemeth1408b842009-11-02 08:13:21 -0300618
619 sd->sof_read = 0;
620
Márton Némethb1784b32009-11-07 05:52:02 -0300621 ret = reg_w_var(gspca_dev, start_7302,
Marton Nemeth1408b842009-11-02 08:13:21 -0300622 page3_7302, sizeof(page3_7302),
623 NULL, 0);
Márton Némethb1784b32009-11-07 05:52:02 -0300624 if (0 <= ret)
625 ret = setbrightcont(gspca_dev);
626 if (0 <= ret)
627 ret = setcolors(gspca_dev);
628 if (0 <= ret)
629 setgain(gspca_dev);
630 if (0 <= ret)
631 setexposure(gspca_dev);
632 if (0 <= ret)
633 sethvflip(gspca_dev);
Marton Nemeth1408b842009-11-02 08:13:21 -0300634
635 /* only resolution 640x480 is supported for pac7302 */
636
637 sd->sof_read = 0;
638 sd->autogain_ignore_frames = 0;
639 atomic_set(&sd->avg_lum, -1);
640
641 /* start stream */
Márton Némethb1784b32009-11-07 05:52:02 -0300642 if (0 <= ret)
643 ret = reg_w(gspca_dev, 0xff, 0x01);
644 if (0 <= ret)
645 ret = reg_w(gspca_dev, 0x78, 0x01);
Marton Nemeth1408b842009-11-02 08:13:21 -0300646
Márton Némethb1784b32009-11-07 05:52:02 -0300647 return ret;
Marton Nemeth1408b842009-11-02 08:13:21 -0300648}
649
650static void sd_stopN(struct gspca_dev *gspca_dev)
651{
Márton Némethb1784b32009-11-07 05:52:02 -0300652 int ret;
653
Márton Németh67c98f72009-11-07 05:45:33 -0300654 /* stop stream */
Márton Némethb1784b32009-11-07 05:52:02 -0300655 ret = reg_w(gspca_dev, 0xff, 0x01);
656 if (0 <= ret)
657 ret = reg_w(gspca_dev, 0x78, 0x00);
Marton Nemeth1408b842009-11-02 08:13:21 -0300658}
659
660/* called on streamoff with alt 0 and on disconnect for pac7302 */
661static void sd_stop0(struct gspca_dev *gspca_dev)
662{
Márton Némethb1784b32009-11-07 05:52:02 -0300663 int ret;
664
Marton Nemeth1408b842009-11-02 08:13:21 -0300665 if (!gspca_dev->present)
666 return;
Márton Némethb1784b32009-11-07 05:52:02 -0300667 ret = reg_w(gspca_dev, 0xff, 0x01);
668 if (0 <= ret)
669 ret = reg_w(gspca_dev, 0x78, 0x40);
Marton Nemeth1408b842009-11-02 08:13:21 -0300670}
671
672/* Include pac common sof detection functions */
673#include "pac_common.h"
674
675static void do_autogain(struct gspca_dev *gspca_dev)
676{
677 struct sd *sd = (struct sd *) gspca_dev;
678 int avg_lum = atomic_read(&sd->avg_lum);
679 int desired_lum, deadzone;
680
681 if (avg_lum == -1)
682 return;
683
684 desired_lum = 270 + sd->brightness * 4;
685 /* Hack hack, with the 7202 the first exposure step is
686 pretty large, so if we're about to make the first
687 exposure increase make the deadzone large to avoid
688 oscilating */
689 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
690 sd->exposure > EXPOSURE_DEF &&
691 sd->exposure < 42)
692 deadzone = 90;
693 else
694 deadzone = 30;
695
696 if (sd->autogain_ignore_frames > 0)
697 sd->autogain_ignore_frames--;
698 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
699 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
700 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
701}
702
703/* JPEG header, part 1 */
704static const unsigned char pac_jpeg_header1[] = {
705 0xff, 0xd8, /* SOI: Start of Image */
706
707 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
708 0x00, 0x11, /* length = 17 bytes (including this length field) */
709 0x08 /* Precision: 8 */
710 /* 2 bytes is placed here: number of image lines */
711 /* 2 bytes is placed here: samples per line */
712};
713
714/* JPEG header, continued */
715static const unsigned char pac_jpeg_header2[] = {
716 0x03, /* Number of image components: 3 */
717 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
718 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
719 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
720
721 0xff, 0xda, /* SOS: Start Of Scan */
722 0x00, 0x0c, /* length = 12 bytes (including this length field) */
723 0x03, /* number of components: 3 */
724 0x01, 0x00, /* selector 1, table 0x00 */
725 0x02, 0x11, /* selector 2, table 0x11 */
726 0x03, 0x11, /* selector 3, table 0x11 */
727 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
728 0x00 /* Successive approximation: 0 */
729};
730
731static void pac_start_frame(struct gspca_dev *gspca_dev,
732 struct gspca_frame *frame,
733 __u16 lines, __u16 samples_per_line)
734{
735 unsigned char tmpbuf[4];
736
737 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
738 pac_jpeg_header1, sizeof(pac_jpeg_header1));
739
740 tmpbuf[0] = lines >> 8;
741 tmpbuf[1] = lines & 0xff;
742 tmpbuf[2] = samples_per_line >> 8;
743 tmpbuf[3] = samples_per_line & 0xff;
744
745 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
746 tmpbuf, sizeof(tmpbuf));
747 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
748 pac_jpeg_header2, sizeof(pac_jpeg_header2));
749}
750
751/* this function is run at interrupt level */
752static void sd_pkt_scan(struct gspca_dev *gspca_dev,
753 struct gspca_frame *frame, /* target */
754 __u8 *data, /* isoc packet */
755 int len) /* iso packet length */
756{
757 struct sd *sd = (struct sd *) gspca_dev;
758 unsigned char *sof;
759
760 sof = pac_find_sof(&sd->sof_read, data, len);
761 if (sof) {
762 int n, lum_offset, footer_length;
763
764 /* 6 bytes after the FF D9 EOF marker a number of lumination
765 bytes are send corresponding to different parts of the
766 image, the 14th and 15th byte after the EOF seem to
767 correspond to the center of the image */
768 lum_offset = 61 + sizeof pac_sof_marker;
769 footer_length = 74;
770
771 /* Finish decoding current frame */
772 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
773 if (n < 0) {
774 frame->data_end += n;
775 n = 0;
776 }
777 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
778 data, n);
779 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
780 frame->data_end[-2] == 0xff &&
781 frame->data_end[-1] == 0xd9)
782 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
783 NULL, 0);
784
785 n = sof - data;
786 len -= n;
787 data = sof;
788
789 /* Get average lumination */
790 if (gspca_dev->last_packet_type == LAST_PACKET &&
791 n >= lum_offset)
792 atomic_set(&sd->avg_lum, data[-lum_offset] +
793 data[-lum_offset + 1]);
794 else
795 atomic_set(&sd->avg_lum, -1);
796
797 /* Start the new frame with the jpeg header */
798 /* The PAC7302 has the image rotated 90 degrees */
799 pac_start_frame(gspca_dev, frame,
800 gspca_dev->width, gspca_dev->height);
801 }
802 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
803}
804
805static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
806{
807 struct sd *sd = (struct sd *) gspca_dev;
808
809 sd->brightness = val;
810 if (gspca_dev->streaming)
811 setbrightcont(gspca_dev);
812 return 0;
813}
814
815static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
816{
817 struct sd *sd = (struct sd *) gspca_dev;
818
819 *val = sd->brightness;
820 return 0;
821}
822
823static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826
827 sd->contrast = val;
828 if (gspca_dev->streaming) {
829 setbrightcont(gspca_dev);
830 }
831 return 0;
832}
833
834static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
835{
836 struct sd *sd = (struct sd *) gspca_dev;
837
838 *val = sd->contrast;
839 return 0;
840}
841
842static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
843{
844 struct sd *sd = (struct sd *) gspca_dev;
845
846 sd->colors = val;
847 if (gspca_dev->streaming)
848 setcolors(gspca_dev);
849 return 0;
850}
851
852static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
853{
854 struct sd *sd = (struct sd *) gspca_dev;
855
856 *val = sd->colors;
857 return 0;
858}
859
860static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
861{
862 struct sd *sd = (struct sd *) gspca_dev;
863
864 sd->gain = val;
865 if (gspca_dev->streaming)
866 setgain(gspca_dev);
867 return 0;
868}
869
870static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 *val = sd->gain;
875 return 0;
876}
877
878static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
879{
880 struct sd *sd = (struct sd *) gspca_dev;
881
882 sd->exposure = val;
883 if (gspca_dev->streaming)
884 setexposure(gspca_dev);
885 return 0;
886}
887
888static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
889{
890 struct sd *sd = (struct sd *) gspca_dev;
891
892 *val = sd->exposure;
893 return 0;
894}
895
896static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
897{
898 struct sd *sd = (struct sd *) gspca_dev;
899
900 sd->autogain = val;
901 /* when switching to autogain set defaults to make sure
902 we are on a valid point of the autogain gain /
903 exposure knee graph, and give this change time to
904 take effect before doing autogain. */
905 if (sd->autogain) {
906 sd->exposure = EXPOSURE_DEF;
907 sd->gain = GAIN_DEF;
908 if (gspca_dev->streaming) {
909 sd->autogain_ignore_frames =
910 PAC_AUTOGAIN_IGNORE_FRAMES;
911 setexposure(gspca_dev);
912 setgain(gspca_dev);
913 }
914 }
915
916 return 0;
917}
918
919static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
920{
921 struct sd *sd = (struct sd *) gspca_dev;
922
923 *val = sd->autogain;
924 return 0;
925}
926
927static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
928{
929 struct sd *sd = (struct sd *) gspca_dev;
930
931 sd->hflip = val;
932 if (gspca_dev->streaming)
933 sethvflip(gspca_dev);
934 return 0;
935}
936
937static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940
941 *val = sd->hflip;
942 return 0;
943}
944
945static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
946{
947 struct sd *sd = (struct sd *) gspca_dev;
948
949 sd->vflip = val;
950 if (gspca_dev->streaming)
951 sethvflip(gspca_dev);
952 return 0;
953}
954
955static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
956{
957 struct sd *sd = (struct sd *) gspca_dev;
958
959 *val = sd->vflip;
960 return 0;
961}
962
963/* sub-driver description for pac7302 */
964static struct sd_desc sd_desc = {
965 .name = MODULE_NAME,
966 .ctrls = sd_ctrls,
967 .nctrls = ARRAY_SIZE(sd_ctrls),
968 .config = sd_config,
969 .init = sd_init,
970 .start = sd_start,
971 .stopN = sd_stopN,
972 .stop0 = sd_stop0,
973 .pkt_scan = sd_pkt_scan,
974 .dq_callback = do_autogain,
975};
976
977/* -- module initialisation -- */
978static __devinitdata struct usb_device_id device_table[] = {
979 {USB_DEVICE(0x06f8, 0x3009)},
980 {USB_DEVICE(0x093a, 0x2620)},
981 {USB_DEVICE(0x093a, 0x2621)},
982 {USB_DEVICE(0x093a, 0x2622)},
983 {USB_DEVICE(0x093a, 0x2624)},
984 {USB_DEVICE(0x093a, 0x2626)},
985 {USB_DEVICE(0x093a, 0x2628)},
986 {USB_DEVICE(0x093a, 0x2629)},
987 {USB_DEVICE(0x093a, 0x262a)},
988 {USB_DEVICE(0x093a, 0x262c)},
989 {}
990};
991MODULE_DEVICE_TABLE(usb, device_table);
992
993/* -- device connect -- */
994static int sd_probe(struct usb_interface *intf,
995 const struct usb_device_id *id)
996{
997 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
998 THIS_MODULE);
999}
1000
1001static struct usb_driver sd_driver = {
1002 .name = MODULE_NAME,
1003 .id_table = device_table,
1004 .probe = sd_probe,
1005 .disconnect = gspca_disconnect,
1006#ifdef CONFIG_PM
1007 .suspend = gspca_suspend,
1008 .resume = gspca_resume,
1009#endif
1010};
1011
1012/* -- module insert / remove -- */
1013static int __init sd_mod_init(void)
1014{
1015 int ret;
1016 ret = usb_register(&sd_driver);
1017 if (ret < 0)
1018 return ret;
1019 PDEBUG(D_PROBE, "registered");
1020 return 0;
1021}
1022static void __exit sd_mod_exit(void)
1023{
1024 usb_deregister(&sd_driver);
1025 PDEBUG(D_PROBE, "deregistered");
1026}
1027
1028module_init(sd_mod_init);
1029module_exit(sd_mod_exit);