media: cx231xx: convert to the vb2 framework
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Thu, 5 Sep 2019 11:31:11 +0000 (08:31 -0300)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Tue, 1 Oct 2019 20:23:44 +0000 (17:23 -0300)
This patch converts the cx231xx driver to the vb2 framework.
Since you can't do a partial conversion this is a big-bang patch,
i.e. large and hard to review. I never found a way around this.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Co-developed-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/usb/cx231xx/Kconfig
drivers/media/usb/cx231xx/cx231xx-417.c
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/cx231xx/cx231xx-vbi.c
drivers/media/usb/cx231xx/cx231xx-vbi.h
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/cx231xx/cx231xx.h

index 74f3b29..2fe2b2d 100644 (file)
@@ -4,7 +4,7 @@ config VIDEO_CX231XX
        depends on VIDEO_DEV && I2C && I2C_MUX
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEOBUF_VMALLOC
+       select VIDEOBUF2_VMALLOC
        select VIDEO_CX25840
        select VIDEO_CX2341X
 
index 6d218a0..46d0215 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/firmware.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/slab.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-event.h>
 #define  MCI_MODE_MEMORY_READ           0x000
 #define  MCI_MODE_MEMORY_WRITE          0x4000
 
-static unsigned int mpegbufs = 8;
-module_param(mpegbufs, int, 0644);
-MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
-
 static unsigned int mpeglines = 128;
 module_param(mpeglines, int, 0644);
 MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
@@ -1080,16 +1077,6 @@ static int cx231xx_load_firmware(struct cx231xx *dev)
        return 0;
 }
 
-static void cx231xx_417_check_encoder(struct cx231xx *dev)
-{
-       u32 status, seq;
-
-       status = 0;
-       seq = 0;
-       cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
-       dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
-}
-
 static void cx231xx_codec_settings(struct cx231xx *dev)
 {
        dprintk(1, "%s()\n", __func__);
@@ -1227,40 +1214,25 @@ static int cx231xx_initialize_codec(struct cx231xx *dev)
 
 /* ------------------------------------------------------------------ */
 
-static int bb_buf_setup(struct videobuf_queue *q,
-       unsigned int *count, unsigned int *size)
+static int queue_setup(struct vb2_queue *vq,
+                      unsigned int *nbuffers, unsigned int *nplanes,
+                      unsigned int sizes[], struct device *alloc_devs[])
 {
-       struct cx231xx_fh *fh = q->priv_data;
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
+       unsigned int size = mpeglinesize * mpeglines;
 
-       fh->dev->ts1.ts_packet_size  = mpeglinesize;
-       fh->dev->ts1.ts_packet_count = mpeglines;
+       dev->ts1.ts_packet_size  = mpeglinesize;
+       dev->ts1.ts_packet_count = mpeglines;
 
-       *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
-       *count = mpegbufs;
-
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       unsigned long flags = 0;
+       if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF)
+               *nbuffers = CX231XX_MIN_BUF - vq->num_buffers;
 
-       BUG_ON(in_interrupt());
+       if (*nplanes)
+               return sizes[0] < size ? -EINVAL : 0;
+       *nplanes = 1;
+       sizes[0] = mpeglinesize * mpeglines;
 
-       spin_lock_irqsave(&dev->video_mode.slock, flags);
-       if (dev->USE_ISO) {
-               if (dev->video_mode.isoc_ctl.buf == buf)
-                       dev->video_mode.isoc_ctl.buf = NULL;
-       } else {
-               if (dev->video_mode.bulk_ctl.buf == buf)
-                       dev->video_mode.bulk_ctl.buf = NULL;
-       }
-       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
-       videobuf_waiton(vq, &buf->vb, 0, 0);
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+       return 0;
 }
 
 static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,
@@ -1276,13 +1248,13 @@ static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *ur
                        return;
 
                buf = list_entry(dma_q->active.next,
-                               struct cx231xx_buffer, vb.queue);
+                               struct cx231xx_buffer, list);
                dev->video_mode.isoc_ctl.buf = buf;
                dma_q->mpeg_buffer_done = 1;
        }
        /* Fill buffer */
        buf = dev->video_mode.isoc_ctl.buf;
-       vbuf = videobuf_to_vmalloc(&buf->vb);
+       vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 
        if ((dma_q->mpeg_buffer_completed+len) <
                        mpeglines*mpeglinesize) {
@@ -1306,11 +1278,10 @@ static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *ur
                memcpy(vbuf+dma_q->mpeg_buffer_completed,
                                data, tail_data);
 
-               buf->vb.state = VIDEOBUF_DONE;
-               buf->vb.field_count++;
-               buf->vb.ts = ktime_get_ns();
-               list_del(&buf->vb.queue);
-               wake_up(&buf->vb.done);
+               buf->vb.vb2_buf.timestamp = ktime_get_ns();
+               buf->vb.sequence = dma_q->sequence++;
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
                dma_q->mpeg_buffer_completed = 0;
 
                if (len - tail_data > 0) {
@@ -1331,17 +1302,15 @@ static void buffer_filled(char *data, int len, struct urb *urb,
        if (list_empty(&dma_q->active))
                return;
 
-       buf = list_entry(dma_q->active.next,
-                       struct cx231xx_buffer, vb.queue);
+       buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list);
 
        /* Fill buffer */
-       vbuf = videobuf_to_vmalloc(&buf->vb);
+       vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
        memcpy(vbuf, data, len);
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       buf->vb.ts = ktime_get_ns();
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
+       buf->vb.sequence = dma_q->sequence++;
+       buf->vb.vb2_buf.timestamp = ktime_get_ns();
+       list_del(&buf->list);
+       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 static int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
@@ -1394,100 +1363,104 @@ static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
        return 0;
 }
 
-static int bb_buf_prepare(struct videobuf_queue *q,
-       struct videobuf_buffer *vb, enum v4l2_field field)
+static void buffer_queue(struct vb2_buffer *vb)
 {
-       struct cx231xx_fh *fh = q->priv_data;
        struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       int rc = 0, urb_init = 0;
-       int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+           container_of(vb, struct cx231xx_buffer, vb.vb2_buf);
+       struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       unsigned long flags;
 
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-       buf->vb.width = fh->dev->ts1.ts_packet_size;
-       buf->vb.height = fh->dev->ts1.ts_packet_count;
-       buf->vb.size = size;
-       buf->vb.field = field;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
+       spin_lock_irqsave(&dev->video_mode.slock, flags);
+       list_add_tail(&buf->list, &vidq->active);
+       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
+}
 
-       if (dev->USE_ISO) {
-               if (!dev->video_mode.isoc_ctl.num_bufs)
-                       urb_init = 1;
-       } else {
-               if (!dev->video_mode.bulk_ctl.num_bufs)
-                       urb_init = 1;
+static void return_all_buffers(struct cx231xx *dev,
+                              enum vb2_buffer_state state)
+{
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       struct cx231xx_buffer *buf, *node;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->video_mode.slock, flags);
+       list_for_each_entry_safe(buf, node, &vidq->active, list) {
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+               list_del(&buf->list);
        }
-       dev_dbg(dev->dev,
-               "urb_init=%d dev->video_mode.max_pkt_size=%d\n",
-               urb_init, dev->video_mode.max_pkt_size);
+       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       int ret = 0;
+
+       vidq->sequence = 0;
        dev->mode_tv = 1;
 
-       if (urb_init) {
-               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-               rc = cx231xx_unmute_audio(dev);
-               if (dev->USE_ISO) {
-                       cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
-                       rc = cx231xx_init_isoc(dev, mpeglines,
-                                      mpegbufs,
-                                      dev->ts1_mode.max_pkt_size,
-                                      cx231xx_isoc_copy);
-               } else {
-                       cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-                       rc = cx231xx_init_bulk(dev, mpeglines,
-                                      mpegbufs,
-                                      dev->ts1_mode.max_pkt_size,
-                                      cx231xx_bulk_copy);
-               }
-               if (rc < 0)
-                       goto fail;
-       }
+       cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
+       cx231xx_set_gpio_value(dev, 2, 0);
 
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
+       cx231xx_initialize_codec(dev);
+
+       cx231xx_start_TS1(dev);
 
-fail:
-       free_buffer(q, buf);
-       return rc;
+       cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+       cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+       if (dev->USE_ISO)
+               ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
+                                       CX231XX_NUM_BUFS,
+                                       dev->ts1_mode.max_pkt_size,
+                                       cx231xx_isoc_copy);
+       else
+               ret = cx231xx_init_bulk(dev, 320, 5,
+                                       dev->ts1_mode.max_pkt_size,
+                                       cx231xx_bulk_copy);
+       if (ret)
+               return_all_buffers(dev, VB2_BUF_STATE_QUEUED);
+
+       call_all(dev, video, s_stream, 1);
+       return ret;
 }
 
