These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / media / usb / usbvision / usbvision-video.c
index 12b403e..b693206 100644 (file)
@@ -62,6 +62,7 @@
 #include <media/saa7115.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
 #include <media/tuner.h>
 
 #include <linux/workqueue.h>
@@ -122,8 +123,6 @@ static void usbvision_release(struct usb_usbvision *usbvision);
 static int isoc_mode = ISOC_MODE_COMPRESS;
 /* Set the default Debug Mode of the device driver */
 static int video_debug;
-/* Set the default device to power on at startup */
-static int power_on_at_open = 1;
 /* Sequential Number of Video Device */
 static int video_nr = -1;
 /* Sequential Number of Radio Device */
@@ -134,13 +133,11 @@ static int radio_nr = -1;
 /* Showing parameters under SYSFS */
 module_param(isoc_mode, int, 0444);
 module_param(video_debug, int, 0444);
-module_param(power_on_at_open, int, 0444);
 module_param(video_nr, int, 0444);
 module_param(radio_nr, int, 0444);
 
 MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint.  Default: 0x60 (Compression On)");
 MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver.  Default: 0 (Off)");
-MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened.  Default: 1 (On)");
 MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX).  Default: -1 (autodetect)");
 MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX).  Default: -1 (autodetect)");
 
@@ -351,11 +348,14 @@ static int usbvision_v4l2_open(struct file *file)
 
        if (mutex_lock_interruptible(&usbvision->v4l2_lock))
                return -ERESTARTSYS;
-       usbvision_reset_power_off_timer(usbvision);
 
-       if (usbvision->user)
+       if (usbvision->user) {
                err_code = -EBUSY;
-       else {
+       } else {
+               err_code = v4l2_fh_open(file);
+               if (err_code)
+                       goto unlock;
+
                /* Allocate memory for the scratch ring buffer */
                err_code = usbvision_scratch_alloc(usbvision);
                if (isoc_mode == ISOC_MODE_COMPRESS) {
@@ -372,11 +372,6 @@ static int usbvision_v4l2_open(struct file *file)
 
        /* If so far no errors then we shall start the camera */
        if (!err_code) {
-               if (usbvision->power == 0) {
-                       usbvision_power_on(usbvision);
-                       usbvision_i2c_register(usbvision);
-               }
-
                /* Send init sequence only once, it's large! */
                if (!usbvision->initialized) {
                        int setup_ok = 0;
@@ -392,18 +387,14 @@ static int usbvision_v4l2_open(struct file *file)
                        err_code = usbvision_init_isoc(usbvision);
                        /* device must be initialized before isoc transfer */
                        usbvision_muxsel(usbvision, 0);
+
+                       /* prepare queues */
+                       usbvision_empty_framequeues(usbvision);
                        usbvision->user++;
-               } else {
-                       if (power_on_at_open) {
-                               usbvision_i2c_unregister(usbvision);
-                               usbvision_power_off(usbvision);
-                               usbvision->initialized = 0;
-                       }
                }
        }
 
-       /* prepare queues */
-       usbvision_empty_framequeues(usbvision);
+unlock:
        mutex_unlock(&usbvision->v4l2_lock);
 
        PDEBUG(DBG_IO, "success");
@@ -435,23 +426,16 @@ static int usbvision_v4l2_close(struct file *file)
        usbvision_scratch_free(usbvision);
 
        usbvision->user--;
-
-       if (power_on_at_open) {
-               /* power off in a little while
-                  to avoid off/on every close/open short sequences */
-               usbvision_set_power_off_timer(usbvision);
-               usbvision->initialized = 0;
-       }
+       mutex_unlock(&usbvision->v4l2_lock);
 
        if (usbvision->remove_pending) {
                printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
                return 0;
        }
-       mutex_unlock(&usbvision->v4l2_lock);
 
        PDEBUG(DBG_IO, "success");
-       return 0;
+       return v4l2_fh_release(file);
 }
 
 
@@ -503,18 +487,24 @@ static int vidioc_querycap(struct file *file, void  *priv,
                                        struct v4l2_capability *vc)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
+       struct video_device *vdev = video_devdata(file);
 
        strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
        strlcpy(vc->card,
                usbvision_device_data[usbvision->dev_model].model_string,
                sizeof(vc->card));
        usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
-       vc->device_caps = V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_AUDIO |
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING |
-               (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
-       vc->capabilities = vc->device_caps | V4L2_CAP_DEVICE_CAPS;
+       vc->device_caps = usbvision->have_tuner ? V4L2_CAP_TUNER : 0;
+       if (vdev->vfl_type == VFL_TYPE_GRABBER)
+               vc->device_caps |= V4L2_CAP_VIDEO_CAPTURE |
+                       V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       else
+               vc->device_caps |= V4L2_CAP_RADIO;
+
+       vc->capabilities = vc->device_caps | V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
+       if (usbvision_device_data[usbvision->dev_model].radio)
+               vc->capabilities |= V4L2_CAP_RADIO;
        return 0;
 }
 
@@ -540,7 +530,6 @@ static int vidioc_enum_input(struct file *file, void *priv,
                } else {
                        strcpy(vi->name, "Television");
                        vi->type = V4L2_INPUT_TYPE_TUNER;
-                       vi->audioset = 1;
                        vi->tuner = chan;
                        vi->std = USBVISION_NORMS;
                }
@@ -551,7 +540,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
                        strcpy(vi->name, "Green Video Input");
                else
                        strcpy(vi->name, "Composite Video Input");
-               vi->std = V4L2_STD_PAL;
+               vi->std = USBVISION_NORMS;
                break;
        case 2:
                vi->type = V4L2_INPUT_TYPE_CAMERA;
@@ -559,12 +548,12 @@ static int vidioc_enum_input(struct file *file, void *priv,
                        strcpy(vi->name, "Yellow Video Input");
                else
                        strcpy(vi->name, "S-Video Input");
-               vi->std = V4L2_STD_PAL;
+               vi->std = USBVISION_NORMS;
                break;
        case 3:
                vi->type = V4L2_INPUT_TYPE_CAMERA;
                strcpy(vi->name, "Red Video Input");
-               vi->std = V4L2_STD_PAL;
+               vi->std = USBVISION_NORMS;
                break;
        }
        return 0;
@@ -619,14 +608,13 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
 
-       if (!usbvision->have_tuner || vt->index)        /* Only tuner 0 */
+       if (vt->index)  /* Only tuner 0 */
                return -EINVAL;
-       if (usbvision->radio) {
+       if (vt->type == V4L2_TUNER_RADIO)
                strcpy(vt->name, "Radio");
-               vt->type = V4L2_TUNER_RADIO;
-       } else {
+       else
                strcpy(vt->name, "Television");
-       }
+
        /* Let clients fill in the remainder of this struct */
        call_all(usbvision, tuner, g_tuner, vt);
 
@@ -638,8 +626,8 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
 
-       /* Only no or one tuner for now */
-       if (!usbvision->have_tuner || vt->index)
+       /* Only one tuner for now */
+       if (vt->index)
                return -EINVAL;
        /* let clients handle this */
        call_all(usbvision, tuner, s_tuner, vt);
@@ -652,12 +640,13 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
 
-       freq->tuner = 0; /* Only one tuner */
-       if (usbvision->radio)
-               freq->type = V4L2_TUNER_RADIO;
+       /* Only one tuner */
+       if (freq->tuner)
+               return -EINVAL;
+       if (freq->type == V4L2_TUNER_RADIO)
+               freq->frequency = usbvision->radio_freq;
        else
-               freq->type = V4L2_TUNER_ANALOG_TV;
-       freq->frequency = usbvision->freq;
+               freq->frequency = usbvision->tv_freq;
 
        return 0;
 }
@@ -666,68 +655,22 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                                const struct v4l2_frequency *freq)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
+       struct v4l2_frequency new_freq = *freq;
 
