diff options
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 134 |
1 files changed, 23 insertions, 111 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 1225c0fe26f0..cb0aeb0c0a45 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -43,13 +43,11 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 4) | 46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5) |
47 | static const char version[] = "2.1.4"; | 47 | static const char version[] = "2.1.5"; |
48 | 48 | ||
49 | static int video_nr = -1; | 49 | static int video_nr = -1; |
50 | 50 | ||
51 | static int comp_fac = 30; /* Buffer size ratio when compressed in % */ | ||
52 | |||
53 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 51 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
54 | int gspca_debug = D_ERR | D_PROBE; | 52 | int gspca_debug = D_ERR | D_PROBE; |
55 | EXPORT_SYMBOL(gspca_debug); | 53 | EXPORT_SYMBOL(gspca_debug); |
@@ -361,58 +359,6 @@ static void rvfree(void *mem, unsigned long size) | |||
361 | vfree(mem); | 359 | vfree(mem); |
362 | } | 360 | } |
363 | 361 | ||
364 | static __u32 get_v4l2_depth(__u32 pixfmt) | ||
365 | { | ||
366 | switch (pixfmt) { | ||
367 | /* case V4L2_PIX_FMT_BGR32: | ||
368 | case V4L2_PIX_FMT_RGB32: | ||
369 | return 32; */ | ||
370 | case V4L2_PIX_FMT_RGB24: /* 'RGB3' */ | ||
371 | case V4L2_PIX_FMT_BGR24: | ||
372 | return 24; | ||
373 | /* case V4L2_PIX_FMT_RGB565: * 'RGBP' */ | ||
374 | case V4L2_PIX_FMT_YUYV: /* 'YUYV' packed 4.2.2 */ | ||
375 | case V4L2_PIX_FMT_YYUV: /* 'YYUV' */ | ||
376 | return 16; | ||
377 | case V4L2_PIX_FMT_YUV420: /* 'YU12' planar 4.2.0 */ | ||
378 | case V4L2_PIX_FMT_SPCA501: /* 'S501' YUYV per line */ | ||
379 | return 12; | ||
380 | case V4L2_PIX_FMT_MJPEG: | ||
381 | case V4L2_PIX_FMT_JPEG: | ||
382 | case V4L2_PIX_FMT_SBGGR8: /* 'BA81' Bayer */ | ||
383 | case V4L2_PIX_FMT_SN9C10X: /* 'S910' SN9C10x compression */ | ||
384 | case V4L2_PIX_FMT_SPCA561: /* 'S561' compressed GBRG bayer */ | ||
385 | case V4L2_PIX_FMT_PAC207: /* 'P207' compressed BGGR bayer */ | ||
386 | return 8; | ||
387 | } | ||
388 | PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c", | ||
389 | pixfmt & 0xff, | ||
390 | (pixfmt >> 8) & 0xff, | ||
391 | (pixfmt >> 16) & 0xff, | ||
392 | pixfmt >> 24); | ||
393 | return 24; | ||
394 | } | ||
395 | |||
396 | static int gspca_get_buff_size(struct gspca_dev *gspca_dev, int mode) | ||
397 | { | ||
398 | unsigned int size; | ||
399 | |||
400 | if (gspca_dev->sd_desc->get_buff_size) | ||
401 | return gspca_dev->sd_desc->get_buff_size(gspca_dev, mode); | ||
402 | |||
403 | size = gspca_dev->cam.cam_mode[mode].width * | ||
404 | gspca_dev->cam.cam_mode[mode].height * | ||
405 | get_v4l2_depth(gspca_dev->cam.cam_mode[mode].pixfmt) / 8; | ||
406 | if (!size) | ||
407 | return -ENOMEM; | ||
408 | |||
409 | /* if compressed (JPEG), reduce the buffer size */ | ||
410 | if (gspca_is_compressed(gspca_dev->cam.cam_mode[mode].pixfmt)) | ||
411 | size = (size * comp_fac) / 100 + 600; /* (+ JPEG header sz) */ | ||
412 | |||
413 | return size; | ||
414 | } | ||
415 | |||
416 | static int frame_alloc(struct gspca_dev *gspca_dev, | 362 | static int frame_alloc(struct gspca_dev *gspca_dev, |
417 | unsigned int count) | 363 | unsigned int count) |
418 | { | 364 | { |
@@ -420,15 +366,14 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
420 | unsigned int frsz; | 366 | unsigned int frsz; |
421 | int i; | 367 | int i; |
422 | 368 | ||
423 | frsz = gspca_get_buff_size(gspca_dev, gspca_dev->curr_mode); | 369 | i = gspca_dev->curr_mode; |
424 | if (frsz < 0) | 370 | frsz = gspca_dev->cam.cam_mode[i].sizeimage; |
425 | return frsz; | ||
426 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); | 371 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); |
427 | if (count > GSPCA_MAX_FRAMES) | ||
428 | count = GSPCA_MAX_FRAMES; | ||
429 | frsz = PAGE_ALIGN(frsz); | 372 | frsz = PAGE_ALIGN(frsz); |
430 | PDEBUG(D_STREAM, "new fr_sz: %d", frsz); | 373 | PDEBUG(D_STREAM, "new fr_sz: %d", frsz); |
431 | gspca_dev->frsz = frsz; | 374 | gspca_dev->frsz = frsz; |
375 | if (count > GSPCA_MAX_FRAMES) | ||
376 | count = GSPCA_MAX_FRAMES; | ||
432 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { | 377 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { |
433 | gspca_dev->frbuf = rvmalloc(frsz * count); | 378 | gspca_dev->frbuf = rvmalloc(frsz * count); |
434 | if (!gspca_dev->frbuf) { | 379 | if (!gspca_dev->frbuf) { |
@@ -711,7 +656,7 @@ static void gspca_set_default_mode(struct gspca_dev *gspca_dev) | |||
711 | gspca_dev->curr_mode = i; | 656 | gspca_dev->curr_mode = i; |
712 | gspca_dev->width = gspca_dev->cam.cam_mode[i].width; | 657 | gspca_dev->width = gspca_dev->cam.cam_mode[i].width; |
713 | gspca_dev->height = gspca_dev->cam.cam_mode[i].height; | 658 | gspca_dev->height = gspca_dev->cam.cam_mode[i].height; |
714 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt; | 659 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat; |
715 | } | 660 | } |
716 | 661 | ||
717 | static int wxh_to_mode(struct gspca_dev *gspca_dev, | 662 | static int wxh_to_mode(struct gspca_dev *gspca_dev, |
@@ -739,11 +684,13 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev, | |||
739 | modeU = modeD = mode; | 684 | modeU = modeD = mode; |
740 | while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) { | 685 | while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) { |
741 | if (--modeD >= 0) { | 686 | if (--modeD >= 0) { |
742 | if (gspca_dev->cam.cam_mode[modeD].pixfmt == pixfmt) | 687 | if (gspca_dev->cam.cam_mode[modeD].pixelformat |
688 | == pixfmt) | ||
743 | return modeD; | 689 | return modeD; |
744 | } | 690 | } |
745 | if (++modeU < gspca_dev->cam.nmodes) { | 691 | if (++modeU < gspca_dev->cam.nmodes) { |
746 | if (gspca_dev->cam.cam_mode[modeU].pixfmt == pixfmt) | 692 | if (gspca_dev->cam.cam_mode[modeU].pixelformat |
693 | == pixfmt) | ||
747 | return modeU; | 694 | return modeU; |
748 | } | 695 | } |
749 | } | 696 | } |
@@ -761,7 +708,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
761 | index = 0; | 708 | index = 0; |
762 | j = 0; | 709 | j = 0; |
763 | for (i = gspca_dev->cam.nmodes; --i >= 0; ) { | 710 | for (i = gspca_dev->cam.nmodes; --i >= 0; ) { |
764 | fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixfmt; | 711 | fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat; |
765 | j = 0; | 712 | j = 0; |
766 | for (;;) { | 713 | for (;;) { |
767 | if (fmt_tb[j] == fmt_tb[index]) | 714 | if (fmt_tb[j] == fmt_tb[index]) |
@@ -795,20 +742,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
795 | struct v4l2_format *fmt) | 742 | struct v4l2_format *fmt) |
796 | { | 743 | { |
797 | struct gspca_dev *gspca_dev = priv; | 744 | struct gspca_dev *gspca_dev = priv; |
745 | int mode; | ||
798 | 746 | ||
799 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 747 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
800 | return -EINVAL; | 748 | return -EINVAL; |
801 | fmt->fmt.pix.width = gspca_dev->width; | 749 | mode = gspca_dev->curr_mode; |
802 | fmt->fmt.pix.height = gspca_dev->height; | 750 | memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode], |
803 | fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; | 751 | sizeof fmt->fmt.pix); |
804 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
805 | fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat) | ||
806 | * fmt->fmt.pix.width / 8; | ||
807 | fmt->fmt.pix.sizeimage = gspca_get_buff_size(gspca_dev, | ||
808 | gspca_dev->curr_mode); | ||
809 | /* (should be in the subdriver) */ | ||
810 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; | ||
811 | fmt->fmt.pix.priv = 0; | ||
812 | return 0; | 752 | return 0; |
813 | } | 753 | } |
814 | 754 | ||
@@ -833,34 +773,19 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, | |||
833 | mode = wxh_to_mode(gspca_dev, w, h); | 773 | mode = wxh_to_mode(gspca_dev, w, h); |
834 | 774 | ||
835 | /* OK if right palette */ | 775 | /* OK if right palette */ |
836 | if (gspca_dev->cam.cam_mode[mode].pixfmt != fmt->fmt.pix.pixelformat) { | 776 | if (gspca_dev->cam.cam_mode[mode].pixelformat |
777 | != fmt->fmt.pix.pixelformat) { | ||
837 | 778 | ||
838 | /* else, search the closest mode with the same pixel format */ | 779 | /* else, search the closest mode with the same pixel format */ |
839 | mode2 = gspca_get_mode(gspca_dev, mode, | 780 | mode2 = gspca_get_mode(gspca_dev, mode, |
840 | fmt->fmt.pix.pixelformat); | 781 | fmt->fmt.pix.pixelformat); |
841 | if (mode2 >= 0) { | 782 | if (mode2 >= 0) |
842 | mode = mode2; | 783 | mode = mode2; |
843 | } else { | 784 | /* else |
844 | 785 | ; * no chance, return this mode */ | |
845 | /* no chance, return this mode */ | ||
846 | fmt->fmt.pix.pixelformat = | ||
847 | gspca_dev->cam.cam_mode[mode].pixfmt; | ||
848 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
849 | if (gspca_debug & D_CONF) { | ||
850 | PDEBUG_MODE("new format", | ||
851 | fmt->fmt.pix.pixelformat, | ||
852 | gspca_dev->cam.cam_mode[mode].width, | ||
853 | gspca_dev->cam.cam_mode[mode].height); | ||
854 | } | ||
855 | #endif | ||
856 | } | ||
857 | } | 786 | } |
858 | fmt->fmt.pix.width = gspca_dev->cam.cam_mode[mode].width; | 787 | memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode], |
859 | fmt->fmt.pix.height = gspca_dev->cam.cam_mode[mode].height; | 788 | sizeof fmt->fmt.pix); |
860 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
861 | fmt->fmt.pix.bytesperline = get_v4l2_depth(fmt->fmt.pix.pixelformat) | ||
862 | * fmt->fmt.pix.width / 8; | ||
863 | fmt->fmt.pix.sizeimage = gspca_get_buff_size(gspca_dev, mode); | ||
864 | return mode; /* used when s_fmt */ | 789 | return mode; /* used when s_fmt */ |
865 | } | 790 | } |
866 | 791 | ||
@@ -883,16 +808,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
883 | struct gspca_dev *gspca_dev = priv; | 808 | struct gspca_dev *gspca_dev = priv; |
884 | int ret; | 809 | int ret; |
885 | 810 | ||
886 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
887 | /* if v4l1 got JPEG */ | ||
888 | if (fmt->fmt.pix.pixelformat == 0 | ||
889 | && gspca_dev->streaming) { | ||
890 | fmt->fmt.pix.width = gspca_dev->width; | ||
891 | fmt->fmt.pix.height = gspca_dev->height; | ||
892 | fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; | ||
893 | return 0; | ||
894 | } | ||
895 | #endif | ||
896 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 811 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
897 | return -ERESTARTSYS; | 812 | return -ERESTARTSYS; |
898 | 813 | ||
@@ -1994,6 +1909,3 @@ MODULE_PARM_DESC(debug, | |||
1994 | " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout" | 1909 | " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout" |
1995 | " 0x0100: v4l2"); | 1910 | " 0x0100: v4l2"); |
1996 | #endif | 1911 | #endif |
1997 | module_param(comp_fac, int, 0644); | ||
1998 | MODULE_PARM_DESC(comp_fac, | ||
1999 | "Buffer size ratio when compressed in percent"); | ||