Re: [PATCH] s2255drv: port to videobuf2

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

 



Hi Dean,

Some specific comments below, but first two general comments:

It is easier to review if at least the removal of the old s2255_fh struct
was done as a separate patch. It's always good to try and keep the changes
in patches as small as possible. The actual vb2 conversion is always a
'big bang' patch, that's unavoidable, but it's easier if it isn't mixed in
with other changes that are not directly related to the vb2 conversion.

And did you also run the v4l2-compliance utility for this driver? That's
useful to check that everything it still correct.

On 01/31/2014 06:35 PM, Dean Anderson wrote:
> 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

<snip>

> @@ -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;

Just drop field_count (left-over from vivi) and use frame_count directly.

> +	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;

Unfortunately vivi was a bad example to use for this (I'm going to post patches
to fix vivi to avoid this in the future).

What really needs to happen is that you test against the minimum number of
buffers required to stream (usually somewhere between 1 and 3, test with e.g.
qv4l2 or v4l2-ctl) and if it is less, set *nbuffers to that minimum.

>  
> -	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;

This vid_limit makes no sense. If the application wants 32 buffers (the maximum),
then it should be able to get 32 buffers if there is enough memory. Having a
vid_limit is pointless. I plan on removing this from vivi as well.

> +	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;

buf->fmt can be dropped. It's used in only one place, and there vc->fmt can be
used as well. I need to remove that in vivi as well.

>  	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;

Please add an empty line here to make it more readable. In general, after
declaring variables add a newline before starting the actual code.

> +	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);

I noticed that s2255_start_acquire can fail and that that is not checked here.
In fact, s2255_start_acquire also ignores an error from s2255_write_config().
Several s2255 functions allocate a 512 buffer and release it again after use.
Would it not make more sense to allocate that buffer in probe() and use that
everywhere?

> +	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;

You can add VB2_USERPTR here as well, that should work out-of-the-box.

> +		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);
> 

Regards,

	Hans
--
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