[media] media i.MX27 camera: migrate driver to videobuf2
authorJavier Martin <javier.martin@vista-silicon.com>
Mon, 30 Jan 2012 12:14:10 +0000 (09:14 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 8 Mar 2012 12:37:52 +0000 (09:37 -0300)
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/mx2_camera.c

index f771f53b2998891ec3d4a739b4d4de4bf4fbe966..22f5dbcf6db83aea681528ca8f74136a1ddb26eb 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2008, Sascha Hauer, Pengutronix
  * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography
+ * Copyright (C) 2012, Javier Martin, Vista Silicon S.L.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,8 +31,8 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
-#include <media/videobuf-core.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
 
@@ -221,6 +222,22 @@ struct mx2_fmt_cfg {
        struct mx2_prp_cfg              cfg;
 };
 
+enum mx2_buffer_state {
+       MX2_STATE_QUEUED,
+       MX2_STATE_ACTIVE,
+       MX2_STATE_DONE,
+};
+
+/* buffer for one video frame */
+struct mx2_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_buffer               vb;
+       struct list_head                queue;
+       enum mx2_buffer_state           state;
+
+       int bufnum;
+};
+
 struct mx2_camera_dev {
        struct device           *dev;
        struct soc_camera_host  soc_host;
@@ -252,16 +269,7 @@ struct mx2_camera_dev {
        size_t                  discard_size;
        struct mx2_fmt_cfg      *emma_prp;
        u32                     frame_count;
-};
-
-/* buffer for one video frame */
-struct mx2_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer          vb;
-
-       enum v4l2_mbus_pixelcode        code;
-
-       int bufnum;
+       struct vb2_alloc_ctx    *alloc_ctx;
 };
 
 static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
@@ -398,7 +406,7 @@ static void mx2_camera_remove_device(struct soc_camera_device *icd)
 static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
                int state)
 {
-       struct videobuf_buffer *vb;
+       struct vb2_buffer *vb;
        struct mx2_buffer *buf;
        struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active :
                &pcdev->fb2_active;
@@ -411,25 +419,24 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
                goto out;
 
        vb = &(*fb_active)->vb;
-       dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-               vb, vb->baddr, vb->bsize);
+       dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
-       vb->state = state;
-       do_gettimeofday(&vb->ts);
-       vb->field_count++;
-
-       wake_up(&vb->done);
+       do_gettimeofday(&vb->v4l2_buf.timestamp);
+       vb->v4l2_buf.sequence++;
+       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 
        if (list_empty(&pcdev->capture)) {
                buf = NULL;
                writel(0, pcdev->base_csi + fb_reg);
        } else {
                buf = list_entry(pcdev->capture.next, struct mx2_buffer,
-                               vb.queue);
+                               queue);
                vb = &buf->vb;
-               list_del(&vb->queue);
-               vb->state = VIDEOBUF_ACTIVE;
-               writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg);
+               list_del(&buf->queue);
+               buf->state = MX2_STATE_ACTIVE;
+               writel(vb2_dma_contig_plane_dma_addr(vb, 0),
+                      pcdev->base_csi + fb_reg);
        }
 
        *fb_active = buf;
@@ -444,9 +451,9 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
        u32 status = readl(pcdev->base_csi + CSISR);
 
        if (status & CSISR_DMA_TSF_FB1_INT)
-               mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE);
+               mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE);
        else if (status & CSISR_DMA_TSF_FB2_INT)
-               mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE);
+               mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE);
 
        /* FIXME: handle CSISR_RFF_OR_INT */
 
@@ -458,59 +465,50 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data)
 /*
  *  Videobuf operations
  */
-static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
-                             unsigned int *size)
+static int mx2_videobuf_setup(struct vb2_queue *vq,
+                       const struct v4l2_format *fmt,
+                       unsigned int *count, unsigned int *num_planes,
+                       unsigned int sizes[], void *alloc_ctxs[])
 {
-       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       struct mx2_camera_dev *pcdev = ici->priv;
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
 
-       dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
+       dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]);
+
+       /* TODO: support for VIDIOC_CREATE_BUFS not ready */
+       if (fmt != NULL)
+               return -ENOTTY;
 
        if (bytes_per_line < 0)
                return bytes_per_line;
 
-       *size = bytes_per_line * icd->user_height;
+       alloc_ctxs[0] = pcdev->alloc_ctx;
+
+       sizes[0] = bytes_per_line * icd->user_height;
 
        if (0 == *count)
                *count = 32;
