#define MP4_QS                 16
 #define DMA_ALIGN              4096
 
-enum solo_enc_types {
-       SOLO_ENC_TYPE_STD,
-       SOLO_ENC_TYPE_EXT,
-};
-
-struct solo_enc_fh {
-       struct v4l2_fh          fh;
-       struct solo_enc_dev     *enc;
-       u32                     fmt;
-       u8                      enc_on;
-       enum solo_enc_types     type;
-       struct videobuf_queue   vidq;
-       struct list_head        vidq_active;
-       int                     desc_count;
-       int                     desc_nelts;
-       struct solo_p2m_desc    *desc_items;
-       dma_addr_t              desc_dma;
-       spinlock_t              av_lock;
-       struct list_head        list;
-};
-
 struct solo_videobuf {
        struct videobuf_buffer  vb;
        unsigned int            flags;
 }
 
 /* MUST be called with solo_enc->enable_lock held */
-static int __solo_enc_on(struct solo_enc_fh *fh)
+static int __solo_enc_on(struct solo_enc_dev *solo_enc)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
        u8 ch = solo_enc->ch;
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        u8 interval;
 
        BUG_ON(!mutex_is_locked(&solo_enc->enable_lock));
 
-       if (fh->enc_on)
+       if (solo_enc->enc_on)
                return 0;
 
        solo_update_mode(solo_enc);
                        solo_dev->enc_bw_remain -= solo_enc->bw_weight;
        }
 
-       fh->enc_on = 1;
-       list_add(&fh->list, &solo_enc->listeners);
+       solo_enc->enc_on = 1;
 
-       if (fh->type == SOLO_ENC_TYPE_EXT)
+       if (solo_enc->type == SOLO_ENC_TYPE_EXT)
                solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
 
        /* Reset the encoder if we are the first mpeg reader, else only reset
         * on the first mjpeg reader. */
-       if (fh->fmt == V4L2_PIX_FMT_MPEG) {
+       if (solo_enc->fmt == V4L2_PIX_FMT_MPEG) {
                atomic_inc(&solo_enc->readers);
                if (atomic_inc_return(&solo_enc->mpeg_readers) > 1)
                        return 0;
        return 0;
 }
 
-static int solo_enc_on(struct solo_enc_fh *fh)
+static int solo_enc_on(struct solo_enc_dev *solo_enc)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
        int ret;
 
        mutex_lock(&solo_enc->enable_lock);
-       ret = __solo_enc_on(fh);
+       ret = __solo_enc_on(solo_enc);
        mutex_unlock(&solo_enc->enable_lock);
 
        return ret;
 }
 
-static void __solo_enc_off(struct solo_enc_fh *fh)
+static void __solo_enc_off(struct solo_enc_dev *solo_enc)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
        struct solo_dev *solo_dev = solo_enc->solo_dev;
 
        BUG_ON(!mutex_is_locked(&solo_enc->enable_lock));
 
-       if (!fh->enc_on)
+       if (!solo_enc->enc_on)
                return;
 
-       list_del(&fh->list);
-       fh->enc_on = 0;
+       solo_enc->enc_on = 0;
 
-       if (fh->fmt == V4L2_PIX_FMT_MPEG)
+       if (solo_enc->fmt == V4L2_PIX_FMT_MPEG)
                atomic_dec(&solo_enc->mpeg_readers);
 
        if (atomic_dec_return(&solo_enc->readers) > 0)
        solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
 }
 
-static void solo_enc_off(struct solo_enc_fh *fh)
+static void solo_enc_off(struct solo_enc_dev *solo_enc)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
-
        mutex_lock(&solo_enc->enable_lock);
-       __solo_enc_off(fh);
+       __solo_enc_off(solo_enc);
        mutex_unlock(&solo_enc->enable_lock);
 }
 
 
 /* Build a descriptor queue out of an SG list and send it to the P2M for
  * processing. */
