aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLamarque Vieira Souza <lamarque@gmail.com>2009-07-20 19:46:42 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:18:06 -0400
commit8c5f32ac2f8c1b92149b08bba673ccecb7578e57 (patch)
tree7cb69dc8cb1501eec4069b12c75d55a400e3be95
parent6ace40effd34331a604c5eeae90838cf8dd7eb8f (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.c65
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 */
911static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, 915static 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
941out: 986out:
@@ -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 }