2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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
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.
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
22 #define MODULE_NAME "pac7311"
26 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5)
27 static const char version[] = "2.1.5";
29 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
30 MODULE_DESCRIPTION("Pixart PAC7311");
31 MODULE_LICENSE("GPL");
33 /* specific webcam descriptor */
35 struct gspca_dev gspca_dev; /* !! must be the first item */
39 unsigned char brightness;
40 unsigned char contrast;
42 unsigned char autogain;
46 #define AG_CNT_START 13
49 /* V4L2 controls supported by the driver */
50 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
51 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
52 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
53 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
54 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
55 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
56 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
57 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
59 static struct ctrl sd_ctrls[] = {
62 .id = V4L2_CID_BRIGHTNESS,
63 .type = V4L2_CTRL_TYPE_INTEGER,
66 #define BRIGHTNESS_MAX 0x20
67 .maximum = BRIGHTNESS_MAX,
69 #define BRIGHTNESS_DEF 0x10
70 .default_value = BRIGHTNESS_DEF,
72 .set = sd_setbrightness,
73 .get = sd_getbrightness,
77 .id = V4L2_CID_CONTRAST,
78 .type = V4L2_CTRL_TYPE_INTEGER,
83 #define CONTRAST_DEF 127
84 .default_value = CONTRAST_DEF,
86 .set = sd_setcontrast,
87 .get = sd_getcontrast,
91 .id = V4L2_CID_SATURATION,
92 .type = V4L2_CTRL_TYPE_INTEGER,
98 .default_value = COLOR_DEF,
105 .id = V4L2_CID_AUTOGAIN,
106 .type = V4L2_CTRL_TYPE_BOOLEAN,
111 #define AUTOGAIN_DEF 1
112 .default_value = AUTOGAIN_DEF,
114 .set = sd_setautogain,
115 .get = sd_getautogain,
119 static struct v4l2_pix_format vga_mode[] = {
120 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
122 .sizeimage = 160 * 120 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
125 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
127 .sizeimage = 320 * 240 * 3 / 8 + 590,
128 .colorspace = V4L2_COLORSPACE_JPEG,
130 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .sizeimage = 640 * 480 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
137 #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
139 static const __u8 pac7311_jpeg_header[] = {
141 0xff, 0xe0, 0x00, 0x03, 0x20,
142 0xff, 0xc0, 0x00, 0x11, 0x08,
143 0x01, 0xe0, /* 12: height */
144 0x02, 0x80, /* 14: width */
149 0xff, 0xdb, 0x00, 0x84,
150 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
151 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
152 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
153 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
154 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
155 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
156 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
157 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
158 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
159 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
160 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
161 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
162 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
163 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
164 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
166 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
167 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
168 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
169 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
170 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
171 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
172 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
173 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
174 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
175 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
176 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
177 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
178 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
179 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
180 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
181 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
182 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
183 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
184 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
185 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
187 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
188 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
189 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
190 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
191 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
192 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
193 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
194 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
195 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
196 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
197 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
198 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
199 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
200 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
201 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
202 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
203 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
204 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
205 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
206 0x11, 0x00, 0x3f, 0x00
209 static void reg_w(struct usb_device *dev,
211 const char *buffer, __u16 len)
215 memcpy(tmpbuf, buffer, len);
217 usb_sndctrlpipe(dev, 0),
219 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
225 static void pac7311_reg_read(struct usb_device *dev, __u16 index,
229 usb_rcvctrlpipe(dev, 0),
231 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
237 static void pac7311_reg_write(struct usb_device *dev,
245 usb_sndctrlpipe(dev, 0),
247 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
248 value, index, &buf, 1,
252 /* this function is called at probe time */
253 static int sd_config(struct gspca_dev *gspca_dev,
254 const struct usb_device_id *id)
256 struct sd *sd = (struct sd *) gspca_dev;
257 struct usb_device *dev = gspca_dev->dev;
260 PDEBUG(D_CONF, "Find Sensor PAC7311");
261 pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
262 pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
263 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
264 pac7311_reg_write(dev, 0xff, 0x04);
265 pac7311_reg_write(dev, 0x27, 0x80);
266 pac7311_reg_write(dev, 0x28, 0xca);
267 pac7311_reg_write(dev, 0x29, 0x53);
268 pac7311_reg_write(dev, 0x2a, 0x0e);
269 pac7311_reg_write(dev, 0xff, 0x01);
270 pac7311_reg_write(dev, 0x3e, 0x20);
272 cam = &gspca_dev->cam;
273 cam->dev_name = (char *) id->driver_info;
275 cam->cam_mode = vga_mode;
276 cam->nmodes = ARRAY_SIZE(vga_mode);
278 sd->brightness = BRIGHTNESS_DEF;
279 sd->contrast = CONTRAST_DEF;
280 sd->colors = COLOR_DEF;
281 sd->autogain = AUTOGAIN_DEF;
285 static void setbrightness(struct gspca_dev *gspca_dev)
287 struct sd *sd = (struct sd *) gspca_dev;
291 brightness = BRIGHTNESS_MAX - sd->brightness;
292 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
293 /* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
294 pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
295 /* load registers to sensor (Bit 0, auto clear) */
296 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
297 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
300 static void setcontrast(struct gspca_dev *gspca_dev)
302 struct sd *sd = (struct sd *) gspca_dev;
304 pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
305 pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
306 /* load registers to sensor (Bit 0, auto clear) */
307 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
308 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
311 static void setcolors(struct gspca_dev *gspca_dev)
313 struct sd *sd = (struct sd *) gspca_dev;
315 pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
316 pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
317 /* load registers to sensor (Bit 0, auto clear) */
318 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
319 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
322 /* this function is called at open time */
323 static int sd_open(struct gspca_dev *gspca_dev)
325 pac7311_reg_write(gspca_dev->dev, 0x78, 0x00); /* Turn on LED */
329 static void sd_start(struct gspca_dev *gspca_dev)
331 struct usb_device *dev = gspca_dev->dev;
332 struct sd *sd = (struct sd *) gspca_dev;
334 pac7311_reg_write(dev, 0xff, 0x01);
335 reg_w(dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
336 reg_w(dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
337 reg_w(dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
338 reg_w(dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
339 reg_w(dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
340 reg_w(dev, 0x002a, "\x00\x00\x00", 3);
341 reg_w(dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
342 reg_w(dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
343 reg_w(dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
344 reg_w(dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
345 reg_w(dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
346 reg_w(dev, 0x0066, "\xd0\xff", 2);
347 reg_w(dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
348 reg_w(dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
349 reg_w(dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
350 reg_w(dev, 0x008f, "\x18\x20", 2);
351 reg_w(dev, 0x0096, "\x01\x08\x04", 3);
352 reg_w(dev, 0x00a0, "\x44\x44\x44\x04", 4);
353 reg_w(dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
354 reg_w(dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
356 pac7311_reg_write(dev, 0xff, 0x04);
357 pac7311_reg_write(dev, 0x02, 0x04);
358 pac7311_reg_write(dev, 0x03, 0x54);
359 pac7311_reg_write(dev, 0x04, 0x07);
360 pac7311_reg_write(dev, 0x05, 0x2b);
361 pac7311_reg_write(dev, 0x06, 0x09);
362 pac7311_reg_write(dev, 0x07, 0x0f);
363 pac7311_reg_write(dev, 0x08, 0x09);
364 pac7311_reg_write(dev, 0x09, 0x00);
365 pac7311_reg_write(dev, 0x0c, 0x07);
366 pac7311_reg_write(dev, 0x0d, 0x00);
367 pac7311_reg_write(dev, 0x0e, 0x00);
368 pac7311_reg_write(dev, 0x0f, 0x62);
369 pac7311_reg_write(dev, 0x10, 0x08);
370 pac7311_reg_write(dev, 0x12, 0x07);
371 pac7311_reg_write(dev, 0x13, 0x00);
372 pac7311_reg_write(dev, 0x14, 0x00);
373 pac7311_reg_write(dev, 0x15, 0x00);
374 pac7311_reg_write(dev, 0x16, 0x00);
375 pac7311_reg_write(dev, 0x17, 0x00);
376 pac7311_reg_write(dev, 0x18, 0x00);
377 pac7311_reg_write(dev, 0x19, 0x00);
378 pac7311_reg_write(dev, 0x1a, 0x00);
379 pac7311_reg_write(dev, 0x1b, 0x03);
380 pac7311_reg_write(dev, 0x1c, 0xa0);
381 pac7311_reg_write(dev, 0x1d, 0x01);
382 pac7311_reg_write(dev, 0x1e, 0xf4);
383 pac7311_reg_write(dev, 0x21, 0x00);
384 pac7311_reg_write(dev, 0x22, 0x08);
385 pac7311_reg_write(dev, 0x24, 0x03);
386 pac7311_reg_write(dev, 0x26, 0x00);
387 pac7311_reg_write(dev, 0x27, 0x01);
388 pac7311_reg_write(dev, 0x28, 0xca);
389 pac7311_reg_write(dev, 0x29, 0x10);
390 pac7311_reg_write(dev, 0x2a, 0x06);
391 pac7311_reg_write(dev, 0x2b, 0x78);
392 pac7311_reg_write(dev, 0x2c, 0x00);
393 pac7311_reg_write(dev, 0x2d, 0x00);
394 pac7311_reg_write(dev, 0x2e, 0x00);
395 pac7311_reg_write(dev, 0x2f, 0x00);
396 pac7311_reg_write(dev, 0x30, 0x23);
397 pac7311_reg_write(dev, 0x31, 0x28);
398 pac7311_reg_write(dev, 0x32, 0x04);
399 pac7311_reg_write(dev, 0x33, 0x11);
400 pac7311_reg_write(dev, 0x34, 0x00);
401 pac7311_reg_write(dev, 0x35, 0x00);
402 pac7311_reg_write(dev, 0x11, 0x01);
403 setcontrast(gspca_dev);
404 setbrightness(gspca_dev);
405 setcolors(gspca_dev);
407 /* set correct resolution */
408 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
409 case 2: /* 160x120 */
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, 0x09);
414 pac7311_reg_write(dev, 0x17, 0x20);
415 pac7311_reg_write(dev, 0x1b, 0x00);
416 /* pac7311_reg_write(dev, 0x80, 0x69); */
417 pac7311_reg_write(dev, 0x87, 0x10);
419 case 1: /* 320x240 */
420 pac7311_reg_write(dev, 0xff, 0x04);
421 pac7311_reg_write(dev, 0x02, 0x03);
422 pac7311_reg_write(dev, 0xff, 0x01);
423 pac7311_reg_write(dev, 0x08, 0x09);
424 pac7311_reg_write(dev, 0x17, 0x30);
425 /* pac7311_reg_write(dev, 0x80, 0x3f); */
426 pac7311_reg_write(dev, 0x87, 0x11);
428 case 0: /* 640x480 */
429 pac7311_reg_write(dev, 0xff, 0x04);
430 pac7311_reg_write(dev, 0x02, 0x03);
431 pac7311_reg_write(dev, 0xff, 0x01);
432 pac7311_reg_write(dev, 0x08, 0x08);
433 pac7311_reg_write(dev, 0x17, 0x00);
434 /* pac7311_reg_write(dev, 0x80, 0x1c); */
435 pac7311_reg_write(dev, 0x87, 0x12);
440 pac7311_reg_write(dev, 0xff, 0x01);
441 pac7311_reg_write(dev, 0x78, 0x04);
442 pac7311_reg_write(dev, 0x78, 0x05);
445 sd->ag_cnt = AG_CNT_START;
452 static void sd_stopN(struct gspca_dev *gspca_dev)
454 struct usb_device *dev = gspca_dev->dev;
456 pac7311_reg_write(dev, 0xff, 0x04);
457 pac7311_reg_write(dev, 0x27, 0x80);
458 pac7311_reg_write(dev, 0x28, 0xca);
459 pac7311_reg_write(dev, 0x29, 0x53);
460 pac7311_reg_write(dev, 0x2a, 0x0e);
461 pac7311_reg_write(dev, 0xff, 0x01);
462 pac7311_reg_write(dev, 0x3e, 0x20);
463 pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
464 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
465 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
468 static void sd_stop0(struct gspca_dev *gspca_dev)
472 /* this function is called at close time */
473 static void sd_close(struct gspca_dev *gspca_dev)
475 struct usb_device *dev = gspca_dev->dev;
477 pac7311_reg_write(dev, 0xff, 0x04);
478 pac7311_reg_write(dev, 0x27, 0x80);
479 pac7311_reg_write(dev, 0x28, 0xca);
480 pac7311_reg_write(dev, 0x29, 0x53);
481 pac7311_reg_write(dev, 0x2a, 0x0e);
482 pac7311_reg_write(dev, 0xff, 0x01);
483 pac7311_reg_write(dev, 0x3e, 0x20);
484 pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
485 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
486 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
489 static void setautogain(struct gspca_dev *gspca_dev, int luma)
497 pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
499 PDEBUG(D_FRAM, "luma mean %d", luma);
500 if (luma < luma_mean - luma_delta ||
501 luma > luma_mean + luma_delta) {
502 Gbright += (luma_mean - luma) >> spring;
505 else if (Gbright < 4)
507 PDEBUG(D_FRAM, "gbright %d", Gbright);
508 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
509 pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
510 /* load registers to sensor (Bit 0, auto clear) */
511 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
515 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
516 struct gspca_frame *frame, /* target */
517 __u8 *data, /* isoc packet */
518 int len) /* iso packet length */
520 struct sd *sd = (struct sd *) gspca_dev;
521 unsigned char tmpbuf[4];
526 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
532 for (p = 0; p < len - 6; p++) {
533 if ((data[0 + p] == 0xff)
534 && (data[1 + p] == 0xff)
535 && (data[2 + p] == 0x00)
536 && (data[3 + p] == 0xff)
537 && (data[4 + p] == 0x96)) {
540 if (sd->ag_cnt >= 0 && p > 28) {
541 sd->avg_lum += data[p - 23];
542 if (--sd->ag_cnt < 0) {
543 sd->ag_cnt = AG_CNT_START;
544 setautogain(gspca_dev,
545 sd->avg_lum / AG_CNT_START);
550 /* copy the end of data to the current frame */
551 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
554 /* put the JPEG header in the new frame */
555 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
556 (unsigned char *) pac7311_jpeg_header,
558 tmpbuf[0] = gspca_dev->height >> 8;
559 tmpbuf[1] = gspca_dev->height & 0xff;
560 tmpbuf[2] = gspca_dev->width >> 8;
561 tmpbuf[3] = gspca_dev->width & 0xff;
562 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
564 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
565 (unsigned char *) &pac7311_jpeg_header[16],
566 PAC7311_JPEG_HEADER_SIZE - 16);
575 /* remove the 'ff ff ff xx' sequences */
582 if (data[0] == 0xff) {
585 frame->data_end -= 2;
590 && data[1] == 0xff) {
593 frame->data_end -= 1;
597 for (i = 0; i < len - 4; i++) {
599 && data[i + 1] == 0xff
600 && data[i + 2] == 0xff) {
601 memmove(&data[i], &data[i + 4], len - i - 4);
606 if (data[len - 4] == 0xff) {
607 if (data[len - 3] == 0xff
608 && data[len - 2] == 0xff) {
611 } else if (data[len - 3] == 0xff) {
612 if (data[len - 2] == 0xff
613 && data[len - 1] == 0xff)
615 } else if (data[len - 2] == 0xff) {
616 if (data[len - 1] == 0xff)
618 } else if (data[len - 1] == 0xff)
621 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
624 static void getbrightness(struct gspca_dev *gspca_dev)
626 /* __u8 brightness = 0;
628 pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
629 spca50x->brightness = brightness;
630 return spca50x->brightness; */
631 /* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
636 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
638 struct sd *sd = (struct sd *) gspca_dev;
640 sd->brightness = val;
641 if (gspca_dev->streaming)
642 setbrightness(gspca_dev);
646 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
648 struct sd *sd = (struct sd *) gspca_dev;
650 getbrightness(gspca_dev);
651 *val = sd->brightness;
655 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
657 struct sd *sd = (struct sd *) gspca_dev;
660 if (gspca_dev->streaming)
661 setcontrast(gspca_dev);
665 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
667 struct sd *sd = (struct sd *) gspca_dev;
669 /* getcontrast(gspca_dev); */
674 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
676 struct sd *sd = (struct sd *) gspca_dev;
679 if (gspca_dev->streaming)
680 setcolors(gspca_dev);
684 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
686 struct sd *sd = (struct sd *) gspca_dev;
688 /* getcolors(gspca_dev); */
693 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
695 struct sd *sd = (struct sd *) gspca_dev;
699 sd->ag_cnt = AG_CNT_START;
707 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
709 struct sd *sd = (struct sd *) gspca_dev;
715 /* sub-driver description */
716 static struct sd_desc sd_desc = {
719 .nctrls = ARRAY_SIZE(sd_ctrls),
726 .pkt_scan = sd_pkt_scan,
729 /* -- module initialisation -- */
730 #define DVNM(name) .driver_info = (kernel_ulong_t) name
731 static __devinitdata struct usb_device_id device_table[] = {
732 {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
733 {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
734 {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
735 {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
736 {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
737 /* and also ', Trust WB-3350p, SIGMA cam 2350' */
738 {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
739 {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
742 MODULE_DEVICE_TABLE(usb, device_table);
744 /* -- device connect -- */
745 static int sd_probe(struct usb_interface *intf,
746 const struct usb_device_id *id)
748 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
752 static struct usb_driver sd_driver = {
754 .id_table = device_table,
756 .disconnect = gspca_disconnect,
759 /* -- module insert / remove -- */
760 static int __init sd_mod_init(void)
762 if (usb_register(&sd_driver) < 0)
764 PDEBUG(D_PROBE, "v%s registered", version);
767 static void __exit sd_mod_exit(void)
769 usb_deregister(&sd_driver);
770 PDEBUG(D_PROBE, "deregistered");
773 module_init(sd_mod_init);
774 module_exit(sd_mod_exit);