-       if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
-               *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
+       if (!*num_planes &&
+           sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
+               *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0];
 
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf)
-{
-       struct soc_camera_device *icd = vq->priv_data;
-       struct videobuf_buffer *vb = &buf->vb;
+       *num_planes = 1;
 
-       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-               vb, vb->baddr, vb->bsize);
-
-       /*
-        * This waits until this buffer is out of danger, i.e., until it is no
-        * longer in state VIDEOBUF_QUEUED or VIDEOBUF_ACTIVE
-        */
-       videobuf_waiton(vq, vb, 0, 0);
-
-       videobuf_dma_contig_free(vq, vb);
-       dev_dbg(icd->parent, "%s freed\n", __func__);
-
-       vb->state = VIDEOBUF_NEEDS_INIT;
+       return 0;
 }
 
-static int mx2_videobuf_prepare(struct videobuf_queue *vq,
-               struct videobuf_buffer *vb, enum v4l2_field field)
+static int mx2_videobuf_prepare(struct vb2_buffer *vb)
 {
-       struct soc_camera_device *icd = vq->priv_data;
-       struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
        int ret = 0;
 
-       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-               vb, vb->baddr, vb->bsize);
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
        if (bytes_per_line < 0)
                return bytes_per_line;
@@ -520,78 +518,58 @@ static int mx2_videobuf_prepare(struct videobuf_queue *vq,
         * This can be useful if you want to see if we actually fill
         * the buffer with something
         */
-       memset((void *)vb->baddr, 0xaa, vb->bsize);
+       memset((void *)vb2_plane_vaddr(vb, 0),
+              0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
-       if (buf->code   != icd->current_fmt->code ||
-           vb->width   != icd->user_width ||
-           vb->height  != icd->user_height ||
-           vb->field   != field) {
-               buf->code       = icd->current_fmt->code;
-               vb->width       = icd->user_width;
-               vb->height      = icd->user_height;
-               vb->field       = field;
-               vb->state       = VIDEOBUF_NEEDS_INIT;
-       }
-
-       vb->size = bytes_per_line * vb->height;
-       if (vb->baddr && vb->bsize < vb->size) {
+       vb2_set_plane_payload(vb, 0, bytes_per_line * icd->user_height);
+       if (vb2_plane_vaddr(vb, 0) &&
+           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
                ret = -EINVAL;
                goto out;
        }
 
-       if (vb->state == VIDEOBUF_NEEDS_INIT) {
-               ret = videobuf_iolock(vq, vb, NULL);
-               if (ret)
-                       goto fail;
-
-               vb->state = VIDEOBUF_PREPARED;
-       }
-
        return 0;
 
-fail:
-       free_buffer(vq, buf);
 out:
        return ret;
 }
 
-static void mx2_videobuf_queue(struct videobuf_queue *vq,
-                              struct videobuf_buffer *vb)
+static void mx2_videobuf_queue(struct vb2_buffer *vb)
 {
-       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
        struct soc_camera_host *ici =
                to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
        struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
        unsigned long flags;
 
-       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-               vb, vb->baddr, vb->bsize);
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
        spin_lock_irqsave(&pcdev->lock, flags);
 
-       vb->state = VIDEOBUF_QUEUED;
-       list_add_tail(&vb->queue, &pcdev->capture);
+       buf->state = MX2_STATE_QUEUED;
+       list_add_tail(&buf->queue, &pcdev->capture);
 
        if (cpu_is_mx25()) {
                u32 csicr3, dma_inten = 0;
 
                if (pcdev->fb1_active == NULL) {
-                       writel(videobuf_to_dma_contig(vb),
+                       writel(vb2_dma_contig_plane_dma_addr(vb, 0),
                                        pcdev->base_csi + CSIDMASA_FB1);
                        pcdev->fb1_active = buf;
                        dma_inten = CSICR1_FB1_DMA_INTEN;
                } else if (pcdev->fb2_active == NULL) {
-                       writel(videobuf_to_dma_contig(vb),
+                       writel(vb2_dma_contig_plane_dma_addr(vb, 0),
                                        pcdev->base_csi + CSIDMASA_FB2);
                        pcdev->fb2_active = buf;
                        dma_inten = CSICR1_FB2_DMA_INTEN;
                }
 
                if (dma_inten) {
-                       list_del(&vb->queue);
-                       vb->state = VIDEOBUF_ACTIVE;
+                       list_del(&buf->queue);
+                       buf->state = MX2_STATE_ACTIVE;
 
                        csicr3 = readl(pcdev->base_csi + CSICR3);
 
@@ -613,32 +591,28 @@ static void mx2_videobuf_queue(struct videobuf_queue *vq,
        spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
-static void mx2_videobuf_release(struct videobuf_queue *vq,
-                                struct videobuf_buffer *vb)
+static void mx2_videobuf_release(struct vb2_buffer *vb)
 {
-       struct soc_camera_device *icd = vq->priv_data;
+       struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx2_camera_dev *pcdev = ici->priv;
        struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
        unsigned long flags;
 
 #ifdef DEBUG
-       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-               vb, vb->baddr, vb->bsize);
+       dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+               vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
-       switch (vb->state) {
-       case VIDEOBUF_ACTIVE:
+       switch (buf->state) {
+       case MX2_STATE_ACTIVE:
                dev_info(icd->parent, "%s (active)\n", __func__);
                break;
-       case VIDEOBUF_QUEUED:
+       case MX2_STATE_QUEUED:
                dev_info(icd->parent, "%s (queued)\n", __func__);
                break;
-       case VIDEOBUF_PREPARED:
-               dev_info(icd->parent, "%s (prepared)\n", __func__);
-               break;
        default:
                dev_info(icd->parent, "%s (unknown) %d\n", __func__,
-                               vb->state);
+                               buf->state);
                break;
        }
 #endif
@@ -652,11 +626,10 @@ static void mx2_videobuf_release(struct videobuf_queue *vq,
         * state. This requires a specific handling for each of the these DMA
         * types.
         */
+
        spin_lock_irqsave(&pcdev->lock, flags);
-       if (vb->state == VIDEOBUF_QUEUED) {
-               list_del(&vb->queue);
-               vb->state = VIDEOBUF_ERROR;
-       } else if (cpu_is_mx25() && vb->state == VIDEOBUF_ACTIVE) {
+       list_del_init(&buf->queue);
+       if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) {
                if (pcdev->fb1_active == buf) {
                        pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN;
                        writel(0, pcdev->base_csi + CSIDMASA_FB1);
@@ -667,30 +640,28 @@ static void mx2_videobuf_release(struct videobuf_queue *vq,
                        pcdev->fb2_active = NULL;
                }
                writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
-               vb->state = VIDEOBUF_ERROR;
        }
        spin_unlock_irqrestore(&pcdev->lock, flags);
-
-       free_buffer(vq, buf);
 }
 
-static struct videobuf_queue_ops mx2_videobuf_ops = {
-       .buf_setup      = mx2_videobuf_setup,
-       .buf_prepare    = mx2_videobuf_prepare,
-       .buf_queue      = mx2_videobuf_queue,
-       .buf_release    = mx2_videobuf_release,
+static struct vb2_ops mx2_videobuf_ops = {
+       .queue_setup    = mx2_videobuf_setup,
+       .buf_prepare    = mx2_videobuf_prepare,
+       .buf_queue      = mx2_videobuf_queue,
+       .buf_cleanup    = mx2_videobuf_release,
 };
 
-static void mx2_camera_init_videobuf(struct videobuf_queue *q,
+static int mx2_camera_init_videobuf(struct vb2_queue *q,
                              struct soc_camera_device *icd)
 {
-       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct mx2_camera_dev *pcdev = ici->priv;
-
-       videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev,
-                       &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       V4L2_FIELD_NONE, sizeof(struct mx2_buffer),
-                       icd, &icd->video_lock);
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_MMAP | VB2_USERPTR;
+       q->drv_priv = icd;
+       q->ops = &mx2_videobuf_ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct mx2_buffer);
+
+       return vb2_queue_init(q);
 }
 
 #define MX2_BUS_FLAGS  (V4L2_MBUS_MASTER | \
@@ -1122,25 +1093,11 @@ static int mx2_camera_querycap(struct soc_camera_host *ici,
        return 0;
 }
 
-static int mx2_camera_reqbufs(struct soc_camera_device *icd,
-                             struct v4l2_requestbuffers *p)
-{
-       int i;
-
-       for (i = 0; i < p->count; i++) {
-               struct mx2_buffer *buf = container_of(icd->vb_vidq.bufs[i],
-                                                     struct mx2_buffer, vb);
-               INIT_LIST_HEAD(&buf->vb.queue);
-       }
-
-       return 0;
-}
-
 static unsigned int mx2_camera_poll(struct file *file, poll_table *pt)
 {
        struct soc_camera_device *icd = file->private_data;
 
-       return videobuf_poll_stream(file, &icd->vb_vidq, pt);
+       return vb2_poll(&icd->vb2_vidq, file, pt);
 }
 
 static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
@@ -1151,31 +1108,30 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
        .set_crop       = mx2_camera_set_crop,
        .get_formats    = mx2_camera_get_formats,
        .try_fmt        = mx2_camera_try_fmt,
-       .init_videobuf  = mx2_camera_init_videobuf,
-       .reqbufs        = mx2_camera_reqbufs,
+       .init_videobuf2 = mx2_camera_init_videobuf,
        .poll           = mx2_camera_poll,
        .querycap       = mx2_camera_querycap,
        .set_bus_param  = mx2_camera_set_bus_param,
 };
 
 static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
-               int bufnum, int state)
+               int bufnum)
 {
        u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
        struct mx2_fmt_cfg *prp = pcdev->emma_prp;
        struct mx2_buffer *buf;
-       struct videobuf_buffer *vb;
+       struct vb2_buffer *vb;
        unsigned long phys;
 
        if (!list_empty(&pcdev->active_bufs)) {
                buf = list_entry(pcdev->active_bufs.next,
-                       struct mx2_buffer, vb.queue);
+                       struct mx2_buffer, queue);
 
                BUG_ON(buf->bufnum != bufnum);
 
                vb = &buf->vb;
 #ifdef DEBUG
-               phys = videobuf_to_dma_contig(vb);
+               phys = vb2_dma_contig_plane_dma_addr(vb, 0);
                if (prp->cfg.channel == 1) {
                        if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR +
                                4 * bufnum) != phys) {
@@ -1194,16 +1150,15 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
                        }
                }
 #endif
-               dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb,
-                               vb->baddr, vb->bsize);
+               dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb,
+                               vb2_plane_vaddr(vb, 0),
+                               vb2_get_plane_payload(vb, 0));
 
-               list_del(&vb->queue);
-               vb->state = state;
-               do_gettimeofday(&vb->ts);
-               vb->field_count = pcdev->frame_count * 2;
+               list_del_init(&buf->queue);
+               do_gettimeofday(&vb->v4l2_buf.timestamp);
                pcdev->frame_count++;
-
-               wake_up(&vb->done);
+               vb->v4l2_buf.sequence = pcdev->frame_count;
+               vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
        }
 
        if (list_empty(&pcdev->capture)) {
@@ -1227,16 +1182,16 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
        }
 
        buf = list_entry(pcdev->capture.next,
-                       struct mx2_buffer, vb.queue);
+                       struct mx2_buffer, queue);
 
        buf->bufnum = !bufnum;
 
        list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
 
        vb = &buf->vb;
