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, 4)
27 static const char version[] = "2.1.4";
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 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},
125 #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
127 static const __u8 pac7311_jpeg_header[] = {
129 0xff, 0xe0, 0x00, 0x03, 0x20,
130 0xff, 0xc0, 0x00, 0x11, 0x08,
131 0x01, 0xe0, /* 12: height */
132 0x02, 0x80, /* 14: width */
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
197 static void reg_w(struct usb_device *dev,
199 const char *buffer, __u16 len)
203 memcpy(tmpbuf, buffer, len);
205 usb_sndctrlpipe(dev, 0),
207 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
213 static void pac7311_reg_read(struct usb_device *dev, __u16 index,
217 usb_rcvctrlpipe(dev, 0),
219 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
225 static void pac7311_reg_write(struct usb_device *dev,
233 usb_sndctrlpipe(dev, 0),
235 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236 value, index, &buf, 1,
240 /* this function is called at probe time */
241 static int sd_config(struct gspca_dev *gspca_dev,
242 const struct usb_device_id *id)
244 struct sd *sd = (struct sd *) gspca_dev;
245 struct usb_device *dev = gspca_dev->dev;
248 PDEBUG(D_CONF, "Find Sensor PAC7311");
249 pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
250 pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
251 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
252 pac7311_reg_write(dev, 0xff, 0x04);
253 pac7311_reg_write(dev, 0x27, 0x80);
254 pac7311_reg_write(dev, 0x28, 0xca);
255 pac7311_reg_write(dev, 0x29, 0x53);
256 pac7311_reg_write(dev, 0x2a, 0x0e);
257 pac7311_reg_write(dev, 0xff, 0x01);
258 pac7311_reg_write(dev, 0x3e, 0x20);
260 cam = &gspca_dev->cam;
261 cam->dev_name = (char *) id->driver_info;
263 cam->cam_mode = vga_mode;
264 cam->nmodes = ARRAY_SIZE(vga_mode);
266 sd->brightness = BRIGHTNESS_DEF;
267 sd->contrast = CONTRAST_DEF;
268 sd->colors = COLOR_DEF;
269 sd->autogain = AUTOGAIN_DEF;
273 static void setbrightness(struct gspca_dev *gspca_dev)
275 struct sd *sd = (struct sd *) gspca_dev;
279 brightness = BRIGHTNESS_MAX - sd->brightness;
280 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
281 /* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
282 pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
283 /* load registers to sensor (Bit 0, auto clear) */
284 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
285 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
288 static void setcontrast(struct gspca_dev *gspca_dev)
290 struct sd *sd = (struct sd *) gspca_dev;
292 pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
293 pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
294 /* load registers to sensor (Bit 0, auto clear) */
295 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
296 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
299 static void setcolors(struct gspca_dev *gspca_dev)
301 struct sd *sd = (struct sd *) gspca_dev;
303 pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
304 pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
305 /* load registers to sensor (Bit 0, auto clear) */
306 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
307 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
310 /* this function is called at open time */
311 static int sd_open(struct gspca_dev *gspca_dev)
313 pac7311_reg_write(gspca_dev->dev, 0x78, 0x00); /* Turn on LED */
317 static void sd_start(struct gspca_dev *gspca_dev)
319 struct usb_device *dev = gspca_dev->dev;
320 struct sd *sd = (struct sd *) gspca_dev;
322 pac7311_reg_write(dev, 0xff, 0x01);
323 reg_w(dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
324 reg_w(dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
325 reg_w(dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
326 reg_w(dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
327 reg_w(dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
328 reg_w(dev, 0x002a, "\x00\x00\x00", 3);
329 reg_w(dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
330 reg_w(dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
331 reg_w(dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
332 reg_w(dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
333 reg_w(dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
334 reg_w(dev, 0x0066, "\xd0\xff", 2);
335 reg_w(dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
336 reg_w(dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
337 reg_w(dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
338 reg_w(dev, 0x008f, "\x18\x20", 2);
339 reg_w(dev, 0x0096, "\x01\x08\x04", 3);
340 reg_w(dev, 0x00a0, "\x44\x44\x44\x04", 4);
341 reg_w(dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
342 reg_w(dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
344 pac7311_reg_write(dev, 0xff, 0x04);
345 pac7311_reg_write(dev, 0x02, 0x04);
346 pac7311_reg_write(dev, 0x03, 0x54);
347 pac7311_reg_write(dev, 0x04, 0x07);
348 pac7311_reg_write(dev, 0x05, 0x2b);
349 pac7311_reg_write(dev, 0x06, 0x09);
350 pac7311_reg_write(dev, 0x07, 0x0f);
351 pac7311_reg_write(dev, 0x08, 0x09);
352 pac7311_reg_write(dev, 0x09, 0x00);
353 pac7311_reg_write(dev, 0x0c, 0x07);
354 pac7311_reg_write(dev, 0x0d, 0x00);
355 pac7311_reg_write(dev, 0x0e, 0x00);
356 pac7311_reg_write(dev, 0x0f, 0x62);
357 pac7311_reg_write(dev, 0x10, 0x08);
358 pac7311_reg_write(dev, 0x12, 0x07);
359 pac7311_reg_write(dev, 0x13, 0x00);
360 pac7311_reg_write(dev, 0x14, 0x00);
361 pac7311_reg_write(dev, 0x15, 0x00);
362 pac7311_reg_write(dev, 0x16, 0x00);
363 pac7311_reg_write(dev, 0x17, 0x00);
364 pac7311_reg_write(dev, 0x18, 0x00);
365 pac7311_reg_write(dev, 0x19, 0x00);
366 pac7311_reg_write(dev, 0x1a, 0x00);
367 pac7311_reg_write(dev, 0x1b, 0x03);
368 pac7311_reg_write(dev, 0x1c, 0xa0);
369 pac7311_reg_write(dev, 0x1d, 0x01);
370 pac7311_reg_write(dev, 0x1e, 0xf4);
371 pac7311_reg_write(dev, 0x21, 0x00);
372 pac7311_reg_write(dev, 0x22, 0x08);
373 pac7311_reg_write(dev, 0x24, 0x03);
374 pac7311_reg_write(dev, 0x26, 0x00);
375 pac7311_reg_write(dev, 0x27, 0x01);
376 pac7311_reg_write(dev, 0x28, 0xca);
377 pac7311_reg_write(dev, 0x29, 0x10);
378 pac7311_reg_write(dev, 0x2a, 0x06);
379 pac7311_reg_write(dev, 0x2b, 0x78);
380 pac7311_reg_write(dev, 0x2c, 0x00);
381 pac7311_reg_write(dev, 0x2d, 0x00);
382 pac7311_reg_write(dev, 0x2e, 0x00);
383 pac7311_reg_write(dev, 0x2f, 0x00);
384 pac7311_reg_write(dev, 0x30, 0x23);
385 pac7311_reg_write(dev, 0x31, 0x28);
386 pac7311_reg_write(dev, 0x32, 0x04);
387 pac7311_reg_write(dev, 0x33, 0x11);
388 pac7311_reg_write(dev, 0x34, 0x00);
389 pac7311_reg_write(dev, 0x35, 0x00);
390 pac7311_reg_write(dev, 0x11, 0x01);
391 setcontrast(gspca_dev);
392 setbrightness(gspca_dev);
393 setcolors(gspca_dev);
395 /* set correct resolution */
396 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
397 case 2: /* 160x120 */
398 pac7311_reg_write(dev, 0xff, 0x04);
399 pac7311_reg_write(dev, 0x02, 0x03);
400 pac7311_reg_write(dev, 0xff, 0x01);
401 pac7311_reg_write(dev, 0x08, 0x09);
402 pac7311_reg_write(dev, 0x17, 0x20);
403 pac7311_reg_write(dev, 0x1b, 0x00);
404 /* pac7311_reg_write(dev, 0x80, 0x69); */
405 pac7311_reg_write(dev, 0x87, 0x10);
407 case 1: /* 320x240 */
408 pac7311_reg_write(dev, 0xff, 0x04);
409 pac7311_reg_write(dev, 0x02, 0x03);
410 pac7311_reg_write(dev, 0xff, 0x01);
411 pac7311_reg_write(dev, 0x08, 0x09);
412 pac7311_reg_write(dev, 0x17, 0x30);
413 /* pac7311_reg_write(dev, 0x80, 0x3f); */
414 pac7311_reg_write(dev, 0x87, 0x11);
416 case 0: /* 640x480 */
417 pac7311_reg_write(dev, 0xff, 0x04);
418 pac7311_reg_write(dev, 0x02, 0x03);
419 pac7311_reg_write(dev, 0xff, 0x01);
420 pac7311_reg_write(dev, 0x08, 0x08);
421 pac7311_reg_write(dev, 0x17, 0x00);
422 /* pac7311_reg_write(dev, 0x80, 0x1c); */
423 pac7311_reg_write(dev, 0x87, 0x12);
428 pac7311_reg_write(dev, 0xff, 0x01);
429 pac7311_reg_write(dev, 0x78, 0x04);
430 pac7311_reg_write(dev, 0x78, 0x05);
433 sd->ag_cnt = AG_CNT_START;
440 static void sd_stopN(struct gspca_dev *gspca_dev)
442 struct usb_device *dev = gspca_dev->dev;
444 pac7311_reg_write(dev, 0xff, 0x04);
445 pac7311_reg_write(dev, 0x27, 0x80);
446 pac7311_reg_write(dev, 0x28, 0xca);
447 pac7311_reg_write(dev, 0x29, 0x53);
448 pac7311_reg_write(dev, 0x2a, 0x0e);
449 pac7311_reg_write(dev, 0xff, 0x01);
450 pac7311_reg_write(dev, 0x3e, 0x20);
451 pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
452 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
453 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
456 static void sd_stop0(struct gspca_dev *gspca_dev)
460 /* this function is called at close time */
461 static void sd_close(struct gspca_dev *gspca_dev)
463 struct usb_device *dev = gspca_dev->dev;
465 pac7311_reg_write(dev, 0xff, 0x04);
466 pac7311_reg_write(dev, 0x27, 0x80);
467 pac7311_reg_write(dev, 0x28, 0xca);
468 pac7311_reg_write(dev, 0x29, 0x53);
469 pac7311_reg_write(dev, 0x2a, 0x0e);
470 pac7311_reg_write(dev, 0xff, 0x01);
471 pac7311_reg_write(dev, 0x3e, 0x20);
472 pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
473 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
474 pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
477 static void setautogain(struct gspca_dev *gspca_dev, int luma)
485 pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
487 PDEBUG(D_FRAM, "luma mean %d", luma);
488 if (luma < luma_mean - luma_delta ||
489 luma > luma_mean + luma_delta) {
490 Gbright += (luma_mean - luma) >> spring;
493 else if (Gbright < 4)
495 PDEBUG(D_FRAM, "gbright %d", Gbright);
496 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
497 pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
498 /* load registers to sensor (Bit 0, auto clear) */
499 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
503 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
504 struct gspca_frame *frame, /* target */
505 __u8 *data, /* isoc packet */
506 int len) /* iso packet length */
508 struct sd *sd = (struct sd *) gspca_dev;
509 unsigned char tmpbuf[4];
514 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
520 for (p = 0; p < len - 6; p++) {
521 if ((data[0 + p] == 0xff)
522 && (data[1 + p] == 0xff)
523 && (data[2 + p] == 0x00)
524 && (data[3 + p] == 0xff)
525 && (data[4 + p] == 0x96)) {
528 if (sd->ag_cnt >= 0 && p > 28) {
529 sd->avg_lum += data[p - 23];
530 if (--sd->ag_cnt < 0) {
531 sd->ag_cnt = AG_CNT_START;
532 setautogain(gspca_dev,
533 sd->avg_lum / AG_CNT_START);
538 /* copy the end of data to the current frame */
539 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
542 /* put the JPEG header in the new frame */
543 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
544 (unsigned char *) pac7311_jpeg_header,
546 tmpbuf[0] = gspca_dev->height >> 8;
547 tmpbuf[1] = gspca_dev->height & 0xff;
548 tmpbuf[2] = gspca_dev->width >> 8;
549 tmpbuf[3] = gspca_dev->width & 0xff;
550 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
552 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
553 (unsigned char *) &pac7311_jpeg_header[16],
554 PAC7311_JPEG_HEADER_SIZE - 16);
563 /* remove the 'ff ff ff xx' sequences */
570 if (data[0] == 0xff) {
573 frame->data_end -= 2;
578 && data[1] == 0xff) {
581 frame->data_end -= 1;
585 for (i = 0; i < len - 4; i++) {
587 && data[i + 1] == 0xff
588 && data[i + 2] == 0xff) {
589 memmove(&data[i], &data[i + 4], len - i - 4);
594 if (data[len - 4] == 0xff) {
595 if (data[len - 3] == 0xff
596 && data[len - 2] == 0xff) {
599 } else if (data[len - 3] == 0xff) {
600 if (data[len - 2] == 0xff
601 && data[len - 1] == 0xff)
603 } else if (data[len - 2] == 0xff) {
604 if (data[len - 1] == 0xff)
606 } else if (data[len - 1] == 0xff)
609 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
612 static void getbrightness(struct gspca_dev *gspca_dev)
614 /* __u8 brightness = 0;
616 pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
617 spca50x->brightness = brightness;
618 return spca50x->brightness; */
619 /* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
624 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
626 struct sd *sd = (struct sd *) gspca_dev;
628 sd->brightness = val;
629 if (gspca_dev->streaming)
630 setbrightness(gspca_dev);
634 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
636 struct sd *sd = (struct sd *) gspca_dev;
638 getbrightness(gspca_dev);
639 *val = sd->brightness;
643 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
645 struct sd *sd = (struct sd *) gspca_dev;
648 if (gspca_dev->streaming)
649 setcontrast(gspca_dev);
653 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
655 struct sd *sd = (struct sd *) gspca_dev;
657 /* getcontrast(gspca_dev); */
662 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
664 struct sd *sd = (struct sd *) gspca_dev;
667 if (gspca_dev->streaming)
668 setcolors(gspca_dev);
672 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
674 struct sd *sd = (struct sd *) gspca_dev;
676 /* getcolors(gspca_dev); */
681 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
683 struct sd *sd = (struct sd *) gspca_dev;
687 sd->ag_cnt = AG_CNT_START;
695 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
697 struct sd *sd = (struct sd *) gspca_dev;
703 /* sub-driver description */
704 static struct sd_desc sd_desc = {
707 .nctrls = ARRAY_SIZE(sd_ctrls),
714 .pkt_scan = sd_pkt_scan,
717 /* -- module initialisation -- */
718 #define DVNM(name) .driver_info = (kernel_ulong_t) name
719 static __devinitdata struct usb_device_id device_table[] = {
720 {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
721 {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
722 {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
723 {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
724 {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
725 /* and also ', Trust WB-3350p, SIGMA cam 2350' */
726 {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
727 {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
730 MODULE_DEVICE_TABLE(usb, device_table);
732 /* -- device connect -- */
733 static int sd_probe(struct usb_interface *intf,
734 const struct usb_device_id *id)
736 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
740 static struct usb_driver sd_driver = {
742 .id_table = device_table,
744 .disconnect = gspca_disconnect,
747 /* -- module insert / remove -- */
748 static int __init sd_mod_init(void)
750 if (usb_register(&sd_driver) < 0)
752 PDEBUG(D_PROBE, "v%s registered", version);
755 static void __exit sd_mod_exit(void)
757 usb_deregister(&sd_driver);
758 PDEBUG(D_PROBE, "deregistered");
761 module_init(sd_mod_init);
762 module_exit(sd_mod_exit);