-static void bb_buf_queue(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
+static void stop_streaming(struct vb2_queue *vq)
 {
-       struct cx231xx_fh *fh = q->priv_data;
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
+       unsigned long flags;
 
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       call_all(dev, video, s_stream, 0);
 
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
+       cx231xx_stop_TS1(dev);
 
-}
+       /* do this before setting alternate! */
+       if (dev->USE_ISO)
+               cx231xx_uninit_isoc(dev);
+       else
+               cx231xx_uninit_bulk(dev);
+       cx231xx_set_mode(dev, CX231XX_SUSPEND);
 
-static void bb_buf_release(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
-{
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       /*struct cx231xx_fh *fh = q->priv_data;*/
-       /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/
+       cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                       CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
+                       CX231xx_RAW_BITS_NONE);
 
-       free_buffer(q, buf);
+       spin_lock_irqsave(&dev->video_mode.slock, flags);
+       if (dev->USE_ISO)
+               dev->video_mode.isoc_ctl.buf = NULL;
+       else
+               dev->video_mode.bulk_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
+       return_all_buffers(dev, VB2_BUF_STATE_ERROR);
 }
 
-static const struct videobuf_queue_ops cx231xx_qops = {
-       .buf_setup    = bb_buf_setup,
-       .buf_prepare  = bb_buf_prepare,
-       .buf_queue    = bb_buf_queue,
-       .buf_release  = bb_buf_release,
+static struct vb2_ops cx231xx_video_qops = {
+       .queue_setup            = queue_setup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
 };
 
 /* ------------------------------------------------------------------ */
@@ -1495,8 +1468,7 @@ static const struct videobuf_queue_ops cx231xx_qops = {
 static int vidioc_g_pixelaspect(struct file *file, void *priv,
                                int type, struct v4l2_fract *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        bool is_50hz = dev->encodernorm.id & V4L2_STD_625_50;
 
        if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -1511,8 +1483,7 @@ static int vidioc_g_pixelaspect(struct file *file, void *priv,
 static int vidioc_g_selection(struct file *file, void *priv,
                              struct v4l2_selection *s)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
@@ -1533,8 +1504,7 @@ static int vidioc_g_selection(struct file *file, void *priv,
 
 static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
 {
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        *norm = dev->encodernorm.id;
        return 0;
@@ -1542,8 +1512,7 @@ static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 {
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)
@@ -1575,8 +1544,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctl)
 {
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        struct v4l2_subdev *sd;
 
        dprintk(3, "enter vidioc_s_ctrl()\n");
@@ -1601,8 +1569,7 @@ 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 cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
@@ -1621,8 +1588,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
@@ -1636,230 +1602,21 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static int vidioc_reqbufs(struct file *file, void *priv,
-                               struct v4l2_requestbuffers *p)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_reqbufs(&fh->vidq, p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                               struct v4l2_buffer *p)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_querybuf(&fh->vidq, p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv,
-                               struct v4l2_buffer *p)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_qbuf(&fh->vidq, p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh  *fh  = priv;
-
-       return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK);
-}
-
-
-static int vidioc_streamon(struct file *file, void *priv,
-                               enum v4l2_buf_type i)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       dprintk(3, "enter vidioc_streamon()\n");
-       cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-       cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-       if (dev->USE_ISO)
-               cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
-                               CX231XX_NUM_BUFS,
-                               dev->video_mode.max_pkt_size,
-                               cx231xx_isoc_copy);
-       else {
-               cx231xx_init_bulk(dev, 320,
-                               5,
-                               dev->ts1_mode.max_pkt_size,
-                               cx231xx_bulk_copy);
-       }
-       dprintk(3, "exit vidioc_streamon()\n");
-       return videobuf_streamon(&fh->vidq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_streamoff(&fh->vidq);
-}
-
 static int vidioc_log_status(struct file *file, void *priv)
 {
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        call_all(dev, core, log_status);
        return v4l2_ctrl_log_status(file, priv);
 }
 
-static int mpeg_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx231xx *dev = video_drvdata(file);
-       struct cx231xx_fh *fh;
-
-       dprintk(2, "%s()\n", __func__);
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh) {
-               mutex_unlock(&dev->lock);
-               return -ENOMEM;
-       }
-
-       file->private_data = fh;
-       v4l2_fh_init(&fh->fh, vdev);
-       fh->dev = dev;
-
-
-       videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,
-                           NULL, &dev->video_mode.slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
-                           sizeof(struct cx231xx_buffer), fh, &dev->lock);
-/*
-       videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
-                           dev->dev, &dev->ts1.slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                           V4L2_FIELD_INTERLACED,
-                           sizeof(struct cx231xx_buffer),
-                           fh, &dev->lock);
-*/
-
-       cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
-       cx231xx_set_gpio_value(dev, 2, 0);
-
-       cx231xx_initialize_codec(dev);
-
-       mutex_unlock(&dev->lock);
-       v4l2_fh_add(&fh->fh);
-       cx231xx_start_TS1(dev);
-
-       return 0;
-}
-
-static int mpeg_release(struct file *file)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       dprintk(3, "mpeg_release()! dev=0x%p\n", dev);
-
-       mutex_lock(&dev->lock);
-
-       cx231xx_stop_TS1(dev);
-
-       /* do this before setting alternate! */
-       if (dev->USE_ISO)
-               cx231xx_uninit_isoc(dev);
-       else
-               cx231xx_uninit_bulk(dev);
-       cx231xx_set_mode(dev, CX231XX_SUSPEND);
-
-       cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-                       CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
-                       CX231xx_RAW_BITS_NONE);
-
-       /* FIXME: Review this crap */
-       /* Shut device down on last close */
-       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
-               if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
-                       /* stop mpeg capture */
-
-                       msleep(500);
-                       cx231xx_417_check_encoder(dev);
-
-               }
-       }
-
-       if (fh->vidq.streaming)
-               videobuf_streamoff(&fh->vidq);
-       if (fh->vidq.reading)
-               videobuf_read_stop(&fh->vidq);
-
-       videobuf_mmap_free(&fh->vidq);
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-       kfree(fh);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-static ssize_t mpeg_read(struct file *file, char __user *data,
-       size_t count, loff_t *ppos)
-{
-       struct cx231xx_fh *fh = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
-       /* Start mpeg encoder on first read. */
-       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
-               if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
-                       if (cx231xx_initialize_codec(dev) < 0)
-                               return -EINVAL;
-               }
-       }
-
-       return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
-                                   file->f_flags & O_NONBLOCK);
-}
-
-static __poll_t mpeg_poll(struct file *file,
-       struct poll_table_struct *wait)
-{
-       __poll_t req_events = poll_requested_events(wait);
-       struct cx231xx_fh *fh = file->private_data;
-       struct cx231xx *dev = fh->dev;
-       __poll_t res = 0;
-
-       if (v4l2_event_pending(&fh->fh))
-               res |= EPOLLPRI;
-       else
-               poll_wait(file, &fh->fh.wait, wait);
-
-       if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
-               return res;
-
-       mutex_lock(&dev->lock);
-       res |= videobuf_poll_stream(file, &fh->vidq, wait);
-       mutex_unlock(&dev->lock);
-       return res;
-}
-
-static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct cx231xx_fh *fh = file->private_data;
-
-       dprintk(2, "%s()\n", __func__);
-
-       return videobuf_mmap_mapper(&fh->vidq, vma);
-}
-
 static const struct v4l2_file_operations mpeg_fops = {
        .owner         = THIS_MODULE,
-       .open          = mpeg_open,
-       .release       = mpeg_release,
-       .read          = mpeg_read,
-       .poll          = mpeg_poll,
-       .mmap          = mpeg_mmap,
+       .open          = v4l2_fh_open,
+       .release       = vb2_fop_release,
+       .read          = vb2_fop_read,
+       .poll          = vb2_fop_poll,
+       .mmap          = vb2_fop_mmap,
        .unlocked_ioctl = video_ioctl2,
 };
 
