diff options
author | Lamarque Vieira Souza <lamarque@gmail.com> | 2009-07-20 19:46:42 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:18:06 -0400 |
commit | 8c5f32ac2f8c1b92149b08bba673ccecb7578e57 (patch) | |
tree | 7cb69dc8cb1501eec4069b12c75d55a400e3be95 | |
parent | 6ace40effd34331a604c5eeae90838cf8dd7eb8f (diff) |
V4L/DVB (12325): Implement changing resolution on the fly for zr364xx driver
This patch implements changing resolution in zr364xx_vidioc_s_fmt_vid_cap for
zr364xx driver. This version is synced with v4l-dvb as of 20/Jul/2009. Tested
with Creative PC-CAM 880.
OBS: I had to increase MAX_FRAME_SIZE to prevent a hard crash in my notebook
(caps lock blinking) when testing with mplayer, which automatically sets
resolution to the maximum (640x480). Maybe we should add code to auto-detect
frame size to prevent this kind of crash in the future.
Signed-off-by: Lamarque V. Souza <lamarque@gmail.com>
Signed-off-by: Antoine Jacquet <royale@zerezo.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/zr364xx.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index aba908151b62..009f8733cb16 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -43,14 +43,14 @@ | |||
43 | 43 | ||
44 | /* Version Information */ | 44 | /* Version Information */ |
45 | #define DRIVER_VERSION "v0.73" | 45 | #define DRIVER_VERSION "v0.73" |
46 | #define ZR364_VERSION_CODE KERNEL_VERSION(0, 7, 3) | 46 | #define ZR364XX_VERSION_CODE KERNEL_VERSION(0, 7, 3) |
47 | #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" | 47 | #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" |
48 | #define DRIVER_DESC "Zoran 364xx" | 48 | #define DRIVER_DESC "Zoran 364xx" |
49 | 49 | ||
50 | 50 | ||
51 | /* Camera */ | 51 | /* Camera */ |
52 | #define FRAMES 1 | 52 | #define FRAMES 1 |
53 | #define MAX_FRAME_SIZE 100000 | 53 | #define MAX_FRAME_SIZE 200000 |
54 | #define BUFFER_SIZE 0x1000 | 54 | #define BUFFER_SIZE 0x1000 |
55 | #define CTRL_TIMEOUT 500 | 55 | #define CTRL_TIMEOUT 500 |
56 | 56 | ||
@@ -734,7 +734,7 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv, | |||
734 | strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); | 734 | strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); |
735 | strlcpy(cap->bus_info, dev_name(&cam->udev->dev), | 735 | strlcpy(cap->bus_info, dev_name(&cam->udev->dev), |
736 | sizeof(cap->bus_info)); | 736 | sizeof(cap->bus_info)); |
737 | cap->version = ZR364_VERSION_CODE; | 737 | cap->version = ZR364XX_VERSION_CODE; |
738 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 738 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | |
739 | V4L2_CAP_READWRITE | | 739 | V4L2_CAP_READWRITE | |
740 | V4L2_CAP_STREAMING; | 740 | V4L2_CAP_STREAMING; |
@@ -874,9 +874,14 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
874 | return -EINVAL; | 874 | return -EINVAL; |
875 | } | 875 | } |
876 | 876 | ||
877 | if (!(f->fmt.pix.width == 160 && f->fmt.pix.height == 120) && | ||
878 | !(f->fmt.pix.width == 640 && f->fmt.pix.height == 480)) { | ||
879 | f->fmt.pix.width = 320; | ||
880 | f->fmt.pix.height = 240; | ||
881 | } | ||
882 | |||
877 | f->fmt.pix.field = V4L2_FIELD_NONE; | 883 | f->fmt.pix.field = V4L2_FIELD_NONE; |
878 | f->fmt.pix.width = cam->width; | 884 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
879 | f->fmt.pix.height = cam->height; | ||
880 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 885 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
881 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 886 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
882 | f->fmt.pix.colorspace = 0; | 887 | f->fmt.pix.colorspace = 0; |
@@ -907,7 +912,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
907 | return 0; | 912 | return 0; |
908 | } | 913 | } |
909 | 914 | ||
910 | /* Lamarque TODO: implement changing resolution on the fly */ | ||
911 | static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 915 | static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
912 | struct v4l2_format *f) | 916 | struct v4l2_format *f) |
913 | { | 917 | { |
@@ -915,6 +919,7 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
915 | struct videobuf_queue *q = &cam->vb_vidq; | 919 | struct videobuf_queue *q = &cam->vb_vidq; |
916 | char pixelformat_name[5]; | 920 | char pixelformat_name[5]; |
917 | int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); | 921 | int ret = zr364xx_vidioc_try_fmt_vid_cap(file, cam, f); |
922 | int i; | ||
918 | 923 | ||
919 | if (ret < 0) | 924 | if (ret < 0) |
920 | return ret; | 925 | return ret; |
@@ -927,15 +932,55 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
927 | goto out; | 932 | goto out; |
928 | } | 933 | } |
929 | 934 | ||
930 | f->fmt.pix.field = V4L2_FIELD_NONE; | 935 | if (res_check(cam)) { |
931 | f->fmt.pix.width = cam->width; | 936 | DBG("%s can't change format after started\n", __func__); |
932 | f->fmt.pix.height = cam->height; | 937 | ret = -EBUSY; |
938 | goto out; | ||
939 | } | ||
940 | |||
941 | cam->width = f->fmt.pix.width; | ||
942 | cam->height = f->fmt.pix.height; | ||
943 | dev_info(&cam->udev->dev, "%s: %dx%d mode selected\n", __func__, | ||
944 | cam->width, cam->height); | ||
933 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 945 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
934 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 946 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
935 | f->fmt.pix.colorspace = 0; | 947 | f->fmt.pix.colorspace = 0; |
936 | f->fmt.pix.priv = 0; | 948 | f->fmt.pix.priv = 0; |
937 | cam->vb_vidq.field = f->fmt.pix.field; | 949 | cam->vb_vidq.field = f->fmt.pix.field; |
938 | cam->mode.color = V4L2_PIX_FMT_JPEG; | 950 | cam->mode.color = V4L2_PIX_FMT_JPEG; |
951 | |||
952 | if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) | ||
953 | mode = 1; | ||
954 | else if (f->fmt.pix.width == 640 && f->fmt.pix.height == 480) | ||
955 | mode = 2; | ||
956 | else | ||
957 | mode = 0; | ||
958 | |||
959 | m0d1[0] = mode; | ||
960 | m1[2].value = 0xf000 + mode; | ||
961 | m2[1].value = 0xf000 + mode; | ||
962 | header2[437] = cam->height / 256; | ||
963 | header2[438] = cam->height % 256; | ||
964 | header2[439] = cam->width / 256; | ||
965 | header2[440] = cam->width % 256; | ||
966 | |||
967 | for (i = 0; init[cam->method][i].size != -1; i++) { | ||
968 | ret = | ||
969 | send_control_msg(cam->udev, 1, init[cam->method][i].value, | ||
970 | 0, init[cam->method][i].bytes, | ||
971 | init[cam->method][i].size); | ||
972 | if (ret < 0) { | ||
973 | dev_err(&cam->udev->dev, | ||
974 | "error during resolution change sequence: %d\n", i); | ||
975 | goto out; | ||
976 | } | ||
977 | } | ||
978 | |||
979 | /* Added some delay here, since opening/closing the camera quickly, | ||
980 | * like Ekiga does during its startup, can crash the webcam | ||
981 | */ | ||
982 | mdelay(100); | ||
983 | cam->skip = 2; | ||
939 | ret = 0; | 984 | ret = 0; |
940 | 985 | ||
941 | out: | 986 | out: |
@@ -1123,6 +1168,7 @@ static int zr364xx_start_acquire(struct zr364xx_camera *cam) | |||
1123 | cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; | 1168 | cam->buffer.frame[j].ulState = ZR364XX_READ_IDLE; |
1124 | cam->buffer.frame[j].cur_size = 0; | 1169 | cam->buffer.frame[j].cur_size = 0; |
1125 | } | 1170 | } |
1171 | cam->b_acquire = 1; | ||
1126 | return 0; | 1172 | return 0; |
1127 | } | 1173 | } |
1128 | 1174 | ||
@@ -1165,7 +1211,6 @@ static int zr364xx_vidioc_streamon(struct file *file, void *priv, | |||
1165 | res = videobuf_streamon(&cam->vb_vidq); | 1211 | res = videobuf_streamon(&cam->vb_vidq); |
1166 | if (res == 0) { | 1212 | if (res == 0) { |
1167 | zr364xx_start_acquire(cam); | 1213 | zr364xx_start_acquire(cam); |
1168 | cam->b_acquire = 1; | ||
1169 | } else { | 1214 | } else { |
1170 | res_free(cam); | 1215 | res_free(cam); |
1171 | } | 1216 | } |