Merge branch 'clk/mxs-for-3.6' of git://git.linaro.org/people/shawnguo/linux-2.6...
[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 22/* Some documentation about various registers as determined by trial and error.
4b8ceb6c
HG
23 *
24 * Register page 1:
25 *
26 * Address Description
27 * 0x08 Unknown compressor related, must always be 8 except when not
28 * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
29 * 0x1b Auto white balance related, bit 0 is AWB enable (inverted)
30 * bits 345 seem to toggle per color gains on/off (inverted)
31 * 0x78 Global control, bit 6 controls the LED (inverted)
282ddfbc
HG
32 * 0x80 Compression balance, interesting settings:
33 * 0x01 Use this to allow the camera to switch to higher compr.
34 * on the fly. Needed to stay within bandwidth @ 640x480@30
35 * 0x1c From usb captures under Windows for 640x480
36 * 0x2a Values >= this switch the camera to a lower compression,
37 * using the same table for both luminance and chrominance.
38 * This gives a sharper picture. Usable only at 640x480@ <
39 * 15 fps or 320x240 / 160x120. Note currently the driver
40 * does not use this as the quality gain is small and the
41 * generated JPG-s are only understood by v4l-utils >= 0.8.9
42 * 0x3f From usb captures under Windows for 320x240
43 * 0x69 From usb captures under Windows for 160x120
4b8ceb6c
HG
44 *
45 * Register page 4:
46 *
47 * Address Description
48 * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
49 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
50 * 0x0f Master gain 1-245, low value = high gain
51 * 0x10 Another gain 0-15, limited influence (1-2x gain I guess)
52 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
6a6c70b8
HG
53 * Note setting vflip disabled leads to a much lower image quality,
54 * so we always vflip, and tell userspace to flip it back
4b8ceb6c
HG
55 * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
56 * completely disable the analog amplification block. Set to 0x68
57 * for max gain, 0x14 for minimal gain.
58 */
327c4abf 59
133a9fe9
JP
60#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
61
6a7eba24
JFM
62#define MODULE_NAME "pac7311"
63
32ea3e44 64#include <linux/input.h>
6a7eba24 65#include "gspca.h"
a5340ce5
HG
66/* Include pac common sof detection functions */
67#include "pac_common.h"
6a7eba24 68
43f52bf2
HG
69#define PAC7311_GAIN_DEFAULT 122
70#define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */
71
6a7eba24
JFM
72MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
73MODULE_DESCRIPTION("Pixart PAC7311");
74MODULE_LICENSE("GPL");
75
6a7eba24
JFM
76struct sd {
77 struct gspca_dev gspca_dev; /* !! must be the first item */
43f52bf2
HG
78
79 struct v4l2_ctrl *contrast;
6a6c70b8 80 struct v4l2_ctrl *hflip;
49b57dba 81
327c4abf 82 u8 sof_read;
327c4abf
HG
83 u8 autogain_ignore_frames;
84
85 atomic_t avg_lum;
6a7eba24
JFM
86};
87
cc611b8a 88static const struct v4l2_pix_format vga_mode[] = {
f75c4950 89 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
90 .bytesperline = 160,
91 .sizeimage = 160 * 120 * 3 / 8 + 590,
92 .colorspace = V4L2_COLORSPACE_JPEG,
93 .priv = 2},
f75c4950 94 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
95 .bytesperline = 320,
96 .sizeimage = 320 * 240 * 3 / 8 + 590,
97 .colorspace = V4L2_COLORSPACE_JPEG,
98 .priv = 1},
f75c4950 99 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
c2446b3e
JFM
100 .bytesperline = 640,
101 .sizeimage = 640 * 480 * 3 / 8 + 590,
102 .colorspace = V4L2_COLORSPACE_JPEG,
103 .priv = 0},
6a7eba24
JFM
104};
105
5a2e8d9f
MN
106#define LOAD_PAGE4 254
107#define END_OF_SEQUENCE 0
108
271315a9 109static const __u8 init_7311[] = {
42f85d0a 110 0xff, 0x01,
327c4abf
HG
111 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
112 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
113 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
49b57dba
JFM
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/* index, len, [value]* */
285a4f6c
JFM
125 0xff, 1, 0x01, /* page 1 */
126 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
49b57dba
JFM
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,
285a4f6c 132 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
49b57dba
JFM
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,
285a4f6c 146 0xff, 1, 0x04, /* page 4 */
5a2e8d9f 147 0, LOAD_PAGE4, /* load the page 4 */
49b57dba 148 0x11, 1, 0x01,
5a2e8d9f 149 0, END_OF_SEQUENCE /* end of sequence */
49b57dba
JFM
150};
151
1408b847 152#define SKIP 0xaa
ff75e99c 153/* page 4 - the value SKIP says skip the index - see reg_w_page() */
49b57dba 154static const __u8 page4_7311[] = {
ff75e99c
MN
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,
49b57dba
JFM
160 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
161 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
162};
163
14799f6c 164static void reg_w_buf(struct gspca_dev *gspca_dev,
49b57dba 165 __u8 index,
0aeb5ec7 166 const u8 *buffer, int len)
6a7eba24 167{
4f7309e2
MN
168 int ret;
169
14799f6c
JFM
170 if (gspca_dev->usb_err < 0)
171 return;
739570bb 172 memcpy(gspca_dev->usb_buf, buffer, len);
4f7309e2 173 ret = usb_control_msg(gspca_dev->dev,
739570bb 174 usb_sndctrlpipe(gspca_dev->dev, 0),
a1317135 175 0, /* request */
6a7eba24 176 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
bf7f0b98 177 0, /* value */
739570bb 178 index, gspca_dev->usb_buf, len,
6a7eba24 179 500);
14799f6c 180 if (ret < 0) {
133a9fe9
JP
181 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
182 index, ret);
14799f6c
JFM
183 gspca_dev->usb_err = ret;
184 }
6a7eba24
JFM
185}
186
6a7eba24 187
14799f6c 188static void reg_w(struct gspca_dev *gspca_dev,
49b57dba 189 __u8 index,
739570bb 190 __u8 value)
6a7eba24 191{
4f7309e2
MN
192 int ret;
193
14799f6c
JFM
194 if (gspca_dev->usb_err < 0)
195 return;
739570bb 196 gspca_dev->usb_buf[0] = value;
4f7309e2 197 ret = usb_control_msg(gspca_dev->dev,
739570bb 198 usb_sndctrlpipe(gspca_dev->dev, 0),
bf7f0b98
JFM
199 0, /* request */
200 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
8a5b2e90 201 0, index, gspca_dev->usb_buf, 1,
bf7f0b98 202 500);
14799f6c 203 if (ret < 0) {
133a9fe9
JP
204 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
205 index, value, ret);
14799f6c
JFM
206 gspca_dev->usb_err = ret;
207 }
6a7eba24
JFM
208}
209
14799f6c 210static void reg_w_seq(struct gspca_dev *gspca_dev,
49b57dba
JFM
211 const __u8 *seq, int len)
212{
213 while (--len >= 0) {
14799f6c 214 reg_w(gspca_dev, seq[0], seq[1]);
49b57dba
JFM
215 seq += 2;
216 }
217}
218
219/* load the beginning of a page */
14799f6c 220static void reg_w_page(struct gspca_dev *gspca_dev,
49b57dba
JFM
221 const __u8 *page, int len)
222{
223 int index;
b1784b33 224 int ret = 0;
49b57dba 225
14799f6c
JFM
226 if (gspca_dev->usb_err < 0)
227 return;
49b57dba 228 for (index = 0; index < len; index++) {
ff75e99c 229 if (page[index] == SKIP) /* skip this index */
49b57dba
JFM
230 continue;
231 gspca_dev->usb_buf[0] = page[index];
4f7309e2 232 ret = usb_control_msg(gspca_dev->dev,
49b57dba
JFM
233 usb_sndctrlpipe(gspca_dev->dev, 0),
234 0, /* request */
235 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236 0, index, gspca_dev->usb_buf, 1,
237 500);
b1784b33 238 if (ret < 0) {
133a9fe9
JP
239 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
240 index, page[index], ret);
14799f6c 241 gspca_dev->usb_err = ret;
b1784b33
MN
242 break;
243 }
49b57dba
JFM
244 }
245}
246
247/* output a variable sequence */
14799f6c 248static void reg_w_var(struct gspca_dev *gspca_dev,
1408b847 249 const __u8 *seq,
1408b847 250 const __u8 *page4, unsigned int page4_len)
49b57dba
JFM
251{
252 int index, len;
253
254 for (;;) {
255 index = *seq++;
256 len = *seq++;
257 switch (len) {
5a2e8d9f 258 case END_OF_SEQUENCE:
14799f6c 259 return;
5a2e8d9f 260 case LOAD_PAGE4:
14799f6c 261 reg_w_page(gspca_dev, page4, page4_len);
49b57dba 262 break;
49b57dba 263 default:
24067bb5 264 if (len > USB_BUF_SZ) {
49b57dba
JFM
265 PDEBUG(D_ERR|D_STREAM,
266 "Incorrect variable sequence");
14799f6c 267 return;
49b57dba
JFM
268 }
269 while (len > 0) {
270 if (len < 8) {
14799f6c 271 reg_w_buf(gspca_dev,
b1784b33 272 index, seq, len);
49b57dba
JFM
273 seq += len;
274 break;
275 }
14799f6c 276 reg_w_buf(gspca_dev, index, seq, 8);
49b57dba
JFM
277 seq += 8;
278 index += 8;
279 len -= 8;
280 }
281 }
282 }
283 /* not reached */
284}
285
1408b847 286/* this function is called at probe time for pac7311 */
6a7eba24
JFM
287static int sd_config(struct gspca_dev *gspca_dev,
288 const struct usb_device_id *id)
289{
a5340ce5 290 struct cam *cam = &gspca_dev->cam;
49b57dba 291
1408b847
MN
292 cam->cam_mode = vga_mode;
293 cam->nmodes = ARRAY_SIZE(vga_mode);
6a6c70b8 294 cam->input_flags = V4L2_IN_ST_VFLIP;
6a7eba24 295
6a7eba24
JFM
296 return 0;
297}
298
43f52bf2 299static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 300{
14799f6c 301 reg_w(gspca_dev, 0xff, 0x04);
43f52bf2 302 reg_w(gspca_dev, 0x10, val);
6a7eba24 303 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 304 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
305}
306
43f52bf2 307static void setgain(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 308{
14799f6c
JFM
309 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
310 reg_w(gspca_dev, 0x0e, 0x00);
43f52bf2 311 reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
6a7eba24 312
6a7eba24 313 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 314 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
315}
316
43f52bf2 317static void setexposure(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 318{
14799f6c 319 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
43f52bf2 320 reg_w(gspca_dev, 0x02, val);
14799f6c 321
51ae23df
HG
322 /* load registers to sensor (Bit 0, auto clear) */
323 reg_w(gspca_dev, 0x11, 0x01);
324
4b8ceb6c
HG
325 /*
326 * Page 1 register 8 must always be 0x08 except when not in
327 * 640x480 mode and page 4 reg 2 <= 3 then it must be 9
328 */
14799f6c 329 reg_w(gspca_dev, 0xff, 0x01);
43f52bf2 330 if (gspca_dev->width != 640 && val <= 3)
14799f6c 331 reg_w(gspca_dev, 0x08, 0x09);
282ddfbc 332 else
14799f6c 333 reg_w(gspca_dev, 0x08, 0x08);
282ddfbc
HG
334
335 /*
336 * Page1 register 80 sets the compression balance, normally we
337 * want / use 0x1c, but for 640x480@30fps we must allow the
338 * camera to use higher compression or we may run out of
339 * bandwidth.
340 */
43f52bf2 341 if (gspca_dev->width == 640 && val == 2)
282ddfbc
HG
342 reg_w(gspca_dev, 0x80, 0x01);
343 else
344 reg_w(gspca_dev, 0x80, 0x1c);
1408b847 345
8a5b2e90 346 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 347 reg_w(gspca_dev, 0x11, 0x01);
6a7eba24
JFM
348}
349
43f52bf2 350static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
41b46974 351{
41b46974
JFM
352 __u8 data;
353
14799f6c 354 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
43f52bf2
HG
355 data = (hflip ? 0x04 : 0x00) |
356 (vflip ? 0x08 : 0x00);
14799f6c
JFM
357 reg_w(gspca_dev, 0x21, data);
358
8a5b2e90 359 /* load registers to sensor (Bit 0, auto clear) */
14799f6c 360 reg_w(gspca_dev, 0x11, 0x01);
41b46974
JFM
361}
362
1408b847 363/* this function is called at probe and resume time for pac7311 */
012d6b02 364static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24 365{
14799f6c
JFM
366 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
367 return gspca_dev->usb_err;
6a7eba24
JFM
368}
369
43f52bf2
HG
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 /* when switching to autogain set defaults to make sure
380 we are on a valid point of the autogain gain /
381 exposure knee graph, and give this change time to
382 take effect before doing autogain. */
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:
6a6c70b8 402 sethvflip(gspca_dev, sd->hflip->val, 1);
43f52bf2
HG
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/* this function is called at probe time */
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;
b6fc2eb9 421 v4l2_ctrl_handler_init(hdl, 5);
43f52bf2
HG
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);
43f52bf2
HG
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);
43f52bf2
HG
442 return 0;
443}
444
445/* -- start the camera -- */
72ab97ce 446static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24 447{
e52a5574
JFM
448 struct sd *sd = (struct sd *) gspca_dev;
449
327c4abf 450 sd->sof_read = 0;
739570bb 451
14799f6c 452 reg_w_var(gspca_dev, start_7311,
1408b847 453 page4_7311, sizeof(page4_7311));
43f52bf2
HG
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));
6a6c70b8 457 sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
6a7eba24
JFM
458
459 /* set correct resolution */
c2446b3e 460 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
b053c1d0 461 case 2: /* 160x120 */
14799f6c
JFM
462 reg_w(gspca_dev, 0xff, 0x01);
463 reg_w(gspca_dev, 0x17, 0x20);
464 reg_w(gspca_dev, 0x87, 0x10);
6a7eba24 465 break;
b053c1d0 466 case 1: /* 320x240 */
14799f6c
JFM
467 reg_w(gspca_dev, 0xff, 0x01);
468 reg_w(gspca_dev, 0x17, 0x30);
469 reg_w(gspca_dev, 0x87, 0x11);
6a7eba24
JFM
470 break;
471 case 0: /* 640x480 */
14799f6c
JFM
472 reg_w(gspca_dev, 0xff, 0x01);
473 reg_w(gspca_dev, 0x17, 0x00);
474 reg_w(gspca_dev, 0x87, 0x12);
6a7eba24
JFM
475 break;
476 }
477
327c4abf
HG
478 sd->sof_read = 0;
479 sd->autogain_ignore_frames = 0;
480 atomic_set(&sd->avg_lum, -1);
8a5b2e90
HG
481
482 /* start stream */
14799f6c
JFM
483 reg_w(gspca_dev, 0xff, 0x01);
484 reg_w(gspca_dev, 0x78, 0x05);
1408b847 485
14799f6c 486 return gspca_dev->usb_err;
6a7eba24
JFM
487}
488
489static void sd_stopN(struct gspca_dev *gspca_dev)
490{
14799f6c
JFM
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); /* Bit_0=start stream, Bit_6=LED */
499 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
500 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
6a7eba24
JFM
501}
502
cebf3b67 503static void do_autogain(struct gspca_dev *gspca_dev)
6a7eba24 504{
8a5b2e90
HG
505 struct sd *sd = (struct sd *) gspca_dev;
506 int avg_lum = atomic_read(&sd->avg_lum);
038ec7c7 507 int desired_lum, deadzone;
8a5b2e90 508
43f52bf2 509 if (avg_lum == -1)
8a5b2e90
HG
510 return;
511
6a6c70b8 512 desired_lum = 170;
1408b847 513 deadzone = 20;
8a5b2e90
HG
514
515 if (sd->autogain_ignore_frames > 0)
516 sd->autogain_ignore_frames--;
43f52bf2
HG
517 else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
518 desired_lum, deadzone))
8a5b2e90 519 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
6a7eba24
JFM
520}
521
56f6f558 522/* JPEG header, part 1 */
cc409c0e 523static const unsigned char pac_jpeg_header1[] = {
56f6f558
MN
524 0xff, 0xd8, /* SOI: Start of Image */
525
526 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
527 0x00, 0x11, /* length = 17 bytes (including this length field) */
528 0x08 /* Precision: 8 */
529 /* 2 bytes is placed here: number of image lines */
530 /* 2 bytes is placed here: samples per line */
327c4abf
HG
531};
532
56f6f558 533/* JPEG header, continued */
cc409c0e 534static const unsigned char pac_jpeg_header2[] = {
56f6f558
MN
535 0x03, /* Number of image components: 3 */
536 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
537 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
538 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
539
540 0xff, 0xda, /* SOS: Start Of Scan */
541 0x00, 0x0c, /* length = 12 bytes (including this length field) */
542 0x03, /* number of components: 3 */
543 0x01, 0x00, /* selector 1, table 0x00 */
544 0x02, 0x11, /* selector 2, table 0x11 */
545 0x03, 0x11, /* selector 3, table 0x11 */
546 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
547 0x00 /* Successive approximation: 0 */
327c4abf
HG
548};
549
cc409c0e 550static void pac_start_frame(struct gspca_dev *gspca_dev,
cc409c0e
MN
551 __u16 lines, __u16 samples_per_line)
552{
553 unsigned char tmpbuf[4];
554
76dd272b 555 gspca_frame_add(gspca_dev, FIRST_PACKET,
cc409c0e
MN
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
76dd272b 563 gspca_frame_add(gspca_dev, INTER_PACKET,
cc409c0e 564 tmpbuf, sizeof(tmpbuf));
76dd272b 565 gspca_frame_add(gspca_dev, INTER_PACKET,
cc409c0e
MN
566 pac_jpeg_header2, sizeof(pac_jpeg_header2));
567}
568
e52a5574 569/* this function is run at interrupt level */
6a7eba24 570static void sd_pkt_scan(struct gspca_dev *gspca_dev,
76dd272b 571 u8 *data, /* isoc packet */
6a7eba24
JFM
572 int len) /* iso packet length */
573{
574 struct sd *sd = (struct sd *) gspca_dev;
b192ca98 575 u8 *image;
327c4abf
HG
576 unsigned char *sof;
577
a6b69e40 578 sof = pac_find_sof(&sd->sof_read, data, len);
327c4abf 579 if (sof) {
327c4abf
HG
580 int n, lum_offset, footer_length;
581
4b8ceb6c
HG
582 /*
583 * 6 bytes after the FF D9 EOF marker a number of lumination
584 * bytes are send corresponding to different parts of the
585 * image, the 14th and 15th byte after the EOF seem to
586 * correspond to the center of the image.
587 */
1408b847
MN
588 lum_offset = 24 + sizeof pac_sof_marker;
589 footer_length = 26;
327c4abf
HG
590
591 /* Finish decoding current frame */
592 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
593 if (n < 0) {
b192ca98 594 gspca_dev->image_len += n;
327c4abf 595 n = 0;
b192ca98
JFM
596 } else {
597 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
327c4abf 598 }
f7059eaa
JFM
599 image = gspca_dev->image;
600 if (image != NULL
b192ca98
JFM
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);
327c4abf
HG
604
605 n = sof - data;
606 len -= n;
607 data = sof;
608
609 /* Get average lumination */
610 if (gspca_dev->last_packet_type == LAST_PACKET &&
038ec7c7
HG
611 n >= lum_offset)
612 atomic_set(&sd->avg_lum, data[-lum_offset] +
327c4abf 613 data[-lum_offset + 1]);
038ec7c7 614 else
327c4abf 615 atomic_set(&sd->avg_lum, -1);
327c4abf
HG
616
617 /* Start the new frame with the jpeg header */
b192ca98 618 pac_start_frame(gspca_dev,
1408b847 619 gspca_dev->height, gspca_dev->width);
6a7eba24 620 }
76dd272b 621 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6a7eba24
JFM
622}
623
2856643e 624#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
32ea3e44
HG
625static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
626 u8 *data, /* interrupt packet data */
627 int len) /* interrupt packet length */
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
aabcdfb6 655static const struct sd_desc sd_desc = {
6a7eba24 656 .name = MODULE_NAME,
6a7eba24 657 .config = sd_config,
012d6b02 658 .init = sd_init,
43f52bf2 659 .init_controls = sd_init_controls,
6a7eba24
JFM
660 .start = sd_start,
661 .stopN = sd_stopN,
6a7eba24 662 .pkt_scan = sd_pkt_scan,
cebf3b67 663 .dq_callback = do_autogain,
2856643e 664#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
32ea3e44
HG
665 .int_pkt_scan = sd_int_pkt_scan,
666#endif
6a7eba24
JFM
667};
668
669/* -- module initialisation -- */
95c967c1 670static const struct usb_device_id device_table[] = {
1408b847
MN
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)},
6a7eba24
JFM
677 {}
678};
679MODULE_DEVICE_TABLE(usb, device_table);
680
681/* -- device connect -- */
95c967c1 682static int sd_probe(struct usb_interface *intf,
6a7eba24
JFM
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,
6a709749
JFM
694#ifdef CONFIG_PM
695 .suspend = gspca_suspend,
696 .resume = gspca_resume,
697#endif
6a7eba24
JFM
698};
699
ecb3b2b3 700module_usb_driver(sd_driver);
This page took 0.493398 seconds and 5 git commands to generate.