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 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
27 MODULE_DESCRIPTION("Pixart PAC7311");
28 MODULE_LICENSE("GPL");
30 /* specific webcam descriptor */
32 struct gspca_dev gspca_dev; /* !! must be the first item */
36 unsigned char brightness;
37 unsigned char contrast;
39 unsigned char autogain;
43 #define AG_CNT_START 13
46 /* V4L2 controls supported by the driver */
47 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
53 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
54 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
56 static struct ctrl sd_ctrls[] = {
59 .id = V4L2_CID_BRIGHTNESS,
60 .type = V4L2_CTRL_TYPE_INTEGER,
63 #define BRIGHTNESS_MAX 0x20
64 .maximum = BRIGHTNESS_MAX,
66 #define BRIGHTNESS_DEF 0x10
67 .default_value = BRIGHTNESS_DEF,
69 .set = sd_setbrightness,
70 .get = sd_getbrightness,
74 .id = V4L2_CID_CONTRAST,
75 .type = V4L2_CTRL_TYPE_INTEGER,
80 #define CONTRAST_DEF 127
81 .default_value = CONTRAST_DEF,
83 .set = sd_setcontrast,
84 .get = sd_getcontrast,
88 .id = V4L2_CID_SATURATION,
89 .type = V4L2_CTRL_TYPE_INTEGER,
95 .default_value = COLOR_DEF,
102 .id = V4L2_CID_AUTOGAIN,
103 .type = V4L2_CTRL_TYPE_BOOLEAN,
108 #define AUTOGAIN_DEF 1
109 .default_value = AUTOGAIN_DEF,
111 .set = sd_setautogain,
112 .get = sd_getautogain,
116 static struct v4l2_pix_format vga_mode[] = {
117 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
119 .sizeimage = 160 * 120 * 3 / 8 + 590,
120 .colorspace = V4L2_COLORSPACE_JPEG,
122 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
124 .sizeimage = 320 * 240 * 3 / 8 + 590,
125 .colorspace = V4L2_COLORSPACE_JPEG,
127 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
129 .sizeimage = 640 * 480 * 3 / 8 + 590,
130 .colorspace = V4L2_COLORSPACE_JPEG,
134 #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
136 static const __u8 pac7311_jpeg_header[] = {
138 0xff, 0xe0, 0x00, 0x03, 0x20,
139 0xff, 0xc0, 0x00, 0x11, 0x08,
140 0x01, 0xe0, /* 12: height */
141 0x02, 0x80, /* 14: width */
146 0xff, 0xdb, 0x00, 0x84,
147 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
148 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
149 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
150 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
151 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
152 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
153 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
154 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
155 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
156 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
157 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
158 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
159 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
160 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
161 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
163 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
164 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
165 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
166 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
167 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
168 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
169 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
170 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
171 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
172 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
173 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
174 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
175 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
176 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
177 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
178 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
179 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
180 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
181 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
182 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
184 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
185 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
186 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
187 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
188 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
189 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
190 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
191 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
192 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
193 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
194 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
195 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
196 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
197 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
198 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
199 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
200 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
201 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
202 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
203 0x11, 0x00, 0x3f, 0x00
206 static void reg_w_buf(struct gspca_dev *gspca_dev,
208 const char *buffer, __u16 len)
210 memcpy(gspca_dev->usb_buf, buffer, len);
211 usb_control_msg(gspca_dev->dev,
212 usb_sndctrlpipe(gspca_dev->dev, 0),
214 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
216 index, gspca_dev->usb_buf, len,
220 static __u8 reg_r(struct gspca_dev *gspca_dev,
223 usb_control_msg(gspca_dev->dev,
224 usb_rcvctrlpipe(gspca_dev->dev, 0),
226 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
228 index, gspca_dev->usb_buf, 1,
230 return gspca_dev->usb_buf[0];
233 static void reg_w(struct gspca_dev *gspca_dev,
237 gspca_dev->usb_buf[0] = value;
238 usb_control_msg(gspca_dev->dev,
239 usb_sndctrlpipe(gspca_dev->dev, 0),
241 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
242 value, index, gspca_dev->usb_buf, 1,
246 /* this function is called at probe time */
247 static int sd_config(struct gspca_dev *gspca_dev,
248 const struct usb_device_id *id)
250 struct sd *sd = (struct sd *) gspca_dev;
253 PDEBUG(D_CONF, "Find Sensor PAC7311");
254 reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
255 reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
256 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
257 reg_w(gspca_dev, 0xff, 0x04);
258 reg_w(gspca_dev, 0x27, 0x80);
259 reg_w(gspca_dev, 0x28, 0xca);
260 reg_w(gspca_dev, 0x29, 0x53);
261 reg_w(gspca_dev, 0x2a, 0x0e);
262 reg_w(gspca_dev, 0xff, 0x01);
263 reg_w(gspca_dev, 0x3e, 0x20);
265 cam = &gspca_dev->cam;
266 cam->dev_name = (char *) id->driver_info;
268 cam->cam_mode = vga_mode;
269 cam->nmodes = ARRAY_SIZE(vga_mode);
271 sd->brightness = BRIGHTNESS_DEF;
272 sd->contrast = CONTRAST_DEF;
273 sd->colors = COLOR_DEF;
274 sd->autogain = AUTOGAIN_DEF;
278 static void setbrightness(struct gspca_dev *gspca_dev)
280 struct sd *sd = (struct sd *) gspca_dev;
284 brightness = BRIGHTNESS_MAX - sd->brightness;
285 reg_w(gspca_dev, 0xff, 0x04);
286 /* reg_w(gspca_dev, 0x0e, 0x00); */
287 reg_w(gspca_dev, 0x0f, brightness);
288 /* load registers to sensor (Bit 0, auto clear) */
289 reg_w(gspca_dev, 0x11, 0x01);
290 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
293 static void setcontrast(struct gspca_dev *gspca_dev)
295 struct sd *sd = (struct sd *) gspca_dev;
297 reg_w(gspca_dev, 0xff, 0x01);
298 reg_w(gspca_dev, 0x80, sd->contrast);
299 /* load registers to sensor (Bit 0, auto clear) */
300 reg_w(gspca_dev, 0x11, 0x01);
301 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
304 static void setcolors(struct gspca_dev *gspca_dev)
306 struct sd *sd = (struct sd *) gspca_dev;
308 reg_w(gspca_dev, 0xff, 0x01);
309 reg_w(gspca_dev, 0x10, sd->colors);
310 /* load registers to sensor (Bit 0, auto clear) */
311 reg_w(gspca_dev, 0x11, 0x01);
312 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
315 /* this function is called at open time */
316 static int sd_open(struct gspca_dev *gspca_dev)
318 reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */
322 static void sd_start(struct gspca_dev *gspca_dev)
324 struct sd *sd = (struct sd *) gspca_dev;
326 reg_w(gspca_dev, 0xff, 0x01);
327 reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
328 reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
329 reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
330 reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
331 reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
332 reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3);
333 reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
334 reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
335 reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
336 reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
337 reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
338 reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2);
339 reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
340 reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
341 reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
342 reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2);
343 reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3);
344 reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4);
345 reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
346 reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
348 reg_w(gspca_dev, 0xff, 0x04);
349 reg_w(gspca_dev, 0x02, 0x04);
350 reg_w(gspca_dev, 0x03, 0x54);
351 reg_w(gspca_dev, 0x04, 0x07);
352 reg_w(gspca_dev, 0x05, 0x2b);
353 reg_w(gspca_dev, 0x06, 0x09);
354 reg_w(gspca_dev, 0x07, 0x0f);
355 reg_w(gspca_dev, 0x08, 0x09);
356 reg_w(gspca_dev, 0x09, 0x00);
357 reg_w(gspca_dev, 0x0c, 0x07);
358 reg_w(gspca_dev, 0x0d, 0x00);
359 reg_w(gspca_dev, 0x0e, 0x00);
360 reg_w(gspca_dev, 0x0f, 0x62);
361 reg_w(gspca_dev, 0x10, 0x08);
362 reg_w(gspca_dev, 0x12, 0x07);
363 reg_w(gspca_dev, 0x13, 0x00);
364 reg_w(gspca_dev, 0x14, 0x00);
365 reg_w(gspca_dev, 0x15, 0x00);
366 reg_w(gspca_dev, 0x16, 0x00);
367 reg_w(gspca_dev, 0x17, 0x00);
368 reg_w(gspca_dev, 0x18, 0x00);
369 reg_w(gspca_dev, 0x19, 0x00);
370 reg_w(gspca_dev, 0x1a, 0x00);
371 reg_w(gspca_dev, 0x1b, 0x03);
372 reg_w(gspca_dev, 0x1c, 0xa0);
373 reg_w(gspca_dev, 0x1d, 0x01);
374 reg_w(gspca_dev, 0x1e, 0xf4);
375 reg_w(gspca_dev, 0x21, 0x00);
376 reg_w(gspca_dev, 0x22, 0x08);
377 reg_w(gspca_dev, 0x24, 0x03);
378 reg_w(gspca_dev, 0x26, 0x00);
379 reg_w(gspca_dev, 0x27, 0x01);
380 reg_w(gspca_dev, 0x28, 0xca);
381 reg_w(gspca_dev, 0x29, 0x10);
382 reg_w(gspca_dev, 0x2a, 0x06);
383 reg_w(gspca_dev, 0x2b, 0x78);
384 reg_w(gspca_dev, 0x2c, 0x00);
385 reg_w(gspca_dev, 0x2d, 0x00);
386 reg_w(gspca_dev, 0x2e, 0x00);
387 reg_w(gspca_dev, 0x2f, 0x00);
388 reg_w(gspca_dev, 0x30, 0x23);
389 reg_w(gspca_dev, 0x31, 0x28);
390 reg_w(gspca_dev, 0x32, 0x04);
391 reg_w(gspca_dev, 0x33, 0x11);
392 reg_w(gspca_dev, 0x34, 0x00);
393 reg_w(gspca_dev, 0x35, 0x00);
394 reg_w(gspca_dev, 0x11, 0x01);
395 setcontrast(gspca_dev);
396 setbrightness(gspca_dev);
397 setcolors(gspca_dev);
399 /* set correct resolution */
400 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
401 case 2: /* 160x120 */
402 reg_w(gspca_dev, 0xff, 0x04);
403 reg_w(gspca_dev, 0x02, 0x03);
404 reg_w(gspca_dev, 0xff, 0x01);
405 reg_w(gspca_dev, 0x08, 0x09);
406 reg_w(gspca_dev, 0x17, 0x20);
407 reg_w(gspca_dev, 0x1b, 0x00);
408 /* reg_w(gspca_dev, 0x80, 0x69); */
409 reg_w(gspca_dev, 0x87, 0x10);
411 case 1: /* 320x240 */
412 reg_w(gspca_dev, 0xff, 0x04);
413 reg_w(gspca_dev, 0x02, 0x03);
414 reg_w(gspca_dev, 0xff, 0x01);
415 reg_w(gspca_dev, 0x08, 0x09);
416 reg_w(gspca_dev, 0x17, 0x30);
417 /* reg_w(gspca_dev, 0x80, 0x3f); */
418 reg_w(gspca_dev, 0x87, 0x11);
420 case 0: /* 640x480 */
421 reg_w(gspca_dev, 0xff, 0x04);
422 reg_w(gspca_dev, 0x02, 0x03);
423 reg_w(gspca_dev, 0xff, 0x01);
424 reg_w(gspca_dev, 0x08, 0x08);
425 reg_w(gspca_dev, 0x17, 0x00);
426 /* reg_w(gspca_dev, 0x80, 0x1c); */
427 reg_w(gspca_dev, 0x87, 0x12);
432 reg_w(gspca_dev, 0xff, 0x01);
433 reg_w(gspca_dev, 0x78, 0x04);
434 reg_w(gspca_dev, 0x78, 0x05);
437 sd->ag_cnt = AG_CNT_START;
444 static void sd_stopN(struct gspca_dev *gspca_dev)
446 reg_w(gspca_dev, 0xff, 0x04);
447 reg_w(gspca_dev, 0x27, 0x80);
448 reg_w(gspca_dev, 0x28, 0xca);
449 reg_w(gspca_dev, 0x29, 0x53);
450 reg_w(gspca_dev, 0x2a, 0x0e);
451 reg_w(gspca_dev, 0xff, 0x01);
452 reg_w(gspca_dev, 0x3e, 0x20);
453 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
454 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
455 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
458 static void sd_stop0(struct gspca_dev *gspca_dev)
462 /* this function is called at close time */
463 static void sd_close(struct gspca_dev *gspca_dev)
465 reg_w(gspca_dev, 0xff, 0x04);
466 reg_w(gspca_dev, 0x27, 0x80);
467 reg_w(gspca_dev, 0x28, 0xca);
468 reg_w(gspca_dev, 0x29, 0x53);
469 reg_w(gspca_dev, 0x2a, 0x0e);
470 reg_w(gspca_dev, 0xff, 0x01);
471 reg_w(gspca_dev, 0x3e, 0x20);
472 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
473 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
474 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
477 static void setautogain(struct gspca_dev *gspca_dev, int luma)
484 Gbright = reg_r(gspca_dev, 0x02);
485 PDEBUG(D_FRAM, "luma mean %d", luma);
486 if (luma < luma_mean - luma_delta ||
487 luma > luma_mean + luma_delta) {
488 Gbright += (luma_mean - luma) >> spring;
491 else if (Gbright < 4)
493 PDEBUG(D_FRAM, "gbright %d", Gbright);
494 reg_w(gspca_dev, 0xff, 0x04);
495 reg_w(gspca_dev, 0x0f, Gbright);
496 /* load registers to sensor (Bit 0, auto clear) */
497 reg_w(gspca_dev, 0x11, 0x01);
501 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
502 struct gspca_frame *frame, /* target */
503 __u8 *data, /* isoc packet */
504 int len) /* iso packet length */
506 struct sd *sd = (struct sd *) gspca_dev;
507 unsigned char tmpbuf[4];
512 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
518 for (p = 0; p < len - 6; p++) {
519 if ((data[0 + p] == 0xff)
520 && (data[1 + p] == 0xff)
521 && (data[2 + p] == 0x00)
522 && (data[3 + p] == 0xff)
523 && (data[4 + p] == 0x96)) {
526 if (sd->ag_cnt >= 0 && p > 28) {
527 sd->avg_lum += data[p - 23];
528 if (--sd->ag_cnt < 0) {
529 sd->ag_cnt = AG_CNT_START;
530 setautogain(gspca_dev,
531 sd->avg_lum / AG_CNT_START);
536 /* copy the end of data to the current frame */
537 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
540 /* put the JPEG header in the new frame */
541 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
542 (unsigned char *) pac7311_jpeg_header,
544 tmpbuf[0] = gspca_dev->height >> 8;
545 tmpbuf[1] = gspca_dev->height & 0xff;
546 tmpbuf[2] = gspca_dev->width >> 8;
547 tmpbuf[3] = gspca_dev->width & 0xff;
548 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
550 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
551 (unsigned char *) &pac7311_jpeg_header[16],
552 PAC7311_JPEG_HEADER_SIZE - 16);
561 /* remove the 'ff ff ff xx' sequences */
568 if (data[0] == 0xff) {
571 frame->data_end -= 2;
576 && data[1] == 0xff) {
579 frame->data_end -= 1;
583 for (i = 0; i < len - 4; i++) {
585 && data[i + 1] == 0xff
586 && data[i + 2] == 0xff) {
587 memmove(&data[i], &data[i + 4], len - i - 4);
592 if (data[len - 4] == 0xff) {
593 if (data[len - 3] == 0xff
594 && data[len - 2] == 0xff) {
597 } else if (data[len - 3] == 0xff) {
598 if (data[len - 2] == 0xff
599 && data[len - 1] == 0xff)
601 } else if (data[len - 2] == 0xff) {
602 if (data[len - 1] == 0xff)
604 } else if (data[len - 1] == 0xff)
607 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
610 static void getbrightness(struct gspca_dev *gspca_dev)
612 /* sd->brightness = reg_r(gspca_dev, 0x08);
613 return sd->brightness; */
614 /* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
619 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
621 struct sd *sd = (struct sd *) gspca_dev;
623 sd->brightness = val;
624 if (gspca_dev->streaming)
625 setbrightness(gspca_dev);
629 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
631 struct sd *sd = (struct sd *) gspca_dev;
633 getbrightness(gspca_dev);
634 *val = sd->brightness;
638 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
640 struct sd *sd = (struct sd *) gspca_dev;
643 if (gspca_dev->streaming)
644 setcontrast(gspca_dev);
648 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
650 struct sd *sd = (struct sd *) gspca_dev;
652 /* getcontrast(gspca_dev); */
657 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
659 struct sd *sd = (struct sd *) gspca_dev;
662 if (gspca_dev->streaming)
663 setcolors(gspca_dev);
667 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
669 struct sd *sd = (struct sd *) gspca_dev;
671 /* getcolors(gspca_dev); */
676 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
678 struct sd *sd = (struct sd *) gspca_dev;
682 sd->ag_cnt = AG_CNT_START;
690 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
692 struct sd *sd = (struct sd *) gspca_dev;
698 /* sub-driver description */
699 static struct sd_desc sd_desc = {
702 .nctrls = ARRAY_SIZE(sd_ctrls),
709 .pkt_scan = sd_pkt_scan,
712 /* -- module initialisation -- */
713 #define DVNM(name) .driver_info = (kernel_ulong_t) name
714 static __devinitdata struct usb_device_id device_table[] = {
715 {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
716 {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
717 {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
718 {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
719 {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
720 /* and also ', Trust WB-3350p, SIGMA cam 2350' */
721 {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
722 {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
725 MODULE_DEVICE_TABLE(usb, device_table);
727 /* -- device connect -- */
728 static int sd_probe(struct usb_interface *intf,
729 const struct usb_device_id *id)
731 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
735 static struct usb_driver sd_driver = {
737 .id_table = device_table,
739 .disconnect = gspca_disconnect,
742 /* -- module insert / remove -- */
743 static int __init sd_mod_init(void)
745 if (usb_register(&sd_driver) < 0)
747 PDEBUG(D_PROBE, "registered");
750 static void __exit sd_mod_exit(void)
752 usb_deregister(&sd_driver);
753 PDEBUG(D_PROBE, "deregistered");
756 module_init(sd_mod_init);
757 module_exit(sd_mod_exit);