diff options
Diffstat (limited to 'drivers/media/video/gspca/pac7311.c')
-rw-r--r-- | drivers/media/video/gspca/pac7311.c | 716 |
1 files changed, 257 insertions, 459 deletions
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 052714484e83..e5697a6345e8 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -57,23 +57,17 @@ MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | |||
57 | MODULE_DESCRIPTION("Pixart PAC7311"); | 57 | MODULE_DESCRIPTION("Pixart PAC7311"); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
59 | 59 | ||
60 | /* specific webcam descriptor */ | 60 | /* specific webcam descriptor for pac7311 */ |
61 | struct sd { | 61 | struct sd { |
62 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 62 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
63 | 63 | ||
64 | unsigned char brightness; | ||
65 | unsigned char contrast; | 64 | unsigned char contrast; |
66 | unsigned char colors; | ||
67 | unsigned char gain; | 65 | unsigned char gain; |
68 | unsigned char exposure; | 66 | unsigned char exposure; |
69 | unsigned char autogain; | 67 | unsigned char autogain; |
70 | __u8 hflip; | 68 | __u8 hflip; |
71 | __u8 vflip; | 69 | __u8 vflip; |
72 | 70 | ||
73 | __u8 sensor; | ||
74 | #define SENSOR_PAC7302 0 | ||
75 | #define SENSOR_PAC7311 1 | ||
76 | |||
77 | u8 sof_read; | 71 | u8 sof_read; |
78 | u8 autogain_ignore_frames; | 72 | u8 autogain_ignore_frames; |
79 | 73 | ||
@@ -81,12 +75,8 @@ struct sd { | |||
81 | }; | 75 | }; |
82 | 76 | ||
83 | /* V4L2 controls supported by the driver */ | 77 | /* V4L2 controls supported by the driver */ |
84 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
87 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
88 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
89 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
90 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 80 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
91 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 81 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
92 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | 82 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); |
@@ -99,23 +89,6 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | |||
99 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 89 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
100 | 90 | ||
101 | static struct ctrl sd_ctrls[] = { | 91 | static struct ctrl sd_ctrls[] = { |
102 | /* This control is pac7302 only */ | ||
103 | #define BRIGHTNESS_IDX 0 | ||
104 | { | ||
105 | { | ||
106 | .id = V4L2_CID_BRIGHTNESS, | ||
107 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
108 | .name = "Brightness", | ||
109 | .minimum = 0, | ||
110 | #define BRIGHTNESS_MAX 0x20 | ||
111 | .maximum = BRIGHTNESS_MAX, | ||
112 | .step = 1, | ||
113 | #define BRIGHTNESS_DEF 0x10 | ||
114 | .default_value = BRIGHTNESS_DEF, | ||
115 | }, | ||
116 | .set = sd_setbrightness, | ||
117 | .get = sd_getbrightness, | ||
118 | }, | ||
119 | /* This control is for both the 7302 and the 7311 */ | 92 | /* This control is for both the 7302 and the 7311 */ |
120 | { | 93 | { |
121 | { | 94 | { |
@@ -132,23 +105,6 @@ static struct ctrl sd_ctrls[] = { | |||
132 | .set = sd_setcontrast, | 105 | .set = sd_setcontrast, |
133 | .get = sd_getcontrast, | 106 | .get = sd_getcontrast, |
134 | }, | 107 | }, |
135 | /* This control is pac7302 only */ | ||
136 | #define SATURATION_IDX 2 | ||
137 | { | ||
138 | { | ||
139 | .id = V4L2_CID_SATURATION, | ||
140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
141 | .name = "Saturation", | ||
142 | .minimum = 0, | ||
143 | #define COLOR_MAX 255 | ||
144 | .maximum = COLOR_MAX, | ||
145 | .step = 1, | ||
146 | #define COLOR_DEF 127 | ||
147 | .default_value = COLOR_DEF, | ||
148 | }, | ||
149 | .set = sd_setcolors, | ||
150 | .get = sd_getcolors, | ||
151 | }, | ||
152 | /* All controls below are for both the 7302 and the 7311 */ | 108 | /* All controls below are for both the 7302 and the 7311 */ |
153 | { | 109 | { |
154 | { | 110 | { |
@@ -244,101 +200,9 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
244 | .priv = 0}, | 200 | .priv = 0}, |
245 | }; | 201 | }; |
246 | 202 | ||
247 | /* pac 7302 */ | 203 | #define LOAD_PAGE3 255 |
248 | static const __u8 init_7302[] = { | 204 | #define LOAD_PAGE4 254 |
249 | /* index,value */ | 205 | #define END_OF_SEQUENCE 0 |
250 | 0xff, 0x01, /* page 1 */ | ||
251 | 0x78, 0x00, /* deactivate */ | ||
252 | 0xff, 0x01, | ||
253 | 0x78, 0x40, /* led off */ | ||
254 | }; | ||
255 | static const __u8 start_7302[] = { | ||
256 | /* index, len, [value]* */ | ||
257 | 0xff, 1, 0x00, /* page 0 */ | ||
258 | 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, | ||
259 | 0x00, 0x00, 0x00, 0x00, | ||
260 | 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, | ||
261 | 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, | ||
262 | 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, | ||
263 | 0x26, 2, 0xaa, 0xaa, | ||
264 | 0x2e, 1, 0x31, | ||
265 | 0x38, 1, 0x01, | ||
266 | 0x3a, 3, 0x14, 0xff, 0x5a, | ||
267 | 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, | ||
268 | 0x00, 0x54, 0x11, | ||
269 | 0x55, 1, 0x00, | ||
270 | 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, | ||
271 | 0x6b, 1, 0x00, | ||
272 | 0x6e, 3, 0x08, 0x06, 0x00, | ||
273 | 0x72, 3, 0x00, 0xff, 0x00, | ||
274 | 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, | ||
275 | 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, | ||
276 | 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, | ||
277 | 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, | ||
278 | 0xd2, 0xeb, | ||
279 | 0xaf, 1, 0x02, | ||
280 | 0xb5, 2, 0x08, 0x08, | ||
281 | 0xb8, 2, 0x08, 0x88, | ||
282 | 0xc4, 4, 0xae, 0x01, 0x04, 0x01, | ||
283 | 0xcc, 1, 0x00, | ||
284 | 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, | ||
285 | 0xc1, 0xd7, 0xec, | ||
286 | 0xdc, 1, 0x01, | ||
287 | 0xff, 1, 0x01, /* page 1 */ | ||
288 | 0x12, 3, 0x02, 0x00, 0x01, | ||
289 | 0x3e, 2, 0x00, 0x00, | ||
290 | 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, | ||
291 | 0x7c, 1, 0x00, | ||
292 | 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, | ||
293 | 0x02, 0x00, | ||
294 | 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, | ||
295 | 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, | ||
296 | 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, | ||
297 | 0xd8, 1, 0x01, | ||
298 | 0xdb, 2, 0x00, 0x01, | ||
299 | 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, | ||
300 | 0xe6, 4, 0x00, 0x00, 0x00, 0x01, | ||
301 | 0xeb, 1, 0x00, | ||
302 | 0xff, 1, 0x02, /* page 2 */ | ||
303 | 0x22, 1, 0x00, | ||
304 | 0xff, 1, 0x03, /* page 3 */ | ||
305 | 0x00, 255, /* load the page 3 */ | ||
306 | 0x11, 1, 0x01, | ||
307 | 0xff, 1, 0x02, /* page 2 */ | ||
308 | 0x13, 1, 0x00, | ||
309 | 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, | ||
310 | 0x27, 2, 0x14, 0x0c, | ||
311 | 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, | ||
312 | 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, | ||
313 | 0x6e, 1, 0x08, | ||
314 | 0xff, 1, 0x01, /* page 1 */ | ||
315 | 0x78, 1, 0x00, | ||
316 | 0, 0 /* end of sequence */ | ||
317 | }; | ||
318 | |||
319 | /* page 3 - the value 0xaa says skip the index - see reg_w_page() */ | ||
320 | static const __u8 page3_7302[] = { | ||
321 | 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, | ||
322 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, | ||
323 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
324 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, | ||
325 | 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, | ||
326 | 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, | ||
327 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, | ||
328 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
329 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, | ||
330 | 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, | ||
331 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
332 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, | ||
333 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
334 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, | ||
335 | 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, | ||
336 | 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, | ||
337 | 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, | ||
338 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
339 | 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, | ||
340 | 0x00 | ||
341 | }; | ||
342 | 206 | ||
343 | /* pac 7311 */ | 207 | /* pac 7311 */ |
344 | static const __u8 init_7311[] = { | 208 | static const __u8 init_7311[] = { |
@@ -378,119 +242,154 @@ static const __u8 start_7311[] = { | |||
378 | 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, | 242 | 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, |
379 | 0x3f, 0x00, 0x0a, 0x01, 0x00, | 243 | 0x3f, 0x00, 0x0a, 0x01, 0x00, |
380 | 0xff, 1, 0x04, /* page 4 */ | 244 | 0xff, 1, 0x04, /* page 4 */ |
381 | 0x00, 254, /* load the page 4 */ | 245 | 0, LOAD_PAGE4, /* load the page 4 */ |
382 | 0x11, 1, 0x01, | 246 | 0x11, 1, 0x01, |
383 | 0, 0 /* end of sequence */ | 247 | 0, END_OF_SEQUENCE /* end of sequence */ |
384 | }; | 248 | }; |
385 | 249 | ||
386 | /* page 4 - the value 0xaa says skip the index - see reg_w_page() */ | 250 | #define SKIP 0xaa |
251 | /* page 4 - the value SKIP says skip the index - see reg_w_page() */ | ||
387 | static const __u8 page4_7311[] = { | 252 | static const __u8 page4_7311[] = { |
388 | 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, | 253 | SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, |
389 | 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, | 254 | 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62, |
390 | 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, | 255 | 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, |
391 | 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, | 256 | 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP, |
392 | 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68, | 257 | SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68, |
393 | 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, | 258 | 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, |
394 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 | 259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 |
395 | }; | 260 | }; |
396 | 261 | ||
397 | static void reg_w_buf(struct gspca_dev *gspca_dev, | 262 | static int reg_w_buf(struct gspca_dev *gspca_dev, |
398 | __u8 index, | 263 | __u8 index, |
399 | const char *buffer, int len) | 264 | const char *buffer, int len) |
400 | { | 265 | { |
266 | int ret; | ||
267 | |||
401 | memcpy(gspca_dev->usb_buf, buffer, len); | 268 | memcpy(gspca_dev->usb_buf, buffer, len); |
402 | usb_control_msg(gspca_dev->dev, | 269 | ret = usb_control_msg(gspca_dev->dev, |
403 | usb_sndctrlpipe(gspca_dev->dev, 0), | 270 | usb_sndctrlpipe(gspca_dev->dev, 0), |
404 | 1, /* request */ | 271 | 1, /* request */ |
405 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 272 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
406 | 0, /* value */ | 273 | 0, /* value */ |
407 | index, gspca_dev->usb_buf, len, | 274 | index, gspca_dev->usb_buf, len, |
408 | 500); | 275 | 500); |
276 | if (ret < 0) | ||
277 | PDEBUG(D_ERR, "reg_w_buf(): " | ||
278 | "Failed to write registers to index 0x%x, error %i", | ||
279 | index, ret); | ||
280 | return ret; | ||
409 | } | 281 | } |
410 | 282 | ||
411 | 283 | ||
412 | static void reg_w(struct gspca_dev *gspca_dev, | 284 | static int reg_w(struct gspca_dev *gspca_dev, |
413 | __u8 index, | 285 | __u8 index, |
414 | __u8 value) | 286 | __u8 value) |
415 | { | 287 | { |
288 | int ret; | ||
289 | |||
416 | gspca_dev->usb_buf[0] = value; | 290 | gspca_dev->usb_buf[0] = value; |
417 | usb_control_msg(gspca_dev->dev, | 291 | ret = usb_control_msg(gspca_dev->dev, |
418 | usb_sndctrlpipe(gspca_dev->dev, 0), | 292 | usb_sndctrlpipe(gspca_dev->dev, 0), |
419 | 0, /* request */ | 293 | 0, /* request */ |
420 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 294 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
421 | 0, index, gspca_dev->usb_buf, 1, | 295 | 0, index, gspca_dev->usb_buf, 1, |
422 | 500); | 296 | 500); |
297 | if (ret < 0) | ||
298 | PDEBUG(D_ERR, "reg_w(): " | ||
299 | "Failed to write register to index 0x%x, value 0x%x, error %i", | ||
300 | index, value, ret); | ||
301 | return ret; | ||
423 | } | 302 | } |
424 | 303 | ||
425 | static void reg_w_seq(struct gspca_dev *gspca_dev, | 304 | static int reg_w_seq(struct gspca_dev *gspca_dev, |
426 | const __u8 *seq, int len) | 305 | const __u8 *seq, int len) |
427 | { | 306 | { |
307 | int ret = 0; | ||
428 | while (--len >= 0) { | 308 | while (--len >= 0) { |
429 | reg_w(gspca_dev, seq[0], seq[1]); | 309 | if (0 <= ret) |
310 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
430 | seq += 2; | 311 | seq += 2; |
431 | } | 312 | } |
313 | return ret; | ||
432 | } | 314 | } |
433 | 315 | ||
434 | /* load the beginning of a page */ | 316 | /* load the beginning of a page */ |
435 | static void reg_w_page(struct gspca_dev *gspca_dev, | 317 | static int reg_w_page(struct gspca_dev *gspca_dev, |
436 | const __u8 *page, int len) | 318 | const __u8 *page, int len) |
437 | { | 319 | { |
438 | int index; | 320 | int index; |
321 | int ret = 0; | ||
439 | 322 | ||
440 | for (index = 0; index < len; index++) { | 323 | for (index = 0; index < len; index++) { |
441 | if (page[index] == 0xaa) /* skip this index */ | 324 | if (page[index] == SKIP) /* skip this index */ |
442 | continue; | 325 | continue; |
443 | gspca_dev->usb_buf[0] = page[index]; | 326 | gspca_dev->usb_buf[0] = page[index]; |
444 | usb_control_msg(gspca_dev->dev, | 327 | ret = usb_control_msg(gspca_dev->dev, |
445 | usb_sndctrlpipe(gspca_dev->dev, 0), | 328 | usb_sndctrlpipe(gspca_dev->dev, 0), |
446 | 0, /* request */ | 329 | 0, /* request */ |
447 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 330 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
448 | 0, index, gspca_dev->usb_buf, 1, | 331 | 0, index, gspca_dev->usb_buf, 1, |
449 | 500); | 332 | 500); |
333 | if (ret < 0) { | ||
334 | PDEBUG(D_ERR, "reg_w_page(): " | ||
335 | "Failed to write register to index 0x%x, " | ||
336 | "value 0x%x, error %i", | ||
337 | index, page[index], ret); | ||
338 | break; | ||
339 | } | ||
450 | } | 340 | } |
341 | return ret; | ||
451 | } | 342 | } |
452 | 343 | ||
453 | /* output a variable sequence */ | 344 | /* output a variable sequence */ |
454 | static void reg_w_var(struct gspca_dev *gspca_dev, | 345 | static int reg_w_var(struct gspca_dev *gspca_dev, |
455 | const __u8 *seq) | 346 | const __u8 *seq, |
347 | const __u8 *page3, unsigned int page3_len, | ||
348 | const __u8 *page4, unsigned int page4_len) | ||
456 | { | 349 | { |
457 | int index, len; | 350 | int index, len; |
351 | int ret = 0; | ||
458 | 352 | ||
459 | for (;;) { | 353 | for (;;) { |
460 | index = *seq++; | 354 | index = *seq++; |
461 | len = *seq++; | 355 | len = *seq++; |
462 | switch (len) { | 356 | switch (len) { |
463 | case 0: | 357 | case END_OF_SEQUENCE: |
464 | return; | 358 | return ret; |
465 | case 254: | 359 | case LOAD_PAGE4: |
466 | reg_w_page(gspca_dev, page4_7311, sizeof page4_7311); | 360 | ret = reg_w_page(gspca_dev, page4, page4_len); |
467 | break; | 361 | break; |
468 | case 255: | 362 | case LOAD_PAGE3: |
469 | reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); | 363 | ret = reg_w_page(gspca_dev, page3, page3_len); |
470 | break; | 364 | break; |
471 | default: | 365 | default: |
472 | if (len > 64) { | 366 | if (len > USB_BUF_SZ) { |
473 | PDEBUG(D_ERR|D_STREAM, | 367 | PDEBUG(D_ERR|D_STREAM, |
474 | "Incorrect variable sequence"); | 368 | "Incorrect variable sequence"); |
475 | return; | 369 | return -EINVAL; |
476 | } | 370 | } |
477 | while (len > 0) { | 371 | while (len > 0) { |
478 | if (len < 8) { | 372 | if (len < 8) { |
479 | reg_w_buf(gspca_dev, index, seq, len); | 373 | ret = reg_w_buf(gspca_dev, |
374 | index, seq, len); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
480 | seq += len; | 377 | seq += len; |
481 | break; | 378 | break; |
482 | } | 379 | } |
483 | reg_w_buf(gspca_dev, index, seq, 8); | 380 | ret = reg_w_buf(gspca_dev, index, seq, 8); |
484 | seq += 8; | 381 | seq += 8; |
485 | index += 8; | 382 | index += 8; |
486 | len -= 8; | 383 | len -= 8; |
487 | } | 384 | } |
488 | } | 385 | } |
386 | if (ret < 0) | ||
387 | return ret; | ||
489 | } | 388 | } |
490 | /* not reached */ | 389 | /* not reached */ |
491 | } | 390 | } |
492 | 391 | ||
493 | /* this function is called at probe time */ | 392 | /* this function is called at probe time for pac7311 */ |
494 | static int sd_config(struct gspca_dev *gspca_dev, | 393 | static int sd_config(struct gspca_dev *gspca_dev, |
495 | const struct usb_device_id *id) | 394 | const struct usb_device_id *id) |
496 | { | 395 | { |
@@ -499,22 +398,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
499 | 398 | ||
500 | cam = &gspca_dev->cam; | 399 | cam = &gspca_dev->cam; |
501 | 400 | ||
502 | sd->sensor = id->driver_info; | 401 | PDEBUG(D_CONF, "Find Sensor PAC7311"); |
503 | if (sd->sensor == SENSOR_PAC7302) { | 402 | cam->cam_mode = vga_mode; |
504 | PDEBUG(D_CONF, "Find Sensor PAC7302"); | 403 | cam->nmodes = ARRAY_SIZE(vga_mode); |
505 | cam->cam_mode = &vga_mode[2]; /* only 640x480 */ | ||
506 | cam->nmodes = 1; | ||
507 | } else { | ||
508 | PDEBUG(D_CONF, "Find Sensor PAC7311"); | ||
509 | cam->cam_mode = vga_mode; | ||
510 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
511 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | ||
512 | | (1 << SATURATION_IDX); | ||
513 | } | ||
514 | 404 | ||
515 | sd->brightness = BRIGHTNESS_DEF; | ||
516 | sd->contrast = CONTRAST_DEF; | 405 | sd->contrast = CONTRAST_DEF; |
517 | sd->colors = COLOR_DEF; | ||
518 | sd->gain = GAIN_DEF; | 406 | sd->gain = GAIN_DEF; |
519 | sd->exposure = EXPOSURE_DEF; | 407 | sd->exposure = EXPOSURE_DEF; |
520 | sd->autogain = AUTOGAIN_DEF; | 408 | sd->autogain = AUTOGAIN_DEF; |
@@ -523,91 +411,47 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
523 | return 0; | 411 | return 0; |
524 | } | 412 | } |
525 | 413 | ||
526 | /* This function is used by pac7302 only */ | ||
527 | static void setbrightcont(struct gspca_dev *gspca_dev) | ||
528 | { | ||
529 | struct sd *sd = (struct sd *) gspca_dev; | ||
530 | int i, v; | ||
531 | static const __u8 max[10] = | ||
532 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, | ||
533 | 0xd4, 0xec}; | ||
534 | static const __u8 delta[10] = | ||
535 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, | ||
536 | 0x11, 0x0b}; | ||
537 | |||
538 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
539 | for (i = 0; i < 10; i++) { | ||
540 | v = max[i]; | ||
541 | v += (sd->brightness - BRIGHTNESS_MAX) | ||
542 | * 150 / BRIGHTNESS_MAX; /* 200 ? */ | ||
543 | v -= delta[i] * sd->contrast / CONTRAST_MAX; | ||
544 | if (v < 0) | ||
545 | v = 0; | ||
546 | else if (v > 0xff) | ||
547 | v = 0xff; | ||
548 | reg_w(gspca_dev, 0xa2 + i, v); | ||
549 | } | ||
550 | reg_w(gspca_dev, 0xdc, 0x01); | ||
551 | } | ||
552 | |||
553 | /* This function is used by pac7311 only */ | 414 | /* This function is used by pac7311 only */ |
554 | static void setcontrast(struct gspca_dev *gspca_dev) | 415 | static int setcontrast(struct gspca_dev *gspca_dev) |
555 | { | 416 | { |
556 | struct sd *sd = (struct sd *) gspca_dev; | 417 | struct sd *sd = (struct sd *) gspca_dev; |
418 | int ret; | ||
557 | 419 | ||
558 | reg_w(gspca_dev, 0xff, 0x04); | 420 | ret = reg_w(gspca_dev, 0xff, 0x04); |
559 | reg_w(gspca_dev, 0x10, sd->contrast >> 4); | 421 | if (0 <= ret) |
422 | ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4); | ||
560 | /* load registers to sensor (Bit 0, auto clear) */ | 423 | /* load registers to sensor (Bit 0, auto clear) */ |
561 | reg_w(gspca_dev, 0x11, 0x01); | 424 | if (0 <= ret) |
425 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
426 | return ret; | ||
562 | } | 427 | } |
563 | 428 | ||
564 | /* This function is used by pac7302 only */ | 429 | static int setgain(struct gspca_dev *gspca_dev) |
565 | static void setcolors(struct gspca_dev *gspca_dev) | ||
566 | { | 430 | { |
567 | struct sd *sd = (struct sd *) gspca_dev; | 431 | struct sd *sd = (struct sd *) gspca_dev; |
568 | int i, v; | 432 | int gain = GAIN_MAX - sd->gain; |
569 | static const int a[9] = | 433 | int ret; |
570 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; | ||
571 | static const int b[9] = | ||
572 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; | ||
573 | |||
574 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
575 | reg_w(gspca_dev, 0x11, 0x01); | ||
576 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
577 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
578 | for (i = 0; i < 9; i++) { | ||
579 | v = a[i] * sd->colors / COLOR_MAX + b[i]; | ||
580 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | ||
581 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | ||
582 | } | ||
583 | reg_w(gspca_dev, 0xdc, 0x01); | ||
584 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | ||
585 | } | ||
586 | 434 | ||
587 | static void setgain(struct gspca_dev *gspca_dev) | 435 | if (gain < 1) |
588 | { | 436 | gain = 1; |
589 | struct sd *sd = (struct sd *) gspca_dev; | 437 | else if (gain > 245) |
438 | gain = 245; | ||
439 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | ||
440 | if (0 <= ret) | ||
441 | ret = reg_w(gspca_dev, 0x0e, 0x00); | ||
442 | if (0 <= ret) | ||
443 | ret = reg_w(gspca_dev, 0x0f, gain); | ||
590 | 444 | ||
591 | if (sd->sensor == SENSOR_PAC7302) { | ||
592 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
593 | reg_w(gspca_dev, 0x10, sd->gain >> 3); | ||
594 | } else { | ||
595 | int gain = GAIN_MAX - sd->gain; | ||
596 | if (gain < 1) | ||
597 | gain = 1; | ||
598 | else if (gain > 245) | ||
599 | gain = 245; | ||
600 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | ||
601 | reg_w(gspca_dev, 0x0e, 0x00); | ||
602 | reg_w(gspca_dev, 0x0f, gain); | ||
603 | } | ||
604 | /* load registers to sensor (Bit 0, auto clear) */ | 445 | /* load registers to sensor (Bit 0, auto clear) */ |
605 | reg_w(gspca_dev, 0x11, 0x01); | 446 | if (0 <= ret) |
447 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
448 | return ret; | ||
606 | } | 449 | } |
607 | 450 | ||
608 | static void setexposure(struct gspca_dev *gspca_dev) | 451 | static int setexposure(struct gspca_dev *gspca_dev) |
609 | { | 452 | { |
610 | struct sd *sd = (struct sd *) gspca_dev; | 453 | struct sd *sd = (struct sd *) gspca_dev; |
454 | int ret; | ||
611 | __u8 reg; | 455 | __u8 reg; |
612 | 456 | ||
613 | /* register 2 of frame 3/4 contains the clock divider configuring the | 457 | /* register 2 of frame 3/4 contains the clock divider configuring the |
@@ -619,97 +463,94 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
619 | else if (reg > 63) | 463 | else if (reg > 63) |
620 | reg = 63; | 464 | reg = 63; |
621 | 465 | ||
622 | if (sd->sensor == SENSOR_PAC7302) { | 466 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
623 | /* On the pac7302 reg2 MUST be a multiple of 3, so round it to | 467 | if (0 <= ret) |
624 | the nearest multiple of 3, except when between 6 and 12? */ | 468 | ret = reg_w(gspca_dev, 0x02, reg); |
625 | if (reg < 6 || reg > 12) | 469 | /* Page 1 register 8 must always be 0x08 except when not in |
626 | reg = ((reg + 1) / 3) * 3; | 470 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ |
627 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 471 | if (0 <= ret) |
628 | reg_w(gspca_dev, 0x02, reg); | 472 | ret = reg_w(gspca_dev, 0xff, 0x01); |
473 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | ||
474 | reg <= 3) { | ||
475 | if (0 <= ret) | ||
476 | ret = reg_w(gspca_dev, 0x08, 0x09); | ||
629 | } else { | 477 | } else { |
630 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 478 | if (0 <= ret) |
631 | reg_w(gspca_dev, 0x02, reg); | 479 | ret = reg_w(gspca_dev, 0x08, 0x08); |
632 | /* Page 1 register 8 must always be 0x08 except when not in | ||
633 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ | ||
634 | reg_w(gspca_dev, 0xff, 0x01); | ||
635 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | ||
636 | reg <= 3) | ||
637 | reg_w(gspca_dev, 0x08, 0x09); | ||
638 | else | ||
639 | reg_w(gspca_dev, 0x08, 0x08); | ||
640 | } | 480 | } |
481 | |||
641 | /* load registers to sensor (Bit 0, auto clear) */ | 482 | /* load registers to sensor (Bit 0, auto clear) */ |
642 | reg_w(gspca_dev, 0x11, 0x01); | 483 | if (0 <= ret) |
484 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
485 | return ret; | ||
643 | } | 486 | } |
644 | 487 | ||
645 | static void sethvflip(struct gspca_dev *gspca_dev) | 488 | static int sethvflip(struct gspca_dev *gspca_dev) |
646 | { | 489 | { |
647 | struct sd *sd = (struct sd *) gspca_dev; | 490 | struct sd *sd = (struct sd *) gspca_dev; |
491 | int ret; | ||
648 | __u8 data; | 492 | __u8 data; |
649 | 493 | ||
650 | if (sd->sensor == SENSOR_PAC7302) { | 494 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
651 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 495 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); |
652 | data = (sd->hflip ? 0x08 : 0x00) | 496 | if (0 <= ret) |
653 | | (sd->vflip ? 0x04 : 0x00); | 497 | ret = reg_w(gspca_dev, 0x21, data); |
654 | } else { | ||
655 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | ||
656 | data = (sd->hflip ? 0x04 : 0x00) | ||
657 | | (sd->vflip ? 0x08 : 0x00); | ||
658 | } | ||
659 | reg_w(gspca_dev, 0x21, data); | ||
660 | /* load registers to sensor (Bit 0, auto clear) */ | 498 | /* load registers to sensor (Bit 0, auto clear) */ |
661 | reg_w(gspca_dev, 0x11, 0x01); | 499 | if (0 <= ret) |
500 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
501 | return ret; | ||
662 | } | 502 | } |
663 | 503 | ||
664 | /* this function is called at probe and resume time */ | 504 | /* this function is called at probe and resume time for pac7311 */ |
665 | static int sd_init(struct gspca_dev *gspca_dev) | 505 | static int sd_init(struct gspca_dev *gspca_dev) |
666 | { | 506 | { |
667 | struct sd *sd = (struct sd *) gspca_dev; | 507 | return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); |
668 | |||
669 | if (sd->sensor == SENSOR_PAC7302) | ||
670 | reg_w_seq(gspca_dev, init_7302, sizeof init_7302); | ||
671 | else | ||
672 | reg_w_seq(gspca_dev, init_7311, sizeof init_7311); | ||
673 | |||
674 | return 0; | ||
675 | } | 508 | } |
676 | 509 | ||
677 | static int sd_start(struct gspca_dev *gspca_dev) | 510 | static int sd_start(struct gspca_dev *gspca_dev) |
678 | { | 511 | { |
679 | struct sd *sd = (struct sd *) gspca_dev; | 512 | struct sd *sd = (struct sd *) gspca_dev; |
513 | int ret; | ||
680 | 514 | ||
681 | sd->sof_read = 0; | 515 | sd->sof_read = 0; |
682 | 516 | ||
683 | if (sd->sensor == SENSOR_PAC7302) { | 517 | ret = reg_w_var(gspca_dev, start_7311, |
684 | reg_w_var(gspca_dev, start_7302); | 518 | NULL, 0, |
685 | setbrightcont(gspca_dev); | 519 | page4_7311, sizeof(page4_7311)); |
686 | setcolors(gspca_dev); | 520 | if (0 <= ret) |
687 | } else { | 521 | ret = setcontrast(gspca_dev); |
688 | reg_w_var(gspca_dev, start_7311); | 522 | if (0 <= ret) |
689 | setcontrast(gspca_dev); | 523 | ret = setgain(gspca_dev); |
690 | } | 524 | if (0 <= ret) |
691 | setgain(gspca_dev); | 525 | ret = setexposure(gspca_dev); |
692 | setexposure(gspca_dev); | 526 | if (0 <= ret) |
693 | sethvflip(gspca_dev); | 527 | ret = sethvflip(gspca_dev); |
694 | 528 | ||
695 | /* set correct resolution */ | 529 | /* set correct resolution */ |
696 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { | 530 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
697 | case 2: /* 160x120 pac7311 */ | 531 | case 2: /* 160x120 pac7311 */ |
698 | reg_w(gspca_dev, 0xff, 0x01); | 532 | if (0 <= ret) |
699 | reg_w(gspca_dev, 0x17, 0x20); | 533 | ret = reg_w(gspca_dev, 0xff, 0x01); |
700 | reg_w(gspca_dev, 0x87, 0x10); | 534 | if (0 <= ret) |
535 | ret = reg_w(gspca_dev, 0x17, 0x20); | ||
536 | if (0 <= ret) | ||
537 | ret = reg_w(gspca_dev, 0x87, 0x10); | ||
701 | break; | 538 | break; |
702 | case 1: /* 320x240 pac7311 */ | 539 | case 1: /* 320x240 pac7311 */ |
703 | reg_w(gspca_dev, 0xff, 0x01); | 540 | if (0 <= ret) |
704 | reg_w(gspca_dev, 0x17, 0x30); | 541 | ret = reg_w(gspca_dev, 0xff, 0x01); |
705 | reg_w(gspca_dev, 0x87, 0x11); | 542 | if (0 <= ret) |
543 | ret = reg_w(gspca_dev, 0x17, 0x30); | ||
544 | if (0 <= ret) | ||
545 | ret = reg_w(gspca_dev, 0x87, 0x11); | ||
706 | break; | 546 | break; |
707 | case 0: /* 640x480 */ | 547 | case 0: /* 640x480 */ |
708 | if (sd->sensor == SENSOR_PAC7302) | 548 | if (0 <= ret) |
709 | break; | 549 | ret = reg_w(gspca_dev, 0xff, 0x01); |
710 | reg_w(gspca_dev, 0xff, 0x01); | 550 | if (0 <= ret) |
711 | reg_w(gspca_dev, 0x17, 0x00); | 551 | ret = reg_w(gspca_dev, 0x17, 0x00); |
712 | reg_w(gspca_dev, 0x87, 0x12); | 552 | if (0 <= ret) |
553 | ret = reg_w(gspca_dev, 0x87, 0x12); | ||
713 | break; | 554 | break; |
714 | } | 555 | } |
715 | 556 | ||
@@ -718,47 +559,42 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
718 | atomic_set(&sd->avg_lum, -1); | 559 | atomic_set(&sd->avg_lum, -1); |
719 | 560 | ||
720 | /* start stream */ | 561 | /* start stream */ |
721 | reg_w(gspca_dev, 0xff, 0x01); | 562 | if (0 <= ret) |
722 | if (sd->sensor == SENSOR_PAC7302) | 563 | ret = reg_w(gspca_dev, 0xff, 0x01); |
723 | reg_w(gspca_dev, 0x78, 0x01); | 564 | if (0 <= ret) |
724 | else | 565 | ret = reg_w(gspca_dev, 0x78, 0x05); |
725 | reg_w(gspca_dev, 0x78, 0x05); | 566 | |
726 | return 0; | 567 | return ret; |
727 | } | 568 | } |
728 | 569 | ||
729 | static void sd_stopN(struct gspca_dev *gspca_dev) | 570 | static void sd_stopN(struct gspca_dev *gspca_dev) |
730 | { | 571 | { |
731 | struct sd *sd = (struct sd *) gspca_dev; | 572 | int ret; |
732 | |||
733 | if (sd->sensor == SENSOR_PAC7302) { | ||
734 | reg_w(gspca_dev, 0xff, 0x01); | ||
735 | reg_w(gspca_dev, 0x78, 0x00); | ||
736 | reg_w(gspca_dev, 0x78, 0x00); | ||
737 | return; | ||
738 | } | ||
739 | reg_w(gspca_dev, 0xff, 0x04); | ||
740 | reg_w(gspca_dev, 0x27, 0x80); | ||
741 | reg_w(gspca_dev, 0x28, 0xca); | ||
742 | reg_w(gspca_dev, 0x29, 0x53); | ||
743 | reg_w(gspca_dev, 0x2a, 0x0e); | ||
744 | reg_w(gspca_dev, 0xff, 0x01); | ||
745 | reg_w(gspca_dev, 0x3e, 0x20); | ||
746 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
747 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
748 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
749 | } | ||
750 | 573 | ||
751 | /* called on streamoff with alt 0 and on disconnect */ | 574 | ret = reg_w(gspca_dev, 0xff, 0x04); |
575 | if (0 <= ret) | ||
576 | ret = reg_w(gspca_dev, 0x27, 0x80); | ||
577 | if (0 <= ret) | ||
578 | ret = reg_w(gspca_dev, 0x28, 0xca); | ||
579 | if (0 <= ret) | ||
580 | ret = reg_w(gspca_dev, 0x29, 0x53); | ||
581 | if (0 <= ret) | ||
582 | ret = reg_w(gspca_dev, 0x2a, 0x0e); | ||
583 | if (0 <= ret) | ||
584 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
585 | if (0 <= ret) | ||
586 | ret = reg_w(gspca_dev, 0x3e, 0x20); | ||
587 | if (0 <= ret) | ||
588 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
589 | if (0 <= ret) | ||
590 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
591 | if (0 <= ret) | ||
592 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
593 | } | ||
594 | |||
595 | /* called on streamoff with alt 0 and on disconnect for 7311 */ | ||
752 | static void sd_stop0(struct gspca_dev *gspca_dev) | 596 | static void sd_stop0(struct gspca_dev *gspca_dev) |
753 | { | 597 | { |
754 | struct sd *sd = (struct sd *) gspca_dev; | ||
755 | |||
756 | if (!gspca_dev->present) | ||
757 | return; | ||
758 | if (sd->sensor == SENSOR_PAC7302) { | ||
759 | reg_w(gspca_dev, 0xff, 0x01); | ||
760 | reg_w(gspca_dev, 0x78, 0x40); | ||
761 | } | ||
762 | } | 598 | } |
763 | 599 | ||
764 | /* Include pac common sof detection functions */ | 600 | /* Include pac common sof detection functions */ |
@@ -773,22 +609,8 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
773 | if (avg_lum == -1) | 609 | if (avg_lum == -1) |
774 | return; | 610 | return; |
775 | 611 | ||
776 | if (sd->sensor == SENSOR_PAC7302) { | 612 | desired_lum = 200; |
777 | desired_lum = 270 + sd->brightness * 4; | 613 | deadzone = 20; |
778 | /* Hack hack, with the 7202 the first exposure step is | ||
779 | pretty large, so if we're about to make the first | ||
780 | exposure increase make the deadzone large to avoid | ||
781 | oscilating */ | ||
782 | if (desired_lum > avg_lum && sd->gain == GAIN_DEF && | ||
783 | sd->exposure > EXPOSURE_DEF && | ||
784 | sd->exposure < 42) | ||
785 | deadzone = 90; | ||
786 | else | ||
787 | deadzone = 30; | ||
788 | } else { | ||
789 | desired_lum = 200; | ||
790 | deadzone = 20; | ||
791 | } | ||
792 | 614 | ||
793 | if (sd->autogain_ignore_frames > 0) | 615 | if (sd->autogain_ignore_frames > 0) |
794 | sd->autogain_ignore_frames--; | 616 | sd->autogain_ignore_frames--; |
@@ -797,53 +619,92 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
797 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; | 619 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; |
798 | } | 620 | } |
799 | 621 | ||
800 | static const unsigned char pac7311_jpeg_header1[] = { | 622 | /* JPEG header, part 1 */ |
801 | 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08 | 623 | static const unsigned char pac_jpeg_header1[] = { |
624 | 0xff, 0xd8, /* SOI: Start of Image */ | ||
625 | |||
626 | 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ | ||
627 | 0x00, 0x11, /* length = 17 bytes (including this length field) */ | ||
628 | 0x08 /* Precision: 8 */ | ||
629 | /* 2 bytes is placed here: number of image lines */ | ||
630 | /* 2 bytes is placed here: samples per line */ | ||
802 | }; | 631 | }; |
803 | 632 | ||
804 | static const unsigned char pac7311_jpeg_header2[] = { | 633 | /* JPEG header, continued */ |
805 | 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, | 634 | static const unsigned char pac_jpeg_header2[] = { |
806 | 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 | 635 | 0x03, /* Number of image components: 3 */ |
636 | 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ | ||
637 | 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ | ||
638 | 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ | ||
639 | |||
640 | 0xff, 0xda, /* SOS: Start Of Scan */ | ||
641 | 0x00, 0x0c, /* length = 12 bytes (including this length field) */ | ||
642 | 0x03, /* number of components: 3 */ | ||
643 | 0x01, 0x00, /* selector 1, table 0x00 */ | ||
644 | 0x02, 0x11, /* selector 2, table 0x11 */ | ||
645 | 0x03, 0x11, /* selector 3, table 0x11 */ | ||
646 | 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ | ||
647 | 0x00 /* Successive approximation: 0 */ | ||
807 | }; | 648 | }; |
808 | 649 | ||
650 | static void pac_start_frame(struct gspca_dev *gspca_dev, | ||
651 | struct gspca_frame *frame, | ||
652 | __u16 lines, __u16 samples_per_line) | ||
653 | { | ||
654 | unsigned char tmpbuf[4]; | ||
655 | |||
656 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
657 | pac_jpeg_header1, sizeof(pac_jpeg_header1)); | ||
658 | |||
659 | tmpbuf[0] = lines >> 8; | ||
660 | tmpbuf[1] = lines & 0xff; | ||
661 | tmpbuf[2] = samples_per_line >> 8; | ||
662 | tmpbuf[3] = samples_per_line & 0xff; | ||
663 | |||
664 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
665 | tmpbuf, sizeof(tmpbuf)); | ||
666 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
667 | pac_jpeg_header2, sizeof(pac_jpeg_header2)); | ||
668 | } | ||
669 | |||
809 | /* this function is run at interrupt level */ | 670 | /* this function is run at interrupt level */ |
810 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 671 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
811 | struct gspca_frame *frame, /* target */ | 672 | u8 *data, /* isoc packet */ |
812 | __u8 *data, /* isoc packet */ | ||
813 | int len) /* iso packet length */ | 673 | int len) /* iso packet length */ |
814 | { | 674 | { |
815 | struct sd *sd = (struct sd *) gspca_dev; | 675 | struct sd *sd = (struct sd *) gspca_dev; |
816 | unsigned char *sof; | 676 | unsigned char *sof; |
677 | struct gspca_frame *frame; | ||
817 | 678 | ||
818 | sof = pac_find_sof(gspca_dev, data, len); | 679 | sof = pac_find_sof(&sd->sof_read, data, len); |
819 | if (sof) { | 680 | if (sof) { |
820 | unsigned char tmpbuf[4]; | ||
821 | int n, lum_offset, footer_length; | 681 | int n, lum_offset, footer_length; |
822 | 682 | ||
823 | if (sd->sensor == SENSOR_PAC7302) { | 683 | frame = gspca_get_i_frame(gspca_dev); |
824 | /* 6 bytes after the FF D9 EOF marker a number of lumination | 684 | if (frame == NULL) { |
825 | bytes are send corresponding to different parts of the | 685 | gspca_dev->last_packet_type = DISCARD_PACKET; |
826 | image, the 14th and 15th byte after the EOF seem to | 686 | return; |
827 | correspond to the center of the image */ | ||
828 | lum_offset = 61 + sizeof pac_sof_marker; | ||
829 | footer_length = 74; | ||
830 | } else { | ||
831 | lum_offset = 24 + sizeof pac_sof_marker; | ||
832 | footer_length = 26; | ||
833 | } | 687 | } |
834 | 688 | ||
689 | /* 6 bytes after the FF D9 EOF marker a number of lumination | ||
690 | bytes are send corresponding to different parts of the | ||
691 | image, the 14th and 15th byte after the EOF seem to | ||
692 | correspond to the center of the image */ | ||
693 | lum_offset = 24 + sizeof pac_sof_marker; | ||
694 | footer_length = 26; | ||
695 | |||
835 | /* Finish decoding current frame */ | 696 | /* Finish decoding current frame */ |
836 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); | 697 | n = (sof - data) - (footer_length + sizeof pac_sof_marker); |
837 | if (n < 0) { | 698 | if (n < 0) { |
838 | frame->data_end += n; | 699 | frame->data_end += n; |
839 | n = 0; | 700 | n = 0; |
840 | } | 701 | } |
841 | frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 702 | gspca_frame_add(gspca_dev, INTER_PACKET, |
842 | data, n); | 703 | data, n); |
843 | if (gspca_dev->last_packet_type != DISCARD_PACKET && | 704 | if (gspca_dev->last_packet_type != DISCARD_PACKET && |
844 | frame->data_end[-2] == 0xff && | 705 | frame->data_end[-2] == 0xff && |
845 | frame->data_end[-1] == 0xd9) | 706 | frame->data_end[-1] == 0xd9) |
846 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | 707 | gspca_frame_add(gspca_dev, LAST_PACKET, |
847 | NULL, 0); | 708 | NULL, 0); |
848 | 709 | ||
849 | n = sof - data; | 710 | n = sof - data; |
@@ -859,43 +720,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
859 | atomic_set(&sd->avg_lum, -1); | 720 | atomic_set(&sd->avg_lum, -1); |
860 | 721 | ||
861 | /* Start the new frame with the jpeg header */ | 722 | /* Start the new frame with the jpeg header */ |
862 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | 723 | pac_start_frame(gspca_dev, frame, |
863 | pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1)); | 724 | gspca_dev->height, gspca_dev->width); |
864 | if (sd->sensor == SENSOR_PAC7302) { | ||
865 | /* The PAC7302 has the image rotated 90 degrees */ | ||
866 | tmpbuf[0] = gspca_dev->width >> 8; | ||
867 | tmpbuf[1] = gspca_dev->width & 0xff; | ||
868 | tmpbuf[2] = gspca_dev->height >> 8; | ||
869 | tmpbuf[3] = gspca_dev->height & 0xff; | ||
870 | } else { | ||
871 | tmpbuf[0] = gspca_dev->height >> 8; | ||
872 | tmpbuf[1] = gspca_dev->height & 0xff; | ||
873 | tmpbuf[2] = gspca_dev->width >> 8; | ||
874 | tmpbuf[3] = gspca_dev->width & 0xff; | ||
875 | } | ||
876 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4); | ||
877 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
878 | pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2)); | ||
879 | } | 725 | } |
880 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | 726 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
881 | } | ||
882 | |||
883 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
884 | { | ||
885 | struct sd *sd = (struct sd *) gspca_dev; | ||
886 | |||
887 | sd->brightness = val; | ||
888 | if (gspca_dev->streaming) | ||
889 | setbrightcont(gspca_dev); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
894 | { | ||
895 | struct sd *sd = (struct sd *) gspca_dev; | ||
896 | |||
897 | *val = sd->brightness; | ||
898 | return 0; | ||
899 | } | 727 | } |
900 | 728 | ||
901 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 729 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) |
@@ -904,10 +732,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
904 | 732 | ||
905 | sd->contrast = val; | 733 | sd->contrast = val; |
906 | if (gspca_dev->streaming) { | 734 | if (gspca_dev->streaming) { |
907 | if (sd->sensor == SENSOR_PAC7302) | 735 | setcontrast(gspca_dev); |
908 | setbrightcont(gspca_dev); | ||
909 | else | ||
910 | setcontrast(gspca_dev); | ||
911 | } | 736 | } |
912 | return 0; | 737 | return 0; |
913 | } | 738 | } |
@@ -920,24 +745,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | |||
920 | return 0; | 745 | return 0; |
921 | } | 746 | } |
922 | 747 | ||
923 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
924 | { | ||
925 | struct sd *sd = (struct sd *) gspca_dev; | ||
926 | |||
927 | sd->colors = val; | ||
928 | if (gspca_dev->streaming) | ||
929 | setcolors(gspca_dev); | ||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
934 | { | ||
935 | struct sd *sd = (struct sd *) gspca_dev; | ||
936 | |||
937 | *val = sd->colors; | ||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | 748 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) |
942 | { | 749 | { |
943 | struct sd *sd = (struct sd *) gspca_dev; | 750 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1041,7 +848,7 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
1041 | return 0; | 848 | return 0; |
1042 | } | 849 | } |
1043 | 850 | ||
1044 | /* sub-driver description */ | 851 | /* sub-driver description for pac7311 */ |
1045 | static struct sd_desc sd_desc = { | 852 | static struct sd_desc sd_desc = { |
1046 | .name = MODULE_NAME, | 853 | .name = MODULE_NAME, |
1047 | .ctrls = sd_ctrls, | 854 | .ctrls = sd_ctrls, |
@@ -1057,21 +864,12 @@ static struct sd_desc sd_desc = { | |||
1057 | 864 | ||
1058 | /* -- module initialisation -- */ | 865 | /* -- module initialisation -- */ |
1059 | static __devinitdata struct usb_device_id device_table[] = { | 866 | static __devinitdata struct usb_device_id device_table[] = { |
1060 | {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302}, | 867 | {USB_DEVICE(0x093a, 0x2600)}, |
1061 | {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, | 868 | {USB_DEVICE(0x093a, 0x2601)}, |
1062 | {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, | 869 | {USB_DEVICE(0x093a, 0x2603)}, |
1063 | {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, | 870 | {USB_DEVICE(0x093a, 0x2608)}, |
1064 | {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311}, | 871 | {USB_DEVICE(0x093a, 0x260e)}, |
1065 | {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, | 872 | {USB_DEVICE(0x093a, 0x260f)}, |
1066 | {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, | ||
1067 | {USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302}, | ||
1068 | {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, | ||
1069 | {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302}, | ||
1070 | {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, | ||
1071 | {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, | ||
1072 | {USB_DEVICE(0x093a, 0x2629), .driver_info = SENSOR_PAC7302}, | ||
1073 | {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302}, | ||
1074 | {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302}, | ||
1075 | {} | 873 | {} |
1076 | }; | 874 | }; |
1077 | MODULE_DEVICE_TABLE(usb, device_table); | 875 | MODULE_DEVICE_TABLE(usb, device_table); |