-static int solo_send_desc(struct solo_enc_fh *fh, int skip,
+static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
                          struct videobuf_dmabuf *vbuf, int off, int size,
                          unsigned int base, unsigned int base_size)
 {
-       struct solo_dev *solo_dev = fh->enc->solo_dev;
+       struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct scatterlist *sg;
        int i;
        int ret;
        if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
                return -EINVAL;
 
-       fh->desc_count = 1;
+       solo_enc->desc_count = 1;
 
        for_each_sg(vbuf->sglist, sg, vbuf->sglen, i) {
                struct solo_p2m_desc *desc;
                int len;
                int left = base_size - off;
 
-               desc = &fh->desc_items[fh->desc_count++];
+               desc = &solo_enc->desc_items[solo_enc->desc_count++];
                dma = sg_dma_address(sg);
                len = sg_dma_len(sg);
 
                        if (ret)
                                return ret;
 
-                       fh->desc_count--;
+                       solo_enc->desc_count--;
                }
 
                size -= len;
                        off -= base_size;
 
                /* Because we may use two descriptors per loop */
-               if (fh->desc_count >= (fh->desc_nelts - 1)) {
-                       ret = solo_p2m_dma_desc(solo_dev, fh->desc_items,
-                                               fh->desc_dma,
-                                               fh->desc_count - 1);
+               if (solo_enc->desc_count >= (solo_enc->desc_nelts - 1)) {
+                       ret = solo_p2m_dma_desc(solo_dev, solo_enc->desc_items,
+                                               solo_enc->desc_dma,
+                                               solo_enc->desc_count - 1);
                        if (ret)
                                return ret;
-                       fh->desc_count = 1;
+                       solo_enc->desc_count = 1;
                }
        }
 
-       if (fh->desc_count <= 1)
+       if (solo_enc->desc_count <= 1)
                return 0;
 
-       return solo_p2m_dma_desc(solo_dev, fh->desc_items, fh->desc_dma,
-                                fh->desc_count - 1);
+       return solo_p2m_dma_desc(solo_dev, solo_enc->desc_items, solo_enc->desc_dma,
+                                solo_enc->desc_count - 1);
 }
 
-static int solo_fill_jpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb,
+static int solo_fill_jpeg(struct solo_enc_dev *solo_enc, struct videobuf_buffer *vb,
                          struct videobuf_dmabuf *vbuf, struct vop_header *vh)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct solo_videobuf *svb = (struct solo_videobuf *)vb;
        int frame_size;
        frame_size = (vh->jpeg_size + solo_enc->jpeg_len + (DMA_ALIGN - 1))
                & ~(DMA_ALIGN - 1);
 
-       return solo_send_desc(fh, solo_enc->jpeg_len, vbuf, vh->jpeg_off,
+       return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, vh->jpeg_off,
                              frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
                              SOLO_JPEG_EXT_SIZE(solo_dev));
 }
 
-static int solo_fill_mpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb,
+static int solo_fill_mpeg(struct solo_enc_dev *solo_enc, struct videobuf_buffer *vb,
                          struct videobuf_dmabuf *vbuf, struct vop_header *vh)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct solo_videobuf *svb = (struct solo_videobuf *)vb;
        int frame_off, frame_size;
        frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1))
                & ~(DMA_ALIGN - 1);
 
-       return solo_send_desc(fh, skip, vbuf, frame_off, frame_size,
+       return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
                              SOLO_MP4E_EXT_ADDR(solo_dev),
                              SOLO_MP4E_EXT_SIZE(solo_dev));
 }
 
-static int solo_enc_fillbuf(struct solo_enc_fh *fh,
+static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
                            struct videobuf_buffer *vb,
                            struct solo_enc_buf *enc_buf)
 {
-       struct solo_enc_dev *solo_enc = fh->enc;
        struct solo_videobuf *svb = (struct solo_videobuf *)vb;
        struct videobuf_dmabuf *vbuf = NULL;
        struct vop_header *vh = enc_buf->vh;
                        svb->flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
        }
 
-       if (fh->fmt == V4L2_PIX_FMT_MPEG)
-               ret = solo_fill_mpeg(fh, vb, vbuf, vh);
+       if (solo_enc->fmt == V4L2_PIX_FMT_MPEG)
+               ret = solo_fill_mpeg(solo_enc, vb, vbuf, vh);
        else