-       /* Only no or one tuner for now */
-       if (!usbvision->have_tuner || freq->tuner)
+       /* Only one tuner for now */
+       if (freq->tuner)
                return -EINVAL;
 
-       usbvision->freq = freq->frequency;
        call_all(usbvision, tuner, s_frequency, freq);
-
-       return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       if (usbvision->radio)
-               strcpy(a->name, "Radio");
+       call_all(usbvision, tuner, g_frequency, &new_freq);
+       if (freq->type == V4L2_TUNER_RADIO)
+               usbvision->radio_freq = new_freq.frequency;
        else
-               strcpy(a->name, "TV");
+               usbvision->tv_freq = new_freq.frequency;
 
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *fh,
-                         const struct v4l2_audio *a)
-{
-       if (a->index)
-               return -EINVAL;
-       return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *ctrl)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       call_all(usbvision, core, queryctrl, ctrl);
-
-       if (!ctrl->type)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       call_all(usbvision, core, g_ctrl, ctrl);
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       call_all(usbvision, core, s_ctrl, ctrl);
-       return 0;
-}
-
 static int vidioc_reqbufs(struct file *file,
                           void *priv, struct v4l2_requestbuffers *vr)
 {
@@ -937,6 +880,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        vf->fmt.pix.bytesperline = vf->fmt.pix.width*
                usbvision->palette.bytes_per_pixel;
        vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
+       vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
 
        return 0;
 }
@@ -1061,13 +1006,24 @@ static ssize_t usbvision_read(struct file *file, char __user *buf,
               __func__,
               (unsigned long)count, frame->bytes_read);
 