-       vb->state = VIDEOBUF_ACTIVE;
+       buf->state = MX2_STATE_ACTIVE;
 
-       phys = videobuf_to_dma_contig(vb);
+       phys = vb2_dma_contig_plane_dma_addr(vb, 0);
        if (prp->cfg.channel == 1) {
                writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
        } else {
@@ -1280,14 +1235,14 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
                 * to first
                 */
                buf = list_entry(pcdev->active_bufs.next,
-                       struct mx2_buffer, vb.queue);
-               mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE);
+                       struct mx2_buffer, queue);
+               mx27_camera_frame_done_emma(pcdev, buf->bufnum);
                status &= ~(1 << (6 - buf->bufnum)); /* mark processed */
        }
        if ((status & (1 << 6)) || (status & (1 << 4)))
-               mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE);
+               mx27_camera_frame_done_emma(pcdev, 0);
        if ((status & (1 << 5)) || (status & (1 << 3)))
-               mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE);
+               mx27_camera_frame_done_emma(pcdev, 1);
 
        writel(status, pcdev->base_emma + PRP_INTRSTATUS);
 
@@ -1449,6 +1404,12 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
        pcdev->soc_host.priv            = pcdev;
        pcdev->soc_host.v4l2_dev.dev    = &pdev->dev;
        pcdev->soc_host.nr              = pdev->id;
+
+       pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(pcdev->alloc_ctx)) {
+               err = PTR_ERR(pcdev->alloc_ctx);
+               goto eallocctx;
+       }
        err = soc_camera_host_register(&pcdev->soc_host);
        if (err)
                goto exit_free_emma;
@@ -1459,6 +1420,8 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
        return 0;
 
 exit_free_emma:
+       vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
+eallocctx:
        if (cpu_is_mx27()) {
                free_irq(pcdev->irq_emma, pcdev);
                clk_disable(pcdev->clk_emma);
@@ -1496,6 +1459,8 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)
 
        soc_camera_host_unregister(&pcdev->soc_host);
 
+       vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
+
        iounmap(pcdev->base_csi);
 
        if (cpu_is_mx27()) {