@@ -1881,12 +1638,12 @@ static const struct v4l2_ioctl_ops mpeg_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_try_fmt_vid_cap,
-       .vidioc_reqbufs          = vidioc_reqbufs,
-       .vidioc_querybuf         = vidioc_querybuf,
-       .vidioc_qbuf             = vidioc_qbuf,
-       .vidioc_dqbuf            = vidioc_dqbuf,
-       .vidioc_streamon         = vidioc_streamon,
-       .vidioc_streamoff        = vidioc_streamoff,
+       .vidioc_reqbufs          = vb2_ioctl_reqbufs,
+       .vidioc_querybuf         = vb2_ioctl_querybuf,
+       .vidioc_qbuf             = vb2_ioctl_qbuf,
+       .vidioc_dqbuf            = vb2_ioctl_dqbuf,
+       .vidioc_streamon         = vb2_ioctl_streamon,
+       .vidioc_streamoff        = vb2_ioctl_streamoff,
        .vidioc_log_status       = vidioc_log_status,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register       = cx231xx_g_register,
@@ -1980,6 +1737,7 @@ int cx231xx_417_register(struct cx231xx *dev)
        /* FIXME: Port1 hardcoded here */
        int err = -ENODEV;
        struct cx231xx_tsport *tsport = &dev->ts1;
+       struct vb2_queue *q;
 
        dprintk(1, "%s()\n", __func__);
 
@@ -2017,6 +1775,21 @@ int cx231xx_417_register(struct cx231xx *dev)
        /* Allocate and initialize V4L video device */
        cx231xx_video_dev_init(dev, dev->udev,
                        &dev->v4l_device, &cx231xx_mpeg_template, "mpeg");
+       q = &dev->mpegq;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ;
+       q->drv_priv = dev;
+       q->buf_struct_size = sizeof(struct cx231xx_buffer);
+       q->ops = &cx231xx_video_qops;
+       q->mem_ops = &vb2_vmalloc_memops;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->min_buffers_needed = 1;
+       q->lock = &dev->lock;
+       err = vb2_queue_init(q);
+       if (err)
+               return err;
+       dev->v4l_device.queue = q;
+
        err = video_register_device(&dev->v4l_device,
                VFL_TYPE_GRABBER, -1);
        if (err < 0) {
index e123e74..92efe6c 100644 (file)
@@ -1479,13 +1479,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
                goto err_dev_init;
        }
 
-       /* init video dma queues */
+       /* init video dma queue */
        INIT_LIST_HEAD(&dev->video_mode.vidq.active);
-       INIT_LIST_HEAD(&dev->video_mode.vidq.queued);
 
-       /* init vbi dma queues */
+       /* init vbi dma queue */
        INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
-       INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
 
        /* Reset other chips required if they are tied up with GPIO pins */
        cx231xx_add_into_devlist(dev);
index fba7ccd..d2f143a 100644 (file)
@@ -153,131 +153,98 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
        Vbi buf operations
    ------------------------------------------------------------------*/
 
-static int
-vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-                unsigned int *size)
+static int vbi_queue_setup(struct vb2_queue *vq,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], struct device *alloc_devs[])
 {
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
        u32 height = 0;
 
        height = ((dev->norm & V4L2_STD_625_50) ?
                  PAL_VBI_LINES : NTSC_VBI_LINES);
 
-       *size = (dev->width * height * 2 * 2);
-       if (0 == *count)
-               *count = CX231XX_DEF_VBI_BUF;
-
-       if (*count < CX231XX_MIN_BUF)
-               *count = CX231XX_MIN_BUF;
-
+       *nplanes = 1;
+       sizes[0] = (dev->width * height * 2 * 2);
        return 0;
 }
 
 /* This is called *without* dev->slock held; please keep it that way */
-static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       unsigned long flags = 0;
-       BUG_ON(in_interrupt());
-
-       /* We used to wait for the buffer to finish here, but this didn't work
-          because, as we were keeping the state as VIDEOBUF_QUEUED,
-          videobuf_queue_cancel marked it as finished for us.
-          (Also, it could wedge forever if the hardware was misconfigured.)
-
-          This should be safe; by the time we get here, the buffer isn't
-          queued anymore. If we ever start marking the buffers as
-          VIDEOBUF_ACTIVE, it won't be, though.
-        */
-       spin_lock_irqsave(&dev->vbi_mode.slock, flags);
-       if (dev->vbi_mode.bulk_ctl.buf == buf)
-               dev->vbi_mode.bulk_ctl.buf = NULL;
-       spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int
-vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                  enum v4l2_field field)
+static int vbi_buf_prepare(struct vb2_buffer *vb)
 {
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       int rc = 0, urb_init = 0;
+       struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue);
        u32 height = 0;