-               ret = solo_fill_jpeg(fh, vb, vbuf, vh);
+               ret = solo_fill_jpeg(solo_enc, vb, vbuf, vh);
 
 vbuf_error:
        /* On error, we push this buffer back into the queue. The
        if (ret) {
                unsigned long flags;
 
-               spin_lock_irqsave(&fh->av_lock, flags);
-               list_add(&vb->queue, &fh->vidq_active);
+               spin_lock_irqsave(&solo_enc->av_lock, flags);
+               list_add(&vb->queue, &solo_enc->vidq_active);
                vb->state = VIDEOBUF_QUEUED;
-               spin_unlock_irqrestore(&fh->av_lock, flags);
+               spin_unlock_irqrestore(&solo_enc->av_lock, flags);
        } else {
                vb->state = VIDEOBUF_DONE;
                vb->field_count++;
 static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
                                struct solo_enc_buf *enc_buf)
 {
-       struct solo_enc_fh *fh;
+       struct videobuf_buffer *vb;
+       unsigned long flags;
 
        mutex_lock(&solo_enc->enable_lock);
 
-       list_for_each_entry(fh, &solo_enc->listeners, list) {
-               struct videobuf_buffer *vb;
-               unsigned long flags;
-
-               if (fh->type != enc_buf->type)
-                       continue;
-
-
-               if (list_empty(&fh->vidq_active))
-                       continue;
+       if (solo_enc->type != enc_buf->type)
+               goto unlock;
 
-               spin_lock_irqsave(&fh->av_lock, flags);
+       if (list_empty(&solo_enc->vidq_active))
+               goto unlock;
 
-               vb = list_first_entry(&fh->vidq_active,
-                                     struct videobuf_buffer, queue);
+       spin_lock_irqsave(&solo_enc->av_lock, flags);
 
-               list_del(&vb->queue);
-               vb->state = VIDEOBUF_ACTIVE;
+       vb = list_first_entry(&solo_enc->vidq_active,
+                       struct videobuf_buffer, queue);
 
-               spin_unlock_irqrestore(&fh->av_lock, flags);
+       list_del(&vb->queue);
+       vb->state = VIDEOBUF_ACTIVE;
 
-               solo_enc_fillbuf(fh, vb, enc_buf);
-       }
+       spin_unlock_irqrestore(&solo_enc->av_lock, flags);
 
+       solo_enc_fillbuf(solo_enc, vb, enc_buf);
+unlock:
        mutex_unlock(&solo_enc->enable_lock);
 }
 
 static void solo_enc_buf_queue(struct videobuf_queue *vq,
                               struct videobuf_buffer *vb)
 {
-       struct solo_enc_fh *fh = vq->priv_data;
+       struct solo_enc_dev *solo_enc = vq->priv_data;
 
        vb->state = VIDEOBUF_QUEUED;
-       list_add_tail(&vb->queue, &fh->vidq_active);
+       list_add_tail(&vb->queue, &solo_enc->vidq_active);
 }
 
 static void solo_enc_buf_release(struct videobuf_queue *vq,
 static unsigned int solo_enc_poll(struct file *file,
                                  struct poll_table_struct *wait)
 {
-       struct solo_enc_fh *fh = file->private_data;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        unsigned long req_events = poll_requested_events(wait);
        unsigned res = v4l2_ctrl_poll(file, wait);
 
        if (!(req_events & (POLLIN | POLLRDNORM)))
                return res;
-       return videobuf_poll_stream(file, &fh->vidq, wait);
+       return videobuf_poll_stream(file, &solo_enc->vidq, wait);
 }
 
 static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct solo_enc_fh *fh = file->private_data;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-       return videobuf_mmap_mapper(&fh->vidq, vma);
+       return videobuf_mmap_mapper(&solo_enc->vidq, vma);
 }
 
 static int solo_ring_start(struct solo_dev *solo_dev)
 {
        struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
-       struct solo_enc_fh *fh;
-       int ret;
+       int ret = v4l2_fh_open(file);
 
-       ret = solo_ring_start(solo_dev);
        if (ret)
                return ret;
-
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (fh == NULL) {
-               solo_ring_stop(solo_dev);
-               return -ENOMEM;
-       }
-
-       fh->desc_nelts = 32;
-       fh->desc_items = pci_alloc_consistent(solo_dev->pdev,
-                                     sizeof(struct solo_p2m_desc) *
-                                     fh->desc_nelts, &fh->desc_dma);
-       if (fh->desc_items == NULL) {
-               kfree(fh);
-               solo_ring_stop(solo_dev);
-               return -ENOMEM;
+       ret = solo_ring_start(solo_dev);
+       if (ret) {
+               v4l2_fh_release(file);
+               return ret;
        }
-
-       v4l2_fh_init(&fh->fh, video_devdata(file));
-       fh->enc = solo_enc;
-       spin_lock_init(&fh->av_lock);
-       file->private_data = fh;
-       INIT_LIST_HEAD(&fh->vidq_active);
-       fh->fmt = V4L2_PIX_FMT_MPEG;
-       fh->type = SOLO_ENC_TYPE_STD;
-
-       videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops,
-                               &solo_dev->pdev->dev,
-                               &fh->av_lock,
-                               V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                               V4L2_FIELD_INTERLACED,
-                               sizeof(struct solo_videobuf),
-                               fh, NULL);
-       v4l2_fh_add(&fh->fh);
        return 0;
 }
 
 static ssize_t solo_enc_read(struct file *file, char __user *data,
                             size_t count, loff_t *ppos)
 {
-       struct solo_enc_fh *fh = file->private_data;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        int ret;
 
        /* Make sure the encoder is on */
