1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
61
62#define MODULE_NAME "pac7311"
63
64#include <linux/input.h>
65#include "gspca.h"
66
67#include "pac_common.h"
68
69#define PAC7311_GAIN_DEFAULT 122
70#define PAC7311_EXPOSURE_DEFAULT 3
71
72MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
73MODULE_DESCRIPTION("Pixart PAC7311");
74MODULE_LICENSE("GPL");
75
76struct sd {
77 struct gspca_dev gspca_dev;
78
79 struct v4l2_ctrl *contrast;
80 struct v4l2_ctrl *hflip;
81
82 u8 sof_read;
83 u8 autogain_ignore_frames;
84
85 atomic_t avg_lum;
86};
87
88static const struct v4l2_pix_format vga_mode[] = {
89 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
90 .bytesperline = 160,
91 .sizeimage = 160 * 120 * 3 / 8 + 590,
92 .colorspace = V4L2_COLORSPACE_JPEG,
93 .priv = 2},
94 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
95 .bytesperline = 320,
96 .sizeimage = 320 * 240 * 3 / 8 + 590,
97 .colorspace = V4L2_COLORSPACE_JPEG,
98 .priv = 1},
99 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
100 .bytesperline = 640,
101 .sizeimage = 640 * 480 * 3 / 8 + 590,
102 .colorspace = V4L2_COLORSPACE_JPEG,
103 .priv = 0},
104};
105
106#define LOAD_PAGE4 254
107#define END_OF_SEQUENCE 0
108
109static const __u8 init_7311[] = {
110 0xff, 0x01,
111 0x78, 0x40,
112 0x78, 0x40,
113 0x78, 0x44,
114 0xff, 0x04,
115 0x27, 0x80,
116 0x28, 0xca,
117 0x29, 0x53,
118 0x2a, 0x0e,
119 0xff, 0x01,
120 0x3e, 0x20,
121};
122
123static const __u8 start_7311[] = {
124
125 0xff, 1, 0x01,
126 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
127 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
128 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
129 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00,
132 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
133 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
134 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
135 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
136 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
137 0xd0, 0xff,
138 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
139 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
140 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
141 0x18, 0x20,
142 0x96, 3, 0x01, 0x08, 0x04,
143 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
144 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
145 0x3f, 0x00, 0x0a, 0x01, 0x00,
146 0xff, 1, 0x04,
147 0, LOAD_PAGE4,
148 0x11, 1, 0x01,
149 0, END_OF_SEQUENCE
150};
151
152#define SKIP 0xaa
153
154static const __u8 page4_7311[] = {
155 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
156 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
157 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
159 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
160 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
161 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
162};
163
164static void reg_w_buf(struct gspca_dev *gspca_dev,
165 __u8 index,
166 const u8 *buffer, int len)
167{
168 int ret;
169
170 if (gspca_dev->usb_err < 0)
171 return;
172 memcpy(gspca_dev->usb_buf, buffer, len);
173 ret = usb_control_msg(gspca_dev->dev,
174 usb_sndctrlpipe(gspca_dev->dev, 0),
175 0,
176 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
177 0,
178 index, gspca_dev->usb_buf, len,
179 500);
180 if (ret < 0) {
181 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
182 index, ret);
183 gspca_dev->usb_err = ret;
184 }
185}
186
187
188static void reg_w(struct gspca_dev *gspca_dev,
189 __u8 index,
190 __u8 value)
191{
192 int ret;
193
194 if (gspca_dev->usb_err < 0)
195 return;
196 gspca_dev->usb_buf[0] = value;
197 ret = usb_control_msg(gspca_dev->dev,
198 usb_sndctrlpipe(gspca_dev->dev, 0),
199 0,
200 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
201 0, index, gspca_dev->usb_buf, 1,
202 500);
203 if (ret < 0) {
204 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
205 index, value, ret);
206 gspca_dev->usb_err = ret;
207 }
208}
209
210static void reg_w_seq(struct gspca_dev *gspca_dev,
211 const __u8 *seq, int len)
212{
213 while (--len >= 0) {
214 reg_w(gspca_dev, seq[0], seq[1]);
215 seq += 2;
216 }
217}
218
219
220static void reg_w_page(struct gspca_dev *gspca_dev,
221 const __u8 *page, int len)
222{
223 int index;
224 int ret = 0;
225
226 if (gspca_dev->usb_err < 0)
227 return;
228 for (index = 0; index < len; index++) {
229 if (page[index] == SKIP)
230 continue;
231 gspca_dev->usb_buf[0] = page[index];
232 ret = usb_control_msg(gspca_dev->dev,
233 usb_sndctrlpipe(gspca_dev->dev, 0),
234 0,
235 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236 0, index, gspca_dev->usb_buf, 1,
237 500);
238 if (ret < 0) {
239 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
240 index, page[index], ret);
241 gspca_dev->usb_err = ret;
242 break;
243 }
244 }
245}
246
247
248static void reg_w_var(struct gspca_dev *gspca_dev,
249 const __u8 *seq,
250 const __u8 *page4, unsigned int page4_len)
251{
252 int index, len;
253
254 for (;;) {
255 index = *seq++;
256 len = *seq++;
257 switch (len) {
258 case END_OF_SEQUENCE:
259 return;
260 case LOAD_PAGE4:
261 reg_w_page(gspca_dev, page4, page4_len);
262 break;
263 default:
264 if (len > USB_BUF_SZ) {
265 PDEBUG(D_ERR|D_STREAM,
266 "Incorrect variable sequence");
267 return;
268 }
269 while (len > 0) {
270 if (len < 8) {
271 reg_w_buf(gspca_dev,
272 index, seq, len);
273 seq += len;
274 break;
275 }
276 reg_w_buf(gspca_dev, index, seq, 8);
277 seq += 8;
278 index += 8;
279 len -= 8;
280 }
281 }
282 }
283
284}
285
286
287static int sd_config(struct gspca_dev *gspca_dev,
288 const struct usb_device_id *id)
289{
290 struct cam *cam = &gspca_dev->cam;
291
292 cam->cam_mode = vga_mode;
293 cam->nmodes = ARRAY_SIZE(vga_mode);
294 cam->input_flags = V4L2_IN_ST_VFLIP;
295
296 return 0;
297}
298
299static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
300{
301 reg_w(gspca_dev, 0xff, 0x04);
302 reg_w(gspca_dev, 0x10, val);
303
304 reg_w(gspca_dev, 0x11, 0x01);
305}
306
307static void setgain(struct gspca_dev *gspca_dev, s32 val)
308{
309 reg_w(gspca_dev, 0xff, 0x04);
310 reg_w(gspca_dev, 0x0e, 0x00);
311 reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
312
313
314 reg_w(gspca_dev, 0x11, 0x01);
315}
316
317static void setexposure(struct gspca_dev *gspca_dev, s32 val)
318{
319 reg_w(gspca_dev, 0xff, 0x04);
320 reg_w(gspca_dev, 0x02, val);
321
322
323 reg_w(gspca_dev, 0x11, 0x01);
324
325
326
327
328
329 reg_w(gspca_dev, 0xff, 0x01);
330 if (gspca_dev->width != 640 && val <= 3)
331 reg_w(gspca_dev, 0x08, 0x09);
332 else
333 reg_w(gspca_dev, 0x08, 0x08);
334
335
336
337
338
339
340
341 if (gspca_dev->width == 640 && val == 2)
342 reg_w(gspca_dev, 0x80, 0x01);
343 else
344 reg_w(gspca_dev, 0x80, 0x1c);
345
346
347 reg_w(gspca_dev, 0x11, 0x01);
348}
349
350static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
351{
352 __u8 data;
353
354 reg_w(gspca_dev, 0xff, 0x04);
355 data = (hflip ? 0x04 : 0x00) |
356 (vflip ? 0x08 : 0x00);
357 reg_w(gspca_dev, 0x21, data);
358
359
360 reg_w(gspca_dev, 0x11, 0x01);
361}
362
363
364static int sd_init(struct gspca_dev *gspca_dev)
365{
366 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
367 return gspca_dev->usb_err;
368}
369
370static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
371{
372 struct gspca_dev *gspca_dev =
373 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
374 struct sd *sd = (struct sd *)gspca_dev;
375
376 gspca_dev->usb_err = 0;
377
378 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
379
380
381
382
383 gspca_dev->exposure->val = PAC7311_EXPOSURE_DEFAULT;
384 gspca_dev->gain->val = PAC7311_GAIN_DEFAULT;
385 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
386 }
387
388 if (!gspca_dev->streaming)
389 return 0;
390
391 switch (ctrl->id) {
392 case V4L2_CID_CONTRAST:
393 setcontrast(gspca_dev, ctrl->val);
394 break;
395 case V4L2_CID_AUTOGAIN:
396 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
397 setexposure(gspca_dev, gspca_dev->exposure->val);
398 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
399 setgain(gspca_dev, gspca_dev->gain->val);
400 break;
401 case V4L2_CID_HFLIP:
402 sethvflip(gspca_dev, sd->hflip->val, 1);
403 break;
404 default:
405 return -EINVAL;
406 }
407 return gspca_dev->usb_err;
408}
409
410static const struct v4l2_ctrl_ops sd_ctrl_ops = {
411 .s_ctrl = sd_s_ctrl,
412};
413
414
415static int sd_init_controls(struct gspca_dev *gspca_dev)
416{
417 struct sd *sd = (struct sd *) gspca_dev;
418 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
419
420 gspca_dev->vdev.ctrl_handler = hdl;
421 v4l2_ctrl_handler_init(hdl, 5);
422
423 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
424 V4L2_CID_CONTRAST, 0, 15, 1, 7);
425 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
426 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
427 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
428 V4L2_CID_EXPOSURE, 2, 63, 1,
429 PAC7311_EXPOSURE_DEFAULT);
430 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
431 V4L2_CID_GAIN, 0, 244, 1,
432 PAC7311_GAIN_DEFAULT);
433 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
434 V4L2_CID_HFLIP, 0, 1, 1, 0);
435
436 if (hdl->error) {
437 pr_err("Could not initialize controls\n");
438 return hdl->error;
439 }
440
441 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
442 return 0;
443}
444
445
446static int sd_start(struct gspca_dev *gspca_dev)
447{
448 struct sd *sd = (struct sd *) gspca_dev;
449
450 sd->sof_read = 0;
451
452 reg_w_var(gspca_dev, start_7311,
453 page4_7311, sizeof(page4_7311));
454 setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
455 setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
456 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
457 sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
458
459
460 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
461 case 2:
462 reg_w(gspca_dev, 0xff, 0x01);
463 reg_w(gspca_dev, 0x17, 0x20);
464 reg_w(gspca_dev, 0x87, 0x10);
465 break;
466 case 1:
467 reg_w(gspca_dev, 0xff, 0x01);
468 reg_w(gspca_dev, 0x17, 0x30);
469 reg_w(gspca_dev, 0x87, 0x11);
470 break;
471 case 0:
472 reg_w(gspca_dev, 0xff, 0x01);
473 reg_w(gspca_dev, 0x17, 0x00);
474 reg_w(gspca_dev, 0x87, 0x12);
475 break;
476 }
477
478 sd->sof_read = 0;
479 sd->autogain_ignore_frames = 0;
480 atomic_set(&sd->avg_lum, -1);
481
482
483 reg_w(gspca_dev, 0xff, 0x01);
484 reg_w(gspca_dev, 0x78, 0x05);
485
486 return gspca_dev->usb_err;
487}
488
489static void sd_stopN(struct gspca_dev *gspca_dev)
490{
491 reg_w(gspca_dev, 0xff, 0x04);
492 reg_w(gspca_dev, 0x27, 0x80);
493 reg_w(gspca_dev, 0x28, 0xca);
494 reg_w(gspca_dev, 0x29, 0x53);
495 reg_w(gspca_dev, 0x2a, 0x0e);
496 reg_w(gspca_dev, 0xff, 0x01);
497 reg_w(gspca_dev, 0x3e, 0x20);
498 reg_w(gspca_dev, 0x78, 0x44);
499 reg_w(gspca_dev, 0x78, 0x44);
500 reg_w(gspca_dev, 0x78, 0x44);
501}
502
503static void do_autogain(struct gspca_dev *gspca_dev)
504{
505 struct sd *sd = (struct sd *) gspca_dev;
506 int avg_lum = atomic_read(&sd->avg_lum);
507 int desired_lum, deadzone;
508
509 if (avg_lum == -1)
510 return;
511
512 desired_lum = 170;
513 deadzone = 20;
514
515 if (sd->autogain_ignore_frames > 0)
516 sd->autogain_ignore_frames--;
517 else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
518 desired_lum, deadzone))
519 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
520}
521
522
523static const unsigned char pac_jpeg_header1[] = {
524 0xff, 0xd8,
525
526 0xff, 0xc0,
527 0x00, 0x11,
528 0x08
529
530
531};
532
533
534static const unsigned char pac_jpeg_header2[] = {
535 0x03,
536 0x01, 0x21, 0x00,
537 0x02, 0x11, 0x01,
538 0x03, 0x11, 0x01,
539
540 0xff, 0xda,
541 0x00, 0x0c,
542 0x03,
543 0x01, 0x00,
544 0x02, 0x11,
545 0x03, 0x11,
546 0x00, 0x3f,
547 0x00
548};
549
550static void pac_start_frame(struct gspca_dev *gspca_dev,
551 __u16 lines, __u16 samples_per_line)
552{
553 unsigned char tmpbuf[4];
554
555 gspca_frame_add(gspca_dev, FIRST_PACKET,
556 pac_jpeg_header1, sizeof(pac_jpeg_header1));
557
558 tmpbuf[0] = lines >> 8;
559 tmpbuf[1] = lines & 0xff;
560 tmpbuf[2] = samples_per_line >> 8;
561 tmpbuf[3] = samples_per_line & 0xff;
562
563 gspca_frame_add(gspca_dev, INTER_PACKET,
564 tmpbuf, sizeof(tmpbuf));
565 gspca_frame_add(gspca_dev, INTER_PACKET,
566 pac_jpeg_header2, sizeof(pac_jpeg_header2));
567}
568
569
570static void sd_pkt_scan(struct gspca_dev *gspca_dev,
571 u8 *data,
572 int len)
573{
574 struct sd *sd = (struct sd *) gspca_dev;
575 u8 *image;
576 unsigned char *sof;
577
578 sof = pac_find_sof(&sd->sof_read, data, len);
579 if (sof) {
580 int n, lum_offset, footer_length;
581
582
583
584
585
586
587
588 lum_offset = 24 + sizeof pac_sof_marker;
589 footer_length = 26;
590
591
592 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
593 if (n < 0) {
594 gspca_dev->image_len += n;
595 n = 0;
596 } else {
597 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
598 }
599 image = gspca_dev->image;
600 if (image != NULL
601 && image[gspca_dev->image_len - 2] == 0xff
602 && image[gspca_dev->image_len - 1] == 0xd9)
603 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
604
605 n = sof - data;
606 len -= n;
607 data = sof;
608
609
610 if (gspca_dev->last_packet_type == LAST_PACKET &&
611 n >= lum_offset)
612 atomic_set(&sd->avg_lum, data[-lum_offset] +
613 data[-lum_offset + 1]);
614 else
615 atomic_set(&sd->avg_lum, -1);
616
617
618 pac_start_frame(gspca_dev,
619 gspca_dev->height, gspca_dev->width);
620 }
621 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
622}
623
624#if IS_ENABLED(CONFIG_INPUT)
625static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
626 u8 *data,
627 int len)
628{
629 int ret = -EINVAL;
630 u8 data0, data1;
631
632 if (len == 2) {
633 data0 = data[0];
634 data1 = data[1];
635 if ((data0 == 0x00 && data1 == 0x11) ||
636 (data0 == 0x22 && data1 == 0x33) ||
637 (data0 == 0x44 && data1 == 0x55) ||
638 (data0 == 0x66 && data1 == 0x77) ||
639 (data0 == 0x88 && data1 == 0x99) ||
640 (data0 == 0xaa && data1 == 0xbb) ||
641 (data0 == 0xcc && data1 == 0xdd) ||
642 (data0 == 0xee && data1 == 0xff)) {
643 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
644 input_sync(gspca_dev->input_dev);
645 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
646 input_sync(gspca_dev->input_dev);
647 ret = 0;
648 }
649 }
650
651 return ret;
652}
653#endif
654
655static const struct sd_desc sd_desc = {
656 .name = MODULE_NAME,
657 .config = sd_config,
658 .init = sd_init,
659 .init_controls = sd_init_controls,
660 .start = sd_start,
661 .stopN = sd_stopN,
662 .pkt_scan = sd_pkt_scan,
663 .dq_callback = do_autogain,
664#if IS_ENABLED(CONFIG_INPUT)
665 .int_pkt_scan = sd_int_pkt_scan,
666#endif
667};
668
669
670static const struct usb_device_id device_table[] = {
671 {USB_DEVICE(0x093a, 0x2600)},
672 {USB_DEVICE(0x093a, 0x2601)},
673 {USB_DEVICE(0x093a, 0x2603)},
674 {USB_DEVICE(0x093a, 0x2608)},
675 {USB_DEVICE(0x093a, 0x260e)},
676 {USB_DEVICE(0x093a, 0x260f)},
677 {}
678};
679MODULE_DEVICE_TABLE(usb, device_table);
680
681
682static int sd_probe(struct usb_interface *intf,
683 const struct usb_device_id *id)
684{
685 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
686 THIS_MODULE);
687}
688
689static struct usb_driver sd_driver = {
690 .name = MODULE_NAME,
691 .id_table = device_table,
692 .probe = sd_probe,
693 .disconnect = gspca_disconnect,
694#ifdef CONFIG_PM
695 .suspend = gspca_suspend,
696 .resume = gspca_resume,
697 .reset_resume = gspca_resume,
698#endif
699};
700
701module_usb_driver(sd_driver);
702