[PATCH] s2255drv: port to videobuf2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Update s2255drv to use videobuf2 instead of videobuf. 
s2255_fh file handle removed and driver simplified.

Signed-off-by: Dean Anderson <linux-dev@xxxxxxxxxxxx>
---
 drivers/media/usb/s2255/s2255drv.c | 1170 +++++++++++++++---------------------
 1 file changed, 473 insertions(+), 697 deletions(-)

diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index c6bdccc..d6e9332 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -1,11 +1,9 @@
 /*
  *  s2255drv.c - a driver for the Sensoray 2255 USB video capture device
  *
- *   Copyright (C) 2007-2013 by Sensoray Company Inc.
+ *   Copyright (C) 2007-2014 by Sensoray Company Inc.
  *                              Dean Anderson
  *
- * Some video buffer code based on vivi driver:
- *
  * Sensoray 2255 device supports 4 simultaneous channels.
  * The channels are not "crossbar" inputs, they are physically
  * attached to separate video decoders.
@@ -45,14 +43,14 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
-#include <media/videobuf-vmalloc.h>
+#include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
 
-#define S2255_VERSION		"1.23.1"
+#define S2255_VERSION "1.25.1"
 #define FIRMWARE_FILE_NAME "f2255usb.bin"
 
 /* default JPEG quality */
@@ -178,11 +176,6 @@ struct s2255_bufferi {
 			DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
 			DEF_HUE, 0, DEF_USB_BLOCK, 0}
 
-struct s2255_dmaqueue {
-	struct list_head	active;
-	struct s2255_dev	*dev;
-};
-
 /* for firmware loading, fw_state */
 #define S2255_FW_NOTLOADED	0
 #define S2255_FW_LOADED_DSPWAIT	1
@@ -214,69 +207,73 @@ struct s2255_pipeinfo {
 	u32 idx;
 };
 
-struct s2255_fmt; /*forward declaration */
+/*forward declarations */
+struct s2255_fmt;
 struct s2255_dev;
 
-struct s2255_channel {
-	struct s2255_dev        *dev;
-	struct video_device	vdev;
+/* 2255 video channel */
+struct s2255_vc {
+	struct v4l2_fh fh;
+	enum v4l2_buf_type type;
+	struct s2255_dev *dev;
+	struct video_device vdev;
 	struct v4l2_ctrl_handler hdl;
-	struct v4l2_ctrl	*jpegqual_ctrl;
-	int			resources;
-	struct s2255_dmaqueue	vidq;
-	struct s2255_bufferi	buffer;
-	struct s2255_mode	mode;
-	v4l2_std_id		std;
+	struct v4l2_ctrl *jpegqual_ctrl;
+	struct list_head buf_list;
+	struct s2255_bufferi buffer;
+	struct s2255_mode mode;
+	v4l2_std_id std;
 	/* jpeg compression */
-	unsigned		jpegqual;
+	unsigned jpegqual;
 	/* capture parameters (for high quality mode full size) */
 	struct v4l2_captureparm cap_parm;
-	int			cur_frame;
-	int			last_frame;
-
-	int			b_acquire;
+	int cur_frame;
+	int last_frame;
 	/* allocated image size */
-	unsigned long		req_image_size;
+	unsigned long req_image_size;
 	/* received packet size */
-	unsigned long		pkt_size;
-	int			bad_payload;
-	unsigned long		frame_count;
+	unsigned long pkt_size;
+	int bad_payload;
+	unsigned long frame_count;
 	/* if JPEG image */
-	int                     jpg_size;
+	int jpg_size;
 	/* if channel configured to default state */
-	int                     configured;
-	wait_queue_head_t       wait_setmode;
-	int                     setmode_ready;
+	int configured;
+	wait_queue_head_t wait_setmode;
+	int setmode_ready;
 	/* video status items */
-	int                     vidstatus;
-	wait_queue_head_t       wait_vidstatus;
-	int                     vidstatus_ready;
-	unsigned int		width;
-	unsigned int		height;
-	const struct s2255_fmt	*fmt;
+	int vidstatus;
+	wait_queue_head_t wait_vidstatus;
+	int vidstatus_ready;
+	unsigned int width;
+	unsigned int height;
+	enum v4l2_field field;
+	unsigned int field_count;
+	const struct s2255_fmt *fmt;
+	spinlock_t qlock; /* lock for buf_list */
 	int idx; /* channel number on device, 0-3 */
+	struct vb2_queue vb_vidq;
+	struct mutex vb_lock; /* streaming lock */
 };
 
-
 struct s2255_dev {
-	struct s2255_channel    channel[MAX_CHANNELS];
-	struct v4l2_device      v4l2_dev;
-	atomic_t                num_channels;
-	int			frames;
-	struct mutex		lock;	/* channels[].vdev.lock */
-	struct usb_device	*udev;
-	struct usb_interface	*interface;
-	u8			read_endpoint;
-	struct timer_list	timer;
+	struct s2255_vc vc[MAX_CHANNELS];
+	struct v4l2_device v4l2_dev;
+	atomic_t num_channels;
+	int frames;
+	struct mutex lock;	/* channels[].vdev.lock */
+	struct usb_device *udev;
+	struct usb_interface *interface;
+	u8 read_endpoint;
+	struct timer_list timer;
 	struct s2255_fw	*fw_data;
-	struct s2255_pipeinfo	pipe;
-	u32			cc;	/* current channel */
-	int			frame_ready;
-	int                     chn_ready;
-	spinlock_t              slock;
+	struct s2255_pipeinfo pipe;
+	u32 cc;	/* current channel */
+	int frame_ready;
+	int chn_ready;
 	/* dsp firmware version (f2255usb.bin) */
-	int                     dsp_fw_ver;
-	u16                     pid; /* product id */
+	int dsp_fw_ver;
+	u16 pid; /* product id */
 };
 
 static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev)
@@ -293,19 +290,11 @@ struct s2255_fmt {
 /* buffer for one video frame */
 struct s2255_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer vb;
+	struct vb2_buffer vb;
+	struct list_head list;
 	const struct s2255_fmt *fmt;
 };
 
-struct s2255_fh {
-	/* this must be the first field in this struct */
-	struct v4l2_fh		fh;
-	struct s2255_dev	*dev;
-	struct videobuf_queue	vb_vidq;
-	enum v4l2_buf_type	type;
-	struct s2255_channel	*channel;
-	int			resources;
-};
 
 /* current cypress EEPROM firmware version */
 #define S2255_CUR_USB_FWVER	((3 << 8) | 12)
@@ -356,11 +345,11 @@ static int debug;
 
 static int s2255_start_readpipe(struct s2255_dev *dev);
 static void s2255_stop_readpipe(struct s2255_dev *dev);
-static int s2255_start_acquire(struct s2255_channel *channel);
-static int s2255_stop_acquire(struct s2255_channel *channel);
-static void s2255_fillbuff(struct s2255_channel *chn, struct s2255_buffer *buf,
+static int s2255_start_acquire(struct s2255_vc *vc);
+static int s2255_stop_acquire(struct s2255_vc *vc);
+static void s2255_fillbuff(struct s2255_vc *vc, struct s2255_buffer *buf,
 			   int jpgsize);
-static int s2255_set_mode(struct s2255_channel *chan, struct s2255_mode *mode);
+static int s2255_set_mode(struct s2255_vc *vc, struct s2255_mode *mode);
 static int s2255_board_shutdown(struct s2255_dev *dev);
 static void s2255_fwload_start(struct s2255_dev *dev, int reset);
 static void s2255_destroy(struct s2255_dev *dev);
@@ -439,35 +428,30 @@ static const struct s2255_fmt formats[] = {
 	}
 };
 
-static int norm_maxw(struct s2255_channel *channel)
+static int norm_maxw(struct s2255_vc *vc)
 {
-	return (channel->std & V4L2_STD_525_60) ?
+	return (vc->std & V4L2_STD_525_60) ?
 	    LINE_SZ_4CIFS_NTSC : LINE_SZ_4CIFS_PAL;
 }
 
-static int norm_maxh(struct s2255_channel *channel)
+static int norm_maxh(struct s2255_vc *vc)
 {
-	return (channel->std & V4L2_STD_525_60) ?
+	return (vc->std & V4L2_STD_525_60) ?
 	    (NUM_LINES_1CIFS_NTSC * 2) : (NUM_LINES_1CIFS_PAL * 2);
 }
 
-static int norm_minw(struct s2255_channel *channel)
+static int norm_minw(struct s2255_vc *vc)
 {
-	return (channel->std & V4L2_STD_525_60) ?
+	return (vc->std & V4L2_STD_525_60) ?
 	    LINE_SZ_1CIFS_NTSC : LINE_SZ_1CIFS_PAL;
 }
 
-static int norm_minh(struct s2255_channel *channel)
+static int norm_minh(struct s2255_vc *vc)
 {
-	return (channel->std & V4L2_STD_525_60) ?
+	return (vc->std & V4L2_STD_525_60) ?
 	    (NUM_LINES_1CIFS_NTSC) : (NUM_LINES_1CIFS_PAL);
 }
 
-
-/*
- * TODO: fixme: move YUV reordering to hardware
- * converts 2255 planar format to yuyv or uyvy
- */
 static void planar422p_to_yuv_packed(const unsigned char *in,
 				     unsigned char *out,
 				     int width, int height,
@@ -572,29 +556,26 @@ static void s2255_fwchunk_complete(struct urb *urb)
 
 }
 