+       u32 size;
 
        height = ((dev->norm & V4L2_STD_625_50) ?
                  PAL_VBI_LINES : NTSC_VBI_LINES);
-       buf->vb.size = ((dev->width << 1) * height * 2);
+       size = ((dev->width << 1) * height * 2);
 
-       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+       if (vb2_plane_size(vb, 0) < size)
                return -EINVAL;
-
-       buf->vb.width = dev->width;
-       buf->vb.height = height;
-       buf->vb.field = field;
-       buf->vb.field = V4L2_FIELD_SEQ_TB;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       if (!dev->vbi_mode.bulk_ctl.num_bufs)
-               urb_init = 1;
-
-       if (urb_init) {
-               rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS,
-                                          CX231XX_NUM_VBI_BUFS,
-                                          dev->vbi_mode.alt_max_pkt_size[0],
-                                          cx231xx_isoc_vbi_copy);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
+       vb2_set_plane_payload(vb, 0, size);
        return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
 }
 
-static void
-vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void vbi_buf_queue(struct vb2_buffer *vb)
 {
+       struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue);
        struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
+           container_of(vb, struct cx231xx_buffer, vb.vb2_buf);
        struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq;
+       unsigned long flags;
 
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
+       spin_lock_irqsave(&dev->vbi_mode.slock, flags);
+       list_add_tail(&buf->list, &vidq->active);
+       spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
+}
+
+static void return_all_buffers(struct cx231xx *dev,
+                              enum vb2_buffer_state state)
+{
+       struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq;
+       struct cx231xx_buffer *buf, *node;
+       unsigned long flags;
 
+       spin_lock_irqsave(&dev->vbi_mode.slock, flags);
+       dev->vbi_mode.bulk_ctl.buf = NULL;
+       list_for_each_entry_safe(buf, node, &vidq->active, list) {
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
+       }
+       spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
 }
 
-static void vbi_buffer_release(struct videobuf_queue *vq,
-                              struct videobuf_buffer *vb)
+static int vbi_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
+       struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq;
+       int ret;
+
+       vidq->sequence = 0;
+       ret = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS,
+                                   CX231XX_NUM_VBI_BUFS,
+                                   dev->vbi_mode.alt_max_pkt_size[0],
+                                   cx231xx_isoc_vbi_copy);
+       if (ret)
+               return_all_buffers(dev, VB2_BUF_STATE_QUEUED);
+       return ret;
+}
 
+static void vbi_stop_streaming(struct vb2_queue *vq)
+{
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
 
-       free_buffer(vq, buf);
+       return_all_buffers(dev, VB2_BUF_STATE_ERROR);
 }
 
-const struct videobuf_queue_ops cx231xx_vbi_qops = {
-       .buf_setup   = vbi_buffer_setup,
-       .buf_prepare = vbi_buffer_prepare,
-       .buf_queue   = vbi_buffer_queue,
-       .buf_release = vbi_buffer_release,
+struct vb2_ops cx231xx_vbi_qops = {
+       .queue_setup = vbi_queue_setup,
+       .buf_prepare = vbi_buf_prepare,
+       .buf_queue = vbi_buf_queue,
+       .start_streaming = vbi_start_streaming,
+       .stop_streaming = vbi_stop_streaming,
+       .wait_prepare = vb2_ops_wait_prepare,
+       .wait_finish = vb2_ops_wait_finish,
 };
 
 /* ------------------------------------------------------------------
@@ -512,16 +479,15 @@ static inline void vbi_buffer_filled(struct cx231xx *dev,
                                     struct cx231xx_buffer *buf)
 {
        /* Advice that buffer was filled */
-       /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.i); */
+       /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.index); */
 
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       buf->vb.ts = ktime_get_ns();
+       buf->vb.sequence = dma_q->sequence++;
+       buf->vb.vb2_buf.timestamp = ktime_get_ns();
 
        dev->vbi_mode.bulk_ctl.buf = NULL;
 
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
+       list_del(&buf->list);
+       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
@@ -611,11 +577,11 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
        }
 
        /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
+       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list);
 
        /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0, (*buf)->vb.size);
+       outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0);
+       memset(outp, 0, vb2_plane_size(&(*buf)->vb.vb2_buf, 0));
 
        dev->vbi_mode.bulk_ctl.buf = *buf;
 
@@ -656,7 +622,7 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
        if (buf == NULL)
                return -EINVAL;
 
-       p_out_buffer = videobuf_to_vmalloc(&buf->vb);
+       p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 
        if (dma_q->bytes_left_in_line != _line_size) {
                current_line_bytes_copied =
index 7cddd62..0b21bee 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef _CX231XX_VBI_H
 #define _CX231XX_VBI_H
 
-extern const struct videobuf_queue_ops cx231xx_vbi_qops;
+extern struct vb2_ops cx231xx_vbi_qops;
 
 #define   NTSC_VBI_START_LINE 10       /* line 10 - 21 */
 #define   NTSC_VBI_END_LINE   21
index 9b51f07..69abafa 100644 (file)
@@ -58,10 +58,10 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CX231XX_VERSION);
 
-static unsigned int card[]     = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[]   = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int card[]     = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
+static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
+static unsigned int vbi_nr[]   = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
+static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = -1U };
 
 module_param_array(card, int, NULL, 0444);
 module_param_array(video_nr, int, NULL, 0444);
@@ -166,18 +166,19 @@ static inline void buffer_filled(struct cx231xx *dev,
                                 struct cx231xx_buffer *buf)
 {
        /* Advice that buffer was filled */
-       cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       buf->vb.ts = ktime_get_ns();
+       cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.vb2_buf.index);
+       buf->vb.sequence = dma_q->sequence++;
+       buf->vb.field = V4L2_FIELD_INTERLACED;
+       buf->vb.vb2_buf.timestamp = ktime_get_ns();
+       vb2_set_plane_payload(&buf->vb.vb2_buf, 0, dev->size);
 
        if (dev->USE_ISO)
                dev->video_mode.isoc_ctl.buf = NULL;
        else
                dev->video_mode.bulk_ctl.buf = NULL;
 
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
+       list_del(&buf->list);
+       vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 static inline void print_err_status(struct cx231xx *dev, int packet, int status)
@@ -241,11 +242,11 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
        }
 
        /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
+       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, list);
 
        /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0, (*buf)->vb.size);
+       outp = vb2_plane_vaddr(&(*buf)->vb.vb2_buf, 0);
+       memset(outp, 0, dev->size);
 
        if (dev->USE_ISO)
                dev->video_mode.isoc_ctl.buf = *buf;
@@ -653,7 +654,7 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
        if (buf == NULL)
                return -1;
 
-       p_out_buffer = videobuf_to_vmalloc(&buf->vb);
+       p_out_buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 
        current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line;
 
@@ -672,7 +673,7 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
        lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
                  bytes_to_copy : dma_q->bytes_left_in_line;
 
-       if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size))
+       if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + dev->size))
                return 0;
 
        /* The below copies the UYVY data straight into video buffer */
