aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/pac7311.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-06-30 14:50:11 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:14:49 -0400
commit6a7eba24e4f0ff725d33159f6265e3a79d53a833 (patch)
tree3e50d669cb91affbcfad9333d74ddc452783094f /drivers/media/video/gspca/pac7311.c
parentd43fa32fec442571f10f5d0c3b553413288728de (diff)
V4L/DVB (8157): gspca: all subdrivers
- remaning subdrivers added - remove the decoding helper and some specific frame decodings Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/pac7311.c')
-rw-r--r--drivers/media/video/gspca/pac7311.c754
1 files changed, 754 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
new file mode 100644
index 000000000000..8f51976db995
--- /dev/null
+++ b/drivers/media/video/gspca/pac7311.c
@@ -0,0 +1,754 @@
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
22#define MODULE_NAME "pac7311"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
27static const char version[] = "2.1.0";
28
29MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
30MODULE_DESCRIPTION("Pixart PAC7311");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 int avg_lum;
38
39 unsigned char brightness;
40#define BRIGHTNESS_MAX 0x20
41 unsigned char contrast;
42 unsigned char colors;
43 unsigned char autogain;
44
45 char ffseq;
46 signed char ag_cnt;
47#define AG_CNT_START 13
48};
49
50/* V4L2 controls supported by the driver */
51static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
53static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
54static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
55static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
57static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
59
60static struct ctrl sd_ctrls[] = {
61#define SD_BRIGHTNESS 0
62 {
63 {
64 .id = V4L2_CID_BRIGHTNESS,
65 .type = V4L2_CTRL_TYPE_INTEGER,
66 .name = "Brightness",
67 .minimum = 0,
68 .maximum = BRIGHTNESS_MAX,
69 .step = 1,
70 .default_value = 0x10,
71 },
72 .set = sd_setbrightness,
73 .get = sd_getbrightness,
74 },
75#define SD_CONTRAST 1
76 {
77 {
78 .id = V4L2_CID_CONTRAST,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Contrast",
81 .minimum = 0,
82 .maximum = 255,
83 .step = 1,
84 .default_value = 127,
85 },
86 .set = sd_setcontrast,
87 .get = sd_getcontrast,
88 },
89#define SD_COLOR 2
90 {
91 {
92 .id = V4L2_CID_SATURATION,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Color",
95 .minimum = 0,
96 .maximum = 255,
97 .step = 1,
98 .default_value = 127,
99 },
100 .set = sd_setcolors,
101 .get = sd_getcolors,
102 },
103#define SD_AUTOGAIN 3
104 {
105 {
106 .id = V4L2_CID_AUTOGAIN,
107 .type = V4L2_CTRL_TYPE_BOOLEAN,
108 .name = "Auto Gain",
109 .minimum = 0,
110 .maximum = 1,
111 .step = 1,
112 .default_value = 1,
113 },
114 .set = sd_setautogain,
115 .get = sd_getautogain,
116 },
117};
118
119static struct cam_mode vga_mode[] = {
120 {V4L2_PIX_FMT_JPEG, 160, 120, 2},
121 {V4L2_PIX_FMT_JPEG, 320, 240, 1},
122 {V4L2_PIX_FMT_JPEG, 640, 480, 0},
123};
124
125#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
126
127const unsigned char pac7311_jpeg_header[] = {
128 0xff, 0xd8,
129 0xff, 0xe0, 0x00, 0x03, 0x20,
130 0xff, 0xc0, 0x00, 0x11, 0x08,
131 0x01, 0xe0, /* 12: height */
132 0x02, 0x80, /* 14: width */
133 0x03, /* 16 */
134 0x01, 0x21, 0x00,
135 0x02, 0x11, 0x01,
136 0x03, 0x11, 0x01,
137 0xff, 0xdb, 0x00, 0x84,
138 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
139 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
140 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
141 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
142 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
143 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
144 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
145 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
146 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
147 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
148 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
149 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
150 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
151 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
152 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
154 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
155 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
156 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
157 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
158 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
159 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
160 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
161 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
162 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
163 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
164 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
165 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
166 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
167 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
168 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
169 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
170 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
171 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
172 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
173 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
175 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
176 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
177 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
178 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
179 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
180 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
181 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
182 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
183 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
184 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
185 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
186 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
187 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
188 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
189 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
190 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
191 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
192 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
193 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
194 0x11, 0x00, 0x3f, 0x00
195};
196
197static void reg_w(struct usb_device *dev,
198 __u16 req,
199 __u16 value,
200 __u16 index,
201 __u8 *buffer, __u16 length)
202{
203 usb_control_msg(dev,
204 usb_sndctrlpipe(dev, 0),
205 req,
206 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
207 value, index, buffer, length,
208 500);
209}
210
211static void pac7311_reg_read(struct usb_device *dev, __u16 index,
212 __u8 *buffer)
213{
214 usb_control_msg(dev,
215 usb_rcvctrlpipe(dev, 0),
216 0, /* request */
217 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
218 0, /* value */
219 index, buffer, 1,
220 500);
221}
222
223static void pac7311_reg_write(struct usb_device *dev,
224 __u16 index,
225 __u8 value)
226{
227 __u8 buf;
228
229 buf = value;
230 reg_w(dev, 0x00, value, index, &buf, 1);
231}
232
233/* this function is called at probe time */
234static int sd_config(struct gspca_dev *gspca_dev,
235 const struct usb_device_id *id)
236{
237 struct sd *sd = (struct sd *) gspca_dev;
238 struct usb_device *dev = gspca_dev->dev;
239 struct cam *cam;
240
241 PDEBUG(D_CONF, "Find Sensor PAC7311");
242 pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
243 pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
244 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
245 pac7311_reg_write(dev, 0xff, 0x04);
246 pac7311_reg_write(dev, 0x27, 0x80);
247 pac7311_reg_write(dev, 0x28, 0xca);
248 pac7311_reg_write(dev, 0x29, 0x53);
249 pac7311_reg_write(dev, 0x2a, 0x0e);
250 pac7311_reg_write(dev, 0xff, 0x01);
251 pac7311_reg_write(dev, 0x3e, 0x20);
252
253 cam = &gspca_dev->cam;
254 cam->dev_name = (char *) id->driver_info;
255 cam->epaddr = 0x05;
256 cam->cam_mode = vga_mode;
257 cam->nmodes = ARRAY_SIZE(vga_mode);
258
259 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
260 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
261 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
262 sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
263 return 0;
264}
265
266static void setbrightness(struct gspca_dev *gspca_dev)
267{
268 struct sd *sd = (struct sd *) gspca_dev;
269 int brightness;
270
271/*jfm: inverted?*/
272 brightness = BRIGHTNESS_MAX - sd->brightness;
273 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
274 /* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
275 pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
276 /* load registers to sensor (Bit 0, auto clear) */
277 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
278 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
279}
280
281static void setcontrast(struct gspca_dev *gspca_dev)
282{
283 struct sd *sd = (struct sd *) gspca_dev;
284
285 pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
286 pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
287 /* load registers to sensor (Bit 0, auto clear) */
288 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
289 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
290}
291
292static void setcolors(struct gspca_dev *gspca_dev)
293{
294 struct sd *sd = (struct sd *) gspca_dev;
295
296 pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
297 pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
298 /* load registers to sensor (Bit 0, auto clear) */
299 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
300 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
301}
302
303/* this function is called at open time */
304static int sd_open(struct gspca_dev *gspca_dev)
305{
306 pac7311_reg_write(gspca_dev->dev, 0x78, 0x00); /* Turn on LED */
307 return 0;
308}
309
310static void sd_start(struct gspca_dev *gspca_dev)
311{
312 struct usb_device *dev = gspca_dev->dev;
313 struct sd *sd = (struct sd *) gspca_dev;
314
315 pac7311_reg_write(dev, 0xff, 0x01);
316 reg_w(dev, 0x01, 0, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
317 reg_w(dev, 0x01, 0, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
318 reg_w(dev, 0x01, 0, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
319 reg_w(dev, 0x01, 0, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
320 reg_w(dev, 0x01, 0, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
321 reg_w(dev, 0x01, 0, 0x002a, "\x00\x00\x00", 3);
322 reg_w(dev, 0x01, 0, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
323 reg_w(dev, 0x01, 0, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
324 reg_w(dev, 0x01, 0, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
325 reg_w(dev, 0x01, 0, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
326 reg_w(dev, 0x01, 0, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
327 reg_w(dev, 0x01, 0, 0x0066, "\xd0\xff", 2);
328 reg_w(dev, 0x01, 0, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
329 reg_w(dev, 0x01, 0, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
330 reg_w(dev, 0x01, 0, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
331 reg_w(dev, 0x01, 0, 0x008f, "\x18\x20", 2);
332 reg_w(dev, 0x01, 0, 0x0096, "\x01\x08\x04", 3);
333 reg_w(dev, 0x01, 0, 0x00a0, "\x44\x44\x44\x04", 4);
334 reg_w(dev, 0x01, 0, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
335 reg_w(dev, 0x01, 0, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
336
337 pac7311_reg_write(dev, 0xff, 0x04);
338 pac7311_reg_write(dev, 0x02, 0x04);
339 pac7311_reg_write(dev, 0x03, 0x54);
340 pac7311_reg_write(dev, 0x04, 0x07);
341 pac7311_reg_write(dev, 0x05, 0x2b);
342 pac7311_reg_write(dev, 0x06, 0x09);
343 pac7311_reg_write(dev, 0x07, 0x0f);
344 pac7311_reg_write(dev, 0x08, 0x09);
345 pac7311_reg_write(dev, 0x09, 0x00);
346 pac7311_reg_write(dev, 0x0c, 0x07);
347 pac7311_reg_write(dev, 0x0d, 0x00);
348 pac7311_reg_write(dev, 0x0e, 0x00);
349 pac7311_reg_write(dev, 0x0f, 0x62);
350 pac7311_reg_write(dev, 0x10, 0x08);
351 pac7311_reg_write(dev, 0x12, 0x07);
352 pac7311_reg_write(dev, 0x13, 0x00);
353 pac7311_reg_write(dev, 0x14, 0x00);
354 pac7311_reg_write(dev, 0x15, 0x00);
355 pac7311_reg_write(dev, 0x16, 0x00);
356 pac7311_reg_write(dev, 0x17, 0x00);
357 pac7311_reg_write(dev, 0x18, 0x00);
358 pac7311_reg_write(dev, 0x19, 0x00);
359 pac7311_reg_write(dev, 0x1a, 0x00);
360 pac7311_reg_write(dev, 0x1b, 0x03);
361 pac7311_reg_write(dev, 0x1c, 0xa0);
362 pac7311_reg_write(dev, 0x1d, 0x01);
363 pac7311_reg_write(dev, 0x1e, 0xf4);
364 pac7311_reg_write(dev, 0x21, 0x00);
365 pac7311_reg_write(dev, 0x22, 0x08);
366 pac7311_reg_write(dev, 0x24, 0x03);
367 pac7311_reg_write(dev, 0x26, 0x00);
368 pac7311_reg_write(dev, 0x27, 0x01);
369 pac7311_reg_write(dev, 0x28, 0xca);
370 pac7311_reg_write(dev, 0x29, 0x10);
371 pac7311_reg_write(dev, 0x2a, 0x06);
372 pac7311_reg_write(dev, 0x2b, 0x78);
373 pac7311_reg_write(dev, 0x2c, 0x00);
374 pac7311_reg_write(dev, 0x2d, 0x00);
375 pac7311_reg_write(dev, 0x2e, 0x00);
376 pac7311_reg_write(dev, 0x2f, 0x00);
377 pac7311_reg_write(dev, 0x30, 0x23);
378 pac7311_reg_write(dev, 0x31, 0x28);
379 pac7311_reg_write(dev, 0x32, 0x04);
380 pac7311_reg_write(dev, 0x33, 0x11);
381 pac7311_reg_write(dev, 0x34, 0x00);
382 pac7311_reg_write(dev, 0x35, 0x00);
383 pac7311_reg_write(dev, 0x11, 0x01);
384 setcontrast(gspca_dev);
385 setbrightness(gspca_dev);
386 setcolors(gspca_dev);
387
388 /* set correct resolution */
389 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
390 case 2: /* 160x120 */
391 pac7311_reg_write(dev, 0xff, 0x04);
392 pac7311_reg_write(dev, 0x02, 0x03);
393 pac7311_reg_write(dev, 0xff, 0x01);
394 pac7311_reg_write(dev, 0x08, 0x09);
395 pac7311_reg_write(dev, 0x17, 0x20);
396 pac7311_reg_write(dev, 0x1b, 0x00);
397/* pac7311_reg_write(dev, 0x80, 0x69); */
398 pac7311_reg_write(dev, 0x87, 0x10);
399 break;
400 case 1: /* 320x240 */
401 pac7311_reg_write(dev, 0xff, 0x04);
402 pac7311_reg_write(dev, 0x02, 0x03);
403 pac7311_reg_write(dev, 0xff, 0x01);
404 pac7311_reg_write(dev, 0x08, 0x09);
405 pac7311_reg_write(dev, 0x17, 0x30);
406/* pac7311_reg_write(dev, 0x80, 0x3f); */
407 pac7311_reg_write(dev, 0x87, 0x11);
408 break;
409 case 0: /* 640x480 */
410 pac7311_reg_write(dev, 0xff, 0x04);
411 pac7311_reg_write(dev, 0x02, 0x03);
412 pac7311_reg_write(dev, 0xff, 0x01);
413 pac7311_reg_write(dev, 0x08, 0x08);
414 pac7311_reg_write(dev, 0x17, 0x00);
415/* pac7311_reg_write(dev, 0x80, 0x1c); */
416 pac7311_reg_write(dev, 0x87, 0x12);
417 break;
418 }
419
420 /* start stream */
421 pac7311_reg_write(dev, 0xff, 0x01);
422 pac7311_reg_write(dev, 0x78, 0x04);
423 pac7311_reg_write(dev, 0x78, 0x05);
424
425 if (sd->autogain) {
426 sd->ag_cnt = AG_CNT_START;
427 sd->avg_lum = 0;
428 } else {
429 sd->ag_cnt = -1;
430 }
431}
432
433static void sd_stopN(struct gspca_dev *gspca_dev)
434{
435 struct usb_device *dev = gspca_dev->dev;
436
437 pac7311_reg_write(dev, 0xff, 0x04);
438 pac7311_reg_write(dev, 0x27, 0x80);
439 pac7311_reg_write(dev, 0x28, 0xca);
440 pac7311_reg_write(dev, 0x29, 0x53);
441 pac7311_reg_write(dev, 0x2a, 0x0e);
442 pac7311_reg_write(dev, 0xff, 0x01);
443 pac7311_reg_write(dev, 0x3e, 0x20);
444 pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
445 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
446 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
447}
448
449static void sd_stop0(struct gspca_dev *gspca_dev)
450{
451}
452
453/* this function is called at close time */
454static void sd_close(struct gspca_dev *gspca_dev)
455{
456 struct usb_device *dev = gspca_dev->dev;
457
458 pac7311_reg_write(dev, 0xff, 0x04);
459 pac7311_reg_write(dev, 0x27, 0x80);
460 pac7311_reg_write(dev, 0x28, 0xca);
461 pac7311_reg_write(dev, 0x29, 0x53);
462 pac7311_reg_write(dev, 0x2a, 0x0e);
463 pac7311_reg_write(dev, 0xff, 0x01);
464 pac7311_reg_write(dev, 0x3e, 0x20);
465 pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
466 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
467 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
468}
469
470static void setautogain(struct gspca_dev *gspca_dev, int luma)
471{
472 int luma_mean = 128;
473 int luma_delta = 20;
474 __u8 spring = 5;
475 __u8 Pxclk;
476 int Gbright;
477
478 pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
479 Gbright = Pxclk;
480 PDEBUG(D_FRAM, "luma mean %d", luma);
481 if (luma < luma_mean - luma_delta ||
482 luma > luma_mean + luma_delta) {
483 Gbright += (luma_mean - luma) >> spring;
484 if (Gbright > 0x1a)
485 Gbright = 0x1a;
486 else if (Gbright < 4)
487 Gbright = 4;
488 PDEBUG(D_FRAM, "gbright %d", Gbright);
489 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
490 pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
491 /* load registers to sensor (Bit 0, auto clear) */
492 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
493 }
494}
495
496static void sd_pkt_scan(struct gspca_dev *gspca_dev,
497 struct gspca_frame *frame, /* target */
498 unsigned char *data, /* isoc packet */
499 int len) /* iso packet length */
500{
501 struct sd *sd = (struct sd *) gspca_dev;
502 unsigned char tmpbuf[4];
503 int i, p, ffseq;
504
505/* if (len < 5) { */
506 if (len < 6) {
507/* gspca_dev->last_packet_type = DISCARD_PACKET; */
508 return;
509 }
510
511 ffseq = sd->ffseq;
512
513 for (p = 0; p < len - 6; p++) {
514 if ((data[0 + p] == 0xff)
515 && (data[1 + p] == 0xff)
516 && (data[2 + p] == 0x00)
517 && (data[3 + p] == 0xff)
518 && (data[4 + p] == 0x96)) {
519
520 /* start of frame */
521 if (sd->ag_cnt >= 0 && p > 28) {
522 sd->avg_lum += data[p - 23];
523 if (--sd->ag_cnt < 0) {
524 sd->ag_cnt = AG_CNT_START;
525 setautogain(gspca_dev,
526 sd->avg_lum / AG_CNT_START);
527 sd->avg_lum = 0;
528 }
529 }
530
531 /* copy the end of data to the current frame */
532 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
533 data, p);
534
535 /* put the JPEG header in the new frame */
536 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
537 (unsigned char *) pac7311_jpeg_header,
538 12);
539 tmpbuf[0] = gspca_dev->height >> 8;
540 tmpbuf[1] = gspca_dev->height & 0xff;
541 tmpbuf[2] = gspca_dev->width >> 8;
542 tmpbuf[3] = gspca_dev->width & 0xff;
543 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
544 tmpbuf, 4);
545 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
546 (unsigned char *) &pac7311_jpeg_header[16],
547 PAC7311_JPEG_HEADER_SIZE - 16);
548
549 data += p + 7;
550 len -= p + 7;
551 ffseq = 0;
552 break;
553 }
554 }
555
556 /* remove the 'ff ff ff xx' sequences */
557 switch (ffseq) {
558 case 3:
559 data += 1;
560 len -= 1;
561 break;
562 case 2:
563 if (data[0] == 0xff) {
564 data += 2;
565 len -= 2;
566 frame->data_end -= 2;
567 }
568 break;
569 case 1:
570 if (data[0] == 0xff
571 && data[1] == 0xff) {
572 data += 3;
573 len -= 3;
574 frame->data_end -= 1;
575 }
576 break;
577 }
578 for (i = 0; i < len - 4; i++) {
579 if (data[i] == 0xff
580 && data[i + 1] == 0xff
581 && data[i + 2] == 0xff) {
582 memmove(&data[i], &data[i + 4], len - i - 4);
583 len -= 4;
584 }
585 }
586 ffseq = 0;
587 if (data[len - 4] == 0xff) {
588 if (data[len - 3] == 0xff
589 && data[len - 2] == 0xff) {
590 len -= 4;
591 }
592 } else if (data[len - 3] == 0xff) {
593 if (data[len - 2] == 0xff
594 && data[len - 1] == 0xff)
595 ffseq = 3;
596 } else if (data[len - 2] == 0xff) {
597 if (data[len - 1] == 0xff)
598 ffseq = 2;
599 } else if (data[len - 1] == 0xff)
600 ffseq = 1;
601 sd->ffseq = ffseq;
602 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
603}
604
605static void getbrightness(struct gspca_dev *gspca_dev)
606{
607/* __u8 brightness = 0;
608
609 pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
610 spca50x->brightness = brightness;
611 return spca50x->brightness; */
612/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
613}
614
615
616
617static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
618{
619 struct sd *sd = (struct sd *) gspca_dev;
620
621 sd->brightness = val;
622 if (gspca_dev->streaming)
623 setbrightness(gspca_dev);
624 return 0;
625}
626
627static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
628{
629 struct sd *sd = (struct sd *) gspca_dev;
630
631 getbrightness(gspca_dev);
632 *val = sd->brightness;
633 return 0;
634}
635
636static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639
640 sd->contrast = val;
641 if (gspca_dev->streaming)
642 setcontrast(gspca_dev);
643 return 0;
644}
645
646static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
647{
648 struct sd *sd = (struct sd *) gspca_dev;
649
650/* getcontrast(gspca_dev); */
651 *val = sd->contrast;
652 return 0;
653}
654
655static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
656{
657 struct sd *sd = (struct sd *) gspca_dev;
658
659 sd->colors = val;
660 if (gspca_dev->streaming)
661 setcolors(gspca_dev);
662 return 0;
663}
664
665static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
666{
667 struct sd *sd = (struct sd *) gspca_dev;
668
669/* getcolors(gspca_dev); */
670 *val = sd->colors;
671 return 0;
672}
673
674static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
675{
676 struct sd *sd = (struct sd *) gspca_dev;
677
678 sd->autogain = val;
679 if (val) {
680 sd->ag_cnt = AG_CNT_START;
681 sd->avg_lum = 0;
682 } else {
683 sd->ag_cnt = -1;
684 }
685 return 0;
686}
687
688static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691
692 *val = sd->autogain;
693 return 0;
694}
695
696/* sub-driver description */
697static struct sd_desc sd_desc = {
698 .name = MODULE_NAME,
699 .ctrls = sd_ctrls,
700 .nctrls = ARRAY_SIZE(sd_ctrls),
701 .config = sd_config,
702 .open = sd_open,
703 .start = sd_start,
704 .stopN = sd_stopN,
705 .stop0 = sd_stop0,
706 .close = sd_close,
707 .pkt_scan = sd_pkt_scan,
708};
709
710/* -- module initialisation -- */
711#define DVNM(name) .driver_info = (kernel_ulong_t) name
712static __devinitdata struct usb_device_id device_table[] = {
713 {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
714 {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
715 {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
716 {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
717 {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350")},
718 {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
719 {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
720 {}
721};
722MODULE_DEVICE_TABLE(usb, device_table);
723
724/* -- device connect -- */
725static int sd_probe(struct usb_interface *intf,
726 const struct usb_device_id *id)
727{
728 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
729 THIS_MODULE);
730}
731
732static struct usb_driver sd_driver = {
733 .name = MODULE_NAME,
734 .id_table = device_table,
735 .probe = sd_probe,
736 .disconnect = gspca_disconnect,
737};
738
739/* -- module insert / remove -- */
740static int __init sd_mod_init(void)
741{
742 if (usb_register(&sd_driver) < 0)
743 return -1;
744 PDEBUG(D_PROBE, "v%s registered", version);
745 return 0;
746}
747static void __exit sd_mod_exit(void)
748{
749 usb_deregister(&sd_driver);
750 PDEBUG(D_PROBE, "deregistered");
751}
752
753module_init(sd_mod_init);
754module_exit(sd_mod_exit);