* the Free Software Foundation.
  */
 
+#include <linux/device.h>
 #include <linux/err.h>
+#include <linux/freezer.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/kthread.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/poll.h>
-#include <linux/slab.h>
 #include <linux/sched.h>
-#include <linux/freezer.h>
-#include <linux/kthread.h>
+#include <linux/slab.h>
 
+#include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-fh.h>
 
 #include <media/videobuf2-v4l2.h>
 
 EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
 #endif
 
+void vb2_video_unregister_device(struct video_device *vdev)
+{
+       /* Check if vdev was ever registered at all */
+       if (!vdev || !video_is_registered(vdev))
+               return;
+
+       /*
+        * Calling this function only makes sense if vdev->queue is set.
+        * If it is NULL, then just call video_unregister_device() instead.
+        */
+       WARN_ON(!vdev->queue);
+
+       /*
+        * Take a reference to the device since video_unregister_device()
+        * calls device_unregister(), but we don't want that to release
+        * the device since we want to clean up the queue first.
+        */
+       get_device(&vdev->dev);
+       video_unregister_device(vdev);
+       if (vdev->queue && vdev->queue->owner) {
+               struct mutex *lock = vdev->queue->lock ?
+                       vdev->queue->lock : vdev->lock;
+
+               if (lock)
+                       mutex_lock(lock);
+               vb2_queue_release(vdev->queue);
+               vdev->queue->owner = NULL;
+               if (lock)
+                       mutex_unlock(lock);
+       }
+       /*
+        * Now we put the device, and in most cases this will release
+        * everything.
+        */
+       put_device(&vdev->dev);
+}
+EXPORT_SYMBOL_GPL(vb2_video_unregister_device);
+
 /* vb2_ops helpers. Only use if vq->lock is non-NULL. */
 
 void vb2_ops_wait_prepare(struct vb2_queue *vq)
 
 #error VB2_MAX_PLANES != VIDEO_MAX_PLANES
 #endif
 
+struct video_device;
+
 /**
  * struct vb2_v4l2_buffer - video buffer information for v4l2.
  *
                unsigned long len, unsigned long pgoff, unsigned long flags);
 #endif
 
+/**
+ * vb2_video_unregister_device - unregister the video device and release queue
+ *
+ * @vdev: pointer to &struct video_device
+ *
+ * If the driver uses vb2_fop_release()/_vb2_fop_release(), then it should use
+ * vb2_video_unregister_device() instead of video_unregister_device().
+ *
+ * This function will call video_unregister_device() and then release the
+ * vb2_queue if streaming is in progress. This will stop streaming and
+ * this will simplify the unbind sequence since after this call all subdevs
+ * will have stopped streaming as well.
+ */
+void vb2_video_unregister_device(struct video_device *vdev);
+
 /**
  * vb2_ops_wait_prepare - helper function to lock a struct &vb2_queue
  *