aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc/pwc-v4l.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pwc/pwc-v4l.c')
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c145
1 files changed, 71 insertions, 74 deletions
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 2834e3e65b39..c691e29cc36e 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -464,26 +464,24 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
464 struct pwc_device *pdev = video_drvdata(file); 464 struct pwc_device *pdev = video_drvdata(file);
465 int ret, pixelformat, compression = 0; 465 int ret, pixelformat, compression = 0;
466 466
467 if (pwc_test_n_set_capt_file(pdev, file))
468 return -EBUSY;
469
470 ret = pwc_vidioc_try_fmt(pdev, f); 467 ret = pwc_vidioc_try_fmt(pdev, f);
471 if (ret < 0) 468 if (ret < 0)
472 return ret; 469 return ret;
473 470
474 pixelformat = f->fmt.pix.pixelformat; 471 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
472 return -ERESTARTSYS;
475 473
476 mutex_lock(&pdev->udevlock); 474 ret = pwc_test_n_set_capt_file(pdev, file);
477 if (!pdev->udev) { 475 if (ret)
478 ret = -ENODEV;
479 goto leave; 476 goto leave;
480 }
481 477
482 if (pdev->iso_init) { 478 if (pdev->vb_queue.streaming) {
483 ret = -EBUSY; 479 ret = -EBUSY;
484 goto leave; 480 goto leave;
485 } 481 }
486 482
483 pixelformat = f->fmt.pix.pixelformat;
484
487 PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " 485 PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
488 "format=%c%c%c%c\n", 486 "format=%c%c%c%c\n",
489 f->fmt.pix.width, f->fmt.pix.height, pdev->vframes, 487 f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
@@ -499,7 +497,7 @@ static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
499 497
500 pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); 498 pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
501leave: 499leave:
502 mutex_unlock(&pdev->udevlock); 500 mutex_unlock(&pdev->vb_queue_lock);
503 return ret; 501 return ret;
504} 502}
505 503
@@ -507,9 +505,6 @@ static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap
507{ 505{
508 struct pwc_device *pdev = video_drvdata(file); 506 struct pwc_device *pdev = video_drvdata(file);
509 507
510 if (!pdev->udev)
511 return -ENODEV;
512
513 strcpy(cap->driver, PWC_NAME); 508 strcpy(cap->driver, PWC_NAME);
514 strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card)); 509 strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
515 usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info)); 510 usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
@@ -540,15 +535,12 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i)
540 return i ? -EINVAL : 0; 535 return i ? -EINVAL : 0;
541} 536}
542 537
543static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl) 538static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
544{ 539{
545 struct pwc_device *pdev = 540 struct pwc_device *pdev =
546 container_of(ctrl->handler, struct pwc_device, ctrl_handler); 541 container_of(ctrl->handler, struct pwc_device, ctrl_handler);
547 int ret = 0; 542 int ret = 0;
548 543
549 if (!pdev->udev)
550 return -ENODEV;
551
552 switch (ctrl->id) { 544 switch (ctrl->id) {
553 case V4L2_CID_AUTO_WHITE_BALANCE: 545 case V4L2_CID_AUTO_WHITE_BALANCE:
554 if (pdev->color_bal_valid && 546 if (pdev->color_bal_valid &&
@@ -615,18 +607,6 @@ static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl)
615 return ret; 607 return ret;
616} 608}
617 609
618static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
619{
620 struct pwc_device *pdev =
621 container_of(ctrl->handler, struct pwc_device, ctrl_handler);
622 int ret;
623
624 mutex_lock(&pdev->udevlock);
625 ret = pwc_g_volatile_ctrl_unlocked(ctrl);
626 mutex_unlock(&pdev->udevlock);
627 return ret;
628}
629
630static int pwc_set_awb(struct pwc_device *pdev) 610static int pwc_set_awb(struct pwc_device *pdev)
631{ 611{
632 int ret; 612 int ret;
@@ -648,7 +628,7 @@ static int pwc_set_awb(struct pwc_device *pdev)
648 if (pdev->auto_white_balance->val == awb_indoor || 628 if (pdev->auto_white_balance->val == awb_indoor ||
649 pdev->auto_white_balance->val == awb_outdoor || 629 pdev->auto_white_balance->val == awb_outdoor ||
650 pdev->auto_white_balance->val == awb_fl) 630 pdev->auto_white_balance->val == awb_fl)
651 pwc_g_volatile_ctrl_unlocked(pdev->auto_white_balance); 631 pwc_g_volatile_ctrl(pdev->auto_white_balance);
652 } 632 }
653 if (pdev->auto_white_balance->val != awb_manual) 633 if (pdev->auto_white_balance->val != awb_manual)
654 return 0; 634 return 0;
@@ -812,13 +792,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
812 container_of(ctrl->handler, struct pwc_device, ctrl_handler); 792 container_of(ctrl->handler, struct pwc_device, ctrl_handler);
813 int ret = 0; 793 int ret = 0;
814 794
815 mutex_lock(&pdev->udevlock);
816
817 if (!pdev->udev) {
818 ret = -ENODEV;
819 goto leave;
820 }
821
822 switch (ctrl->id) { 795 switch (ctrl->id) {
823 case V4L2_CID_BRIGHTNESS: 796 case V4L2_CID_BRIGHTNESS:
824 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, 797 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -915,8 +888,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
915 if (ret) 888 if (ret)
916 PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret); 889 PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
917 890
918leave:
919 mutex_unlock(&pdev->udevlock);
920 return ret; 891 return ret;
921} 892}
922 893
@@ -949,11 +920,9 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
949 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 920 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
950 return -EINVAL; 921 return -EINVAL;
951 922
952 mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */
953 PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", 923 PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
954 pdev->width, pdev->height); 924 pdev->width, pdev->height);
955 pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); 925 pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
956 mutex_unlock(&pdev->udevlock);
957 return 0; 926 return 0;
958} 927}
959 928
@@ -968,70 +937,98 @@ static int pwc_reqbufs(struct file *file, void *fh,
968 struct v4l2_requestbuffers *rb) 937 struct v4l2_requestbuffers *rb)
969{ 938{
970 struct pwc_device *pdev = video_drvdata(file); 939 struct pwc_device *pdev = video_drvdata(file);
940 int ret;
971 941
972 if (pwc_test_n_set_capt_file(pdev, file)) 942 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
973 return -EBUSY; 943 return -ERESTARTSYS;
974 944
975 return vb2_reqbufs(&pdev->vb_queue, rb); 945 ret = pwc_test_n_set_capt_file(pdev, file);
946 if (ret == 0)
947 ret = vb2_reqbufs(&pdev->vb_queue, rb);
948
949 mutex_unlock(&pdev->vb_queue_lock);
950 return ret;
976} 951}
977 952
978static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) 953static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
979{ 954{
980 struct pwc_device *pdev = video_drvdata(file); 955 struct pwc_device *pdev = video_drvdata(file);
956 int ret;
981 957
982 return vb2_querybuf(&pdev->vb_queue, buf); 958 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
959 return -ERESTARTSYS;
960
961 ret = pwc_test_n_set_capt_file(pdev, file);
962 if (ret == 0)
963 ret = vb2_querybuf(&pdev->vb_queue, buf);
964
965 mutex_unlock(&pdev->vb_queue_lock);
966 return ret;
983} 967}
984 968
985static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) 969static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
986{ 970{
987 struct pwc_device *pdev = video_drvdata(file); 971 struct pwc_device *pdev = video_drvdata(file);
972 int ret;
988 973
989 if (!pdev->udev) 974 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
990 return -ENODEV; 975 return -ERESTARTSYS;
991 976
992 if (pdev->capt_file != file) 977 ret = pwc_test_n_set_capt_file(pdev, file);
993 return -EBUSY; 978 if (ret == 0)
979 ret = vb2_qbuf(&pdev->vb_queue, buf);
994 980
995 return vb2_qbuf(&pdev->vb_queue, buf); 981 mutex_unlock(&pdev->vb_queue_lock);
982 return ret;
996} 983}
997 984
998static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) 985static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
999{ 986{
1000 struct pwc_device *pdev = video_drvdata(file); 987 struct pwc_device *pdev = video_drvdata(file);
988 int ret;
1001 989
1002 if (!pdev->udev) 990 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
1003 return -ENODEV; 991 return -ERESTARTSYS;
1004 992
1005 if (pdev->capt_file != file) 993 ret = pwc_test_n_set_capt_file(pdev, file);
1006 return -EBUSY; 994 if (ret == 0)
995 ret = vb2_dqbuf(&pdev->vb_queue, buf,
996 file->f_flags & O_NONBLOCK);
1007 997
1008 return vb2_dqbuf(&pdev->vb_queue, buf, file->f_flags & O_NONBLOCK); 998 mutex_unlock(&pdev->vb_queue_lock);
999 return ret;
1009} 1000}
1010 1001
1011static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i) 1002static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
1012{ 1003{
1013 struct pwc_device *pdev = video_drvdata(file); 1004 struct pwc_device *pdev = video_drvdata(file);
1005 int ret;
1014 1006
1015 if (!pdev->udev) 1007 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
1016 return -ENODEV; 1008 return -ERESTARTSYS;
1017 1009
1018 if (pdev->capt_file != file) 1010 ret = pwc_test_n_set_capt_file(pdev, file);
1019 return -EBUSY; 1011 if (ret == 0)
1012 ret = vb2_streamon(&pdev->vb_queue, i);
1020 1013
1021 return vb2_streamon(&pdev->vb_queue, i); 1014 mutex_unlock(&pdev->vb_queue_lock);
1015 return ret;
1022} 1016}
1023 1017
1024static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) 1018static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
1025{ 1019{
1026 struct pwc_device *pdev = video_drvdata(file); 1020 struct pwc_device *pdev = video_drvdata(file);
1021 int ret;
1027 1022
1028 if (!pdev->udev) 1023 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
1029 return -ENODEV; 1024 return -ERESTARTSYS;
1030 1025
1031 if (pdev->capt_file != file) 1026 ret = pwc_test_n_set_capt_file(pdev, file);
1032 return -EBUSY; 1027 if (ret == 0)
1028 ret = vb2_streamoff(&pdev->vb_queue, i);
1033 1029
1034 return vb2_streamoff(&pdev->vb_queue, i); 1030 mutex_unlock(&pdev->vb_queue_lock);
1031 return ret;
1035} 1032}
1036 1033
1037static int pwc_enum_framesizes(struct file *file, void *fh, 1034static int pwc_enum_framesizes(struct file *file, void *fh,
@@ -1119,19 +1116,17 @@ static int pwc_s_parm(struct file *file, void *fh,
1119 parm->parm.capture.timeperframe.numerator == 0) 1116 parm->parm.capture.timeperframe.numerator == 0)
1120 return -EINVAL; 1117 return -EINVAL;
1121 1118
1122 if (pwc_test_n_set_capt_file(pdev, file))
1123 return -EBUSY;
1124
1125 fps = parm->parm.capture.timeperframe.denominator / 1119 fps = parm->parm.capture.timeperframe.denominator /
1126 parm->parm.capture.timeperframe.numerator; 1120 parm->parm.capture.timeperframe.numerator;
1127 1121
1128 mutex_lock(&pdev->udevlock); 1122 if (mutex_lock_interruptible(&pdev->vb_queue_lock))
1129 if (!pdev->udev) { 1123 return -ERESTARTSYS;
1130 ret = -ENODEV; 1124
1125 ret = pwc_test_n_set_capt_file(pdev, file);
1126 if (ret)
1131 goto leave; 1127 goto leave;
1132 }
1133 1128
1134 if (pdev->iso_init) { 1129 if (pdev->vb_queue.streaming) {
1135 ret = -EBUSY; 1130 ret = -EBUSY;
1136 goto leave; 1131 goto leave;
1137 } 1132 }
@@ -1142,7 +1137,7 @@ static int pwc_s_parm(struct file *file, void *fh,
1142 pwc_g_parm(file, fh, parm); 1137 pwc_g_parm(file, fh, parm);
1143 1138
1144leave: 1139leave:
1145 mutex_unlock(&pdev->udevlock); 1140 mutex_unlock(&pdev->vb_queue_lock);
1146 return ret; 1141 return ret;
1147} 1142}
1148 1143
@@ -1166,4 +1161,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
1166 .vidioc_enum_frameintervals = pwc_enum_frameintervals, 1161 .vidioc_enum_frameintervals = pwc_enum_frameintervals,
1167 .vidioc_g_parm = pwc_g_parm, 1162 .vidioc_g_parm = pwc_g_parm,
1168 .vidioc_s_parm = pwc_s_parm, 1163 .vidioc_s_parm = pwc_s_parm,
1164 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1165 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1169}; 1166};