Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/pac7311.c
17613 views
1
/*
2
* Pixart PAC7311 library
3
* Copyright (C) 2005 Thomas Kaiser [email protected]
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
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
42
the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
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
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.
50
*/
51
52
#define MODULE_NAME "pac7311"
53
54
#include <linux/input.h>
55
#include "gspca.h"
56
57
MODULE_AUTHOR("Thomas Kaiser [email protected]");
58
MODULE_DESCRIPTION("Pixart PAC7311");
59
MODULE_LICENSE("GPL");
60
61
/* specific webcam descriptor for pac7311 */
62
struct sd {
63
struct gspca_dev gspca_dev; /* !! must be the first item */
64
65
unsigned char contrast;
66
unsigned char gain;
67
unsigned char exposure;
68
unsigned char autogain;
69
__u8 hflip;
70
__u8 vflip;
71
72
u8 sof_read;
73
u8 autogain_ignore_frames;
74
75
atomic_t avg_lum;
76
};
77
78
/* V4L2 controls supported by the driver */
79
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83
static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
84
static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
85
static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
86
static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
87
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89
static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
91
92
static const struct ctrl sd_ctrls[] = {
93
/* This control is for both the 7302 and the 7311 */
94
{
95
{
96
.id = V4L2_CID_CONTRAST,
97
.type = V4L2_CTRL_TYPE_INTEGER,
98
.name = "Contrast",
99
.minimum = 0,
100
#define CONTRAST_MAX 255
101
.maximum = CONTRAST_MAX,
102
.step = 1,
103
#define CONTRAST_DEF 127
104
.default_value = CONTRAST_DEF,
105
},
106
.set = sd_setcontrast,
107
.get = sd_getcontrast,
108
},
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
},
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,
150
#define AUTOGAIN_DEF 1
151
.default_value = AUTOGAIN_DEF,
152
},
153
.set = sd_setautogain,
154
.get = sd_getautogain,
155
},
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
},
184
};
185
186
static const struct v4l2_pix_format vga_mode[] = {
187
{160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
188
.bytesperline = 160,
189
.sizeimage = 160 * 120 * 3 / 8 + 590,
190
.colorspace = V4L2_COLORSPACE_JPEG,
191
.priv = 2},
192
{320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
193
.bytesperline = 320,
194
.sizeimage = 320 * 240 * 3 / 8 + 590,
195
.colorspace = V4L2_COLORSPACE_JPEG,
196
.priv = 1},
197
{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
198
.bytesperline = 640,
199
.sizeimage = 640 * 480 * 3 / 8 + 590,
200
.colorspace = V4L2_COLORSPACE_JPEG,
201
.priv = 0},
202
};
203
204
#define LOAD_PAGE4 254
205
#define END_OF_SEQUENCE 0
206
207
/* pac 7311 */
208
static const __u8 init_7311[] = {
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 */
212
0xff, 0x04,
213
0x27, 0x80,
214
0x28, 0xca,
215
0x29, 0x53,
216
0x2a, 0x0e,
217
0xff, 0x01,
218
0x3e, 0x20,
219
};
220
221
static const __u8 start_7311[] = {
222
/* index, len, [value]* */
223
0xff, 1, 0x01, /* page 1 */
224
0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
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,
230
0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
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,
244
0xff, 1, 0x04, /* page 4 */
245
0, LOAD_PAGE4, /* load the page 4 */
246
0x11, 1, 0x01,
247
0, END_OF_SEQUENCE /* end of sequence */
248
};
249
250
#define SKIP 0xaa
251
/* page 4 - the value SKIP says skip the index - see reg_w_page() */
252
static const __u8 page4_7311[] = {
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,
258
0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
259
0x23, 0x28, 0x04, 0x11, 0x00, 0x00
260
};
261
262
static void reg_w_buf(struct gspca_dev *gspca_dev,
263
__u8 index,
264
const u8 *buffer, int len)
265
{
266
int ret;
267
268
if (gspca_dev->usb_err < 0)
269
return;
270
memcpy(gspca_dev->usb_buf, buffer, len);
271
ret = usb_control_msg(gspca_dev->dev,
272
usb_sndctrlpipe(gspca_dev->dev, 0),
273
0, /* request */
274
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
275
0, /* value */
276
index, gspca_dev->usb_buf, len,
277
500);
278
if (ret < 0) {
279
err("reg_w_buf() failed index 0x%02x, error %d",
280
index, ret);
281
gspca_dev->usb_err = ret;
282
}
283
}
284
285
286
static void reg_w(struct gspca_dev *gspca_dev,
287
__u8 index,
288
__u8 value)
289
{
290
int ret;
291
292
if (gspca_dev->usb_err < 0)
293
return;
294
gspca_dev->usb_buf[0] = value;
295
ret = usb_control_msg(gspca_dev->dev,
296
usb_sndctrlpipe(gspca_dev->dev, 0),
297
0, /* request */
298
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
299
0, index, gspca_dev->usb_buf, 1,
300
500);
301
if (ret < 0) {
302
err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
303
index, value, ret);
304
gspca_dev->usb_err = ret;
305
}
306
}
307
308
static void reg_w_seq(struct gspca_dev *gspca_dev,
309
const __u8 *seq, int len)
310
{
311
while (--len >= 0) {
312
reg_w(gspca_dev, seq[0], seq[1]);
313
seq += 2;
314
}
315
}
316
317
/* load the beginning of a page */
318
static void reg_w_page(struct gspca_dev *gspca_dev,
319
const __u8 *page, int len)
320
{
321
int index;
322
int ret = 0;
323
324
if (gspca_dev->usb_err < 0)
325
return;
326
for (index = 0; index < len; index++) {
327
if (page[index] == SKIP) /* skip this index */
328
continue;
329
gspca_dev->usb_buf[0] = page[index];
330
ret = usb_control_msg(gspca_dev->dev,
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);
336
if (ret < 0) {
337
err("reg_w_page() failed index 0x%02x, "
338
"value 0x%02x, error %d",
339
index, page[index], ret);
340
gspca_dev->usb_err = ret;
341
break;
342
}
343
}
344
}
345
346
/* output a variable sequence */
347
static void reg_w_var(struct gspca_dev *gspca_dev,
348
const __u8 *seq,
349
const __u8 *page4, unsigned int page4_len)
350
{
351
int index, len;
352
353
for (;;) {
354
index = *seq++;
355
len = *seq++;
356
switch (len) {
357
case END_OF_SEQUENCE:
358
return;
359
case LOAD_PAGE4:
360
reg_w_page(gspca_dev, page4, page4_len);
361
break;
362
default:
363
if (len > USB_BUF_SZ) {
364
PDEBUG(D_ERR|D_STREAM,
365
"Incorrect variable sequence");
366
return;
367
}
368
while (len > 0) {
369
if (len < 8) {
370
reg_w_buf(gspca_dev,
371
index, seq, len);
372
seq += len;
373
break;
374
}
375
reg_w_buf(gspca_dev, index, seq, 8);
376
seq += 8;
377
index += 8;
378
len -= 8;
379
}
380
}
381
}
382
/* not reached */
383
}
384
385
/* this function is called at probe time for pac7311 */
386
static int sd_config(struct gspca_dev *gspca_dev,
387
const struct usb_device_id *id)
388
{
389
struct sd *sd = (struct sd *) gspca_dev;
390
struct cam *cam;
391
392
cam = &gspca_dev->cam;
393
394
PDEBUG(D_CONF, "Find Sensor PAC7311");
395
cam->cam_mode = vga_mode;
396
cam->nmodes = ARRAY_SIZE(vga_mode);
397
398
sd->contrast = CONTRAST_DEF;
399
sd->gain = GAIN_DEF;
400
sd->exposure = EXPOSURE_DEF;
401
sd->autogain = AUTOGAIN_DEF;
402
sd->hflip = HFLIP_DEF;
403
sd->vflip = VFLIP_DEF;
404
return 0;
405
}
406
407
/* This function is used by pac7311 only */
408
static void setcontrast(struct gspca_dev *gspca_dev)
409
{
410
struct sd *sd = (struct sd *) gspca_dev;
411
412
reg_w(gspca_dev, 0xff, 0x04);
413
reg_w(gspca_dev, 0x10, sd->contrast >> 4);
414
/* load registers to sensor (Bit 0, auto clear) */
415
reg_w(gspca_dev, 0x11, 0x01);
416
}
417
418
static void setgain(struct gspca_dev *gspca_dev)
419
{
420
struct sd *sd = (struct sd *) gspca_dev;
421
int gain = GAIN_MAX - sd->gain;
422
423
if (gain < 1)
424
gain = 1;
425
else if (gain > 245)
426
gain = 245;
427
reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
428
reg_w(gspca_dev, 0x0e, 0x00);
429
reg_w(gspca_dev, 0x0f, gain);
430
431
/* load registers to sensor (Bit 0, auto clear) */
432
reg_w(gspca_dev, 0x11, 0x01);
433
}
434
435
static void setexposure(struct gspca_dev *gspca_dev)
436
{
437
struct sd *sd = (struct sd *) gspca_dev;
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;
448
449
reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
450
reg_w(gspca_dev, 0x02, reg);
451
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 */
454
reg_w(gspca_dev, 0xff, 0x01);
455
if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
456
reg <= 3) {
457
reg_w(gspca_dev, 0x08, 0x09);
458
} else {
459
reg_w(gspca_dev, 0x08, 0x08);
460
}
461
462
/* load registers to sensor (Bit 0, auto clear) */
463
reg_w(gspca_dev, 0x11, 0x01);
464
}
465
466
static void sethvflip(struct gspca_dev *gspca_dev)
467
{
468
struct sd *sd = (struct sd *) gspca_dev;
469
__u8 data;
470
471
reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
472
data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
473
reg_w(gspca_dev, 0x21, data);
474
475
/* load registers to sensor (Bit 0, auto clear) */
476
reg_w(gspca_dev, 0x11, 0x01);
477
}
478
479
/* this function is called at probe and resume time for pac7311 */
480
static int sd_init(struct gspca_dev *gspca_dev)
481
{
482
reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
483
return gspca_dev->usb_err;
484
}
485
486
static int sd_start(struct gspca_dev *gspca_dev)
487
{
488
struct sd *sd = (struct sd *) gspca_dev;
489
490
sd->sof_read = 0;
491
492
reg_w_var(gspca_dev, start_7311,
493
page4_7311, sizeof(page4_7311));
494
setcontrast(gspca_dev);
495
setgain(gspca_dev);
496
setexposure(gspca_dev);
497
sethvflip(gspca_dev);
498
499
/* set correct resolution */
500
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
501
case 2: /* 160x120 pac7311 */
502
reg_w(gspca_dev, 0xff, 0x01);
503
reg_w(gspca_dev, 0x17, 0x20);
504
reg_w(gspca_dev, 0x87, 0x10);
505
break;
506
case 1: /* 320x240 pac7311 */
507
reg_w(gspca_dev, 0xff, 0x01);
508
reg_w(gspca_dev, 0x17, 0x30);
509
reg_w(gspca_dev, 0x87, 0x11);
510
break;
511
case 0: /* 640x480 */
512
reg_w(gspca_dev, 0xff, 0x01);
513
reg_w(gspca_dev, 0x17, 0x00);
514
reg_w(gspca_dev, 0x87, 0x12);
515
break;
516
}
517
518
sd->sof_read = 0;
519
sd->autogain_ignore_frames = 0;
520
atomic_set(&sd->avg_lum, -1);
521
522
/* start stream */
523
reg_w(gspca_dev, 0xff, 0x01);
524
reg_w(gspca_dev, 0x78, 0x05);
525
526
return gspca_dev->usb_err;
527
}
528
529
static void sd_stopN(struct gspca_dev *gspca_dev)
530
{
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 */
541
}
542
543
/* called on streamoff with alt 0 and on disconnect for 7311 */
544
static void sd_stop0(struct gspca_dev *gspca_dev)
545
{
546
}
547
548
/* Include pac common sof detection functions */
549
#include "pac_common.h"
550
551
static void do_autogain(struct gspca_dev *gspca_dev)
552
{
553
struct sd *sd = (struct sd *) gspca_dev;
554
int avg_lum = atomic_read(&sd->avg_lum);
555
int desired_lum, deadzone;
556
557
if (avg_lum == -1)
558
return;
559
560
desired_lum = 200;
561
deadzone = 20;
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,
566
deadzone, GAIN_KNEE, EXPOSURE_KNEE))
567
sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
568
}
569
570
/* JPEG header, part 1 */
571
static const unsigned char pac_jpeg_header1[] = {
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 */
579
};
580
581
/* JPEG header, continued */
582
static const unsigned char pac_jpeg_header2[] = {
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 */
596
};
597
598
static void pac_start_frame(struct gspca_dev *gspca_dev,
599
__u16 lines, __u16 samples_per_line)
600
{
601
unsigned char tmpbuf[4];
602
603
gspca_frame_add(gspca_dev, FIRST_PACKET,
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
611
gspca_frame_add(gspca_dev, INTER_PACKET,
612
tmpbuf, sizeof(tmpbuf));
613
gspca_frame_add(gspca_dev, INTER_PACKET,
614
pac_jpeg_header2, sizeof(pac_jpeg_header2));
615
}
616
617
/* this function is run at interrupt level */
618
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
619
u8 *data, /* isoc packet */
620
int len) /* iso packet length */
621
{
622
struct sd *sd = (struct sd *) gspca_dev;
623
u8 *image;
624
unsigned char *sof;
625
626
sof = pac_find_sof(&sd->sof_read, data, len);
627
if (sof) {
628
int n, lum_offset, footer_length;
629
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;
636
637
/* Finish decoding current frame */
638
n = (sof - data) - (footer_length + sizeof pac_sof_marker);
639
if (n < 0) {
640
gspca_dev->image_len += n;
641
n = 0;
642
} else {
643
gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
644
}
645
image = gspca_dev->image;
646
if (image != NULL
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);
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 &&
657
n >= lum_offset)
658
atomic_set(&sd->avg_lum, data[-lum_offset] +
659
data[-lum_offset + 1]);
660
else
661
atomic_set(&sd->avg_lum, -1);
662
663
/* Start the new frame with the jpeg header */
664
pac_start_frame(gspca_dev,
665
gspca_dev->height, gspca_dev->width);
666
}
667
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
668
}
669
670
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
671
{
672
struct sd *sd = (struct sd *) gspca_dev;
673
674
sd->contrast = val;
675
if (gspca_dev->streaming)
676
setcontrast(gspca_dev);
677
return gspca_dev->usb_err;
678
}
679
680
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
681
{
682
struct sd *sd = (struct sd *) gspca_dev;
683
684
*val = sd->contrast;
685
return 0;
686
}
687
688
static 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);
695
return gspca_dev->usb_err;
696
}
697
698
static 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
706
static 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);
713
return gspca_dev->usb_err;
714
}
715
716
static 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
724
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
725
{
726
struct sd *sd = (struct sd *) gspca_dev;
727
728
sd->autogain = val;
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
}
743
744
return gspca_dev->usb_err;
745
}
746
747
static 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
755
static 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);
762
return gspca_dev->usb_err;
763
}
764
765
static 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
773
static 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);
780
return gspca_dev->usb_err;
781
}
782
783
static 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
791
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
792
static 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
822
/* sub-driver description for pac7311 */
823
static const struct sd_desc sd_desc = {
824
.name = MODULE_NAME,
825
.ctrls = sd_ctrls,
826
.nctrls = ARRAY_SIZE(sd_ctrls),
827
.config = sd_config,
828
.init = sd_init,
829
.start = sd_start,
830
.stopN = sd_stopN,
831
.stop0 = sd_stop0,
832
.pkt_scan = sd_pkt_scan,
833
.dq_callback = do_autogain,
834
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
835
.int_pkt_scan = sd_int_pkt_scan,
836
#endif
837
};
838
839
/* -- module initialisation -- */
840
static const struct usb_device_id device_table[] = {
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)},
847
{}
848
};
849
MODULE_DEVICE_TABLE(usb, device_table);
850
851
/* -- device connect -- */
852
static int sd_probe(struct usb_interface *intf,
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
859
static struct usb_driver sd_driver = {
860
.name = MODULE_NAME,
861
.id_table = device_table,
862
.probe = sd_probe,
863
.disconnect = gspca_disconnect,
864
#ifdef CONFIG_PM
865
.suspend = gspca_suspend,
866
.resume = gspca_resume,
867
#endif
868
};
869
870
/* -- module insert / remove -- */
871
static int __init sd_mod_init(void)
872
{
873
return usb_register(&sd_driver);
874
}
875
static void __exit sd_mod_exit(void)
876
{
877
usb_deregister(&sd_driver);
878
}
879
880
module_init(sd_mod_init);
881
module_exit(sd_mod_exit);
882
883