-static int s2255_got_frame(struct s2255_channel *channel, int jpgsize)
+static int s2255_got_frame(struct s2255_vc *vc, int jpgsize)
 {
-	struct s2255_dmaqueue *dma_q = &channel->vidq;
+
 	struct s2255_buffer *buf;
-	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+	struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
 	unsigned long flags = 0;
-	int rc = 0;
-	spin_lock_irqsave(&dev->slock, flags);
-	if (list_empty(&dma_q->active)) {
+
+	spin_lock_irqsave(&vc->qlock, flags);
+	if (list_empty(&vc->buf_list)) {
 		dprintk(dev, 1, "No active queue to serve\n");
-		rc = -1;
-		goto unlock;
-	}
-	buf = list_entry(dma_q->active.next,
-			 struct s2255_buffer, vb.queue);
-	list_del(&buf->vb.queue);
-	v4l2_get_timestamp(&buf->vb.ts);
-	s2255_fillbuff(channel, buf, jpgsize);
-	wake_up(&buf->vb.done);
-	dprintk(dev, 2, "%s: [buf/i] [%p/%d]\n", __func__, buf, buf->vb.i);
-unlock:
-	spin_unlock_irqrestore(&dev->slock, flags);
-	return rc;
+		spin_unlock_irqrestore(&vc->qlock, flags);
+		return -EINVAL;
+	}
+	buf = list_entry(vc->buf_list.next,
+			 struct s2255_buffer, list);
+	list_del(&buf->list);
+	spin_unlock_irqrestore(&vc->qlock, flags);
+	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	s2255_fillbuff(vc, buf, jpgsize);
+	return 0;
 }
 
 static const struct s2255_fmt *format_by_fourcc(int fourcc)
@@ -612,53 +593,47 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc)
 	return NULL;
 }
 
-/* video buffer vmalloc implementation based partly on VIVI driver which is
- *          Copyright (c) 2006 by
- *                  Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
- *                  Ted Walther <ted--a.t--enumera.com>
- *                  John Sokol <sokol--a.t--videotechnology.com>
- *                  http://v4l.videotechnology.com/
- *
- */
-static void s2255_fillbuff(struct s2255_channel *channel,
+static void s2255_fillbuff(struct s2255_vc *vc,
 			   struct s2255_buffer *buf, int jpgsize)
 {
 	int pos = 0;
 	const char *tmpbuf;
-	char *vbuf = videobuf_to_vmalloc(&buf->vb);
+	char *vbuf;
 	unsigned long last_frame;
-	struct s2255_dev *dev = channel->dev;
+	struct s2255_dev *dev = vc->dev;
 
+	vbuf = vb2_plane_vaddr(&buf->vb, 0);
 	if (!vbuf)
 		return;
-	last_frame = channel->last_frame;
+
+	last_frame = vc->last_frame;
 	if (last_frame != -1) {
 		tmpbuf =
-		    (const char *)channel->buffer.frame[last_frame].lpvbits;
+		    (const char *)vc->buffer.frame[last_frame].lpvbits;
 		switch (buf->fmt->fourcc) {
 		case V4L2_PIX_FMT_YUYV:
 		case V4L2_PIX_FMT_UYVY:
 			planar422p_to_yuv_packed((const unsigned char *)tmpbuf,
-						 vbuf, buf->vb.width,
-						 buf->vb.height,
+						 vbuf, vc->width,
+						 vc->height,
 						 buf->fmt->fourcc);
 			break;
 		case V4L2_PIX_FMT_GREY:
-			memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
+			memcpy(vbuf, tmpbuf, vc->width * vc->height);
 			break;
 		case V4L2_PIX_FMT_JPEG:
 		case V4L2_PIX_FMT_MJPEG:
-			buf->vb.size = jpgsize;
-			memcpy(vbuf, tmpbuf, buf->vb.size);
+			buf->vb.v4l2_buf.length = jpgsize;
+			memcpy(vbuf, tmpbuf, jpgsize);
 			break;
 		case V4L2_PIX_FMT_YUV422P:
 			memcpy(vbuf, tmpbuf,
-			       buf->vb.width * buf->vb.height * 2);
+			       vc->width * vc->height * 2);
 			break;
 		default:
 			pr_info("s2255: unknown format?\n");
 		}
-		channel->last_frame = -1;
+		vc->last_frame = -1;
 	} else {
 		pr_err("s2255: =======no frame\n");
 		return;
@@ -666,146 +641,131 @@ static void s2255_fillbuff(struct s2255_channel *channel,
 	dprintk(dev, 2, "s2255fill at : Buffer 0x%08lx size= %d\n",
 		(unsigned long)vbuf, pos);
 	/* tell v4l buffer was filled */
-	buf->vb.field_count = channel->frame_count * 2;
-	v4l2_get_timestamp(&buf->vb.ts);
-	buf->vb.state = VIDEOBUF_DONE;
+	vc->field_count = vc->frame_count * 2;
+	buf->vb.v4l2_buf.field = vc->field;
+	buf->vb.v4l2_buf.sequence = vc->field_count >> 1;
+	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
 }
 
+/*
+ * setup the contraints of the queue
+ */
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct s2255_vc *vc = vb2_get_drv_priv(vq);
+	unsigned long size;
 
-/* ------------------------------------------------------------------
-   Videobuf operations
-   ------------------------------------------------------------------*/
+	size = vc->width * vc->height * (vc->fmt->depth >> 3);
 
-static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-			unsigned int *size)
-{
-	struct s2255_fh *fh = vq->priv_data;
-	struct s2255_channel *channel = fh->channel;
-	*size = channel->width * channel->height * (channel->fmt->depth >> 3);
+	if (0 == *nbuffers)
+		*nbuffers = S2255_DEF_BUFS;
 
-	if (0 == *count)
-		*count = S2255_DEF_BUFS;
+	if (size * *nbuffers > vid_limit * 1024 * 1024)
+		*nbuffers = (vid_limit * 1024 * 1024) / size;
 
-	if (*size * *count > vid_limit * 1024 * 1024)
-		*count = (vid_limit * 1024 * 1024) / *size;
+	if (size == 0)
+		return -EINVAL;
 
+	*nplanes = 1;
+	sizes[0] = size;
 	return 0;
 }
 
-static void free_buffer(struct videobuf_queue *vq, struct s2255_buffer *buf)
-{
-	videobuf_vmalloc_free(&buf->vb);
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
 
-static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-			  enum v4l2_field field)
+static int buffer_prepare(struct vb2_buffer *vb)
 {
-	struct s2255_fh *fh = vq->priv_data;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue);
 	struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
-	int rc;
-	int w = channel->width;
-	int h = channel->height;
-	dprintk(fh->dev, 4, "%s, field=%d\n", __func__, field);
-	if (channel->fmt == NULL)
-		return -EINVAL;
+	unsigned long size;
+	int w = vc->width;
+	int h = vc->height;
 
-	if ((w < norm_minw(channel)) ||
-	    (w > norm_maxw(channel)) ||
-	    (h < norm_minh(channel)) ||
-	    (h > norm_maxh(channel))) {
-		dprintk(fh->dev, 4, "invalid buffer prepare\n");
+	if (vc->fmt == NULL)
 		return -EINVAL;
-	}
-	buf->vb.size = w * h * (channel->fmt->depth >> 3);
-	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) {
-		dprintk(fh->dev, 4, "invalid buffer prepare\n");
+
+	if ((w < norm_minw(vc)) ||
+	    (w > norm_maxw(vc)) ||
+	    (h < norm_minh(vc)) ||
+	    (h > norm_maxh(vc))) {
+		dprintk(vc->dev, 4, "invalid buffer prepare\n");
 		return -EINVAL;
 	}
+	size = w * h * (vc->fmt->depth >> 3);
 
-	buf->fmt = channel->fmt;
-	buf->vb.width = w;
-	buf->vb.height = h;
-	buf->vb.field = field;
-
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		rc = videobuf_iolock(vq, &buf->vb, NULL);
-		if (rc < 0)
-			goto fail;
-	}
+	if (vb2_plane_size(vb, 0) < size)
+		return -EINVAL;
 
-	buf->vb.state = VIDEOBUF_PREPARED;
+	vb2_set_plane_payload(&buf->vb, 0, size);
+	buf->fmt = vc->fmt;
 	return 0;
-fail:
-	free_buffer(vq, buf);
-	return rc;
 }
 
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void buffer_queue(struct vb2_buffer *vb)
 {
 	struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
-	struct s2255_fh *fh = vq->priv_data;
-	struct s2255_channel *channel = fh->channel;
-	struct s2255_dmaqueue *vidq = &channel->vidq;
-	dprintk(fh->dev, 1, "%s\n", __func__);
-	buf->vb.state = VIDEOBUF_QUEUED;
-	list_add_tail(&buf->vb.queue, &vidq->active);
-}
-
-static void buffer_release(struct videobuf_queue *vq,
-			   struct videobuf_buffer *vb)
-{
-	struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
-	struct s2255_fh *fh = vq->priv_data;
-	dprintk(fh->dev, 4, "%s %d\n", __func__, fh->channel->idx);
-	free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops s2255_video_qops = {
-	.buf_setup = buffer_setup,
-	.buf_prepare = buffer_prepare,
-	.buf_queue = buffer_queue,
-	.buf_release = buffer_release,
-};
-
-
-static int res_get(struct s2255_fh *fh)
-{
-	struct s2255_channel *channel = fh->channel;
-	/* is it free? */
-	if (channel->resources)
-		return 0; /* no, someone else uses it */
-	/* it's free, grab it */
-	channel->resources = 1;
-	fh->resources = 1;
-	dprintk(fh->dev, 1, "s2255: res: get\n");
-	return 1;
+	struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue);
+	struct s2255_dev *dev = vc->dev;
+	unsigned long flags = 0;
+	dprintk(dev, 1, "%s\n", __func__);
+	spin_lock_irqsave(&vc->qlock, flags);
+	list_add_tail(&buf->list, &vc->buf_list);
+	spin_unlock_irqrestore(&vc->qlock, flags);
 }
 