-       ret = solo_enc_on(fh);
+       ret = solo_enc_on(solo_enc);
        if (ret)
                return ret;
 
-       return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
+       return videobuf_read_stream(&solo_enc->vidq, data, count, ppos, 0,
                                    file->f_flags & O_NONBLOCK);
 }
 
 static int solo_enc_release(struct file *file)
 {
-       struct solo_enc_fh *fh = file->private_data;
-       struct solo_dev *solo_dev = fh->enc->solo_dev;
-
-       solo_enc_off(fh);
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-
-       videobuf_stop(&fh->vidq);
-       videobuf_mmap_free(&fh->vidq);
-
-       pci_free_consistent(fh->enc->solo_dev->pdev,
-                           sizeof(struct solo_p2m_desc) *
-                           fh->desc_nelts, fh->desc_items, fh->desc_dma);
-
-       kfree(fh);
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
+       struct solo_dev *solo_dev = solo_enc->solo_dev;
 
+       solo_enc_off(solo_enc);
+       videobuf_stop(&solo_enc->vidq);
+       videobuf_mmap_free(&solo_enc->vidq);
        solo_ring_stop(solo_dev);
 
-       return 0;
+       return v4l2_fh_release(file);
 }
 
 static int solo_enc_querycap(struct file *file, void  *priv,
                             struct v4l2_capability *cap)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
 
        strcpy(cap->driver, SOLO6X10_NAME);
 static int solo_enc_enum_input(struct file *file, void *priv,
                               struct v4l2_input *input)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
 
        if (input->index)
 static int solo_enc_try_fmt_cap(struct file *file, void *priv,
                            struct v4l2_format *f)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct v4l2_pix_format *pix = &f->fmt.pix;
 
 static int solo_enc_set_fmt_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct v4l2_pix_format *pix = &f->fmt.pix;
        int ret;
                solo_enc->mode = SOLO_ENC_MODE_CIF;
 
        /* This does not change the encoder at all */
-       fh->fmt = pix->pixelformat;
+       solo_enc->fmt = pix->pixelformat;
 
        if (pix->priv)
-               fh->type = SOLO_ENC_TYPE_EXT;
+               solo_enc->type = SOLO_ENC_TYPE_EXT;
 
        mutex_unlock(&solo_enc->enable_lock);
 
 static int solo_enc_get_fmt_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct v4l2_pix_format *pix = &f->fmt.pix;
 
        pix->width = solo_enc->width;
        pix->height = solo_enc->height;
