diff options
Diffstat (limited to 'drivers/media/video/gspca/stk014.c')
-rw-r--r-- | drivers/media/video/gspca/stk014.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 60de9af87fbb..f25be20cf1a6 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -35,10 +35,13 @@ struct sd { | |||
35 | unsigned char contrast; | 35 | unsigned char contrast; |
36 | unsigned char colors; | 36 | unsigned char colors; |
37 | unsigned char lightfreq; | 37 | unsigned char lightfreq; |
38 | }; | 38 | u8 quality; |
39 | #define QUALITY_MIN 60 | ||
40 | #define QUALITY_MAX 95 | ||
41 | #define QUALITY_DEF 80 | ||
39 | 42 | ||
40 | /* global parameters */ | 43 | u8 *jpeg_hdr; |
41 | static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */ | 44 | }; |
42 | 45 | ||
43 | /* V4L2 controls supported by the driver */ | 46 | /* V4L2 controls supported by the driver */ |
44 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 47 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
@@ -180,7 +183,7 @@ static int rcv_val(struct gspca_dev *gspca_dev, | |||
180 | reg_w(gspca_dev, 0x63b, 0); | 183 | reg_w(gspca_dev, 0x63b, 0); |
181 | reg_w(gspca_dev, 0x630, 5); | 184 | reg_w(gspca_dev, 0x630, 5); |
182 | ret = usb_bulk_msg(dev, | 185 | ret = usb_bulk_msg(dev, |
183 | usb_rcvbulkpipe(dev, 5), | 186 | usb_rcvbulkpipe(dev, 0x05), |
184 | gspca_dev->usb_buf, | 187 | gspca_dev->usb_buf, |
185 | 4, /* length */ | 188 | 4, /* length */ |
186 | &alen, | 189 | &alen, |
@@ -294,15 +297,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
294 | const struct usb_device_id *id) | 297 | const struct usb_device_id *id) |
295 | { | 298 | { |
296 | struct sd *sd = (struct sd *) gspca_dev; | 299 | struct sd *sd = (struct sd *) gspca_dev; |
297 | struct cam *cam = &gspca_dev->cam; | ||
298 | 300 | ||
299 | cam->epaddr = 0x02; | ||
300 | gspca_dev->cam.cam_mode = vga_mode; | 301 | gspca_dev->cam.cam_mode = vga_mode; |
301 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | 302 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); |
302 | sd->brightness = BRIGHTNESS_DEF; | 303 | sd->brightness = BRIGHTNESS_DEF; |
303 | sd->contrast = CONTRAST_DEF; | 304 | sd->contrast = CONTRAST_DEF; |
304 | sd->colors = COLOR_DEF; | 305 | sd->colors = COLOR_DEF; |
305 | sd->lightfreq = FREQ_DEF; | 306 | sd->lightfreq = FREQ_DEF; |
307 | sd->quality = QUALITY_DEF; | ||
306 | return 0; | 308 | return 0; |
307 | } | 309 | } |
308 | 310 | ||
@@ -326,8 +328,15 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
326 | /* -- start the camera -- */ | 328 | /* -- start the camera -- */ |
327 | static int sd_start(struct gspca_dev *gspca_dev) | 329 | static int sd_start(struct gspca_dev *gspca_dev) |
328 | { | 330 | { |
331 | struct sd *sd = (struct sd *) gspca_dev; | ||
329 | int ret, value; | 332 | int ret, value; |
330 | 333 | ||
334 | /* create the JPEG header */ | ||
335 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | ||
336 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | ||
337 | 0x22); /* JPEG 411 */ | ||
338 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
339 | |||
331 | /* work on alternate 1 */ | 340 | /* work on alternate 1 */ |
332 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); | 341 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); |
333 | 342 | ||
@@ -399,11 +408,19 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
399 | PDEBUG(D_STREAM, "camera stopped"); | 408 | PDEBUG(D_STREAM, "camera stopped"); |
400 | } | 409 | } |
401 | 410 | ||
411 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
412 | { | ||
413 | struct sd *sd = (struct sd *) gspca_dev; | ||
414 | |||
415 | kfree(sd->jpeg_hdr); | ||
416 | } | ||
417 | |||
402 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 418 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
403 | struct gspca_frame *frame, /* target */ | 419 | struct gspca_frame *frame, /* target */ |
404 | __u8 *data, /* isoc packet */ | 420 | __u8 *data, /* isoc packet */ |
405 | int len) /* iso packet length */ | 421 | int len) /* iso packet length */ |
406 | { | 422 | { |
423 | struct sd *sd = (struct sd *) gspca_dev; | ||
407 | static unsigned char ffd9[] = {0xff, 0xd9}; | 424 | static unsigned char ffd9[] = {0xff, 0xd9}; |
408 | 425 | ||
409 | /* a frame starts with: | 426 | /* a frame starts with: |
@@ -420,7 +437,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
420 | ffd9, 2); | 437 | ffd9, 2); |
421 | 438 | ||
422 | /* put the JPEG 411 header */ | 439 | /* put the JPEG 411 header */ |
423 | jpeg_put_header(gspca_dev, frame, sd_quant, 0x22); | 440 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, |
441 | sd->jpeg_hdr, JPEG_HDR_SZ); | ||
424 | 442 | ||
425 | /* beginning of the frame */ | 443 | /* beginning of the frame */ |
426 | #define STKHDRSZ 12 | 444 | #define STKHDRSZ 12 |
@@ -520,6 +538,34 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
520 | return -EINVAL; | 538 | return -EINVAL; |
521 | } | 539 | } |
522 | 540 | ||
541 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | ||
542 | struct v4l2_jpegcompression *jcomp) | ||
543 | { | ||
544 | struct sd *sd = (struct sd *) gspca_dev; | ||
545 | |||
546 | if (jcomp->quality < QUALITY_MIN) | ||
547 | sd->quality = QUALITY_MIN; | ||
548 | else if (jcomp->quality > QUALITY_MAX) | ||
549 | sd->quality = QUALITY_MAX; | ||
550 | else | ||
551 | sd->quality = jcomp->quality; | ||
552 | if (gspca_dev->streaming) | ||
553 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | ||
558 | struct v4l2_jpegcompression *jcomp) | ||
559 | { | ||
560 | struct sd *sd = (struct sd *) gspca_dev; | ||
561 | |||
562 | memset(jcomp, 0, sizeof *jcomp); | ||
563 | jcomp->quality = sd->quality; | ||
564 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | ||
565 | | V4L2_JPEG_MARKER_DQT; | ||
566 | return 0; | ||
567 | } | ||
568 | |||
523 | /* sub-driver description */ | 569 | /* sub-driver description */ |
524 | static const struct sd_desc sd_desc = { | 570 | static const struct sd_desc sd_desc = { |
525 | .name = MODULE_NAME, | 571 | .name = MODULE_NAME, |
@@ -529,8 +575,11 @@ static const struct sd_desc sd_desc = { | |||
529 | .init = sd_init, | 575 | .init = sd_init, |
530 | .start = sd_start, | 576 | .start = sd_start, |
531 | .stopN = sd_stopN, | 577 | .stopN = sd_stopN, |
578 | .stop0 = sd_stop0, | ||
532 | .pkt_scan = sd_pkt_scan, | 579 | .pkt_scan = sd_pkt_scan, |
533 | .querymenu = sd_querymenu, | 580 | .querymenu = sd_querymenu, |
581 | .get_jcomp = sd_get_jcomp, | ||
582 | .set_jcomp = sd_set_jcomp, | ||
534 | }; | 583 | }; |
535 | 584 | ||
536 | /* -- module initialisation -- */ | 585 | /* -- module initialisation -- */ |
@@ -562,8 +611,10 @@ static struct usb_driver sd_driver = { | |||
562 | /* -- module insert / remove -- */ | 611 | /* -- module insert / remove -- */ |
563 | static int __init sd_mod_init(void) | 612 | static int __init sd_mod_init(void) |
564 | { | 613 | { |
565 | if (usb_register(&sd_driver) < 0) | 614 | int ret; |
566 | return -1; | 615 | ret = usb_register(&sd_driver); |
616 | if (ret < 0) | ||
617 | return ret; | ||
567 | info("registered"); | 618 | info("registered"); |
568 | return 0; | 619 | return 0; |
569 | } | 620 | } |
@@ -575,6 +626,3 @@ static void __exit sd_mod_exit(void) | |||
575 | 626 | ||
576 | module_init(sd_mod_init); | 627 | module_init(sd_mod_init); |
577 | module_exit(sd_mod_exit); | 628 | module_exit(sd_mod_exit); |
578 | |||
579 | module_param_named(quant, sd_quant, int, 0644); | ||
580 | MODULE_PARM_DESC(quant, "Quantization index (0..8)"); | ||