-       /* For now, forget the frame if it has not been read in one shot. */
-/*     if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */
+#if 1
+       /*
+        * FIXME:
+        * For now, forget the frame if it has not been read in one shot.
+        */
+       frame->bytes_read = 0;
+
+       /* Mark it as available to be used again. */
+       frame->grabstate = frame_state_unused;
+#else
+       if (frame->bytes_read >= frame->scanlength) {
+               /* All data has been read */
                frame->bytes_read = 0;
 
                /* Mark it as available to be used again. */
                frame->grabstate = frame_state_unused;
-/*     } */
+       }
+#endif
 
        return count;
 }
@@ -1156,20 +1112,15 @@ static int usbvision_radio_open(struct file *file)
 
        if (mutex_lock_interruptible(&usbvision->v4l2_lock))
                return -ERESTARTSYS;
+       err_code = v4l2_fh_open(file);
+       if (err_code)
+               goto out;
        if (usbvision->user) {
                dev_err(&usbvision->rdev.dev,
                        "%s: Someone tried to open an already opened USBVision Radio!\n",
                                __func__);
                err_code = -EBUSY;
        } else {
-               if (power_on_at_open) {
-                       usbvision_reset_power_off_timer(usbvision);
-                       if (usbvision->power == 0) {
-                               usbvision_power_on(usbvision);
-                               usbvision_i2c_register(usbvision);
-                       }
-               }
-
                /* Alternate interface 1 is is the biggest frame size */
                err_code = usbvision_set_alternate(usbvision);
                if (err_code < 0) {
@@ -1184,14 +1135,6 @@ static int usbvision_radio_open(struct file *file)
                usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
                usbvision->user++;
        }
-
-       if (err_code) {
-               if (power_on_at_open) {
-                       usbvision_i2c_unregister(usbvision);
-                       usbvision_power_off(usbvision);
-                       usbvision->initialized = 0;
-               }
-       }
 out:
        mutex_unlock(&usbvision->v4l2_lock);
        return err_code;
@@ -1201,34 +1144,29 @@ out:
 static int usbvision_radio_close(struct file *file)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
-       int err_code = 0;
 
        PDEBUG(DBG_IO, "");
 
        mutex_lock(&usbvision->v4l2_lock);
        /* Set packet size to 0 */
        usbvision->iface_alt = 0;
-       err_code = usb_set_interface(usbvision->dev, usbvision->iface,
+       usb_set_interface(usbvision->dev, usbvision->iface,
                                    usbvision->iface_alt);
 
        usbvision_audio_off(usbvision);
        usbvision->radio = 0;
        usbvision->user--;
 
-       if (power_on_at_open) {
-               usbvision_set_power_off_timer(usbvision);
-               usbvision->initialized = 0;
-       }
-
        if (usbvision->remove_pending) {
                printk(KERN_INFO "%s: Final disconnect\n", __func__);
+               v4l2_fh_release(file);
                usbvision_release(usbvision);
-               return err_code;
+               return 0;
        }
 
        mutex_unlock(&usbvision->v4l2_lock);
        PDEBUG(DBG_IO, "success");
-       return err_code;
+       return v4l2_fh_release(file);
 }
 
 /* Video registration stuff */
@@ -1241,7 +1179,6 @@ static const struct v4l2_file_operations usbvision_fops = {
        .read           = usbvision_v4l2_read,
        .mmap           = usbvision_v4l2_mmap,
        .unlocked_ioctl = video_ioctl2,
-/*     .poll           = video_poll, */
 };
 
 static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
@@ -1259,17 +1196,15 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
        .vidioc_enum_input    = vidioc_enum_input,
        .vidioc_g_input       = vidioc_g_input,
        .vidioc_s_input       = vidioc_s_input,
-       .vidioc_queryctrl     = vidioc_queryctrl,
-       .vidioc_g_audio       = vidioc_g_audio,
-       .vidioc_s_audio       = vidioc_s_audio,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
        .vidioc_streamon      = vidioc_streamon,
        .vidioc_streamoff     = vidioc_streamoff,
        .vidioc_g_tuner       = vidioc_g_tuner,
        .vidioc_s_tuner       = vidioc_s_tuner,
        .vidioc_g_frequency   = vidioc_g_frequency,
        .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_log_status    = v4l2_ctrl_log_status,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register    = vidioc_g_register,
        .vidioc_s_register    = vidioc_s_register,
@@ -1290,23 +1225,19 @@ static const struct v4l2_file_operations usbvision_radio_fops = {
        .owner             = THIS_MODULE,
        .open           = usbvision_radio_open,
        .release        = usbvision_radio_close,
+       .poll           = v4l2_ctrl_poll,
        .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_queryctrl     = vidioc_queryctrl,
-       .vidioc_g_audio       = vidioc_g_audio,
-       .vidioc_s_audio       = vidioc_s_audio,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
        .vidioc_g_tuner       = vidioc_g_tuner,
        .vidioc_s_tuner       = vidioc_s_tuner,
        .vidioc_g_frequency   = vidioc_g_frequency,
        .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_log_status    = v4l2_ctrl_log_status,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static struct video_device usbvision_radio_template = {
@@ -1358,9 +1289,17 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
 /* register video4linux devices */
 static int usbvision_register_video(struct usb_usbvision *usbvision)
 {
+       int res = -ENOMEM;
+
        /* Video Device: */
        usbvision_vdev_init(usbvision, &usbvision->vdev,
                              &usbvision_video_template, "USBVision Video");
+       if (!usbvision->have_tuner) {
+               v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_G_FREQUENCY);
+               v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_S_TUNER);
+               v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_G_FREQUENCY);
+               v4l2_disable_ioctl(&usbvision->vdev, VIDIOC_S_TUNER);
+       }
        if (video_register_device(&usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
                goto err_exit;
        printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n",
@@ -1384,7 +1323,7 @@ static int usbvision_register_video(struct usb_usbvision *usbvision)
                "USBVision[%d]: video_register_device() failed\n",
                        usbvision->nr);
        usbvision_unregister_video(usbvision);
-       return -1;
+       return res;
 }
 
 /*
@@ -1409,6 +1348,9 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev,
        if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev))
                goto err_free;
 
+       if (v4l2_ctrl_handler_init(&usbvision->hdl, 4))
+               goto err_unreg;
+       usbvision->v4l2_dev.ctrl_handler = &usbvision->hdl;
        mutex_init(&usbvision->v4l2_lock);
 
        /* prepare control urb for control messages during interrupts */
@@ -1417,11 +1359,10 @@ static struct usb_usbvision *usbvision_alloc(struct usb_device *dev,
                goto err_unreg;
        init_waitqueue_head(&usbvision->ctrl_urb_wq);
 
-       usbvision_init_power_off_timer(usbvision);
-
        return usbvision;
 
 err_unreg:
+       v4l2_ctrl_handler_free(&usbvision->hdl);
        v4l2_device_unregister(&usbvision->v4l2_dev);
 err_free:
        kfree(usbvision);
@@ -1439,8 +1380,6 @@ static void usbvision_release(struct usb_usbvision *usbvision)
 {
        PDEBUG(DBG_PROBE, "");
 
-       usbvision_reset_power_off_timer(usbvision);
-
        usbvision->initialized = 0;
 
        usbvision_remove_sysfs(&usbvision->vdev);
@@ -1449,6 +1388,7 @@ static void usbvision_release(struct usb_usbvision *usbvision)
 
        usb_free_urb(usbvision->ctrl_urb);
 
+       v4l2_ctrl_handler_free(&usbvision->hdl);
        v4l2_device_unregister(&usbvision->v4l2_dev);
        kfree(usbvision);
 
@@ -1476,19 +1416,18 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision)
        }
 
        usbvision->tvnorm_id = usbvision_device_data[model].video_norm;
-
        usbvision->video_inputs = usbvision_device_data[model].video_channels;
        usbvision->ctl_input = 0;
+       usbvision->radio_freq = 87.5 * 16000;
+       usbvision->tv_freq = 400 * 16;
 
        /* This should be here to make i2c clients to be able to register */
        /* first switch off audio */
        if (usbvision_device_data[model].audio_channels > 0)
                usbvision_audio_off(usbvision);
-       if (!power_on_at_open) {
-               /* and then power up the noisy tuner */
-               usbvision_power_on(usbvision);
-               usbvision_i2c_register(usbvision);
-       }
+       /* and then power up the tuner */
+       usbvision_power_on(usbvision);
+       usbvision_i2c_register(usbvision);
 }
 
 /*
@@ -1581,6 +1520,10 @@ static int usbvision_probe(struct usb_interface *intf,
 
        usbvision->nr = usbvision_nr++;
 
+       spin_lock_init(&usbvision->queue_lock);
+       init_waitqueue_head(&usbvision->wait_frame);
+       init_waitqueue_head(&usbvision->wait_stream);
+
        usbvision->have_tuner = usbvision_device_data[model].tuner;
        if (usbvision->have_tuner)
                usbvision->tuner_type = usbvision_device_data[model].tuner_type;
@@ -1635,11 +1578,7 @@ static void usbvision_disconnect(struct usb_interface *intf)
        usbvision_stop_isoc(usbvision);
 
        v4l2_device_disconnect(&usbvision->v4l2_dev);
-
-       if (usbvision->power) {
-               usbvision_i2c_unregister(usbvision);
-               usbvision_power_off(usbvision);
-       }
+       usbvision_i2c_unregister(usbvision);
        usbvision->remove_pending = 1;  /* Now all ISO data will be ignored */
 
        usb_put_dev(usbvision->dev);