@@ -708,149 +709,98 @@ u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q)
        Videobuf operations
    ------------------------------------------------------------------*/
 
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+static int queue_setup(struct vb2_queue *vq,
+                      unsigned int *nbuffers, unsigned int *nplanes,
+                      unsigned int sizes[], struct device *alloc_devs[])
 {
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
 
-       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3;
-       if (0 == *count)
-               *count = CX231XX_DEF_BUF;
+       dev->size = (dev->width * dev->height * dev->format->depth + 7) >> 3;
 
-       if (*count < CX231XX_MIN_BUF)
-               *count = CX231XX_MIN_BUF;
+       if (vq->num_buffers + *nbuffers < CX231XX_MIN_BUF)
+               *nbuffers = CX231XX_MIN_BUF - vq->num_buffers;
 
-
-       cx231xx_enable_analog_tuner(dev);
+       if (*nplanes)
+               return sizes[0] < dev->size ? -EINVAL : 0;
+       *nplanes = 1;
+       sizes[0] = dev->size;
 
        return 0;
 }
 
-/* This is called *without* dev->slock held; please keep it that way */
-static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
+static void buffer_queue(struct vb2_buffer *vb)
 {
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       unsigned long flags = 0;
-
-       BUG_ON(in_interrupt());
-
-       /* We used to wait for the buffer to finish here, but this didn't work
-          because, as we were keeping the state as VIDEOBUF_QUEUED,
-          videobuf_queue_cancel marked it as finished for us.
-          (Also, it could wedge forever if the hardware was misconfigured.)
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb.vb2_buf);
+       struct cx231xx *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       unsigned long flags;
 
-          This should be safe; by the time we get here, the buffer isn't
-          queued anymore. If we ever start marking the buffers as
-          VIDEOBUF_ACTIVE, it won't be, though.
-        */
        spin_lock_irqsave(&dev->video_mode.slock, flags);
-       if (dev->USE_ISO) {
-               if (dev->video_mode.isoc_ctl.buf == buf)
-                       dev->video_mode.isoc_ctl.buf = NULL;
-       } else {
-               if (dev->video_mode.bulk_ctl.buf == buf)
-                       dev->video_mode.bulk_ctl.buf = NULL;
-       }
+       list_add_tail(&buf->list, &vidq->active);
        spin_unlock_irqrestore(&dev->video_mode.slock, flags);
-
-       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 void return_all_buffers(struct cx231xx *dev,
+                              enum vb2_buffer_state state)
 {
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       int rc = 0, urb_init = 0;
-
-       /* The only currently supported format is 16 bits/pixel */
-       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
-                       + 7) >> 3;
-       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       buf->vb.width = dev->width;
-       buf->vb.height = dev->height;
-       buf->vb.field = field;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       struct cx231xx_buffer *buf, *node;
+       unsigned long flags;
 
-       if (dev->USE_ISO) {
-               if (!dev->video_mode.isoc_ctl.num_bufs)
-                       urb_init = 1;
-       } else {
-               if (!dev->video_mode.bulk_ctl.num_bufs)
-                       urb_init = 1;
-       }
-       dev_dbg(dev->dev,
-               "urb_init=%d dev->video_mode.max_pkt_size=%d\n",
-               urb_init, dev->video_mode.max_pkt_size);
-       if (urb_init) {
-               dev->mode_tv = 0;
-               if (dev->USE_ISO)
-                       rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
-                                      CX231XX_NUM_BUFS,
-                                      dev->video_mode.max_pkt_size,
-                                      cx231xx_isoc_copy);
-               else
-                       rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
-                                      CX231XX_NUM_BUFS,
-                                      dev->video_mode.max_pkt_size,
-                                      cx231xx_bulk_copy);
-               if (rc < 0)
-                       goto fail;
+       spin_lock_irqsave(&dev->video_mode.slock, flags);
+       if (dev->USE_ISO)
+               dev->video_mode.isoc_ctl.buf = NULL;
+       else
+               dev->video_mode.bulk_ctl.buf = NULL;
+       list_for_each_entry_safe(buf, node, &vidq->active, list) {
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb.vb2_buf, state);
        }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
+       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
 }
 
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
 {
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
        struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+       int ret = 0;
 
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
+       vidq->sequence = 0;
+       dev->mode_tv = 0;
 
+       cx231xx_enable_analog_tuner(dev);
+       if (dev->USE_ISO)
+               ret = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
+                                       CX231XX_NUM_BUFS,
+                                       dev->video_mode.max_pkt_size,
+                                       cx231xx_isoc_copy);
+       else
+               ret = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
+                                       CX231XX_NUM_BUFS,
+                                       dev->video_mode.max_pkt_size,
+                                       cx231xx_bulk_copy);
+       if (ret)
+               return_all_buffers(dev, VB2_BUF_STATE_QUEUED);
+       call_all(dev, video, s_stream, 1);
+       return ret;
 }
 
-static void buffer_release(struct videobuf_queue *vq,
-                          struct videobuf_buffer *vb)
+static void stop_streaming(struct vb2_queue *vq)
 {
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = (struct cx231xx *)fh->dev;
-
-       cx231xx_isocdbg("cx231xx: called buffer_release\n");
+       struct cx231xx *dev = vb2_get_drv_priv(vq);
 
-       free_buffer(vq, buf);
+       call_all(dev, video, s_stream, 0);
+       return_all_buffers(dev, VB2_BUF_STATE_ERROR);
 }
 
-static const struct videobuf_queue_ops cx231xx_video_qops = {
-       .buf_setup = buffer_setup,
-       .buf_prepare = buffer_prepare,
-       .buf_queue = buffer_queue,
-       .buf_release = buffer_release,
+static struct vb2_ops cx231xx_video_qops = {
+       .queue_setup            = queue_setup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
 };
 
 /*********************  v4l2 interface  **************************************/
@@ -872,58 +822,6 @@ void video_mux(struct cx231xx *dev, int index)
        cx231xx_do_mode_ctrl_overrides(dev);
 }
 
-/* Usage lock check functions */
-static int res_get(struct cx231xx_fh *fh)
-{
-       struct cx231xx *dev = fh->dev;
-       int rc = 0;
-
-       /* This instance already has stream_on */
-       if (fh->stream_on)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (dev->stream_on)
-                       return -EBUSY;
-               dev->stream_on = 1;
-       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               if (dev->vbi_stream_on)
-                       return -EBUSY;
-               dev->vbi_stream_on = 1;
-       } else
-               return -EINVAL;
-
-       fh->stream_on = 1;
-
-       return rc;
-}
-
-static int res_check(struct cx231xx_fh *fh)
-{
-       return fh->stream_on;
-}
-
-static void res_free(struct cx231xx_fh *fh)
-{
-       struct cx231xx *dev = fh->dev;
-
-       fh->stream_on = 0;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               dev->stream_on = 0;
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               dev->vbi_stream_on = 0;
-}
-
-static int check_dev(struct cx231xx *dev)
-{
-       if (dev->state & DEV_DISCONNECTED) {
-               dev_err(dev->dev, "v4l2 ioctl: device not present\n");
-               return -ENODEV;
-       }
-       return 0;
-}
-
 /* ------------------------------------------------------------------
        IOCTL vidioc handling
    ------------------------------------------------------------------*/
@@ -931,8 +829,7 @@ static int check_dev(struct cx231xx *dev)
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        f->fmt.pix.width = dev->width;
        f->fmt.pix.height = dev->height;