-static int res_locked(struct s2255_fh *fh)
+/* begin streaming on a 2255 video channel */
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-	return fh->channel->resources;
+	struct s2255_vc *vc = vb2_get_drv_priv(vq);
+	int j;
+	vc->last_frame = -1;
+	vc->bad_payload = 0;
+	vc->cur_frame = 0;
+	vc->frame_count = 0;
+	for (j = 0; j < SYS_FRAMES; j++) {
+		vc->buffer.frame[j].ulState = S2255_READ_IDLE;
+		vc->buffer.frame[j].cur_size = 0;
+	}
+	s2255_start_acquire(vc);
+	return 0;
 }
 
-static int res_check(struct s2255_fh *fh)
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
 {
-	return fh->resources;
+	struct s2255_vc *vc = vb2_get_drv_priv(vq);
+	struct s2255_buffer *buf, *node;
+	unsigned long flags;
+	s2255_stop_acquire(vc);
+	spin_lock_irqsave(&vc->qlock, flags);
+	list_for_each_entry_safe(buf, node, &vc->buf_list, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		dprintk(vc->dev, 2, "[%p/%d] done\n",
+			buf, buf->vb.v4l2_buf.index);
+	}
+	spin_unlock_irqrestore(&vc->qlock, flags);
+	return 0;
 }
 
+static struct vb2_ops s2255_video_qops = {
+	.queue_setup = queue_setup,
+	.buf_prepare = buffer_prepare,
+	.buf_queue = buffer_queue,
+	.start_streaming = start_streaming,
+	.stop_streaming = stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
 
-static void res_free(struct s2255_fh *fh)
-{
-	struct s2255_channel *channel = fh->channel;
-	channel->resources = 0;
-	fh->resources = 0;
-}
+};
 
 static int vidioc_querycap(struct file *file, void *priv,
 			   struct v4l2_capability *cap)
 {
-	struct s2255_fh *fh = file->private_data;
-	struct s2255_dev *dev = fh->dev;
+	struct s2255_vc *vc = video_drvdata(file);
+	struct s2255_dev *dev = vc->dev;
 
 	strlcpy(cap->driver, "s2255", sizeof(cap->driver));
 	strlcpy(cap->card, "s2255", sizeof(cap->card));
@@ -833,19 +793,18 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 			    struct v4l2_format *f)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
-	int is_ntsc = channel->std & V4L2_STD_525_60;
+	struct s2255_vc *vc = video_drvdata(file);
+	int is_ntsc = vc->std & V4L2_STD_525_60;
 
-	f->fmt.pix.width = channel->width;
-	f->fmt.pix.height = channel->height;
+	f->fmt.pix.width = vc->width;
+	f->fmt.pix.height = vc->height;
 	if (f->fmt.pix.height >=
 	    (is_ntsc ? NUM_LINES_1CIFS_NTSC : NUM_LINES_1CIFS_PAL) * 2)
 		f->fmt.pix.field = V4L2_FIELD_INTERLACED;
 	else
 		f->fmt.pix.field = V4L2_FIELD_TOP;
