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