[media] gspca: Remove __devinit, __devinitconst and __devinitdata
[deliverable/linux.git] / drivers / media / video / gspca / pac7311.c
CommitLineData
6a7eba24
JFM
1/*
2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
327c4abf
HG
22/* Some documentation about various registers as determined by trial and error.
23 When the register addresses differ between the 7202 and the 7311 the 2
24 different addresses are written as 7302addr/7311addr, when one of the 2
25 addresses is a - sign that register description is not valid for the
26 matching IC.
27
28 Register page 1:
29
30 Address Description
31 -/0x08 Unknown compressor related, must always be 8 except when not
32 in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
33 -/0x1b Auto white balance related, bit 0 is AWB enable (inverted)
34 bits 345 seem to toggle per color gains on/off (inverted)
35 0x78 Global control, bit 6 controls the LED (inverted)
36 -/0x80 JPEG compression ratio ? Best not touched
37
38 Register page 3/4:
39
40 Address Description
41 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
038ec7c7 42 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
327c4abf
HG
43 -/0x0f Master gain 1-245, low value = high gain
44 0x10/- Master gain 0-31
45 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess)
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
8a5b2e90
HG
47 -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
48 completely disable the analog amplification block. Set to 0x68
49 for max gain, 0x14 for minimal gain.
327c4abf
HG
50*/
51
6a7eba24
JFM
52#define MODULE_NAME "pac7311"
53
32ea3e44 54#include <linux/input.h>
6a7eba24
JFM
55#include "gspca.h"
56
6a7eba24
JFM
57MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
58MODULE_DESCRIPTION("Pixart PAC7311");
59MODULE_LICENSE("GPL");
60
1408b847 61/* specific webcam descriptor for pac7311 */
6a7eba24
JFM
62struct sd {
63 struct gspca_dev gspca_dev; /* !! must be the first item */
64
6a7eba24 65 unsigned char contrast;
8a5b2e90
HG
66 unsigned char gain;
67 unsigned char exposure;
6a7eba24 68 unsigned char autogain;
41b46974
JFM
69 __u8 hflip;
70 __u8 vflip;
49b57dba 71
327c4abf 72 u8 sof_read;
327c4abf
HG
73 u8 autogain_ignore_frames;
74
75 atomic_t avg_lum;
6a7eba24
JFM
76};
77
78/* V4L2 controls supported by the driver */
6a7eba24
JFM
79static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
6a7eba24
JFM
81static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
41b46974
JFM
83static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
8a5b2e90
HG
87static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
6a7eba24 91
7e64dc4c 92static const struct ctrl sd_ctrls[] = {
8a5b2e90 93/* This control is for both the 7302 and the 7311 */
6a7eba24
JFM
94 {
95 {
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
dff6d321
JFM
100#define CONTRAST_MAX 255
101 .maximum = CONTRAST_MAX,
6a7eba24 102 .step = 1,
327c4abf 103#define CONTRAST_DEF 127
a5ae2062 104 .default_value = CONTRAST_DEF,
6a7eba24
JFM
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
8a5b2e90
HG
109/* All controls below are for both the 7302 and the 7311 */
110 {
111 {
112 .id = V4L2_CID_GAIN,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Gain",
115 .minimum = 0,
116#define GAIN_MAX 255
117 .maximum = GAIN_MAX,
118 .step = 1,
119#define GAIN_DEF 127
120#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
121 .default_value = GAIN_DEF,
122 },
123 .set = sd_setgain,
124 .get = sd_getgain,
125 },
126 {
127 {
128 .id = V4L2_CID_EXPOSURE,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Exposure",
131 .minimum = 0,
132#define EXPOSURE_MAX 255
133 .maximum = EXPOSURE_MAX,
134 .step = 1,
135#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
136#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
137 .default_value = EXPOSURE_DEF,
138 },
139 .set = sd_setexposure,
140 .get = sd_getexposure,
141 },
6a7eba24
JFM
142 {
143 {
144 .id = V4L2_CID_AUTOGAIN,
145 .type = V4L2_CTRL_TYPE_BOOLEAN,
146 .name = "Auto Gain",
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
a5ae2062
JFM
150#define AUTOGAIN_DEF 1
151 .default_value = AUTOGAIN_DEF,
6a7eba24
JFM
152 },
153 .set = sd_setautogain,
154 .get = sd_getautogain,
155 },
41b46974
JFM
156 {
157 {
158 .id = V4L2_CID_HFLIP,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "Mirror",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164#define HFLIP_DEF 0
165 .default_value = HFLIP_DEF,
166 },
167 .set = sd_sethflip,
168 .get = sd_gethflip,
169 },
170 {
171 {
172 .id = V4L2_CID_VFLIP,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "Vflip",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178#define VFLIP_DEF 0
179 .default_value = VFLIP_DEF,
180 },
181 .set = sd_setvflip,
182 .get = sd_getvflip,
183 },
6a7eba24
JFM
184};
185
cc611b8a 186static const struct v4l2_pix_format vga_mode[] = {
f75c4950 187 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
188 .bytesperline = 160,
189 .sizeimage = 160 * 120 * 3 / 8 + 590,
190 .colorspace = V4L2_COLORSPACE_JPEG,
191 .priv = 2},
f75c4950 192 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
193 .bytesperline = 320,
194 .sizeimage = 320 * 240 * 3 / 8 + 590,
195 .colorspace = V4L2_COLORSPACE_JPEG,
196 .priv = 1},
f75c4950 197 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
198 .bytesperline = 640,
199 .sizeimage = 640 * 480 * 3 / 8 + 590,
200 .colorspace = V4L2_COLORSPACE_JPEG,
201 .priv = 0},
6a7eba24
JFM
202};
203
5a2e8d9f
MN
204#define LOAD_PAGE4 254
205#define END_OF_SEQUENCE 0
206
49b57dba 207/* pac 7311 */
271315a9 208static const __u8 init_7311[] = {
327c4abf
HG
209 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
210 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
211 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
49b57dba
JFM
212 0xff, 0x04,
213 0x27, 0x80,
214 0x28, 0xca,
215 0x29, 0x53,
216 0x2a, 0x0e,
217 0xff, 0x01,
218 0x3e, 0x20,
219};
220
221static const __u8 start_7311[] = {
222/* index, len, [value]* */
285a4f6c
JFM
223 0xff, 1, 0x01, /* page 1 */
224 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
49b57dba
JFM
225 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
226 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
227 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00,
285a4f6c 230 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
49b57dba
JFM
231 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
232 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
233 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
234 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
235 0xd0, 0xff,
236 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
237 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
238 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
239 0x18, 0x20,
240 0x96, 3, 0x01, 0x08, 0x04,
241 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
242 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
243 0x3f, 0x00, 0x0a, 0x01, 0x00,
285a4f6c 244 0xff, 1, 0x04, /* page 4 */
5a2e8d9f 245 0, LOAD_PAGE4, /* load the page 4 */
49b57dba 246 0x11, 1, 0x01,
5a2e8d9f 247 0, END_OF_SEQUENCE /* end of sequence */
49b57dba
JFM
248};
249
1408b847 250#define SKIP 0xaa
ff75e99c 251/* page 4 - the value SKIP says skip the index - see reg_w_page() */
49b57dba 252static const __u8 page4_7311[] = {
ff75e99c
MN
253 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
254 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
255 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
257 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
49b57dba
JFM
258 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
259 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
260};
261
14799f6c 262static void reg_w_buf(struct gspca_dev *gspca_dev,
49b57dba 263 __u8 index,
0aeb5ec7 264 const u8 *buffer, int len)
6a7eba24 265{
4f7309e2
MN
266 int ret;
267
14799f6c
JFM
268 if (gspca_dev->usb_err < 0)
269 return;
739570bb 270 memcpy(gspca_dev->usb_buf, buffer, len);
4f7309e2 271 ret = usb_control_msg(gspca_dev->dev,
739570bb 272 usb_sndctrlpipe(gspca_dev->dev, 0),
a1317135 273 0, /* request */
6a7eba24 274 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
bf7f0b98 275 0, /* value */
739570bb 276 index, gspca_dev->usb_buf, len,
6a7eba24 277 500);
14799f6c 278 if (ret < 0) {
0b656321
JFM
279 err("reg_w_buf() failed index 0x%02x, error %d",
280 index, ret);
14799f6c
JFM
281 gspca_dev->usb_err = ret;
282 }
6a7eba24
JFM
283}
284
6a7eba24 285
14799f6c 286static void reg_w(struct gspca_dev *gspca_dev,
49b57dba 287 __u8 index,
739570bb 288 __u8 value)
6a7eba24 289{
4f7309e2
MN
290 int ret;
291
14799f6c
JFM
292 if (gspca_dev->usb_err < 0)
293 return;
739570bb 294 gspca_dev->usb_buf[0] = value;
4f7309e2 295 ret = usb_control_msg(gspca_dev->dev,
739570bb 296 usb_sndctrlpipe(gspca_dev->dev, 0),
bf7f0b98
JFM
297 0, /* request */
298 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
8a5b2e90 299 0, index, gspca_dev->usb_buf, 1,
bf7f0b98 300 500);
14799f6c 301 if (ret < 0) {
0b656321
JFM
302 err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
303 index, value, ret);
14799f6c
JFM
304 gspca_dev->usb_err = ret;
305 }
6a7eba24
JFM
306}
307
14799f6c 308static void reg_w_seq(struct gspca_dev *gspca_dev,
49b57dba
JFM
309 const __u8 *seq, int len)
310{
311 while (--len >= 0) {
14799f6c 312 reg_w(gspca_dev, seq[0], seq[1]);
49b57dba
JFM
313 seq += 2;
314 }
315}
316
317/* load the beginning of a page */
14799f6c 318static void reg_w_page(struct gspca_dev *gspca_dev,
49b57dba
JFM
319 const __u8 *page, int len)
320{
321 int index;
b1784b33 322 int ret = 0;
49b57dba 323
14799f6c
JFM
324 if (gspca_dev->usb_err < 0)
325 return;
49b57dba 326 for (index = 0; index < len; index++) {
ff75e99c 327 if (page[index] == SKIP) /* skip this index */
49b57dba
JFM
328 continue;
329 gspca_dev->usb_buf[0] = page[index];
4f7309e2 330 ret = usb_control_msg(gspca_dev->dev,
49b57dba
JFM
331 usb_sndctrlpipe(gspca_dev->dev, 0),
332 0, /* request */
333 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
334 0, index, gspca_dev->usb_buf, 1,
335 500);
b1784b33 336 if (ret < 0) {
0b656321
JFM
337 err("reg_w_page() failed index 0x%02x, "
338 "value 0x%02x, error %d",
339 index, page[index], ret);
14799f6c 340 gspca_dev->usb_err = ret;
b1784b33
MN
341 break;
342 }
49b57dba
JFM
343 }
344}
345
346/* output a variable sequence */
14799f6c 347static void reg_w_var(struct gspca_dev *gspca_dev,
1408b847 348 const __u8 *seq,
1408b847 349 const __u8 *page4, unsigned int page4_len)
49b57dba
JFM
350{
351 int index, len;
352
353 for (;;) {
354 index = *seq++;
355 len = *seq++;
356 switch (len) {
5a2e8d9f 357 case END_OF_SEQUENCE:
14799f6c 358 return;
5a2e8d9f 359 case LOAD_PAGE4:
14799f6c 360 reg_w_page(gspca_dev, page4, page4_len);
49b57dba 361 break;
49b57dba 362 default:
24067bb5 363 if (len > USB_BUF_SZ) {
49b57dba
JFM
364 PDEBUG(D_ERR|D_STREAM,
365 "Incorrect variable sequence");
14799f6c 366 return;
49b57dba
JFM
367 }
368 while (len > 0) {
369 if (len < 8) {
14799f6c 370 reg_w_buf(gspca_dev,
b1784b33 371 index, seq, len);
49b57dba
JFM
372 seq += len;
373 break;
374 }
14799f6c 375 reg_w_buf(gspca_dev, index, seq, 8);
49b57dba
JFM
376 seq += 8;
377 index += 8;
378 len -= 8;
379 }
380 }
381 }
382 /* not reached */
383}
384
1408b847 385/* this function is called at probe time for pac7311 */
6a7eba24
JFM
386static int sd_config(struct gspca_dev *gspca_dev,
387 const struct usb_device_id *id)
388{
389 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
390 struct cam *cam;
391
6a7eba24 392 cam = &gspca_dev->cam;
49b57dba 393
1408b847
MN
394 PDEBUG(D_CONF, "Find Sensor PAC7311");
395 cam->cam_mode = vga_mode;
396 cam->nmodes = ARRAY_SIZE(vga_mode);
6a7eba24 397
a5ae2062 398 sd->contrast = CONTRAST_DEF;
8a5b2e90
HG
399 sd->gain = GAIN_DEF;
400 sd->exposure = EXPOSURE_DEF;
a5ae2062 401 sd->autogain = AUTOGAIN_DEF;
4a18625e
JFM
402 sd->hflip = HFLIP_DEF;
403 sd->vflip = VFLIP_DEF;
6a7eba24
JFM
404 return 0;
405}
406
8a5b2e90 407/* This function is used by pac7311 only */
14799f6c 408static void setcontrast(struct gspca_dev *gspca_dev)
6a7eba24
JFM
409{
410 struct sd *sd = (struct sd *) gspca_dev;
327c4abf 411
14799f6c
JFM
412 reg_w(gspca_dev, 0xff, 0x04);
413 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
6a7eba24 414 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 415 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
416}
417
14799f6c 418static void setgain(struct gspca_dev *gspca_dev)
6a7eba24
JFM
419{
420 struct sd *sd = (struct sd *) gspca_dev;
1408b847
MN
421 int gain = GAIN_MAX - sd->gain;
422
423 if (gain < 1)
424 gain = 1;
425 else if (gain > 245)
426 gain = 245;
14799f6c
JFM
427 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
428 reg_w(gspca_dev, 0x0e, 0x00);
429 reg_w(gspca_dev, 0x0f, gain);
6a7eba24 430
6a7eba24 431 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 432 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
433}
434
14799f6c 435static void setexposure(struct gspca_dev *gspca_dev)
6a7eba24
JFM
436{
437 struct sd *sd = (struct sd *) gspca_dev;
8a5b2e90
HG
438 __u8 reg;
439
440 /* register 2 of frame 3/4 contains the clock divider configuring the
441 no fps according to the formula: 60 / reg. sd->exposure is the
442 desired exposure time in ms. */
443 reg = 120 * sd->exposure / 1000;
444 if (reg < 2)
445 reg = 2;
446 else if (reg > 63)
447 reg = 63;
6a7eba24 448
14799f6c
JFM
449 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
450 reg_w(gspca_dev, 0x02, reg);
451
1408b847
MN
452 /* Page 1 register 8 must always be 0x08 except when not in
453 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
14799f6c 454 reg_w(gspca_dev, 0xff, 0x01);
1408b847 455 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
b1784b33 456 reg <= 3) {
14799f6c 457 reg_w(gspca_dev, 0x08, 0x09);
b1784b33 458 } else {
14799f6c 459 reg_w(gspca_dev, 0x08, 0x08);
b1784b33 460 }
1408b847 461
8a5b2e90 462 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 463 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
464}
465
14799f6c 466static void sethvflip(struct gspca_dev *gspca_dev)
41b46974
JFM
467{
468 struct sd *sd = (struct sd *) gspca_dev;
469 __u8 data;
470
14799f6c 471 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
1408b847 472 data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
14799f6c
JFM
473 reg_w(gspca_dev, 0x21, data);
474
8a5b2e90 475 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 476 reg_w(gspca_dev, 0x11, 0x01);
41b46974
JFM
477}
478
1408b847 479/* this function is called at probe and resume time for pac7311 */
012d6b02 480static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24 481{
14799f6c
JFM
482 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
483 return gspca_dev->usb_err;
6a7eba24
JFM
484}
485
72ab97ce 486static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24 487{
e52a5574
JFM
488 struct sd *sd = (struct sd *) gspca_dev;
489
327c4abf 490 sd->sof_read = 0;
739570bb 491
14799f6c 492 reg_w_var(gspca_dev, start_7311,
1408b847 493 page4_7311, sizeof(page4_7311));
14799f6c
JFM
494 setcontrast(gspca_dev);
495 setgain(gspca_dev);
496 setexposure(gspca_dev);
497 sethvflip(gspca_dev);
6a7eba24
JFM
498
499 /* set correct resolution */
c2446b3e 500 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
49b57dba 501 case 2: /* 160x120 pac7311 */
14799f6c
JFM
502 reg_w(gspca_dev, 0xff, 0x01);
503 reg_w(gspca_dev, 0x17, 0x20);
504 reg_w(gspca_dev, 0x87, 0x10);
6a7eba24 505 break;
49b57dba 506 case 1: /* 320x240 pac7311 */
14799f6c
JFM
507 reg_w(gspca_dev, 0xff, 0x01);
508 reg_w(gspca_dev, 0x17, 0x30);
509 reg_w(gspca_dev, 0x87, 0x11);
6a7eba24
JFM
510 break;
511 case 0: /* 640x480 */
14799f6c
JFM
512 reg_w(gspca_dev, 0xff, 0x01);
513 reg_w(gspca_dev, 0x17, 0x00);
514 reg_w(gspca_dev, 0x87, 0x12);
6a7eba24
JFM
515 break;
516 }
517
327c4abf
HG
518 sd->sof_read = 0;
519 sd->autogain_ignore_frames = 0;
520 atomic_set(&sd->avg_lum, -1);
8a5b2e90
HG
521
522 /* start stream */
14799f6c
JFM
523 reg_w(gspca_dev, 0xff, 0x01);
524 reg_w(gspca_dev, 0x78, 0x05);
1408b847 525
14799f6c 526 return gspca_dev->usb_err;
6a7eba24
JFM
527}
528
529static void sd_stopN(struct gspca_dev *gspca_dev)
530{
14799f6c
JFM
531 reg_w(gspca_dev, 0xff, 0x04);
532 reg_w(gspca_dev, 0x27, 0x80);
533 reg_w(gspca_dev, 0x28, 0xca);
534 reg_w(gspca_dev, 0x29, 0x53);
535 reg_w(gspca_dev, 0x2a, 0x0e);
536 reg_w(gspca_dev, 0xff, 0x01);
537 reg_w(gspca_dev, 0x3e, 0x20);
538 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
539 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
540 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
6a7eba24
JFM
541}
542
1408b847 543/* called on streamoff with alt 0 and on disconnect for 7311 */
6a7eba24
JFM
544static void sd_stop0(struct gspca_dev *gspca_dev)
545{
546}
547
8a5b2e90
HG
548/* Include pac common sof detection functions */
549#include "pac_common.h"
550
cebf3b67 551static void do_autogain(struct gspca_dev *gspca_dev)
6a7eba24 552{
8a5b2e90
HG
553 struct sd *sd = (struct sd *) gspca_dev;
554 int avg_lum = atomic_read(&sd->avg_lum);
038ec7c7 555 int desired_lum, deadzone;
8a5b2e90
HG
556
557 if (avg_lum == -1)
558 return;
559
1408b847
MN
560 desired_lum = 200;
561 deadzone = 20;
8a5b2e90
HG
562
563 if (sd->autogain_ignore_frames > 0)
564 sd->autogain_ignore_frames--;
565 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
038ec7c7 566 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
8a5b2e90 567 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
6a7eba24
JFM
568}
569
56f6f558 570/* JPEG header, part 1 */
cc409c0e 571static const unsigned char pac_jpeg_header1[] = {
56f6f558
MN
572 0xff, 0xd8, /* SOI: Start of Image */
573
574 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
575 0x00, 0x11, /* length = 17 bytes (including this length field) */
576 0x08 /* Precision: 8 */
577 /* 2 bytes is placed here: number of image lines */
578 /* 2 bytes is placed here: samples per line */
327c4abf
HG
579};
580
56f6f558 581/* JPEG header, continued */
cc409c0e 582static const unsigned char pac_jpeg_header2[] = {
56f6f558
MN
583 0x03, /* Number of image components: 3 */
584 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
585 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
586 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
587
588 0xff, 0xda, /* SOS: Start Of Scan */
589 0x00, 0x0c, /* length = 12 bytes (including this length field) */
590 0x03, /* number of components: 3 */
591 0x01, 0x00, /* selector 1, table 0x00 */
592 0x02, 0x11, /* selector 2, table 0x11 */
593 0x03, 0x11, /* selector 3, table 0x11 */
594 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
595 0x00 /* Successive approximation: 0 */
327c4abf
HG
596};
597
cc409c0e 598static void pac_start_frame(struct gspca_dev *gspca_dev,
cc409c0e
MN
599 __u16 lines, __u16 samples_per_line)
600{
601 unsigned char tmpbuf[4];
602
76dd272b 603 gspca_frame_add(gspca_dev, FIRST_PACKET,
cc409c0e
MN
604 pac_jpeg_header1, sizeof(pac_jpeg_header1));
605
606 tmpbuf[0] = lines >> 8;
607 tmpbuf[1] = lines & 0xff;
608 tmpbuf[2] = samples_per_line >> 8;
609 tmpbuf[3] = samples_per_line & 0xff;
610
76dd272b 611 gspca_frame_add(gspca_dev, INTER_PACKET,
cc409c0e 612 tmpbuf, sizeof(tmpbuf));
76dd272b 613 gspca_frame_add(gspca_dev, INTER_PACKET,
cc409c0e
MN
614 pac_jpeg_header2, sizeof(pac_jpeg_header2));
615}
616
e52a5574 617/* this function is run at interrupt level */
6a7eba24 618static void sd_pkt_scan(struct gspca_dev *gspca_dev,
76dd272b 619 u8 *data, /* isoc packet */
6a7eba24
JFM
620 int len) /* iso packet length */
621{
622 struct sd *sd = (struct sd *) gspca_dev;
b192ca98 623 u8 *image;
327c4abf
HG
624 unsigned char *sof;
625
a6b69e40 626 sof = pac_find_sof(&sd->sof_read, data, len);
327c4abf 627 if (sof) {
327c4abf
HG
628 int n, lum_offset, footer_length;
629
1408b847
MN
630 /* 6 bytes after the FF D9 EOF marker a number of lumination
631 bytes are send corresponding to different parts of the
632 image, the 14th and 15th byte after the EOF seem to
633 correspond to the center of the image */
634 lum_offset = 24 + sizeof pac_sof_marker;
635 footer_length = 26;
327c4abf
HG
636
637 /* Finish decoding current frame */
638 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
639 if (n < 0) {
b192ca98 640 gspca_dev->image_len += n;
327c4abf 641 n = 0;
b192ca98
JFM
642 } else {
643 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
327c4abf 644 }
f7059eaa
JFM
645 image = gspca_dev->image;
646 if (image != NULL
b192ca98
JFM
647 && image[gspca_dev->image_len - 2] == 0xff
648 && image[gspca_dev->image_len - 1] == 0xd9)
649 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
327c4abf
HG
650
651 n = sof - data;
652 len -= n;
653 data = sof;
654
655 /* Get average lumination */
656 if (gspca_dev->last_packet_type == LAST_PACKET &&
038ec7c7
HG
657 n >= lum_offset)
658 atomic_set(&sd->avg_lum, data[-lum_offset] +
327c4abf 659 data[-lum_offset + 1]);
038ec7c7 660 else
327c4abf 661 atomic_set(&sd->avg_lum, -1);
327c4abf
HG
662
663 /* Start the new frame with the jpeg header */
b192ca98 664 pac_start_frame(gspca_dev,
1408b847 665 gspca_dev->height, gspca_dev->width);
6a7eba24 666 }
76dd272b 667 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6a7eba24
JFM
668}
669
6a7eba24
JFM
670static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673
674 sd->contrast = val;
780e3121 675 if (gspca_dev->streaming)
1408b847 676 setcontrast(gspca_dev);
14799f6c 677 return gspca_dev->usb_err;
6a7eba24
JFM
678}
679
680static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683
6a7eba24
JFM
684 *val = sd->contrast;
685 return 0;
686}
687
8a5b2e90
HG
688static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691
692 sd->gain = val;
693 if (gspca_dev->streaming)
694 setgain(gspca_dev);
14799f6c 695 return gspca_dev->usb_err;
8a5b2e90
HG
696}
697
698static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
699{
700 struct sd *sd = (struct sd *) gspca_dev;
701
702 *val = sd->gain;
703 return 0;
704}
705
706static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
707{
708 struct sd *sd = (struct sd *) gspca_dev;
709
710 sd->exposure = val;
711 if (gspca_dev->streaming)
712 setexposure(gspca_dev);
14799f6c 713 return gspca_dev->usb_err;
8a5b2e90
HG
714}
715
716static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719
720 *val = sd->exposure;
721 return 0;
722}
723
6a7eba24
JFM
724static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
725{
726 struct sd *sd = (struct sd *) gspca_dev;
727
728 sd->autogain = val;
8a5b2e90
HG
729 /* when switching to autogain set defaults to make sure
730 we are on a valid point of the autogain gain /
731 exposure knee graph, and give this change time to
732 take effect before doing autogain. */
733 if (sd->autogain) {
734 sd->exposure = EXPOSURE_DEF;
735 sd->gain = GAIN_DEF;
736 if (gspca_dev->streaming) {
737 sd->autogain_ignore_frames =
738 PAC_AUTOGAIN_IGNORE_FRAMES;
739 setexposure(gspca_dev);
740 setgain(gspca_dev);
741 }
742 }
327c4abf 743
14799f6c 744 return gspca_dev->usb_err;
6a7eba24
JFM
745}
746
747static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
748{
749 struct sd *sd = (struct sd *) gspca_dev;
750
751 *val = sd->autogain;
752 return 0;
753}
754
41b46974
JFM
755static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
756{
757 struct sd *sd = (struct sd *) gspca_dev;
758
759 sd->hflip = val;
760 if (gspca_dev->streaming)
761 sethvflip(gspca_dev);
14799f6c 762 return gspca_dev->usb_err;
41b46974
JFM
763}
764
765static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768
769 *val = sd->hflip;
770 return 0;
771}
772
773static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
774{
775 struct sd *sd = (struct sd *) gspca_dev;
776
777 sd->vflip = val;
778 if (gspca_dev->streaming)
779 sethvflip(gspca_dev);
14799f6c 780 return gspca_dev->usb_err;
41b46974
JFM
781}
782
783static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 *val = sd->vflip;
788 return 0;
789}
790
2856643e 791#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
32ea3e44
HG
792static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
793 u8 *data, /* interrupt packet data */
794 int len) /* interrupt packet length */
795{
796 int ret = -EINVAL;
797 u8 data0, data1;
798
799 if (len == 2) {
800 data0 = data[0];
801 data1 = data[1];
802 if ((data0 == 0x00 && data1 == 0x11) ||
803 (data0 == 0x22 && data1 == 0x33) ||
804 (data0 == 0x44 && data1 == 0x55) ||
805 (data0 == 0x66 && data1 == 0x77) ||
806 (data0 == 0x88 && data1 == 0x99) ||
807 (data0 == 0xaa && data1 == 0xbb) ||
808 (data0 == 0xcc && data1 == 0xdd) ||
809 (data0 == 0xee && data1 == 0xff)) {
810 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
811 input_sync(gspca_dev->input_dev);
812 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
813 input_sync(gspca_dev->input_dev);
814 ret = 0;
815 }
816 }
817
818 return ret;
819}
820#endif
821
1408b847 822/* sub-driver description for pac7311 */
aabcdfb6 823static const struct sd_desc sd_desc = {
6a7eba24
JFM
824 .name = MODULE_NAME,
825 .ctrls = sd_ctrls,
826 .nctrls = ARRAY_SIZE(sd_ctrls),
827 .config = sd_config,
012d6b02 828 .init = sd_init,
6a7eba24
JFM
829 .start = sd_start,
830 .stopN = sd_stopN,
831 .stop0 = sd_stop0,
6a7eba24 832 .pkt_scan = sd_pkt_scan,
cebf3b67 833 .dq_callback = do_autogain,
2856643e 834#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
32ea3e44
HG
835 .int_pkt_scan = sd_int_pkt_scan,
836#endif
6a7eba24
JFM
837};
838
839/* -- module initialisation -- */
95c967c1 840static const struct usb_device_id device_table[] = {
1408b847
MN
841 {USB_DEVICE(0x093a, 0x2600)},
842 {USB_DEVICE(0x093a, 0x2601)},
843 {USB_DEVICE(0x093a, 0x2603)},
844 {USB_DEVICE(0x093a, 0x2608)},
845 {USB_DEVICE(0x093a, 0x260e)},
846 {USB_DEVICE(0x093a, 0x260f)},
6a7eba24
JFM
847 {}
848};
849MODULE_DEVICE_TABLE(usb, device_table);
850
851/* -- device connect -- */
95c967c1 852static int sd_probe(struct usb_interface *intf,
6a7eba24
JFM
853 const struct usb_device_id *id)
854{
855 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
856 THIS_MODULE);
857}
858
859static struct usb_driver sd_driver = {
860 .name = MODULE_NAME,
861 .id_table = device_table,
862 .probe = sd_probe,
863 .disconnect = gspca_disconnect,
6a709749
JFM
864#ifdef CONFIG_PM
865 .suspend = gspca_suspend,
866 .resume = gspca_resume,
867#endif
6a7eba24
JFM
868};
869
870/* -- module insert / remove -- */
871static int __init sd_mod_init(void)
872{
54826437 873 return usb_register(&sd_driver);
6a7eba24
JFM
874}
875static void __exit sd_mod_exit(void)
876{
877 usb_deregister(&sd_driver);
6a7eba24
JFM
878}
879
880module_init(sd_mod_init);
881module_exit(sd_mod_exit);
This page took 0.400486 seconds and 5 git commands to generate.