@@ -960,8 +857,7 @@ static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc)
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                                  struct v4l2_format *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        unsigned int width = f->fmt.pix.width;
        unsigned int height = f->fmt.pix.height;
        unsigned int maxw = norm_maxw(dev);
@@ -993,39 +889,25 @@ 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 cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-       struct cx231xx_fmt *fmt;
+       struct cx231xx *dev = video_drvdata(file);
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
        };
+       int rc;
 
-       rc = check_dev(dev);
-       if (rc < 0)
+       rc = vidioc_try_fmt_vid_cap(file, priv, f);
+       if (rc)
                return rc;
 
-       vidioc_try_fmt_vid_cap(file, priv, f);
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt)
-               return -EINVAL;
-
-       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+       if (vb2_is_busy(&dev->vidq)) {
                dev_err(dev->dev, "%s: queue busy\n", __func__);
                return -EBUSY;
        }
 
-       if (dev->stream_on && !fh->stream_on) {
-               dev_err(dev->dev,
-                       "%s: device in use by another fh\n", __func__);
-               return -EBUSY;
-       }
-
        /* set new image size */
        dev->width = f->fmt.pix.width;
        dev->height = f->fmt.pix.height;
-       dev->format = fmt;
+       dev->format = format_by_fourcc(f->fmt.pix.pixelformat);
 
        v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
        call_all(dev, pad, set_fmt, NULL, &format);
@@ -1036,8 +918,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 
 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        *id = dev->norm;
        return 0;
@@ -1045,21 +926,15 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        struct v4l2_subdev_format format = {
                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
        };
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
 
        if (dev->norm == norm)
                return 0;
 
-       if (videobuf_queue_is_busy(&fh->vb_vidq))
+       if (vb2_is_busy(&dev->vidq))
                return -EBUSY;
 
        dev->norm = norm;
@@ -1141,8 +1016,7 @@ void cx231xx_v4l2_create_entities(struct cx231xx *dev)
 int cx231xx_enum_input(struct file *file, void *priv,
                             struct v4l2_input *i)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        u32 gen_stat;
        unsigned int n;
        int ret;
@@ -1181,8 +1055,7 @@ int cx231xx_enum_input(struct file *file, void *priv,
 
 int cx231xx_g_input(struct file *file, void *priv, unsigned int *i)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        *i = dev->video_input;
 
@@ -1191,14 +1064,9 @@ int cx231xx_g_input(struct file *file, void *priv, unsigned int *i)
 
 int cx231xx_s_input(struct file *file, void *priv, unsigned int i)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
+       struct cx231xx *dev = video_drvdata(file);
 
        dev->mode_tv = 0;
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
 
        if (i >= MAX_CX231XX_INPUT)
                return -EINVAL;
@@ -1220,13 +1088,7 @@ int cx231xx_s_input(struct file *file, void *priv, unsigned int i)
 
 int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
+       struct cx231xx *dev = video_drvdata(file);
 
        if (0 != t->index)
                return -EINVAL;
@@ -1244,27 +1106,15 @@ int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 
 int cx231xx_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
        if (0 != t->index)
                return -EINVAL;
-#if 0
-       call_all(dev, tuner, s_tuner, t);
-#endif
        return 0;
 }
 
 int cx231xx_g_frequency(struct file *file, void *priv,
                              struct v4l2_frequency *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        if (f->tuner)
                return -EINVAL;
@@ -1277,8 +1127,7 @@ int cx231xx_g_frequency(struct file *file, void *priv,
 int cx231xx_s_frequency(struct file *file, void *priv,
                              const struct v4l2_frequency *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        struct v4l2_frequency new_freq = *f;
        int rc;
        u32 if_frequency = 5400000;
@@ -1287,10 +1136,6 @@ int cx231xx_s_frequency(struct file *file, void *priv,
                "Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
                f->frequency, f->type);
 
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
        if (0 != f->tuner)
                return -EINVAL;
 
@@ -1365,8 +1210,7 @@ int cx231xx_g_chip_info(struct file *file, void *fh,
 int cx231xx_g_register(struct file *file, void *priv,
                             struct v4l2_dbg_register *reg)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        int ret;
        u8 value[4] = { 0, 0, 0, 0 };
        u32 data = 0;
@@ -1424,8 +1268,7 @@ int cx231xx_g_register(struct file *file, void *priv,
 int cx231xx_s_register(struct file *file, void *priv,
                             const struct v4l2_dbg_register *reg)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        int ret;
        u8 data[4] = { 0, 0, 0, 0 };
 
@@ -1472,8 +1315,7 @@ int cx231xx_s_register(struct file *file, void *priv,
 static int vidioc_g_pixelaspect(struct file *file, void *priv,
                                int type, struct v4l2_fract *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
        bool is_50hz = dev->norm & V4L2_STD_625_50;
 
        if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -1488,8 +1330,7 @@ static int vidioc_g_pixelaspect(struct file *file, void *priv,
 static int vidioc_g_selection(struct file *file, void *priv,
                              struct v4l2_selection *s)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
@@ -1508,54 +1349,10 @@ static int vidioc_g_selection(struct file *file, void *priv,
        return 0;
 }
 
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       rc = res_get(fh);
-
-       if (likely(rc >= 0))
-               rc = videobuf_streamon(&fh->vb_vidq);
-
-       call_all(dev, video, s_stream, 1);
-
-       return rc;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type type)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (type != fh->type)
-               return -EINVAL;
-
-       cx25840_call(dev, video, s_stream, 0);
-
-       videobuf_streamoff(&fh->vb_vidq);
-       res_free(fh);
-
-       return 0;
-}
-
 int cx231xx_querycap(struct file *file, void *priv,
                           struct v4l2_capability *cap)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        strscpy(cap->driver, "cx231xx", sizeof(cap->driver));
        strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
@@ -1587,8 +1384,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        f->fmt.vbi.sampling_rate = 6750000 * 4;
        f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
@@ -1610,8 +1406,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
                                  struct v4l2_format *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        f->fmt.vbi.sampling_rate = 6750000 * 4;
        f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
@@ -1634,77 +1429,16 @@ static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
 static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
                                  struct v4l2_format *f)
 {
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       if (dev->vbi_stream_on && !fh->stream_on) {
-               dev_err(dev->dev,
-                       "%s device in use by another fh\n", __func__);
-               return -EBUSY;
-       }
        return vidioc_try_fmt_vbi_cap(file, priv, f);
 }
 
-static int vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *rb)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_reqbufs(&fh->vb_vidq, rb);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_querybuf(&fh->vb_vidq, b);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_qbuf(&fh->vb_vidq, b);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
-}
-
 /* ----------------------------------------------------------- */
 /* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
 
 static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
-       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        if (t->index)
                return -EINVAL;
@@ -1717,7 +1451,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 }
 static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t)
 {
-       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+       struct cx231xx *dev = video_drvdata(file);
 
        if (t->index)
                return -EINVAL;
@@ -1733,52 +1467,20 @@ static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner
  */
 static int cx231xx_v4l2_open(struct file *filp)
 {
-       int radio = 0;
        struct video_device *vdev = video_devdata(filp);
        struct cx231xx *dev = video_drvdata(filp);
-       struct cx231xx_fh *fh;
-       enum v4l2_buf_type fh_type = 0;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       cx231xx_videodbg("open dev=%s type=%s users=%d\n",
-                        video_device_node_name(vdev), v4l2_type_names[fh_type],
-                        dev->users);
-
-#if 0
-       errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
-       if (errCode < 0) {
-               dev_err(dev->dev,
-                       "Device locked on digital mode. Can't open analog\n");
-               return -EBUSY;
-       }
-#endif
+       int ret;
 
-       fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
-       if (!fh)
-               return -ENOMEM;
-       if (mutex_lock_interruptible(&dev->lock)) {
-               kfree(fh);
+       if (mutex_lock_interruptible(&dev->lock))
                return -ERESTARTSYS;
+
+       ret = v4l2_fh_open(filp);
+       if (ret) {
+               mutex_unlock(&dev->lock);
+               return ret;
        }
-       fh->dev = dev;
-       fh->type = fh_type;
-       filp->private_data = fh;
-       v4l2_fh_init(&fh->fh, vdev);
 
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+       if (dev->users++ == 0) {
                /* Power up in Analog TV mode */
                if (dev->board.external_av)
                        cx231xx_set_power_mode(dev,
@@ -1786,10 +1488,6 @@ static int cx231xx_v4l2_open(struct file *filp)
                else
                        cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
 
-#if 0
-               cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
-#endif
-
                /* set video alternate setting */
                cx231xx_set_video_alternate(dev);
 
@@ -1799,38 +1497,21 @@ static int cx231xx_v4l2_open(struct file *filp)
 
                /* device needs to be initialized before isoc transfer */
                dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
-
        }
-       if (radio) {
+
+       if (vdev->vfl_type == VFL_TYPE_RADIO) {
                cx231xx_videodbg("video_open: setting radio device\n");
 
                /* cx231xx_start_radio(dev); */
 
                call_all(dev, tuner, s_radio);
        }
-
-       dev->users++;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops,
-                                           NULL, &dev->video_mode.slock,
-                                           fh->type, V4L2_FIELD_INTERLACED,
-                                           sizeof(struct cx231xx_buffer),
-                                           fh, &dev->lock);
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+       if (vdev->vfl_type == VFL_TYPE_VBI) {
                /* Set the required alternate setting  VBI interface works in
                   Bulk mode only */
                cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
-
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
-                                           NULL, &dev->vbi_mode.slock,
-                                           fh->type, V4L2_FIELD_SEQ_TB,
-                                           sizeof(struct cx231xx_buffer),
-                                           fh, &dev->lock);
        }
        mutex_unlock(&dev->lock);
-       v4l2_fh_add(&fh->fh);
-
        return 0;
 }
 
@@ -1871,68 +1552,12 @@ void cx231xx_release_analog_resources(struct cx231xx *dev)
  */
 static int cx231xx_close(struct file *filp)
 {
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       cx231xx_videodbg("users=%d\n", dev->users);
-
-       cx231xx_videodbg("users=%d\n", dev->users);
-       if (res_check(fh))
-               res_free(fh);
-
-       /*
-        * To workaround error number=-71 on EP0 for VideoGrabber,
-        *       need exclude following.
-        * FIXME: It is probably safe to remove most of these, as we're
-        * now avoiding the alternate setting for INDEX_VANC
-        */
-       if (!dev->board.no_alt_vanc)
-               if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-                       videobuf_stop(&fh->vb_vidq);
-                       videobuf_mmap_free(&fh->vb_vidq);
-
-                       /* the device is already disconnect,
-                          free the remaining resources */
-                       if (dev->state & DEV_DISCONNECTED) {
-                               if (atomic_read(&dev->devlist_count) > 0) {
-                                       cx231xx_release_resources(dev);
-                                       fh->dev = NULL;
-                                       return 0;
-                               }
-                               return 0;
-                       }
-
-                       /* do this before setting alternate! */
-                       cx231xx_uninit_vbi_isoc(dev);
-
-                       /* set alternate 0 */
-                       if (!dev->vbi_or_sliced_cc_mode)
-                               cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
-                       else
-                               cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
-
-                       v4l2_fh_del(&fh->fh);
-                       v4l2_fh_exit(&fh->fh);
-                       kfree(fh);
-                       dev->users--;
-                       wake_up_interruptible(&dev->open);
-                       return 0;
-               }
+       struct cx231xx *dev = video_drvdata(filp);
+       struct video_device *vdev = video_devdata(filp);
 
-       v4l2_fh_del(&fh->fh);
-       dev->users--;
-       if (!dev->users) {
-               videobuf_stop(&fh->vb_vidq);
-               videobuf_mmap_free(&fh->vb_vidq);
-
-               /* the device is already disconnect,
-                  free the remaining resources */
-               if (dev->state & DEV_DISCONNECTED) {
-                       cx231xx_release_resources(dev);
-                       fh->dev = NULL;
-                       return 0;
-               }
+       _vb2_fop_release(filp, NULL);
 
+       if (--dev->users == 0) {
                /* Save some power by putting tuner to sleep */
                call_all(dev, tuner, standby);
 
@@ -1942,20 +1567,40 @@ static int cx231xx_close(struct file *filp)
                else
                        cx231xx_uninit_bulk(dev);
                cx231xx_set_mode(dev, CX231XX_SUSPEND);
+       }
+
+       /*
+        * To workaround error number=-71 on EP0 for VideoGrabber,
+        *       need exclude following.
+        * FIXME: It is probably safe to remove most of these, as we're
+        * now avoiding the alternate setting for INDEX_VANC
+        */
+       if (!dev->board.no_alt_vanc && vdev->vfl_type == VFL_TYPE_VBI) {
+               /* do this before setting alternate! */
+               cx231xx_uninit_vbi_isoc(dev);
 
                /* set alternate 0 */
+               if (!dev->vbi_or_sliced_cc_mode)
+                       cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+               else
+                       cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
+
+               wake_up_interruptible_nr(&dev->open, 1);
+               return 0;
+       }
+
+       if (dev->users == 0) {
+               /* set alternate 0 */
                cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
        }
-       v4l2_fh_exit(&fh->fh);
-       kfree(fh);
+
        wake_up_interruptible(&dev->open);
        return 0;
 }
 
 static int cx231xx_v4l2_close(struct file *filp)
 {
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
+       struct cx231xx *dev = video_drvdata(filp);
        int rc;
 
        mutex_lock(&dev->lock);
@@ -1964,116 +1609,13 @@ static int cx231xx_v4l2_close(struct file *filp)
        return rc;
 }
 
-/*
- * cx231xx_v4l2_read()
- * will allocate buffers when called for the first time
- */
-static ssize_t
-cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
-                 loff_t *pos)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
-           (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
-               rc = res_get(fh);
-
-               if (unlikely(rc < 0))
-                       return rc;
-
-               if (mutex_lock_interruptible(&dev->lock))
-                       return -ERESTARTSYS;
-               rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
-                                           filp->f_flags & O_NONBLOCK);
-               mutex_unlock(&dev->lock);
-               return rc;
-       }
-       return 0;
-}
-
-/*
- * cx231xx_v4l2_poll()
- * will allocate buffers when called for the first time
- */
-static __poll_t cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
-{
-       __poll_t req_events = poll_requested_events(wait);
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       __poll_t res = 0;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return EPOLLERR;
-
-       rc = res_get(fh);
-
-       if (unlikely(rc < 0))
-               return EPOLLERR;
-
-       if (v4l2_event_pending(&fh->fh))
-               res |= EPOLLPRI;
-       else
-               poll_wait(filp, &fh->fh.wait, wait);
-
-       if (!(req_events & (EPOLLIN | EPOLLRDNORM)))
-               return res;
-
-       if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
-           (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) {
-               mutex_lock(&dev->lock);
-               res |= videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-               mutex_unlock(&dev->lock);
-               return res;
-       }
-       return res | EPOLLERR;
-}
-
-/*
- * cx231xx_v4l2_mmap()
- */
-static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       rc = res_get(fh);
-
-       if (unlikely(rc < 0))
-               return rc;
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-       mutex_unlock(&dev->lock);
-
-       cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
-                        (unsigned long)vma->vm_start,
-                        (unsigned long)vma->vm_end -
-                        (unsigned long)vma->vm_start, rc);
-
-       return rc;
-}
-
 static const struct v4l2_file_operations cx231xx_v4l_fops = {
        .owner   = THIS_MODULE,
        .open    = cx231xx_v4l2_open,
        .release = cx231xx_v4l2_close,
-       .read    = cx231xx_v4l2_read,
-       .poll    = cx231xx_v4l2_poll,
-       .mmap    = cx231xx_v4l2_mmap,
+       .read    = vb2_fop_read,
+       .poll    = vb2_fop_poll,
+       .mmap    = vb2_fop_mmap,
        .unlocked_ioctl   = video_ioctl2,
 };
 
