]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/usb/gspca/pac7311.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / drivers / media / usb / 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.
6a7eba24
JFM
16 */
17
327c4abf 18/* Some documentation about various registers as determined by trial and error.
4b8ceb6c
HG
19 *
20 * Register page 1:
21 *
22 * Address Description
23 * 0x08 Unknown compressor related, must always be 8 except when not
24 * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
25 * 0x1b Auto white balance related, bit 0 is AWB enable (inverted)
26 * bits 345 seem to toggle per color gains on/off (inverted)
27 * 0x78 Global control, bit 6 controls the LED (inverted)
282ddfbc
HG
28 * 0x80 Compression balance, interesting settings:
29 * 0x01 Use this to allow the camera to switch to higher compr.
30 * on the fly. Needed to stay within bandwidth @ 640x480@30
31 * 0x1c From usb captures under Windows for 640x480
32 * 0x2a Values >= this switch the camera to a lower compression,
33 * using the same table for both luminance and chrominance.
34 * This gives a sharper picture. Usable only at 640x480@ <
35 * 15 fps or 320x240 / 160x120. Note currently the driver
36 * does not use this as the quality gain is small and the
37 * generated JPG-s are only understood by v4l-utils >= 0.8.9
38 * 0x3f From usb captures under Windows for 320x240
39 * 0x69 From usb captures under Windows for 160x120
4b8ceb6c
HG
40 *
41 * Register page 4:
42 *
43 * Address Description
44 * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
45 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
46 * 0x0f Master gain 1-245, low value = high gain
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
6a6c70b8
HG
49 * Note setting vflip disabled leads to a much lower image quality,
50 * so we always vflip, and tell userspace to flip it back
4b8ceb6c
HG
51 * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
52 * completely disable the analog amplification block. Set to 0x68
53 * for max gain, 0x14 for minimal gain.
54 */
327c4abf 55
133a9fe9
JP
56#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
57
6a7eba24
JFM
58#define MODULE_NAME "pac7311"
59
32ea3e44 60#include <linux/input.h>
6a7eba24 61#include "gspca.h"
a5340ce5
HG
62/* Include pac common sof detection functions */
63#include "pac_common.h"
6a7eba24 64
43f52bf2
HG
65#define PAC7311_GAIN_DEFAULT 122
66#define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */
67
6a7eba24
JFM
68MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
69MODULE_DESCRIPTION("Pixart PAC7311");
70MODULE_LICENSE("GPL");
71
6a7eba24
JFM
72struct sd {
73 struct gspca_dev gspca_dev; /* !! must be the first item */
43f52bf2
HG
74
75 struct v4l2_ctrl *contrast;
6a6c70b8 76 struct v4l2_ctrl *hflip;
49b57dba 77
327c4abf 78 u8 sof_read;
327c4abf
HG
79 u8 autogain_ignore_frames;
80
81 atomic_t avg_lum;
6a7eba24
JFM
82};
83
cc611b8a 84static const struct v4l2_pix_format vga_mode[] = {
f75c4950 85 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
86 .bytesperline = 160,
87 .sizeimage = 160 * 120 * 3 / 8 + 590,
88 .colorspace = V4L2_COLORSPACE_JPEG,
89 .priv = 2},
f75c4950 90 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
91 .bytesperline = 320,
92 .sizeimage = 320 * 240 * 3 / 8 + 590,
93 .colorspace = V4L2_COLORSPACE_JPEG,
94 .priv = 1},
f75c4950 95 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
96 .bytesperline = 640,
97 .sizeimage = 640 * 480 * 3 / 8 + 590,
98 .colorspace = V4L2_COLORSPACE_JPEG,
99 .priv = 0},
6a7eba24
JFM
100};
101
5a2e8d9f
MN
102#define LOAD_PAGE4 254
103#define END_OF_SEQUENCE 0
104
271315a9 105static const __u8 init_7311[] = {
42f85d0a 106 0xff, 0x01,
327c4abf
HG
107 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
108 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
109 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
49b57dba
JFM
110 0xff, 0x04,
111 0x27, 0x80,
112 0x28, 0xca,
113 0x29, 0x53,
114 0x2a, 0x0e,
115 0xff, 0x01,
116 0x3e, 0x20,
117};
118
119static const __u8 start_7311[] = {
120/* index, len, [value]* */
285a4f6c
JFM
121 0xff, 1, 0x01, /* page 1 */
122 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
49b57dba
JFM
123 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
124 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
125 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00,
285a4f6c 128 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
49b57dba
JFM
129 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
130 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
131 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
132 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
133 0xd0, 0xff,
134 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
135 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
136 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
137 0x18, 0x20,
138 0x96, 3, 0x01, 0x08, 0x04,
139 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
140 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
141 0x3f, 0x00, 0x0a, 0x01, 0x00,
285a4f6c 142 0xff, 1, 0x04, /* page 4 */
5a2e8d9f 143 0, LOAD_PAGE4, /* load the page 4 */
49b57dba 144 0x11, 1, 0x01,
5a2e8d9f 145 0, END_OF_SEQUENCE /* end of sequence */
49b57dba
JFM
146};
147
1408b847 148#define SKIP 0xaa
ff75e99c 149/* page 4 - the value SKIP says skip the index - see reg_w_page() */
49b57dba 150static const __u8 page4_7311[] = {
ff75e99c
MN
151 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
152 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
153 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
155 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
49b57dba
JFM
156 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
157 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
158};
159
14799f6c 160static void reg_w_buf(struct gspca_dev *gspca_dev,
49b57dba 161 __u8 index,
0aeb5ec7 162 const u8 *buffer, int len)
6a7eba24 163{
4f7309e2
MN
164 int ret;
165
14799f6c
JFM
166 if (gspca_dev->usb_err < 0)
167 return;
739570bb 168 memcpy(gspca_dev->usb_buf, buffer, len);
4f7309e2 169 ret = usb_control_msg(gspca_dev->dev,
739570bb 170 usb_sndctrlpipe(gspca_dev->dev, 0),
a1317135 171 0, /* request */
6a7eba24 172 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
bf7f0b98 173 0, /* value */
739570bb 174 index, gspca_dev->usb_buf, len,
6a7eba24 175 500);
14799f6c 176 if (ret < 0) {
133a9fe9
JP
177 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
178 index, ret);
14799f6c
JFM
179 gspca_dev->usb_err = ret;
180 }
6a7eba24
JFM
181}
182
6a7eba24 183
14799f6c 184static void reg_w(struct gspca_dev *gspca_dev,
49b57dba 185 __u8 index,
739570bb 186 __u8 value)
6a7eba24 187{
4f7309e2
MN
188 int ret;
189
14799f6c
JFM
190 if (gspca_dev->usb_err < 0)
191 return;
739570bb 192 gspca_dev->usb_buf[0] = value;
4f7309e2 193 ret = usb_control_msg(gspca_dev->dev,
739570bb 194 usb_sndctrlpipe(gspca_dev->dev, 0),
bf7f0b98
JFM
195 0, /* request */
196 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
8a5b2e90 197 0, index, gspca_dev->usb_buf, 1,
bf7f0b98 198 500);
14799f6c 199 if (ret < 0) {
133a9fe9
JP
200 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
201 index, value, ret);
14799f6c
JFM
202 gspca_dev->usb_err = ret;
203 }
6a7eba24
JFM
204}
205
14799f6c 206static void reg_w_seq(struct gspca_dev *gspca_dev,
49b57dba
JFM
207 const __u8 *seq, int len)
208{
209 while (--len >= 0) {
14799f6c 210 reg_w(gspca_dev, seq[0], seq[1]);
49b57dba
JFM
211 seq += 2;
212 }
213}
214
215/* load the beginning of a page */
14799f6c 216static void reg_w_page(struct gspca_dev *gspca_dev,
49b57dba
JFM
217 const __u8 *page, int len)
218{
219 int index;
b1784b33 220 int ret = 0;
49b57dba 221
14799f6c
JFM
222 if (gspca_dev->usb_err < 0)
223 return;
49b57dba 224 for (index = 0; index < len; index++) {
ff75e99c 225 if (page[index] == SKIP) /* skip this index */
49b57dba
JFM
226 continue;
227 gspca_dev->usb_buf[0] = page[index];
4f7309e2 228 ret = usb_control_msg(gspca_dev->dev,
49b57dba
JFM
229 usb_sndctrlpipe(gspca_dev->dev, 0),
230 0, /* request */
231 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
232 0, index, gspca_dev->usb_buf, 1,
233 500);
b1784b33 234 if (ret < 0) {
133a9fe9
JP
235 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
236 index, page[index], ret);
14799f6c 237 gspca_dev->usb_err = ret;
b1784b33
MN
238 break;
239 }
49b57dba
JFM
240 }
241}
242
243/* output a variable sequence */
14799f6c 244static void reg_w_var(struct gspca_dev *gspca_dev,
1408b847 245 const __u8 *seq,
1408b847 246 const __u8 *page4, unsigned int page4_len)
49b57dba
JFM
247{
248 int index, len;
249
250 for (;;) {
251 index = *seq++;
252 len = *seq++;
253 switch (len) {
5a2e8d9f 254 case END_OF_SEQUENCE:
14799f6c 255 return;
5a2e8d9f 256 case LOAD_PAGE4:
14799f6c 257 reg_w_page(gspca_dev, page4, page4_len);
49b57dba 258 break;
49b57dba 259 default:
24067bb5 260 if (len > USB_BUF_SZ) {
c93396e1 261 PERR("Incorrect variable sequence");
14799f6c 262 return;
49b57dba
JFM
263 }
264 while (len > 0) {
265 if (len < 8) {
14799f6c 266 reg_w_buf(gspca_dev,
b1784b33 267 index, seq, len);
49b57dba
JFM
268 seq += len;
269 break;
270 }
14799f6c 271 reg_w_buf(gspca_dev, index, seq, 8);
49b57dba
JFM
272 seq += 8;
273 index += 8;
274 len -= 8;
275 }
276 }
277 }
278 /* not reached */
279}
280
1408b847 281/* this function is called at probe time for pac7311 */
6a7eba24
JFM
282static int sd_config(struct gspca_dev *gspca_dev,
283 const struct usb_device_id *id)
284{
a5340ce5 285 struct cam *cam = &gspca_dev->cam;
49b57dba 286
1408b847
MN
287 cam->cam_mode = vga_mode;
288 cam->nmodes = ARRAY_SIZE(vga_mode);
6a6c70b8 289 cam->input_flags = V4L2_IN_ST_VFLIP;
6a7eba24 290
6a7eba24
JFM
291 return 0;
292}
293
43f52bf2 294static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 295{
14799f6c 296 reg_w(gspca_dev, 0xff, 0x04);
43f52bf2 297 reg_w(gspca_dev, 0x10, val);
6a7eba24 298 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 299 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
300}
301
43f52bf2 302static void setgain(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 303{
14799f6c
JFM
304 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
305 reg_w(gspca_dev, 0x0e, 0x00);
43f52bf2 306 reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
6a7eba24 307
6a7eba24 308 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 309 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
310}
311
43f52bf2 312static void setexposure(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 313{
14799f6c 314 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
43f52bf2 315 reg_w(gspca_dev, 0x02, val);
14799f6c 316
51ae23df
HG
317 /* load registers to sensor (Bit 0, auto clear) */
318 reg_w(gspca_dev, 0x11, 0x01);
319
4b8ceb6c
HG
320 /*
321 * Page 1 register 8 must always be 0x08 except when not in
322 * 640x480 mode and page 4 reg 2 <= 3 then it must be 9
323 */
14799f6c 324 reg_w(gspca_dev, 0xff, 0x01);
1966bc2a 325 if (gspca_dev->pixfmt.width != 640 && val <= 3)
14799f6c 326 reg_w(gspca_dev, 0x08, 0x09);
282ddfbc 327 else
14799f6c 328 reg_w(gspca_dev, 0x08, 0x08);
282ddfbc
HG
329
330 /*
331 * Page1 register 80 sets the compression balance, normally we
332 * want / use 0x1c, but for 640x480@30fps we must allow the
333 * camera to use higher compression or we may run out of
334 * bandwidth.
335 */
1966bc2a 336 if (gspca_dev->pixfmt.width == 640 && val == 2)
282ddfbc
HG
337 reg_w(gspca_dev, 0x80, 0x01);
338 else
339 reg_w(gspca_dev, 0x80, 0x1c);
1408b847 340
8a5b2e90 341 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 342 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
343}
344
43f52bf2 345static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
41b46974 346{
41b46974
JFM
347 __u8 data;
348
14799f6c 349 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
43f52bf2
HG
350 data = (hflip ? 0x04 : 0x00) |
351 (vflip ? 0x08 : 0x00);
14799f6c
JFM
352 reg_w(gspca_dev, 0x21, data);
353
8a5b2e90 354 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 355 reg_w(gspca_dev, 0x11, 0x01);
41b46974
JFM
356}
357
1408b847 358/* this function is called at probe and resume time for pac7311 */
012d6b02 359static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24 360{
14799f6c
JFM
361 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
362 return gspca_dev->usb_err;
6a7eba24
JFM
363}
364
43f52bf2
HG
365static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
366{
367 struct gspca_dev *gspca_dev =
368 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
369 struct sd *sd = (struct sd *)gspca_dev;
370
371 gspca_dev->usb_err = 0;
372
373 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
374 /* when switching to autogain set defaults to make sure
375 we are on a valid point of the autogain gain /
376 exposure knee graph, and give this change time to
377 take effect before doing autogain. */
378 gspca_dev->exposure->val = PAC7311_EXPOSURE_DEFAULT;
379 gspca_dev->gain->val = PAC7311_GAIN_DEFAULT;
380 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
381 }
382
383 if (!gspca_dev->streaming)
384 return 0;
385
386 switch (ctrl->id) {
387 case V4L2_CID_CONTRAST:
388 setcontrast(gspca_dev, ctrl->val);
389 break;
390 case V4L2_CID_AUTOGAIN:
391 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
392 setexposure(gspca_dev, gspca_dev->exposure->val);
393 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
394 setgain(gspca_dev, gspca_dev->gain->val);
395 break;
396 case V4L2_CID_HFLIP:
6a6c70b8 397 sethvflip(gspca_dev, sd->hflip->val, 1);
43f52bf2
HG
398 break;
399 default:
400 return -EINVAL;
401 }
402 return gspca_dev->usb_err;
403}
404
405static const struct v4l2_ctrl_ops sd_ctrl_ops = {
406 .s_ctrl = sd_s_ctrl,
407};
408
409/* this function is called at probe time */
410static int sd_init_controls(struct gspca_dev *gspca_dev)
411{
412 struct sd *sd = (struct sd *) gspca_dev;
413 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
414
415 gspca_dev->vdev.ctrl_handler = hdl;
b6fc2eb9 416 v4l2_ctrl_handler_init(hdl, 5);
43f52bf2
HG
417
418 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
419 V4L2_CID_CONTRAST, 0, 15, 1, 7);
420 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
421 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
422 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
423 V4L2_CID_EXPOSURE, 2, 63, 1,
424 PAC7311_EXPOSURE_DEFAULT);
425 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
426 V4L2_CID_GAIN, 0, 244, 1,
427 PAC7311_GAIN_DEFAULT);
428 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
429 V4L2_CID_HFLIP, 0, 1, 1, 0);
43f52bf2
HG
430
431 if (hdl->error) {
432 pr_err("Could not initialize controls\n");
433 return hdl->error;
434 }
435
436 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
43f52bf2
HG
437 return 0;
438}
439
440/* -- start the camera -- */
72ab97ce 441static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24 442{
e52a5574
JFM
443 struct sd *sd = (struct sd *) gspca_dev;
444
327c4abf 445 sd->sof_read = 0;
739570bb 446
14799f6c 447 reg_w_var(gspca_dev, start_7311,
1408b847 448 page4_7311, sizeof(page4_7311));
43f52bf2
HG
449 setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
450 setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
451 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
6a6c70b8 452 sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
6a7eba24
JFM
453
454 /* set correct resolution */
c2446b3e 455 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
b053c1d0 456 case 2: /* 160x120 */
14799f6c
JFM
457 reg_w(gspca_dev, 0xff, 0x01);
458 reg_w(gspca_dev, 0x17, 0x20);
459 reg_w(gspca_dev, 0x87, 0x10);
6a7eba24 460 break;
b053c1d0 461 case 1: /* 320x240 */
14799f6c
JFM
462 reg_w(gspca_dev, 0xff, 0x01);
463 reg_w(gspca_dev, 0x17, 0x30);
464 reg_w(gspca_dev, 0x87, 0x11);
6a7eba24
JFM
465 break;
466 case 0: /* 640x480 */
14799f6c
JFM
467 reg_w(gspca_dev, 0xff, 0x01);
468 reg_w(gspca_dev, 0x17, 0x00);
469 reg_w(gspca_dev, 0x87, 0x12);
6a7eba24
JFM
470 break;
471 }
472
327c4abf
HG
473 sd->sof_read = 0;
474 sd->autogain_ignore_frames = 0;
475 atomic_set(&sd->avg_lum, -1);
8a5b2e90
HG
476
477 /* start stream */
14799f6c
JFM
478 reg_w(gspca_dev, 0xff, 0x01);
479 reg_w(gspca_dev, 0x78, 0x05);
1408b847 480
14799f6c 481 return gspca_dev->usb_err;
6a7eba24
JFM
482}
483
484static void sd_stopN(struct gspca_dev *gspca_dev)
485{
14799f6c
JFM
486 reg_w(gspca_dev, 0xff, 0x04);
487 reg_w(gspca_dev, 0x27, 0x80);
488 reg_w(gspca_dev, 0x28, 0xca);
489 reg_w(gspca_dev, 0x29, 0x53);
490 reg_w(gspca_dev, 0x2a, 0x0e);
491 reg_w(gspca_dev, 0xff, 0x01);
492 reg_w(gspca_dev, 0x3e, 0x20);
493 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
494 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
495 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
6a7eba24
JFM
496}
497
cebf3b67 498static void do_autogain(struct gspca_dev *gspca_dev)
6a7eba24 499{
8a5b2e90
HG
500 struct sd *sd = (struct sd *) gspca_dev;
501 int avg_lum = atomic_read(&sd->avg_lum);
038ec7c7 502 int desired_lum, deadzone;
8a5b2e90 503
43f52bf2 504 if (avg_lum == -1)
8a5b2e90
HG
505 return;
506
6a6c70b8 507 desired_lum = 170;
1408b847 508 deadzone = 20;
8a5b2e90
HG
509
510 if (sd->autogain_ignore_frames > 0)
511 sd->autogain_ignore_frames--;
43f52bf2
HG
512 else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
513 desired_lum, deadzone))
8a5b2e90 514 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
6a7eba24
JFM
515}
516
56f6f558 517/* JPEG header, part 1 */
cc409c0e 518static const unsigned char pac_jpeg_header1[] = {
56f6f558
MN
519 0xff, 0xd8, /* SOI: Start of Image */
520
521 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
522 0x00, 0x11, /* length = 17 bytes (including this length field) */
523 0x08 /* Precision: 8 */
524 /* 2 bytes is placed here: number of image lines */
525 /* 2 bytes is placed here: samples per line */
327c4abf
HG
526};
527
56f6f558 528/* JPEG header, continued */
cc409c0e 529static const unsigned char pac_jpeg_header2[] = {
56f6f558
MN
530 0x03, /* Number of image components: 3 */
531 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
532 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
533 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
534
535 0xff, 0xda, /* SOS: Start Of Scan */
536 0x00, 0x0c, /* length = 12 bytes (including this length field) */
537 0x03, /* number of components: 3 */
538 0x01, 0x00, /* selector 1, table 0x00 */
539 0x02, 0x11, /* selector 2, table 0x11 */
540 0x03, 0x11, /* selector 3, table 0x11 */
541 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
542 0x00 /* Successive approximation: 0 */
327c4abf
HG
543};
544
cc409c0e 545static void pac_start_frame(struct gspca_dev *gspca_dev,
cc409c0e
MN
546 __u16 lines, __u16 samples_per_line)
547{
548 unsigned char tmpbuf[4];
549
76dd272b 550 gspca_frame_add(gspca_dev, FIRST_PACKET,
cc409c0e
MN
551 pac_jpeg_header1, sizeof(pac_jpeg_header1));
552
553 tmpbuf[0] = lines >> 8;
554 tmpbuf[1] = lines & 0xff;
555 tmpbuf[2] = samples_per_line >> 8;
556 tmpbuf[3] = samples_per_line & 0xff;
557
76dd272b 558 gspca_frame_add(gspca_dev, INTER_PACKET,
cc409c0e 559 tmpbuf, sizeof(tmpbuf));
76dd272b 560 gspca_frame_add(gspca_dev, INTER_PACKET,
cc409c0e
MN
561 pac_jpeg_header2, sizeof(pac_jpeg_header2));
562}
563
e52a5574 564/* this function is run at interrupt level */
6a7eba24 565static void sd_pkt_scan(struct gspca_dev *gspca_dev,
76dd272b 566 u8 *data, /* isoc packet */
6a7eba24
JFM
567 int len) /* iso packet length */
568{
569 struct sd *sd = (struct sd *) gspca_dev;
b192ca98 570 u8 *image;
327c4abf
HG
571 unsigned char *sof;
572
c93396e1 573 sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
327c4abf 574 if (sof) {
327c4abf
HG
575 int n, lum_offset, footer_length;
576
4b8ceb6c
HG
577 /*
578 * 6 bytes after the FF D9 EOF marker a number of lumination
579 * bytes are send corresponding to different parts of the
580 * image, the 14th and 15th byte after the EOF seem to
581 * correspond to the center of the image.
582 */
1408b847
MN
583 lum_offset = 24 + sizeof pac_sof_marker;
584 footer_length = 26;
327c4abf
HG
585
586 /* Finish decoding current frame */
587 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
588 if (n < 0) {
b192ca98 589 gspca_dev->image_len += n;
327c4abf 590 n = 0;
b192ca98
JFM
591 } else {
592 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
327c4abf 593 }
f7059eaa
JFM
594 image = gspca_dev->image;
595 if (image != NULL
b192ca98
JFM
596 && image[gspca_dev->image_len - 2] == 0xff
597 && image[gspca_dev->image_len - 1] == 0xd9)
598 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
327c4abf
HG
599
600 n = sof - data;
601 len -= n;
602 data = sof;
603
604 /* Get average lumination */
605 if (gspca_dev->last_packet_type == LAST_PACKET &&
038ec7c7
HG
606 n >= lum_offset)
607 atomic_set(&sd->avg_lum, data[-lum_offset] +
327c4abf 608 data[-lum_offset + 1]);
038ec7c7 609 else
327c4abf 610 atomic_set(&sd->avg_lum, -1);
327c4abf
HG
611
612 /* Start the new frame with the jpeg header */
b192ca98 613 pac_start_frame(gspca_dev,
1966bc2a 614 gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
6a7eba24 615 }
76dd272b 616 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6a7eba24
JFM
617}
618
2d622e91 619#if IS_ENABLED(CONFIG_INPUT)
32ea3e44
HG
620static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
621 u8 *data, /* interrupt packet data */
622 int len) /* interrupt packet length */
623{
624 int ret = -EINVAL;
625 u8 data0, data1;
626
627 if (len == 2) {
628 data0 = data[0];
629 data1 = data[1];
630 if ((data0 == 0x00 && data1 == 0x11) ||
631 (data0 == 0x22 && data1 == 0x33) ||
632 (data0 == 0x44 && data1 == 0x55) ||
633 (data0 == 0x66 && data1 == 0x77) ||
634 (data0 == 0x88 && data1 == 0x99) ||
635 (data0 == 0xaa && data1 == 0xbb) ||
636 (data0 == 0xcc && data1 == 0xdd) ||
637 (data0 == 0xee && data1 == 0xff)) {
638 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
639 input_sync(gspca_dev->input_dev);
640 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
641 input_sync(gspca_dev->input_dev);
642 ret = 0;
643 }
644 }
645
646 return ret;
647}
648#endif
649
aabcdfb6 650static const struct sd_desc sd_desc = {
6a7eba24 651 .name = MODULE_NAME,
6a7eba24 652 .config = sd_config,
012d6b02 653 .init = sd_init,
43f52bf2 654 .init_controls = sd_init_controls,
6a7eba24
JFM
655 .start = sd_start,
656 .stopN = sd_stopN,
6a7eba24 657 .pkt_scan = sd_pkt_scan,
cebf3b67 658 .dq_callback = do_autogain,
2d622e91 659#if IS_ENABLED(CONFIG_INPUT)
32ea3e44
HG
660 .int_pkt_scan = sd_int_pkt_scan,
661#endif
6a7eba24
JFM
662};
663
664/* -- module initialisation -- */
95c967c1 665static const struct usb_device_id device_table[] = {
1408b847
MN
666 {USB_DEVICE(0x093a, 0x2600)},
667 {USB_DEVICE(0x093a, 0x2601)},
668 {USB_DEVICE(0x093a, 0x2603)},
669 {USB_DEVICE(0x093a, 0x2608)},
670 {USB_DEVICE(0x093a, 0x260e)},
671 {USB_DEVICE(0x093a, 0x260f)},
6a7eba24
JFM
672 {}
673};
674MODULE_DEVICE_TABLE(usb, device_table);
675
676/* -- device connect -- */
95c967c1 677static int sd_probe(struct usb_interface *intf,
6a7eba24
JFM
678 const struct usb_device_id *id)
679{
680 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
681 THIS_MODULE);
682}
683
684static struct usb_driver sd_driver = {
685 .name = MODULE_NAME,
686 .id_table = device_table,
687 .probe = sd_probe,
688 .disconnect = gspca_disconnect,
6a709749
JFM
689#ifdef CONFIG_PM
690 .suspend = gspca_suspend,
691 .resume = gspca_resume,
8bb58964 692 .reset_resume = gspca_resume,
6a709749 693#endif
6a7eba24
JFM
694};
695
ecb3b2b3 696module_usb_driver(sd_driver);