-       pix->pixelformat = fh->fmt;
+       pix->pixelformat = solo_enc->fmt;
        pix->field = solo_enc->interlaced ? V4L2_FIELD_INTERLACED :
                     V4L2_FIELD_NONE;
        pix->sizeimage = FRAME_BUF_SIZE;
 static int solo_enc_reqbufs(struct file *file, void *priv,
                            struct v4l2_requestbuffers *req)
 {
-       struct solo_enc_fh *fh = priv;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-       return videobuf_reqbufs(&fh->vidq, req);
+       return videobuf_reqbufs(&solo_enc->vidq, req);
 }
 
 static int solo_enc_querybuf(struct file *file, void *priv,
                             struct v4l2_buffer *buf)
 {
-       struct solo_enc_fh *fh = priv;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-       return videobuf_querybuf(&fh->vidq, buf);
+       return videobuf_querybuf(&solo_enc->vidq, buf);
 }
 
 static int solo_enc_qbuf(struct file *file, void *priv,
                         struct v4l2_buffer *buf)
 {
-       struct solo_enc_fh *fh = priv;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
 
-       return videobuf_qbuf(&fh->vidq, buf);
+       return videobuf_qbuf(&solo_enc->vidq, buf);
 }
 
 static int solo_enc_dqbuf(struct file *file, void *priv,
                          struct v4l2_buffer *buf)
 {
-       struct solo_enc_fh *fh = priv;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_videobuf *svb;
        int ret;
 
        /* Make sure the encoder is on */
-       ret = solo_enc_on(fh);
+       ret = solo_enc_on(solo_enc);
        if (ret)
                return ret;
 
-       ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
+       ret = videobuf_dqbuf(&solo_enc->vidq, buf, file->f_flags & O_NONBLOCK);
        if (ret)
                return ret;
 
        /* Copy over the flags */
-       svb = (struct solo_videobuf *)fh->vidq.bufs[buf->index];
+       svb = (struct solo_videobuf *)solo_enc->vidq.bufs[buf->index];
        buf->flags |= svb->flags;
 
        return 0;
 static int solo_enc_streamon(struct file *file, void *priv,
                             enum v4l2_buf_type i)
 {
-       struct solo_enc_fh *fh = priv;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
 
        if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       return videobuf_streamon(&fh->vidq);
+       return videobuf_streamon(&solo_enc->vidq);
 }
 
 static int solo_enc_streamoff(struct file *file, void *priv,
                              enum v4l2_buf_type i)
 {
-       struct solo_enc_fh *fh = priv;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        int ret;
 
        if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       ret = videobuf_streamoff(&fh->vidq);
+       ret = videobuf_streamoff(&solo_enc->vidq);
        if (!ret)
-               solo_enc_off(fh);
+               solo_enc_off(solo_enc);
 
        return ret;
 }
 static int solo_enum_framesizes(struct file *file, void *priv,
                                struct v4l2_frmsizeenum *fsize)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_dev *solo_dev = fh->enc->solo_dev;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
+       struct solo_dev *solo_dev = solo_enc->solo_dev;
 
        if (fsize->pixel_format != V4L2_PIX_FMT_MPEG &&
            fsize->pixel_format != V4L2_PIX_FMT_MJPEG)
 static int solo_enum_frameintervals(struct file *file, void *priv,
                                    struct v4l2_frmivalenum *fintv)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_dev *solo_dev = fh->enc->solo_dev;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
+       struct solo_dev *solo_dev = solo_enc->solo_dev;
 
        if (fintv->pixel_format != V4L2_PIX_FMT_MPEG &&
            fintv->pixel_format != V4L2_PIX_FMT_MJPEG)
 static int solo_g_parm(struct file *file, void *priv,
                       struct v4l2_streamparm *sp)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct v4l2_captureparm *cp = &sp->parm.capture;
 
 static int solo_s_parm(struct file *file, void *priv,
                       struct v4l2_streamparm *sp)
 {
-       struct solo_enc_fh *fh = priv;
-       struct solo_enc_dev *solo_enc = fh->enc;
+       struct solo_enc_dev *solo_enc = video_drvdata(file);
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct v4l2_captureparm *cp = &sp->parm.capture;
 
        v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
        if (hdl->error) {
                ret = hdl->error;
-               v4l2_ctrl_handler_free(hdl);
-               kfree(solo_enc);
-               return ERR_PTR(ret);
-       }
-
-       solo_enc->vfd = video_device_alloc();
-       if (!solo_enc->vfd) {
-               v4l2_ctrl_handler_free(hdl);
-               kfree(solo_enc);
-               return ERR_PTR(-ENOMEM);
+               goto hdl_free;
        }
 
        solo_enc->solo_dev = solo_dev;
        solo_enc->ch = ch;
-
-       *solo_enc->vfd = solo_enc_template;
-       solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
-       solo_enc->vfd->ctrl_handler = hdl;
-       set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
-       ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
-       if (ret < 0) {
-               video_device_release(solo_enc->vfd);
-               v4l2_ctrl_handler_free(hdl);
-               kfree(solo_enc);
-               return ERR_PTR(ret);
-       }
-
-       video_set_drvdata(solo_enc->vfd, solo_enc);
-
-       snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
-                "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
-                solo_enc->vfd->num);
-
-       INIT_LIST_HEAD(&solo_enc->listeners);
-       mutex_init(&solo_enc->enable_lock);
-       spin_lock_init(&solo_enc->motion_lock);
+       spin_lock_init(&solo_enc->av_lock);
+       INIT_LIST_HEAD(&solo_enc->vidq_active);
+       solo_enc->fmt = V4L2_PIX_FMT_MPEG;
+       solo_enc->type = SOLO_ENC_TYPE_STD;
 
        atomic_set(&solo_enc->readers, 0);
-       atomic_set(&solo_enc->mpeg_readers, 0);
 
        solo_enc->qp = SOLO_DEFAULT_QP;
        solo_enc->gop = solo_dev->fps;
        solo_enc->mode = SOLO_ENC_MODE_CIF;
        solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
 
-       mutex_lock(&solo_enc->enable_lock);
+       spin_lock(&solo_enc->av_lock);
        solo_update_mode(solo_enc);
-       mutex_unlock(&solo_enc->enable_lock);
+       spin_unlock(&solo_enc->av_lock);
+
+       mutex_init(&solo_enc->enable_lock);
+       spin_lock_init(&solo_enc->motion_lock);
+
+       atomic_set(&solo_enc->readers, 0);
+       atomic_set(&solo_enc->mpeg_readers, 0);
 
        /* Initialize this per encoder */
        solo_enc->jpeg_len = sizeof(jpeg_header);
        memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
 
+       solo_enc->desc_nelts = 32;
+       solo_enc->desc_items = pci_alloc_consistent(solo_dev->pdev,
+                                     sizeof(struct solo_p2m_desc) *
+                                     solo_enc->desc_nelts, &solo_enc->desc_dma);
+       ret = -ENOMEM;
+       if (solo_enc->desc_items == NULL)
+               goto hdl_free;
+
+       videobuf_queue_sg_init(&solo_enc->vidq, &solo_enc_video_qops,
+                               &solo_dev->pdev->dev,
+                               &solo_enc->av_lock,
+                               V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                               V4L2_FIELD_INTERLACED,
+                               sizeof(struct solo_videobuf),
+                               solo_enc, NULL);
+
+       solo_enc->vfd = video_device_alloc();
+       if (!solo_enc->vfd)
+               goto pci_free;
+
+       *solo_enc->vfd = solo_enc_template;
+       solo_enc->vfd->v4l2_dev = &solo_dev->v4l2_dev;
+       solo_enc->vfd->ctrl_handler = hdl;
+       set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
+       video_set_drvdata(solo_enc->vfd, solo_enc);
+       ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
+       if (ret < 0)
+               goto vdev_release;
+
+       snprintf(solo_enc->vfd->name, sizeof(solo_enc->vfd->name),
+                "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
+                solo_enc->vfd->num);
+
        return solo_enc;
+
+vdev_release:
+       video_device_release(solo_enc->vfd);
+pci_free:
+       pci_free_consistent(solo_enc->solo_dev->pdev,
+                       sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
+                       solo_enc->desc_items, solo_enc->desc_dma);
+hdl_free:
+       v4l2_ctrl_handler_free(hdl);
+       kfree(solo_enc);
+       return ERR_PTR(ret);
 }
 
 static void solo_enc_free(struct solo_enc_dev *solo_enc)
                        solo_enc_free(solo_dev->v4l2_enc[i]);
                pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
                                    solo_dev->vh_buf, solo_dev->vh_dma);
+               solo_dev->vh_buf = NULL;
                return ret;
        }
 
        for (i = 0; i < solo_dev->nr_chans; i++)
                solo_enc_free(solo_dev->v4l2_enc[i]);
 
-       pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
+       if (solo_dev->vh_buf)
+               pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
                            solo_dev->vh_buf, solo_dev->vh_dma);
 }