@@ -2088,17 +1630,17 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_s_fmt_vbi_cap          = vidioc_s_fmt_vbi_cap,
        .vidioc_g_pixelaspect          = vidioc_g_pixelaspect,
        .vidioc_g_selection            = vidioc_g_selection,
-       .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             = cx231xx_enum_input,
        .vidioc_g_input                = cx231xx_g_input,
        .vidioc_s_input                = cx231xx_s_input,
-       .vidioc_streamon               = vidioc_streamon,
-       .vidioc_streamoff              = vidioc_streamoff,
+       .vidioc_streamon               = vb2_ioctl_streamon,
+       .vidioc_streamoff              = vb2_ioctl_streamoff,
        .vidioc_g_tuner                = cx231xx_g_tuner,
        .vidioc_s_tuner                = cx231xx_s_tuner,
        .vidioc_g_frequency            = cx231xx_g_frequency,
@@ -2175,6 +1717,7 @@ static void cx231xx_vdev_init(struct cx231xx *dev,
 
 int cx231xx_register_analog_devices(struct cx231xx *dev)
 {
+       struct vb2_queue *q;
        int ret;
 
        dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION);
@@ -2221,6 +1764,21 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
                dev_err(dev->dev, "failed to initialize video media entity!\n");
 #endif
        dev->vdev.ctrl_handler = &dev->ctrl_handler;
+
+       q = &dev->vidq;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ;
+       q->drv_priv = dev;
+       q->buf_struct_size = sizeof(struct cx231xx_buffer);
+       q->ops = &cx231xx_video_qops;
+       q->mem_ops = &vb2_vmalloc_memops;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->min_buffers_needed = 1;
+       q->lock = &dev->lock;
+       ret = vb2_queue_init(q);
+       if (ret)
+               return ret;
+       dev->vdev.queue = q;
        dev->vdev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
                                V4L2_CAP_VIDEO_CAPTURE;
        if (dev->tuner_type != TUNER_ABSENT)
@@ -2254,6 +1812,21 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
                dev_err(dev->dev, "failed to initialize vbi media entity!\n");
 #endif
        dev->vbi_dev.ctrl_handler = &dev->ctrl_handler;
+
+       q = &dev->vbiq;
+       q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       q->io_modes = VB2_USERPTR | VB2_MMAP | VB2_DMABUF | VB2_READ;
+       q->drv_priv = dev;
+       q->buf_struct_size = sizeof(struct cx231xx_buffer);
+       q->ops = &cx231xx_vbi_qops;
+       q->mem_ops = &vb2_vmalloc_memops;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       q->min_buffers_needed = 1;
+       q->lock = &dev->lock;
+       ret = vb2_queue_init(q);
+       if (ret)
+               return ret;
+       dev->vbi_dev.queue = q;
        dev->vbi_dev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
                                   V4L2_CAP_VBI_CAPTURE;
        if (dev->tuner_type != TUNER_ABSENT)
index b007611..b32eab6 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <media/drv-intf/cx2341x.h>
 
-#include <media/videobuf-vmalloc.h>
+#include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
@@ -223,8 +223,8 @@ struct cx231xx_fmt {
 /* buffer for one video frame */
 struct cx231xx_buffer {
        /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
+       struct vb2_v4l2_buffer vb;
+       struct list_head list;
        struct list_head frame;
        int top_field;
        int receiving;
@@ -237,7 +237,6 @@ enum ps_package_head {
 
 struct cx231xx_dmaqueue {
        struct list_head active;
-       struct list_head queued;
 
        wait_queue_head_t wq;
 
@@ -251,6 +250,7 @@ struct cx231xx_dmaqueue {
        u32 lines_completed;
        u8 field1_done;
        u32 lines_per_field;
+       u32 sequence;
 
        /*Mpeg2 control buffer*/
        u8 *p_left_data;
@@ -427,23 +427,6 @@ struct cx231xx_audio {
 
 struct cx231xx;
 
-struct cx231xx_fh {
-       struct v4l2_fh fh;
-       struct cx231xx *dev;
-       unsigned int stream_on:1;       /* Locks streams */
-       enum v4l2_buf_type type;
-
-       struct videobuf_queue vb_vidq;
-
-       /* vbi capture */
-       struct videobuf_queue      vidq;
-       struct videobuf_queue      vbiq;
-
-       /* MPEG Encoder specifics ONLY */
-
-       atomic_t                   v4l_reading;
-};
-
 /*****************************************************************/
 /* set/get i2c */
 /* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */
@@ -634,6 +617,7 @@ struct cx231xx {
        int width;              /* current frame width */
        int height;             /* current frame height */
        int interlaced;         /* 1=interlace fields, 0=just top fields */
+       unsigned int size;
 
        struct cx231xx_audio adev;
 
@@ -657,6 +641,9 @@ struct cx231xx {
        struct media_pad input_pad[MAX_CX231XX_INPUT];
 #endif
 
+       struct vb2_queue vidq;
+       struct vb2_queue vbiq;
+
        unsigned char eedata[256];
 
        struct cx231xx_video_mode video_mode;
@@ -717,6 +704,7 @@ struct cx231xx {
        u8 USE_ISO;
        struct cx231xx_tvnorm      encodernorm;
        struct cx231xx_tsport      ts1, ts2;
+       struct vb2_queue           mpegq;
        struct video_device        v4l_device;
        atomic_t                   v4l_reader_count;
        u32                        freq;