-	f->fmt.pix.pixelformat = channel->fmt->fourcc;
-	f->fmt.pix.bytesperline = f->fmt.pix.width * (channel->fmt->depth >> 3);
+	f->fmt.pix.pixelformat = vc->fmt->fourcc;
+	f->fmt.pix.bytesperline = f->fmt.pix.width * (vc->fmt->depth >> 3);
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	f->fmt.pix.priv = 0;
@@ -857,9 +816,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 {
 	const struct s2255_fmt *fmt;
 	enum v4l2_field field;
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
-	int is_ntsc = channel->std & V4L2_STD_525_60;
+	struct s2255_vc *vc = video_drvdata(file);
+	int is_ntsc = vc->std & V4L2_STD_525_60;
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
@@ -868,7 +826,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 
 	field = f->fmt.pix.field;
 
-	dprintk(fh->dev, 50, "%s NTSC: %d suggested width: %d, height: %d\n",
+	dprintk(vc->dev, 50, "%s NTSC: %d suggested width: %d, height: %d\n",
 		__func__, is_ntsc, f->fmt.pix.width, f->fmt.pix.height);
 	if (is_ntsc) {
 		/* NTSC */
@@ -910,7 +868,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 	f->fmt.pix.priv = 0;
-	dprintk(fh->dev, 50, "%s: set width %d height %d field %d\n", __func__,
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dprintk(vc->dev, 50, "%s: set width %d height %d field %d\n", __func__,
 		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
 	return 0;
 }
@@ -918,14 +877,13 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 			    struct v4l2_format *f)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = video_drvdata(file);
 	const struct s2255_fmt *fmt;
-	struct videobuf_queue *q = &fh->vb_vidq;
+	struct vb2_queue *q = &vc->vb_vidq;
 	struct s2255_mode mode;
 	int ret;
 
-	ret = vidioc_try_fmt_vid_cap(file, fh, f);
+	ret = vidioc_try_fmt_vid_cap(file, vc, f);
 
 	if (ret < 0)
 		return ret;
@@ -934,29 +892,24 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 
 	if (fmt == NULL)
 		return -EINVAL;
+	/*
+	 * It is not allowed to change the format while buffers for use with
+	 * streaming have already been allocated.
+	 */
+	if (vb2_is_busy(q))
+		return -EBUSY;
 
-	mutex_lock(&q->vb_lock);
-
-	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-		dprintk(fh->dev, 1, "queue busy\n");
-		ret = -EBUSY;
-		goto out_s_fmt;
-	}
-
-	if (res_locked(fh)) {
-		dprintk(fh->dev, 1, "%s: channel busy\n", __func__);
-		ret = -EBUSY;
-		goto out_s_fmt;
-	}
-	mode = channel->mode;
-	channel->fmt = fmt;
-	channel->width = f->fmt.pix.width;
-	channel->height = f->fmt.pix.height;
-	fh->vb_vidq.field = f->fmt.pix.field;
-	fh->type = f->type;
-	if (channel->width > norm_minw(channel)) {
-		if (channel->height > norm_minh(channel)) {
-			if (channel->cap_parm.capturemode &
+	/* change format */
+	mode = vc->mode;
+	vc->fmt = fmt;
+	vc->width = f->fmt.pix.width;
+	vc->height = f->fmt.pix.height;
+	vc->field = f->fmt.pix.field;
+	vc->type = f->type;
+
+	if (vc->width > norm_minw(vc)) {
+		if (vc->height > norm_minh(vc)) {
+			if (vc->cap_parm.capturemode &
 			    V4L2_MODE_HIGHQUALITY)
 				mode.scale = SCALE_4CIFSI;
 			else
@@ -968,7 +921,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 		mode.scale = SCALE_1CIFS;
 	}
 	/* color mode */
-	switch (channel->fmt->fourcc) {
+	switch (vc->fmt->fourcc) {
 	case V4L2_PIX_FMT_GREY:
 		mode.color &= ~MASK_COLOR;
 		mode.color |= COLOR_Y8;
@@ -977,7 +930,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 	case V4L2_PIX_FMT_MJPEG:
 		mode.color &= ~MASK_COLOR;
 		mode.color |= COLOR_JPG;
-		mode.color |= (channel->jpegqual << 8);
+		mode.color |= (vc->jpegqual << 8);
 		break;
 	case V4L2_PIX_FMT_YUV422P:
 		mode.color &= ~MASK_COLOR;
@@ -990,51 +943,15 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 		mode.color |= COLOR_YUVPK;
 		break;
 	}
-	if ((mode.color & MASK_COLOR) != (channel->mode.color & MASK_COLOR))
+	if ((mode.color & MASK_COLOR) != (vc->mode.color & MASK_COLOR))
 		mode.restart = 1;
-	else if (mode.scale != channel->mode.scale)
+	else if (mode.scale != vc->mode.scale)
 		mode.restart = 1;
-	else if (mode.format != channel->mode.format)
+	else if (mode.format != vc->mode.format)
 		mode.restart = 1;
-	channel->mode = mode;
-	(void) s2255_set_mode(channel, &mode);
-	ret = 0;
-out_s_fmt:
-	mutex_unlock(&q->vb_lock);
-	return ret;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *p)
-{
-	int rc;
-	struct s2255_fh *fh = priv;
-	rc = videobuf_reqbufs(&fh->vb_vidq, p);
-	return rc;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	int rc;
-	struct s2255_fh *fh = priv;
-	rc = videobuf_querybuf(&fh->vb_vidq, p);
-	return rc;
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	int rc;
-	struct s2255_fh *fh = priv;
-	rc = videobuf_qbuf(&fh->vb_vidq, p);
-	return rc;
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	int rc;
-	struct s2255_fh *fh = priv;
-	rc = videobuf_dqbuf(&fh->vb_vidq, p, file->f_flags & O_NONBLOCK);
-	return rc;
+	vc->mode = mode;
+	(void) s2255_set_mode(vc, &mode);
+	return 0;
 }
 
 /* write to the configuration pipe, synchronously */
@@ -1115,16 +1032,6 @@ static u32 get_transfer_size(struct s2255_mode *mode)
 	return usbInSize;
 }
 
-static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode)
-{
-	struct device *dev = &sdev->udev->dev;
-	dev_info(dev, "------------------------------------------------\n");
-	dev_info(dev, "format: %d\nscale %d\n", mode->format, mode->scale);
-	dev_info(dev, "fdec: %d\ncolor %d\n", mode->fdec, mode->color);
-	dev_info(dev, "bright: 0x%x\n", mode->bright);
-	dev_info(dev, "------------------------------------------------\n");
-}
-
 /*
  * set mode is the function which controls the DSP.
  * the restart parameter in struct s2255_mode should be set whenever
@@ -1133,28 +1040,28 @@ static void s2255_print_cfg(struct s2255_dev *sdev, struct s2255_mode *mode)
  * When the restart parameter is set, we sleep for ONE frame to allow the
  * DSP time to get the new frame
  */
-static int s2255_set_mode(struct s2255_channel *channel,
+static int s2255_set_mode(struct s2255_vc *vc,
 			  struct s2255_mode *mode)
 {
 	int res;
 	__le32 *buffer;
 	unsigned long chn_rev;
-	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
+	struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
 	int i;
 
-	chn_rev = G_chnmap[channel->idx];
-	dprintk(dev, 3, "%s channel: %d\n", __func__, channel->idx);
+	chn_rev = G_chnmap[vc->idx];
+	dprintk(dev, 3, "%s channel: %d\n", __func__, vc->idx);
 	/* if JPEG, set the quality */
 	if ((mode->color & MASK_COLOR) == COLOR_JPG) {
 		mode->color &= ~MASK_COLOR;
 		mode->color |= COLOR_JPG;
 		mode->color &= ~MASK_JPG_QUALITY;
-		mode->color |= (channel->jpegqual << 8);
+		mode->color |= (vc->jpegqual << 8);
 	}
 	/* save the mode */
-	channel->mode = *mode;
-	channel->req_image_size = get_transfer_size(mode);
-	dprintk(dev, 1, "%s: reqsize %ld\n", __func__, channel->req_image_size);
+	vc->mode = *mode;
+	vc->req_image_size = get_transfer_size(mode);
+	dprintk(dev, 1, "%s: reqsize %ld\n", __func__, vc->req_image_size);
 	buffer = kzalloc(512, GFP_KERNEL);
 	if (buffer == NULL) {
 		dev_err(&dev->udev->dev, "out of mem\n");
@@ -1165,36 +1072,38 @@ static int s2255_set_mode(struct s2255_channel *channel,
 	buffer[1] = (__le32) cpu_to_le32(chn_rev);
 	buffer[2] = CMD_SET_MODE;
 	for (i = 0; i < sizeof(struct s2255_mode) / sizeof(u32); i++)
-		buffer[3 + i] = cpu_to_le32(((u32 *)&channel->mode)[i]);
-	channel->setmode_ready = 0;
+		buffer[3 + i] = cpu_to_le32(((u32 *)&vc->mode)[i]);
+	vc->setmode_ready = 0;
 	res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
-	if (debug)
-		s2255_print_cfg(dev, mode);
+
+	dprintk(dev, 1, "format: %d\nscale %d\n", mode->format, mode->scale);
+	dprintk(dev, 1, "fdec: %d\ncolor %d\n", mode->fdec, mode->color);
+
 	kfree(buffer);
 	/* wait at least 3 frames before continuing */
 	if (mode->restart) {
-		wait_event_timeout(channel->wait_setmode,
-				   (channel->setmode_ready != 0),
+		wait_event_timeout(vc->wait_setmode,
+				   (vc->setmode_ready != 0),
 				   msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
-		if (channel->setmode_ready != 1) {
+		if (vc->setmode_ready != 1) {
 			dprintk(dev, 0, "s2255: no set mode response\n");
 			res = -EFAULT;
 		}
 	}
 	/* clear the restart flag */
-	channel->mode.restart = 0;
-	dprintk(dev, 1, "%s chn %d, result: %d\n", __func__, channel->idx, res);
+	vc->mode.restart = 0;
+	dprintk(dev, 1, "%s chn %d, result: %d\n", __func__, vc->idx, res);
 	return res;
 }
 
-static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus)
+static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus)
 {
 	int res;
 	__le32 *buffer;
 	u32 chn_rev;
-	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-	chn_rev = G_chnmap[channel->idx];
-	dprintk(dev, 4, "%s chan %d\n", __func__, channel->idx);
+	struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
+	chn_rev = G_chnmap[vc->idx];
+	dprintk(dev, 4, "%s chan %d\n", __func__, vc->idx);
 	buffer = kzalloc(512, GFP_KERNEL);
 	if (buffer == NULL) {
 		dev_err(&dev->udev->dev, "out of mem\n");
@@ -1205,127 +1114,70 @@ static int s2255_cmd_status(struct s2255_channel *channel, u32 *pstatus)
 	buffer[1] = (__le32) cpu_to_le32(chn_rev);
 	buffer[2] = CMD_STATUS;
 	*pstatus = 0;
-	channel->vidstatus_ready = 0;
+	vc->vidstatus_ready = 0;
 	res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
 	kfree(buffer);
-	wait_event_timeout(channel->wait_vidstatus,
-			   (channel->vidstatus_ready != 0),
+	wait_event_timeout(vc->wait_vidstatus,
+			   (vc->vidstatus_ready != 0),
 			   msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT));
-	if (channel->vidstatus_ready != 1) {
+	if (vc->vidstatus_ready != 1) {
 		dprintk(dev, 0, "s2255: no vidstatus response\n");
 		res = -EFAULT;
 	}
-	*pstatus = channel->vidstatus;
+	*pstatus = vc->vidstatus;
 	dprintk(dev, 4, "%s, vid status %d\n", __func__, *pstatus);
 	return res;
 }
 
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	int res;
-	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
-	struct s2255_channel *channel = fh->channel;
-	int j;
-	dprintk(dev, 4, "%s\n", __func__);
-	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		dev_err(&dev->udev->dev, "invalid fh type0\n");
-		return -EINVAL;
-	}
-	if (i != fh->type) {
-		dev_err(&dev->udev->dev, "invalid fh type1\n");
-		return -EINVAL;
-	}
-
-	if (!res_get(fh)) {
-		s2255_dev_err(&dev->udev->dev, "stream busy\n");
-		return -EBUSY;
-	}
-	channel->last_frame = -1;
-	channel->bad_payload = 0;
-	channel->cur_frame = 0;
-	channel->frame_count = 0;
-	for (j = 0; j < SYS_FRAMES; j++) {
-		channel->buffer.frame[j].ulState = S2255_READ_IDLE;
-		channel->buffer.frame[j].cur_size = 0;
-	}
-	res = videobuf_streamon(&fh->vb_vidq);
-	if (res == 0) {
-		s2255_start_acquire(channel);
-		channel->b_acquire = 1;
-	} else
-		res_free(fh);
-
-	return res;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct s2255_fh *fh = priv;
-	dprintk(fh->dev, 4, "%s\n, channel: %d", __func__, fh->channel->idx);
-	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		dprintk(fh->dev, 1, "invalid fh type0\n");
-		return -EINVAL;
-	}
-	if (i != fh->type)
-		return -EINVAL;
-	s2255_stop_acquire(fh->channel);
-	videobuf_streamoff(&fh->vb_vidq);
-	res_free(fh);
-	return 0;
-}
-
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id i)
 {
-	struct s2255_fh *fh = priv;
 	struct s2255_mode mode;
-	struct videobuf_queue *q = &fh->vb_vidq;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = video_drvdata(file);
+	struct vb2_queue *q = &vc->vb_vidq;
 	int ret = 0;
 
-	mutex_lock(&q->vb_lock);
-	if (res_locked(fh)) {
-		dprintk(fh->dev, 1, "can't change standard after started\n");
-		ret = -EBUSY;
-		goto out_s_std;
-	}
-	mode = fh->channel->mode;
+	/*
+	 * Changing the standard implies a format change, which is not allowed
+	 * while buffers for use with streaming have already been allocated.
+	 */
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	mode = vc->mode;
 	if (i & V4L2_STD_525_60) {
-		dprintk(fh->dev, 4, "%s 60 Hz\n", __func__);
+		dprintk(vc->dev, 4, "%s 60 Hz\n", __func__);
 		/* if changing format, reset frame decimation/intervals */
 		if (mode.format != FORMAT_NTSC) {
 			mode.restart = 1;
 			mode.format = FORMAT_NTSC;
 			mode.fdec = FDEC_1;
-			channel->width = LINE_SZ_4CIFS_NTSC;
-			channel->height = NUM_LINES_4CIFS_NTSC * 2;
+			vc->width = LINE_SZ_4CIFS_NTSC;
+			vc->height = NUM_LINES_4CIFS_NTSC * 2;
 		}
 	} else if (i & V4L2_STD_625_50) {
-		dprintk(fh->dev, 4, "%s 50 Hz\n", __func__);
+		dprintk(vc->dev, 4, "%s 50 Hz\n", __func__);
 		if (mode.format != FORMAT_PAL) {
 			mode.restart = 1;
 			mode.format = FORMAT_PAL;
 			mode.fdec = FDEC_1;
-			channel->width = LINE_SZ_4CIFS_PAL;
-			channel->height = NUM_LINES_4CIFS_PAL * 2;
+			vc->width = LINE_SZ_4CIFS_PAL;
+			vc->height = NUM_LINES_4CIFS_PAL * 2;
 		}
 	} else {
 		ret = -EINVAL;
 		goto out_s_std;
 	}
-	fh->channel->std = i;
+	vc->std = i;
 	if (mode.restart)
-		s2255_set_mode(fh->channel, &mode);
+		s2255_set_mode(vc, &mode);
 out_s_std:
-	mutex_unlock(&q->vb_lock);
 	return ret;
 }
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *i)
 {
-	struct s2255_fh *fh = priv;
-
-	*i = fh->channel->std;
+	struct s2255_vc *vc = video_drvdata(file);
+	*i = vc->std;
 	return 0;
 }
 
@@ -1339,9 +1191,8 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *i)
 static int vidioc_enum_input(struct file *file, void *priv,
 			     struct v4l2_input *inp)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_dev *dev = fh->dev;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = video_drvdata(file);
+	struct s2255_dev *dev = vc->dev;
 	u32 status = 0;
 	if (inp->index != 0)
 		return -EINVAL;
@@ -1350,7 +1201,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
 	inp->status = 0;
 	if (dev->dsp_fw_ver >= S2255_MIN_DSP_STATUS) {
 		int rc;
-		rc = s2255_cmd_status(fh->channel, &status);
+		rc = s2255_cmd_status(vc, &status);
 		dprintk(dev, 4, "s2255_cmd_status rc: %d status %x\n",
 			rc, status);
 		if (rc == 0)
@@ -1363,7 +1214,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
 		strlcpy(inp->name, "Composite", sizeof(inp->name));
 		break;
 	case 0x2257:
-		strlcpy(inp->name, (channel->idx < 2) ? "Composite" : "S-Video",
+		strlcpy(inp->name, (vc->idx < 2) ? "Composite" : "S-Video",
 			sizeof(inp->name));
 		break;
 	}
@@ -1384,10 +1235,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 
 static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct s2255_channel *channel =
-		container_of(ctrl->handler, struct s2255_channel, hdl);
+	struct s2255_vc *vc =
+		container_of(ctrl->handler, struct s2255_vc, hdl);
 	struct s2255_mode mode;
-	mode = channel->mode;
+	mode = vc->mode;
 	/* update the mode to the corresponding value */
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
@@ -1407,7 +1258,7 @@ static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
 		mode.color |= !ctrl->val << 16;
 		break;
 	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-		channel->jpegqual = ctrl->val;
+		vc->jpegqual = ctrl->val;
 		return 0;
 	default:
 		return -EINVAL;
@@ -1417,48 +1268,44 @@ static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
 	   some V4L programs restart stream unnecessarily
 	   after a s_crtl.
 	*/
-	s2255_set_mode(channel, &mode);
+	s2255_set_mode(vc, &mode);
 	return 0;
 }
 
 static int vidioc_g_jpegcomp(struct file *file, void *priv,
 			 struct v4l2_jpegcompression *jc)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
-
+	struct s2255_vc *vc = video_drvdata(file);
 	memset(jc, 0, sizeof(*jc));
-	jc->quality = channel->jpegqual;
-	dprintk(fh->dev, 2, "%s: quality %d\n", __func__, jc->quality);
+	jc->quality = vc->jpegqual;
+	dprintk(vc->dev, 2, "%s: quality %d\n", __func__, jc->quality);
 	return 0;
 }
 
 static int vidioc_s_jpegcomp(struct file *file, void *priv,
 			 const struct v4l2_jpegcompression *jc)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = video_drvdata(file);
 	if (jc->quality < 0 || jc->quality > 100)
 		return -EINVAL;
-	v4l2_ctrl_s_ctrl(channel->jpegqual_ctrl, jc->quality);
-	dprintk(fh->dev, 2, "%s: quality %d\n", __func__, jc->quality);
+	v4l2_ctrl_s_ctrl(vc->jpegqual_ctrl, jc->quality);
+	dprintk(vc->dev, 2, "%s: quality %d\n", __func__, jc->quality);
 	return 0;
 }
 
 static int vidioc_g_parm(struct file *file, void *priv,
 			 struct v4l2_streamparm *sp)
 {
-	struct s2255_fh *fh = priv;
+	struct s2255_vc *vc = video_drvdata(file);
 	__u32 def_num, def_dem;
-	struct s2255_channel *channel = fh->channel;
 	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
 	sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
-	sp->parm.capture.capturemode = channel->cap_parm.capturemode;
-	def_num = (channel->mode.format == FORMAT_NTSC) ? 1001 : 1000;
-	def_dem = (channel->mode.format == FORMAT_NTSC) ? 30000 : 25000;
+	sp->parm.capture.capturemode = vc->cap_parm.capturemode;
+	def_num = (vc->mode.format == FORMAT_NTSC) ? 1001 : 1000;
+	def_dem = (vc->mode.format == FORMAT_NTSC) ? 30000 : 25000;
 	sp->parm.capture.timeperframe.denominator = def_dem;
-	switch (channel->mode.fdec) {
+	switch (vc->mode.fdec) {
 	default:
 	case FDEC_1:
 		sp->parm.capture.timeperframe.numerator = def_num;
@@ -1473,7 +1320,7 @@ static int vidioc_g_parm(struct file *file, void *priv,
 		sp->parm.capture.timeperframe.numerator = def_num * 5;
 		break;
 	}
-	dprintk(fh->dev, 4, "%s capture mode, %d timeperframe %d/%d\n",
+	dprintk(vc->dev, 4, "%s capture mode, %d timeperframe %d/%d\n",
 		__func__,
 		sp->parm.capture.capturemode,
 		sp->parm.capture.timeperframe.numerator,
@@ -1484,18 +1331,19 @@ static int vidioc_g_parm(struct file *file, void *priv,
 static int vidioc_s_parm(struct file *file, void *priv,
 			 struct v4l2_streamparm *sp)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = video_drvdata(file);
 	struct s2255_mode mode;
 	int fdec = FDEC_1;
 	__u32 def_num, def_dem;
 	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	mode = channel->mode;
+	mode = vc->mode;
 	/* high quality capture mode requires a stream restart */
-	if (channel->cap_parm.capturemode
-	    != sp->parm.capture.capturemode && res_locked(fh))
+	if ((vc->cap_parm.capturemode != sp->parm.capture.capturemode)
+	    && vb2_is_busy(&vc->vb_vidq))
 		return -EBUSY;
+
+	vc->cap_parm.capturemode = sp->parm.capture.capturemode;
 	def_num = (mode.format == FORMAT_NTSC) ? 1001 : 1000;
 	def_dem = (mode.format == FORMAT_NTSC) ? 30000 : 25000;
 	if (def_dem != sp->parm.capture.timeperframe.denominator)
@@ -1514,8 +1362,8 @@ static int vidioc_s_parm(struct file *file, void *priv,
 	}
 	mode.fdec = fdec;
 	sp->parm.capture.timeperframe.denominator = def_dem;
-	s2255_set_mode(channel, &mode);
-	dprintk(fh->dev, 4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n",
+	s2255_set_mode(vc, &mode);
+	dprintk(vc->dev, 4, "%s capture mode, %d timeperframe %d/%d, fdec %d\n",
 		__func__,
 		sp->parm.capture.capturemode,
 		sp->parm.capture.timeperframe.numerator,
@@ -1538,9 +1386,8 @@ static const struct v4l2_frmsize_discrete pal_sizes[] = {
 static int vidioc_enum_framesizes(struct file *file, void *priv,
 			    struct v4l2_frmsizeenum *fe)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
-	int is_ntsc = channel->std & V4L2_STD_525_60;
+	struct s2255_vc *vc = video_drvdata(file);
+	int is_ntsc = vc->std & V4L2_STD_525_60;
 	const struct s2255_fmt *fmt;
 
 	if (fe->index >= NUM_SIZE_ENUMS)
@@ -1557,11 +1404,10 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
 static int vidioc_enum_frameintervals(struct file *file, void *priv,
 			    struct v4l2_frmivalenum *fe)
 {
-	struct s2255_fh *fh = priv;
-	struct s2255_channel *channel = fh->channel;
+	struct s2255_vc *vc = video_drvdata(file);
 	const struct s2255_fmt *fmt;
 	const struct v4l2_frmsize_discrete *sizes;
-	int is_ntsc = channel->std & V4L2_STD_525_60;
+	int is_ntsc = vc->std & V4L2_STD_525_60;
 #define NUM_FRAME_ENUMS 4
 	int frm_dec[NUM_FRAME_ENUMS] = {1, 2, 3, 5};
 	int i;
@@ -1584,22 +1430,25 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
 	fe->type = V4L2_FRMIVAL_TYPE_DISCRETE;
 	fe->discrete.denominator = is_ntsc ? 30000 : 25000;
 	fe->discrete.numerator = (is_ntsc ? 1001 : 1000) * frm_dec[fe->index];
-	dprintk(fh->dev, 4, "%s discrete %d/%d\n", __func__,
+	dprintk(vc->dev, 4, "%s discrete %d/%d\n", __func__,
 		fe->discrete.numerator,
 		fe->discrete.denominator);
 	return 0;
 }
 
-static int __s2255_open(struct file *file)
+static int s2255_open(struct file *file)
 {
-	struct video_device *vdev = video_devdata(file);
-	struct s2255_channel *channel = video_drvdata(file);
-	struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
-	struct s2255_fh *fh;
-	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	struct s2255_vc *vc = video_drvdata(file);
+	struct s2255_dev *dev = vc->dev;
 	int state;
-	dprintk(dev, 1, "s2255: open called (dev=%s)\n",
-		video_device_node_name(vdev));
+	int rc = 0;
+
+	/* allocate + initialize per filehandle data */
+	rc = v4l2_fh_open(file);
+	if (rc != 0)
+		return rc;
+
+	/* load firmware */
 	state = atomic_read(&dev->fw_data->fw_state);
 	switch (state) {
 	case S2255_FW_DISCONNECTING:
@@ -1661,66 +1510,23 @@ static int __s2255_open(struct file *file)
 		pr_info("%s: unknown state\n", __func__);
 		return -EFAULT;
 	}
-	/* allocate + initialize per filehandle data */
-	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh)
-		return -ENOMEM;
-	v4l2_fh_init(&fh->fh, vdev);
-	v4l2_fh_add(&fh->fh);
-	file->private_data = &fh->fh;
-	fh->dev = dev;
-	fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fh->channel = channel;
-	if (!channel->configured) {
+
+	if (!vc->configured) {
+		int rc;
 		/* configure channel to default state */
-		channel->fmt = &formats[0];
-		s2255_set_mode(channel, &channel->mode);
-		channel->configured = 1;
-	}
-	dprintk(dev, 1, "%s: dev=%s type=%s\n", __func__,
-		video_device_node_name(vdev), v4l2_type_names[type]);
-	dprintk(dev, 2, "%s: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", __func__,
-		(unsigned long)fh, (unsigned long)dev,
-		(unsigned long)&channel->vidq);
-	dprintk(dev, 4, "%s: list_empty active=%d\n", __func__,
-		list_empty(&channel->vidq.active));
-	videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops,
-				    NULL, &dev->slock,
-				    fh->type,
-				    V4L2_FIELD_INTERLACED,
-				    sizeof(struct s2255_buffer),
-				    fh, vdev->lock);
+		vc->fmt = &formats[0];
+		rc = s2255_set_mode(vc, &vc->mode);
+		if (rc != 0) {
+			/* resend set mode. */
+			rc = s2255_set_mode(vc, &vc->mode);
+		}
+		if (rc == 0)
+			vc->configured = 1;
+	}
+	dprintk(dev, 2, "%s:\n", __func__);
 	return 0;
 }
 
-static int s2255_open(struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	int ret;
-
-	if (mutex_lock_interruptible(vdev->lock))
-		return -ERESTARTSYS;
-	ret = __s2255_open(file);
-	mutex_unlock(vdev->lock);
-	return ret;
-}
-
-static unsigned int s2255_poll(struct file *file,
-			       struct poll_table_struct *wait)
-{
-	struct s2255_fh *fh = file->private_data;
-	struct s2255_dev *dev = fh->dev;
-	int rc = v4l2_ctrl_poll(file, wait);
-
-	dprintk(dev, 100, "%s\n", __func__);
-	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
-		return POLLERR;
-	mutex_lock(&dev->lock);
-	rc |= videobuf_poll_stream(file, &fh->vb_vidq, wait);
-	mutex_unlock(&dev->lock);
-	return rc;
-}
-
 static void s2255_destroy(struct s2255_dev *dev)
 {
 	dprintk(dev, 1, "%s", __func__);
@@ -1744,57 +1550,14 @@ static void s2255_destroy(struct s2255_dev *dev)
 	kfree(dev);
 }
 
-static int s2255_release(struct file *file)
-{
-	struct s2255_fh *fh = file->private_data;
-	struct s2255_dev *dev = fh->dev;
-	struct video_device *vdev = video_devdata(file);
-	struct s2255_channel *channel = fh->channel;
-	if (!dev)
-		return -ENODEV;
-	mutex_lock(&dev->lock);
-	/* turn off stream */
-	if (res_check(fh)) {
-		if (channel->b_acquire)
-			s2255_stop_acquire(fh->channel);
-		videobuf_streamoff(&fh->vb_vidq);
-		res_free(fh);
-	}
-	videobuf_mmap_free(&fh->vb_vidq);
-	mutex_unlock(&dev->lock);
-	dprintk(dev, 1, "%s[%s]\n", __func__, video_device_node_name(vdev));
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
-	kfree(fh);
-	return 0;
-}
-
-static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
-{
-	struct s2255_fh *fh = file->private_data;
-	struct s2255_dev *dev;
-	int ret;
-	if (!fh)
-		return -ENODEV;
-	dev = fh->dev;
-	dprintk(dev, 4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma);
-	if (mutex_lock_interruptible(&dev->lock))
-		return -ERESTARTSYS;
-	ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-	mutex_unlock(&dev->lock);
-	dprintk(dev, 4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__,
-		(unsigned long)vma->vm_start,
-		(unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
-	return ret;
-}
-
 static const struct v4l2_file_operations s2255_fops_v4l = {
 	.owner = THIS_MODULE,
 	.open = s2255_open,
-	.release = s2255_release,
-	.poll = s2255_poll,
-	.unlocked_ioctl = video_ioctl2,	/* V4L2 ioctl handler */
-	.mmap = s2255_mmap_v4l,
+	.release = vb2_fop_release,
+	.unlocked_ioctl = video_ioctl2,
+	.read = vb2_fop_read,
+	.mmap = vb2_fop_mmap,
+	.poll = vb2_fop_poll,
 };
 
 static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
@@ -1803,17 +1566,17 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
 	.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
 	.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
 	.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
-	.vidioc_reqbufs = vidioc_reqbufs,
-	.vidioc_querybuf = vidioc_querybuf,
-	.vidioc_qbuf = vidioc_qbuf,
-	.vidioc_dqbuf = vidioc_dqbuf,
+	.vidioc_reqbufs =  vb2_ioctl_reqbufs,
+	.vidioc_querybuf = vb2_ioctl_querybuf,
+	.vidioc_qbuf = vb2_ioctl_qbuf,
+	.vidioc_dqbuf = vb2_ioctl_dqbuf,
 	.vidioc_s_std = vidioc_s_std,
 	.vidioc_g_std = vidioc_g_std,
 	.vidioc_enum_input = vidioc_enum_input,
 	.vidioc_g_input = vidioc_g_input,
 	.vidioc_s_input = vidioc_s_input,
-	.vidioc_streamon = vidioc_streamon,
-	.vidioc_streamoff = vidioc_streamoff,
+	.vidioc_streamon = vb2_ioctl_streamon,
+	.vidioc_streamoff = vb2_ioctl_streamoff,
 	.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
 	.vidioc_g_jpegcomp = vidioc_g_jpegcomp,
 	.vidioc_s_parm = vidioc_s_parm,
@@ -1828,13 +1591,13 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
 static void s2255_video_device_release(struct video_device *vdev)
 {
 	struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
-	struct s2255_channel *channel =
-		container_of(vdev, struct s2255_channel, vdev);
+	struct s2255_vc *vc =
+		container_of(vdev, struct s2255_vc, vdev);
 
 	dprintk(dev, 4, "%s, chnls: %d\n", __func__,
 		atomic_read(&dev->num_channels));
 
-	v4l2_ctrl_handler_free(&channel->hdl);
+	v4l2_ctrl_handler_free(&vc->hdl);
 
 	if (atomic_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
@@ -1868,64 +1631,82 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
 	int ret;
 	int i;
 	int cur_nr = video_nr;
-	struct s2255_channel *channel;
+	struct vb2_queue *q;
+	struct s2255_vc *vc;
 	ret = v4l2_device_register(&dev->interface->dev, &dev->v4l2_dev);
 	if (ret)
 		return ret;
 	/* initialize all video 4 linux */
 	/* register 4 video devices */
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		channel = &dev->channel[i];
-		INIT_LIST_HEAD(&channel->vidq.active);
+		vc = &dev->vc[i];
+		INIT_LIST_HEAD(&vc->buf_list);
 
-		v4l2_ctrl_handler_init(&channel->hdl, 6);
-		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+		v4l2_ctrl_handler_init(&vc->hdl, 6);
+		v4l2_ctrl_new_std(&vc->hdl, &s2255_ctrl_ops,
 				V4L2_CID_BRIGHTNESS, -127, 127, 1, DEF_BRIGHT);
-		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+		v4l2_ctrl_new_std(&vc->hdl, &s2255_ctrl_ops,
 				V4L2_CID_CONTRAST, 0, 255, 1, DEF_CONTRAST);
-		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+		v4l2_ctrl_new_std(&vc->hdl, &s2255_ctrl_ops,
 				V4L2_CID_SATURATION, 0, 255, 1, DEF_SATURATION);
-		v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
+		v4l2_ctrl_new_std(&vc->hdl, &s2255_ctrl_ops,
 				V4L2_CID_HUE, 0, 255, 1, DEF_HUE);
-		channel->jpegqual_ctrl = v4l2_ctrl_new_std(&channel->hdl,
+		vc->jpegqual_ctrl = v4l2_ctrl_new_std(&vc->hdl,
 				&s2255_ctrl_ops,
 				V4L2_CID_JPEG_COMPRESSION_QUALITY,
 				0, 100, 1, S2255_DEF_JPEG_QUAL);
 		if (dev->dsp_fw_ver >= S2255_MIN_DSP_COLORFILTER &&
-		    (dev->pid != 0x2257 || channel->idx <= 1))
-			v4l2_ctrl_new_custom(&channel->hdl, &color_filter_ctrl,
+		    (dev->pid != 0x2257 || vc->idx <= 1))
+			v4l2_ctrl_new_custom(&vc->hdl, &color_filter_ctrl,
 					     NULL);
-		if (channel->hdl.error) {
-			ret = channel->hdl.error;
-			v4l2_ctrl_handler_free(&channel->hdl);
+		if (vc->hdl.error) {
+			ret = vc->hdl.error;
+			v4l2_ctrl_handler_free(&vc->hdl);
 			dev_err(&dev->udev->dev, "couldn't register control\n");
 			break;
 		}
-		channel->vidq.dev = dev;
+		q = &vc->vb_vidq;
+		memset(q, 0, sizeof(vc->vb_vidq));
+		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		q->io_modes = VB2_MMAP | VB2_READ;
+		q->drv_priv = vc;
+		q->lock = &vc->vb_lock;
+		q->buf_struct_size = sizeof(struct s2255_buffer);
+		q->mem_ops = &vb2_vmalloc_memops;
+		q->ops = &s2255_video_qops;
+		q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+		ret = vb2_queue_init(q);
+		if (ret != 0) {
+			dev_err(&dev->udev->dev,
+				"%s vb2_queue_init err: 0x%x\n", __func__, ret);
+			break;
+		}
 		/* register 4 video devices */
-		channel->vdev = template;
-		channel->vdev.ctrl_handler = &channel->hdl;
-		channel->vdev.lock = &dev->lock;
-		channel->vdev.v4l2_dev = &dev->v4l2_dev;
-		set_bit(V4L2_FL_USE_FH_PRIO, &channel->vdev.flags);
-		video_set_drvdata(&channel->vdev, channel);
+		vc->vdev = template;
+		vc->vdev.queue = q;
+		vc->vdev.ctrl_handler = &vc->hdl;
+		/* main device lock */
+		vc->vdev.lock = &dev->lock;
+		vc->vdev.v4l2_dev = &dev->v4l2_dev;
+		set_bit(V4L2_FL_USE_FH_PRIO, &vc->vdev.flags);
+		video_set_drvdata(&vc->vdev, vc);
 		if (video_nr == -1)
-			ret = video_register_device(&channel->vdev,
+			ret = video_register_device(&vc->vdev,
 						    VFL_TYPE_GRABBER,
 						    video_nr);
 		else
-			ret = video_register_device(&channel->vdev,
+			ret = video_register_device(&vc->vdev,
 						    VFL_TYPE_GRABBER,
 						    cur_nr + i);
 
 		if (ret) {
 			dev_err(&dev->udev->dev,
-				"failed to register video device!\n");
+				"failed to register vid device: 0x%x!\n", ret);
 			break;
 		}
 		atomic_inc(&dev->num_channels);
 		v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
-			  video_device_node_name(&channel->vdev));
+			  video_device_node_name(&vc->vdev));
 
 	}
 	pr_info("Sensoray 2255 V4L driver Revision: %s\n",
@@ -1962,11 +1743,11 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 	s32 idx = -1;
 	struct s2255_framei *frm;
 	unsigned char *pdata;
-	struct s2255_channel *ch;
+	struct s2255_vc *vc;
 	dprintk(dev, 100, "buffer to user\n");
-	ch = &dev->channel[dev->cc];
-	idx = ch->cur_frame;
-	frm = &ch->buffer.frame[idx];
+	vc = &dev->vc[dev->cc];
+	idx = vc->cur_frame;
+	frm = &vc->buffer.frame[idx];
 	if (frm->ulState == S2255_READ_IDLE) {
 		int jj;
 		unsigned int cc;
@@ -1990,15 +1771,15 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 				}
 				/* reverse it */
 				dev->cc = G_chnmap[cc];
-				ch = &dev->channel[dev->cc];
+				vc = &dev->vc[dev->cc];
 				payload =  le32_to_cpu(pdword[3]);
-				if (payload > ch->req_image_size) {
-					ch->bad_payload++;
+				if (payload > vc->req_image_size) {
+					vc->bad_payload++;
 					/* discard the bad frame */
 					return -EINVAL;
 				}
-				ch->pkt_size = payload;
-				ch->jpg_size = le32_to_cpu(pdword[4]);
+				vc->pkt_size = payload;
+				vc->jpg_size = le32_to_cpu(pdword[4]);
 				break;
 			case S2255_MARKER_RESPONSE:
 
@@ -2009,13 +1790,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 				cc = G_chnmap[le32_to_cpu(pdword[1])];
 				if (cc >= MAX_CHANNELS)
 					break;
-				ch = &dev->channel[cc];
+				vc = &dev->vc[cc];
 				switch (pdword[2]) {
 				case S2255_RESPONSE_SETMODE:
 					/* check if channel valid */
 					/* set mode ready */
-					ch->setmode_ready = 1;
-					wake_up(&ch->wait_setmode);
+					vc->setmode_ready = 1;
+					wake_up(&vc->wait_setmode);
 					dprintk(dev, 5, "setmode rdy %d\n", cc);
 					break;
 				case S2255_RESPONSE_FW:
@@ -2029,9 +1810,9 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 					wake_up(&dev->fw_data->wait_fw);
 					break;
 				case S2255_RESPONSE_STATUS:
-					ch->vidstatus = le32_to_cpu(pdword[3]);
-					ch->vidstatus_ready = 1;
-					wake_up(&ch->wait_vidstatus);
+					vc->vidstatus = le32_to_cpu(pdword[3]);
+					vc->vidstatus_ready = 1;
+					wake_up(&vc->wait_vidstatus);
 					dprintk(dev, 5, "vstat %x chan %d\n",
 						le32_to_cpu(pdword[3]), cc);
 					break;
@@ -2048,11 +1829,12 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 		if (!bframe)
 			return -EINVAL;
 	}
-	ch = &dev->channel[dev->cc];
-	idx = ch->cur_frame;
-	frm = &ch->buffer.frame[idx];
+	vc = &dev->vc[dev->cc];
+	idx = vc->cur_frame;
+	frm = &vc->buffer.frame[idx];
+
 	/* search done.  now find out if should be acquiring on this channel */
-	if (!ch->b_acquire) {
+	if (!vb2_is_streaming(&vc->vb_vidq)) {
 		/* we found a frame, but this channel is turned off */
 		frm->ulState = S2255_READ_IDLE;
 		return -EINVAL;
@@ -2066,7 +1848,6 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 	/* skip the marker 512 bytes (and offset if out of sync) */
 	psrc = (u8 *)pipe_info->transfer_buffer + offset;
 
-
 	if (frm->lpvbits == NULL) {
 		dprintk(dev, 1, "s2255 frame buffer == NULL.%p %p %d %d",
 			frm, dev, dev->cc, idx);
@@ -2074,13 +1855,11 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 	}
 
 	pdest = frm->lpvbits + frm->cur_size;
-
 	copy_size = (pipe_info->cur_transfer_size - offset);
-
-	size = ch->pkt_size - PREFIX_SIZE;
+	size = vc->pkt_size - PREFIX_SIZE;
 
 	/* sanity check on pdest */
-	if ((copy_size + frm->cur_size) < ch->req_image_size)
+	if ((copy_size + frm->cur_size) < vc->req_image_size)
 		memcpy(pdest, psrc, copy_size);
 
 	frm->cur_size += copy_size;
@@ -2089,19 +1868,18 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 	if (frm->cur_size >= size) {
 		dprintk(dev, 2, "******[%d]Buffer[%d]full*******\n",
 			dev->cc, idx);
-		ch->last_frame = ch->cur_frame;
-		ch->cur_frame++;
+		vc->last_frame = vc->cur_frame;
+		vc->cur_frame++;
 		/* end of system frame ring buffer, start at zero */
-		if ((ch->cur_frame == SYS_FRAMES) ||
-		    (ch->cur_frame == ch->buffer.dwFrames))
-			ch->cur_frame = 0;
+		if ((vc->cur_frame == SYS_FRAMES) ||
+		    (vc->cur_frame == vc->buffer.dwFrames))
+			vc->cur_frame = 0;
 		/* frame ready */
-		if (ch->b_acquire)
-			s2255_got_frame(ch, ch->jpg_size);
-		ch->frame_count++;
+		if (vb2_is_streaming(&vc->vb_vidq))
+			s2255_got_frame(vc, vc->jpg_size);
+		vc->frame_count++;
 		frm->ulState = S2255_READ_IDLE;
 		frm->cur_size = 0;
-
 	}
 	/* done successfully */
 	return 0;
@@ -2121,7 +1899,7 @@ static void s2255_read_video_callback(struct s2255_dev *dev,
 	/* otherwise copy to the system buffers */
 	res = save_frame(dev, pipe_info);
 	if (res != 0)
-		dprintk(dev, 4, "s2255: read callback failed\n");
+		dprintk(dev, 50, "s2255: read callback: %d\n", res);
 
 	dprintk(dev, 50, "callback read video done\n");
 	return;
@@ -2171,11 +1949,11 @@ static int s2255_get_fx2fw(struct s2255_dev *dev)
  * Create the system ring buffer to copy frames into from the
  * usb read pipe.
  */
-static int s2255_create_sys_buffers(struct s2255_channel *channel)
+static int s2255_create_sys_buffers(struct s2255_vc *vc)
 {
 	unsigned long i;
 	unsigned long reqsize;
-	channel->buffer.dwFrames = SYS_FRAMES;
+	vc->buffer.dwFrames = SYS_FRAMES;
 	/* always allocate maximum size(PAL) for system buffers */
 	reqsize = SYS_FRAMES_MAXSIZE;
 
@@ -2184,33 +1962,33 @@ static int s2255_create_sys_buffers(struct s2255_channel *channel)
 
 	for (i = 0; i < SYS_FRAMES; i++) {
 		/* allocate the frames */
-		channel->buffer.frame[i].lpvbits = vmalloc(reqsize);
-		channel->buffer.frame[i].size = reqsize;
-		if (channel->buffer.frame[i].lpvbits == NULL) {
+		vc->buffer.frame[i].lpvbits = vmalloc(reqsize);
+		vc->buffer.frame[i].size = reqsize;
+		if (vc->buffer.frame[i].lpvbits == NULL) {
 			pr_info("out of memory.  using less frames\n");
-			channel->buffer.dwFrames = i;
+			vc->buffer.dwFrames = i;
 			break;
 		}
 	}
 
 	/* make sure internal states are set */
 	for (i = 0; i < SYS_FRAMES; i++) {
-		channel->buffer.frame[i].ulState = 0;
-		channel->buffer.frame[i].cur_size = 0;
+		vc->buffer.frame[i].ulState = 0;
+		vc->buffer.frame[i].cur_size = 0;
 	}
 
-	channel->cur_frame = 0;
-	channel->last_frame = -1;
+	vc->cur_frame = 0;
+	vc->last_frame = -1;
 	return 0;
 }
 
-static int s2255_release_sys_buffers(struct s2255_channel *channel)
+static int s2255_release_sys_buffers(struct s2255_vc *vc)
 {
 	unsigned long i;
 	for (i = 0; i < SYS_FRAMES; i++) {
-		if (channel->buffer.frame[i].lpvbits)
-			vfree(channel->buffer.frame[i].lpvbits);
-		channel->buffer.frame[i].lpvbits = NULL;
+		if (vc->buffer.frame[i].lpvbits)
+			vfree(vc->buffer.frame[i].lpvbits);
+		vc->buffer.frame[i].lpvbits = NULL;
 	}
 	return 0;
 }
@@ -2244,21 +2022,20 @@ static int s2255_board_init(struct s2255_dev *dev)
 		pr_info("s2255: newer USB firmware available\n");
 
 	for (j = 0; j < MAX_CHANNELS; j++) {
-		struct s2255_channel *channel = &dev->channel[j];
-		channel->b_acquire = 0;
-		channel->mode = mode_def;
+		struct s2255_vc *vc = &dev->vc[j];
+		vc->mode = mode_def;
 		if (dev->pid == 0x2257 && j > 1)
-			channel->mode.color |= (1 << 16);
-		channel->jpegqual = S2255_DEF_JPEG_QUAL;
-		channel->width = LINE_SZ_4CIFS_NTSC;
-		channel->height = NUM_LINES_4CIFS_NTSC * 2;
-		channel->std = V4L2_STD_NTSC_M;
-		channel->fmt = &formats[0];
-		channel->mode.restart = 1;
-		channel->req_image_size = get_transfer_size(&mode_def);
-		channel->frame_count = 0;
+			vc->mode.color |= (1 << 16);
+		vc->jpegqual = S2255_DEF_JPEG_QUAL;
+		vc->width = LINE_SZ_4CIFS_NTSC;
+		vc->height = NUM_LINES_4CIFS_NTSC * 2;
+		vc->std = V4L2_STD_NTSC_M;
+		vc->fmt = &formats[0];
+		vc->mode.restart = 1;
+		vc->req_image_size = get_transfer_size(&mode_def);
+		vc->frame_count = 0;
 		/* create the system buffers */
-		s2255_create_sys_buffers(channel);
+		s2255_create_sys_buffers(vc);
 	}
 	/* start read pipe */
 	s2255_start_readpipe(dev);
@@ -2270,14 +2047,13 @@ static int s2255_board_shutdown(struct s2255_dev *dev)
 {
 	u32 i;
 	dprintk(dev, 1, "%s: dev: %p", __func__,  dev);
-
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		if (dev->channel[i].b_acquire)
-			s2255_stop_acquire(&dev->channel[i]);
+		if (vb2_is_streaming(&dev->vc[i].vb_vidq))
+			s2255_stop_acquire(&dev->vc[i]);
 	}
 	s2255_stop_readpipe(dev);
 	for (i = 0; i < MAX_CHANNELS; i++)
-		s2255_release_sys_buffers(&dev->channel[i]);
+		s2255_release_sys_buffers(&dev->vc[i]);
 	/* release transfer buffer */
 	kfree(dev->pipe.transfer_buffer);
 	return 0;
@@ -2366,26 +2142,26 @@ static int s2255_start_readpipe(struct s2255_dev *dev)
 }
 
 /* starts acquisition process */
-static int s2255_start_acquire(struct s2255_channel *channel)
+static int s2255_start_acquire(struct s2255_vc *vc)
 {
 	unsigned char *buffer;
 	int res;
 	unsigned long chn_rev;
 	int j;
-	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-	chn_rev = G_chnmap[channel->idx];
+	struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
+	chn_rev = G_chnmap[vc->idx];
 	buffer = kzalloc(512, GFP_KERNEL);
 	if (buffer == NULL) {
 		dev_err(&dev->udev->dev, "out of mem\n");
 		return -ENOMEM;
 	}
 
-	channel->last_frame = -1;
-	channel->bad_payload = 0;
-	channel->cur_frame = 0;
+	vc->last_frame = -1;
+	vc->bad_payload = 0;
+	vc->cur_frame = 0;
 	for (j = 0; j < SYS_FRAMES; j++) {
-		channel->buffer.frame[j].ulState = 0;
-		channel->buffer.frame[j].cur_size = 0;
+		vc->buffer.frame[j].ulState = 0;
+		vc->buffer.frame[j].cur_size = 0;
 	}
 
 	/* send the start command */
@@ -2396,18 +2172,18 @@ static int s2255_start_acquire(struct s2255_channel *channel)
 	if (res != 0)
 		dev_err(&dev->udev->dev, "CMD_START error\n");
 
-	dprintk(dev, 2, "start acquire exit[%d] %d\n", channel->idx, res);
+	dprintk(dev, 2, "start acquire exit[%d] %d\n", vc->idx, res);
 	kfree(buffer);
 	return 0;
 }
 
-static int s2255_stop_acquire(struct s2255_channel *channel)
+static int s2255_stop_acquire(struct s2255_vc *vc)
 {
 	unsigned char *buffer;
 	int res;
 	unsigned long chn_rev;
-	struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
-	chn_rev = G_chnmap[channel->idx];
+	struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
+	chn_rev = G_chnmap[vc->idx];
 	buffer = kzalloc(512, GFP_KERNEL);
 	if (buffer == NULL) {
 		dev_err(&dev->udev->dev, "out of mem\n");
@@ -2421,8 +2197,7 @@ static int s2255_stop_acquire(struct s2255_channel *channel)
 	if (res != 0)
 		dev_err(&dev->udev->dev, "CMD_STOP error\n");
 	kfree(buffer);
-	channel->b_acquire = 0;
-	dprintk(dev, 4, "%s: chn %d, res %d\n", __func__, channel->idx, res);
+	dprintk(dev, 4, "%s: chn %d, res %d\n", __func__, vc->idx, res);
 	return res;
 }
 
@@ -2512,11 +2287,13 @@ static int s2255_probe(struct usb_interface *interface,
 	dev->timer.data = (unsigned long)dev->fw_data;
 	init_waitqueue_head(&dev->fw_data->wait_fw);
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		struct s2255_channel *channel = &dev->channel[i];
-		channel->idx = i;
-		channel->dev = dev;
-		init_waitqueue_head(&channel->wait_setmode);
-		init_waitqueue_head(&channel->wait_vidstatus);
+		struct s2255_vc *vc = &dev->vc[i];
+		vc->idx = i;
+		vc->dev = dev;
+		init_waitqueue_head(&vc->wait_setmode);
+		init_waitqueue_head(&vc->wait_vidstatus);
+		spin_lock_init(&vc->qlock);
+		mutex_init(&vc->vb_lock);
 	}
 
 	dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -2562,8 +2339,7 @@ static int s2255_probe(struct usb_interface *interface,
 	retval = s2255_board_init(dev);
 	if (retval)
 		goto errorBOARDINIT;
-	spin_lock_init(&dev->slock);
-	s2255_fwload_start(dev, 0);
+	s2255_fwload_start(dev, 1);
 	/* loads v4l specific */
 	retval = s2255_probe_v4l(dev);
 	if (retval)
@@ -2604,15 +2380,15 @@ static void s2255_disconnect(struct usb_interface *interface)
 	atomic_inc(&dev->num_channels);
 	/* unregister each video device. */
 	for (i = 0; i < channels; i++)
-		video_unregister_device(&dev->channel[i].vdev);
+		video_unregister_device(&dev->vc[i].vdev);
 	/* wake up any of our timers */
 	atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
 	wake_up(&dev->fw_data->wait_fw);
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		dev->channel[i].setmode_ready = 1;
-		wake_up(&dev->channel[i].wait_setmode);
-		dev->channel[i].vidstatus_ready = 1;
-		wake_up(&dev->channel[i].wait_vidstatus);
+		dev->vc[i].setmode_ready = 1;
+		wake_up(&dev->vc[i].wait_setmode);
+		dev->vc[i].vidstatus_ready = 1;
+		wake_up(&dev->vc[i].wait_vidstatus);
 	}
 	if (atomic_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux