[PATCH-V1,09/10] VPFE Capture: Add support for USERPTR mode of operation

Message ID 1266914073-30135-10-git-send-email-hvaibhav@ti.com (mailing list archive)
State Superseded, archived
Headers

Commit Message

Hiremath, Vaibhav Feb. 23, 2010, 8:34 a.m. UTC
  From: Vaibhav Hiremath <hvaibhav@ti.com>


Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
---
 drivers/media/video/ti-media/vpfe_capture.c |   94 ++++++++++++++++++++++----
 1 files changed, 79 insertions(+), 15 deletions(-)

--
1.6.2.4

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

Comments

Muralidharan Karicheri Feb. 23, 2010, 11:22 p.m. UTC | #1
Vaibhav,

There are changes to vpfe capture on Arago tree on top of this. For
example, vpfe_uservirt_to_phys() is removed and is replaced with
videobuf_iolock(). So please get the latest changes to upstream.

Murali

On Tue, Feb 23, 2010 at 3:34 AM,  <hvaibhav@ti.com> wrote:
> From: Vaibhav Hiremath <hvaibhav@ti.com>
>
>
> Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> ---
>  drivers/media/video/ti-media/vpfe_capture.c |   94 ++++++++++++++++++++++----
>  1 files changed, 79 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/media/video/ti-media/vpfe_capture.c b/drivers/media/video/ti-media/vpfe_capture.c
> index cece265..7d4ab44 100644
> --- a/drivers/media/video/ti-media/vpfe_capture.c
> +++ b/drivers/media/video/ti-media/vpfe_capture.c
> @@ -538,7 +538,24 @@ static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)
>                                        struct videobuf_buffer, queue);
>        list_del(&vpfe_dev->next_frm->queue);
>        vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
> -       addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
> +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
> +               addr = vpfe_dev->cur_frm->boff;
> +       else
> +               addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
> +
> +       ccdc_dev->hw_ops.setfbaddr(addr);
> +}
> +
> +static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)
> +{
> +       unsigned long addr;
> +
> +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
> +               addr = vpfe_dev->cur_frm->boff;
> +       else
> +               addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
> +
> +       addr += vpfe_dev->field_off;
>        ccdc_dev->hw_ops.setfbaddr(addr);
>  }
>
> @@ -559,7 +576,6 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id)
>  {
>        struct vpfe_device *vpfe_dev = dev_id;
>        enum v4l2_field field;
> -       unsigned long addr;
>        int fid;
>
>        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n");
> @@ -604,10 +620,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id)
>                         * the CCDC memory address
>                         */
>                        if (field == V4L2_FIELD_SEQ_TB) {
> -                               addr =
> -                                 videobuf_to_dma_contig(vpfe_dev->cur_frm);
> -                               addr += vpfe_dev->field_off;
> -                               ccdc_dev->hw_ops.setfbaddr(addr);
> +                               vpfe_schedule_bottom_field(vpfe_dev);
>                        }
>                        goto clear_intr;
>                }
> @@ -1234,7 +1247,10 @@ static int vpfe_videobuf_setup(struct videobuf_queue *vq,
>        struct vpfe_device *vpfe_dev = fh->vpfe_dev;
>
>        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
> -       *size = config_params.device_bufsize;
> +       *size = vpfe_dev->fmt.fmt.pix.sizeimage;
> +       if (vpfe_dev->memory == V4L2_MEMORY_MMAP &&
> +               vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize)
> +               *size = config_params.device_bufsize;
>
>        if (*count < config_params.min_numbuffers)
>                *count = config_params.min_numbuffers;
> @@ -1243,6 +1259,46 @@ static int vpfe_videobuf_setup(struct videobuf_queue *vq,
>        return 0;
>  }
>
> +/*
> + * vpfe_uservirt_to_phys: This function is used to convert user
> + * space virtual address to physical address.
> + */
> +static u32 vpfe_uservirt_to_phys(struct vpfe_device *vpfe_dev, u32 virtp)
> +{
> +       struct mm_struct *mm = current->mm;
> +       unsigned long physp = 0;
> +       struct vm_area_struct *vma;
> +
> +       vma = find_vma(mm, virtp);
> +
> +       /* For kernel direct-mapped memory, take the easy way */
> +       if (virtp >= PAGE_OFFSET)
> +               physp = virt_to_phys((void *)virtp);
> +       else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff))
> +               /* this will catch, kernel-allocated, mmaped-to-usermode addr */
> +               physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
> +       else {
> +               /* otherwise, use get_user_pages() for general userland pages */
> +               int res, nr_pages = 1;
> +               struct page *pages;
> +               down_read(&current->mm->mmap_sem);
> +
> +               res = get_user_pages(current, current->mm,
> +                                    virtp, nr_pages, 1, 0, &pages, NULL);
> +               up_read(&current->mm->mmap_sem);
> +
> +               if (res == nr_pages)
> +                       physp = __pa(page_address(&pages[0]) +
> +                                    (virtp & ~PAGE_MASK));
> +               else {
> +                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +                               "get_user_pages failed\n");
> +                       return 0;
> +               }
> +       }
> +       return physp;
> +}
> +
>  static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
>                                struct videobuf_buffer *vb,
>                                enum v4l2_field field)
> @@ -1259,6 +1315,18 @@ static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
>                vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
>                vb->field = field;
>        }
> +
> +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory) {
> +               if (!vb->baddr) {
> +                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> +                               "buffer address is 0\n");
> +                       return -EINVAL;
> +               }
> +               vb->boff = vpfe_uservirt_to_phys(vpfe_dev, vb->baddr);
> +               /* Make sure user addresses are aligned to 32 bytes */
> +               if (!ALIGN(vb->boff, 32))
> +                       return -EINVAL;
> +       }
>        vb->state = VIDEOBUF_PREPARED;
>        return 0;
>  }
> @@ -1327,13 +1395,6 @@ static int vpfe_reqbufs(struct file *file, void *priv,
>                return -EINVAL;
>        }
>
> -       if (V4L2_MEMORY_USERPTR == req_buf->memory) {
> -               /* we don't support user ptr IO */
> -               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
> -                        " USERPTR IO not supported\n");
> -               return  -EINVAL;
> -       }
> -
>        ret = mutex_lock_interruptible(&vpfe_dev->lock);
>        if (ret)
>                return ret;
> @@ -1541,7 +1602,10 @@ static int vpfe_streamon(struct file *file, void *priv,
>        vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
>        /* Initialize field_id and started member */
>        vpfe_dev->field_id = 0;
> -       addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
> +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
> +               addr = vpfe_dev->cur_frm->boff;
> +       else
> +               addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
>
>        /* Calculate field offset */
>        vpfe_calculate_offsets(vpfe_dev);
> --
> 1.6.2.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
  
Hiremath, Vaibhav Feb. 24, 2010, 5:37 a.m. UTC | #2
> -----Original Message-----
> From: Muralidharan Karicheri [mailto:mkaricheri@gmail.com]
> Sent: Wednesday, February 24, 2010 4:53 AM
> To: Hiremath, Vaibhav
> Cc: linux-media@vger.kernel.org; linux-omap@vger.kernel.org;
> hverkuil@xs4all.nl; Karicheri, Muralidharan
> Subject: Re: [PATCH-V1 09/10] VPFE Capture: Add support for USERPTR mode of
> operation
> 
> Vaibhav,
> 
> There are changes to vpfe capture on Arago tree on top of this. For
> example, vpfe_uservirt_to_phys() is removed and is replaced with
> videobuf_iolock(). So please get the latest changes to upstream.
> 
[Hiremath, Vaibhav] No, the Arago version doesn't support USERPTR mode at all,


1386		if (V4L2_MEMORY_USERPTR == req_buf->memory) {
1386                 /* we don't support user ptr IO */
1387                 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
1388                          " USERPTR IO not supported\n");
1389                 return  -EINVAL;
1390         }

And also, I have received important comment from Mauro, which expects some code tobe moved to generic VideoBuf layer. I will be submitting patch for the same separately.

Thanks,
Vaibhav

> Murali
> 
> On Tue, Feb 23, 2010 at 3:34 AM,  <hvaibhav@ti.com> wrote:
> > From: Vaibhav Hiremath <hvaibhav@ti.com>
> >
> >
> > Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
> > Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
> > ---
> >  drivers/media/video/ti-media/vpfe_capture.c |   94
> ++++++++++++++++++++++----
> >  1 files changed, 79 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/media/video/ti-media/vpfe_capture.c
> b/drivers/media/video/ti-media/vpfe_capture.c
> > index cece265..7d4ab44 100644
> > --- a/drivers/media/video/ti-media/vpfe_capture.c
> > +++ b/drivers/media/video/ti-media/vpfe_capture.c
> > @@ -538,7 +538,24 @@ static void vpfe_schedule_next_buffer(struct
> vpfe_device *vpfe_dev)
> >                                        struct videobuf_buffer, queue);
> >        list_del(&vpfe_dev->next_frm->queue);
> >        vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
> > -       addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
> > +               addr = vpfe_dev->cur_frm->boff;
> > +       else
> > +               addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
> > +
> > +       ccdc_dev->hw_ops.setfbaddr(addr);
> > +}
> > +
> > +static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)
> > +{
> > +       unsigned long addr;
> > +
> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
> > +               addr = vpfe_dev->cur_frm->boff;
> > +       else
> > +               addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
> > +
> > +       addr += vpfe_dev->field_off;
> >        ccdc_dev->hw_ops.setfbaddr(addr);
> >  }
> >
> > @@ -559,7 +576,6 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id)
> >  {
> >        struct vpfe_device *vpfe_dev = dev_id;
> >        enum v4l2_field field;
> > -       unsigned long addr;
> >        int fid;
> >
> >        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting
> vpfe_isr...\n");
> > @@ -604,10 +620,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id)
> >                         * the CCDC memory address
> >                         */
> >                        if (field == V4L2_FIELD_SEQ_TB) {
> > -                               addr =
> > -                                 videobuf_to_dma_contig(vpfe_dev-
> >cur_frm);
> > -                               addr += vpfe_dev->field_off;
> > -                               ccdc_dev->hw_ops.setfbaddr(addr);
> > +                               vpfe_schedule_bottom_field(vpfe_dev);
> >                        }
> >                        goto clear_intr;
> >                }
> > @@ -1234,7 +1247,10 @@ static int vpfe_videobuf_setup(struct
> videobuf_queue *vq,
> >        struct vpfe_device *vpfe_dev = fh->vpfe_dev;
> >
> >        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
> > -       *size = config_params.device_bufsize;
> > +       *size = vpfe_dev->fmt.fmt.pix.sizeimage;
> > +       if (vpfe_dev->memory == V4L2_MEMORY_MMAP &&
> > +               vpfe_dev->fmt.fmt.pix.sizeimage >
> config_params.device_bufsize)
> > +               *size = config_params.device_bufsize;
> >
> >        if (*count < config_params.min_numbuffers)
> >                *count = config_params.min_numbuffers;
> > @@ -1243,6 +1259,46 @@ static int vpfe_videobuf_setup(struct
> videobuf_queue *vq,
> >        return 0;
> >  }
> >
> > +/*
> > + * vpfe_uservirt_to_phys: This function is used to convert user
> > + * space virtual address to physical address.
> > + */
> > +static u32 vpfe_uservirt_to_phys(struct vpfe_device *vpfe_dev, u32 virtp)
> > +{
> > +       struct mm_struct *mm = current->mm;
> > +       unsigned long physp = 0;
> > +       struct vm_area_struct *vma;
> > +
> > +       vma = find_vma(mm, virtp);
> > +
> > +       /* For kernel direct-mapped memory, take the easy way */
> > +       if (virtp >= PAGE_OFFSET)
> > +               physp = virt_to_phys((void *)virtp);
> > +       else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff))
> > +               /* this will catch, kernel-allocated, mmaped-to-usermode
> addr */
> > +               physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma-
> >vm_start);
> > +       else {
> > +               /* otherwise, use get_user_pages() for general userland
> pages */
> > +               int res, nr_pages = 1;
> > +               struct page *pages;
> > +               down_read(&current->mm->mmap_sem);
> > +
> > +               res = get_user_pages(current, current->mm,
> > +                                    virtp, nr_pages, 1, 0, &pages, NULL);
> > +               up_read(&current->mm->mmap_sem);
> > +
> > +               if (res == nr_pages)
> > +                       physp = __pa(page_address(&pages[0]) +
> > +                                    (virtp & ~PAGE_MASK));
> > +               else {
> > +                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> > +                               "get_user_pages failed\n");
> > +                       return 0;
> > +               }
> > +       }
> > +       return physp;
> > +}
> > +
> >  static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
> >                                struct videobuf_buffer *vb,
> >                                enum v4l2_field field)
> > @@ -1259,6 +1315,18 @@ static int vpfe_videobuf_prepare(struct
> videobuf_queue *vq,
> >                vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
> >                vb->field = field;
> >        }
> > +
> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory) {
> > +               if (!vb->baddr) {
> > +                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
> > +                               "buffer address is 0\n");
> > +                       return -EINVAL;
> > +               }
> > +               vb->boff = vpfe_uservirt_to_phys(vpfe_dev, vb->baddr);
> > +               /* Make sure user addresses are aligned to 32 bytes */
> > +               if (!ALIGN(vb->boff, 32))
> > +                       return -EINVAL;
> > +       }
> >        vb->state = VIDEOBUF_PREPARED;
> >        return 0;
> >  }
> > @@ -1327,13 +1395,6 @@ static int vpfe_reqbufs(struct file *file, void
> *priv,
> >                return -EINVAL;
> >        }
> >
> > -       if (V4L2_MEMORY_USERPTR == req_buf->memory) {
> > -               /* we don't support user ptr IO */
> > -               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
> > -                        " USERPTR IO not supported\n");
> > -               return  -EINVAL;
> > -       }
> > -
> >        ret = mutex_lock_interruptible(&vpfe_dev->lock);
> >        if (ret)
> >                return ret;
> > @@ -1541,7 +1602,10 @@ static int vpfe_streamon(struct file *file, void
> *priv,
> >        vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
> >        /* Initialize field_id and started member */
> >        vpfe_dev->field_id = 0;
> > -       addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
> > +               addr = vpfe_dev->cur_frm->boff;
> > +       else
> > +               addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
> >
> >        /* Calculate field offset */
> >        vpfe_calculate_offsets(vpfe_dev);
> > --
> > 1.6.2.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> 
> 
> 
> --
> Murali Karicheri
> mkaricheri@gmail.com
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
Muralidharan Karicheri Feb. 24, 2010, 1:02 p.m. UTC | #3
On Wed, Feb 24, 2010 at 12:37 AM, Hiremath, Vaibhav <hvaibhav@ti.com> wrote:
>
>> -----Original Message-----
>> From: Muralidharan Karicheri [mailto:mkaricheri@gmail.com]
>> Sent: Wednesday, February 24, 2010 4:53 AM
>> To: Hiremath, Vaibhav
>> Cc: linux-media@vger.kernel.org; linux-omap@vger.kernel.org;
>> hverkuil@xs4all.nl; Karicheri, Muralidharan
>> Subject: Re: [PATCH-V1 09/10] VPFE Capture: Add support for USERPTR mode of
>> operation
>>
>> Vaibhav,
>>
>> There are changes to vpfe capture on Arago tree on top of this. For
>> example, vpfe_uservirt_to_phys() is removed and is replaced with
>> videobuf_iolock(). So please get the latest changes to upstream.
>>
> [Hiremath, Vaibhav] No, the Arago version doesn't support USERPTR mode at all,

Probably you are referring to the wrong tree. This code has gone
through test cycles and I prefer re-using the code as much as
possible. Check out below...

http://arago-project.org/git/people/sneha/linux-davinci-staging.git

My linux-davinci-video.git tree just track the upstream...

Murali
>
>
> 1386            if (V4L2_MEMORY_USERPTR == req_buf->memory) {
> 1386                 /* we don't support user ptr IO */
> 1387                 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
> 1388                          " USERPTR IO not supported\n");
> 1389                 return  -EINVAL;
> 1390         }
>
> And also, I have received important comment from Mauro, which expects some code tobe moved to generic VideoBuf layer. I will be submitting patch for the same separately.


>
> Thanks,
> Vaibhav
>
>> Murali
>>
>> On Tue, Feb 23, 2010 at 3:34 AM,  <hvaibhav@ti.com> wrote:
>> > From: Vaibhav Hiremath <hvaibhav@ti.com>
>> >
>> >
>> > Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
>> > Signed-off-by: Muralidharan Karicheri <m-karicheri2@ti.com>
>> > ---
>> >  drivers/media/video/ti-media/vpfe_capture.c |   94
>> ++++++++++++++++++++++----
>> >  1 files changed, 79 insertions(+), 15 deletions(-)
>> >
>> > diff --git a/drivers/media/video/ti-media/vpfe_capture.c
>> b/drivers/media/video/ti-media/vpfe_capture.c
>> > index cece265..7d4ab44 100644
>> > --- a/drivers/media/video/ti-media/vpfe_capture.c
>> > +++ b/drivers/media/video/ti-media/vpfe_capture.c
>> > @@ -538,7 +538,24 @@ static void vpfe_schedule_next_buffer(struct
>> vpfe_device *vpfe_dev)
>> >                                        struct videobuf_buffer, queue);
>> >        list_del(&vpfe_dev->next_frm->queue);
>> >        vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
>> > -       addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
>> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
>> > +               addr = vpfe_dev->cur_frm->boff;
>> > +       else
>> > +               addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
>> > +
>> > +       ccdc_dev->hw_ops.setfbaddr(addr);
>> > +}
>> > +
>> > +static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)
>> > +{
>> > +       unsigned long addr;
>> > +
>> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
>> > +               addr = vpfe_dev->cur_frm->boff;
>> > +       else
>> > +               addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
>> > +
>> > +       addr += vpfe_dev->field_off;
>> >        ccdc_dev->hw_ops.setfbaddr(addr);
>> >  }
>> >
>> > @@ -559,7 +576,6 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id)
>> >  {
>> >        struct vpfe_device *vpfe_dev = dev_id;
>> >        enum v4l2_field field;
>> > -       unsigned long addr;
>> >        int fid;
>> >
>> >        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting
>> vpfe_isr...\n");
>> > @@ -604,10 +620,7 @@ static irqreturn_t vpfe_isr(int irq, void *dev_id)
>> >                         * the CCDC memory address
>> >                         */
>> >                        if (field == V4L2_FIELD_SEQ_TB) {
>> > -                               addr =
>> > -                                 videobuf_to_dma_contig(vpfe_dev-
>> >cur_frm);
>> > -                               addr += vpfe_dev->field_off;
>> > -                               ccdc_dev->hw_ops.setfbaddr(addr);
>> > +                               vpfe_schedule_bottom_field(vpfe_dev);
>> >                        }
>> >                        goto clear_intr;
>> >                }
>> > @@ -1234,7 +1247,10 @@ static int vpfe_videobuf_setup(struct
>> videobuf_queue *vq,
>> >        struct vpfe_device *vpfe_dev = fh->vpfe_dev;
>> >
>> >        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
>> > -       *size = config_params.device_bufsize;
>> > +       *size = vpfe_dev->fmt.fmt.pix.sizeimage;
>> > +       if (vpfe_dev->memory == V4L2_MEMORY_MMAP &&
>> > +               vpfe_dev->fmt.fmt.pix.sizeimage >
>> config_params.device_bufsize)
>> > +               *size = config_params.device_bufsize;
>> >
>> >        if (*count < config_params.min_numbuffers)
>> >                *count = config_params.min_numbuffers;
>> > @@ -1243,6 +1259,46 @@ static int vpfe_videobuf_setup(struct
>> videobuf_queue *vq,
>> >        return 0;
>> >  }
>> >
>> > +/*
>> > + * vpfe_uservirt_to_phys: This function is used to convert user
>> > + * space virtual address to physical address.
>> > + */
>> > +static u32 vpfe_uservirt_to_phys(struct vpfe_device *vpfe_dev, u32 virtp)
>> > +{
>> > +       struct mm_struct *mm = current->mm;
>> > +       unsigned long physp = 0;
>> > +       struct vm_area_struct *vma;
>> > +
>> > +       vma = find_vma(mm, virtp);
>> > +
>> > +       /* For kernel direct-mapped memory, take the easy way */
>> > +       if (virtp >= PAGE_OFFSET)
>> > +               physp = virt_to_phys((void *)virtp);
>> > +       else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff))
>> > +               /* this will catch, kernel-allocated, mmaped-to-usermode
>> addr */
>> > +               physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma-
>> >vm_start);
>> > +       else {
>> > +               /* otherwise, use get_user_pages() for general userland
>> pages */
>> > +               int res, nr_pages = 1;
>> > +               struct page *pages;
>> > +               down_read(&current->mm->mmap_sem);
>> > +
>> > +               res = get_user_pages(current, current->mm,
>> > +                                    virtp, nr_pages, 1, 0, &pages, NULL);
>> > +               up_read(&current->mm->mmap_sem);
>> > +
>> > +               if (res == nr_pages)
>> > +                       physp = __pa(page_address(&pages[0]) +
>> > +                                    (virtp & ~PAGE_MASK));
>> > +               else {
>> > +                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
>> > +                               "get_user_pages failed\n");
>> > +                       return 0;
>> > +               }
>> > +       }
>> > +       return physp;
>> > +}
>> > +
>> >  static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
>> >                                struct videobuf_buffer *vb,
>> >                                enum v4l2_field field)
>> > @@ -1259,6 +1315,18 @@ static int vpfe_videobuf_prepare(struct
>> videobuf_queue *vq,
>> >                vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
>> >                vb->field = field;
>> >        }
>> > +
>> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory) {
>> > +               if (!vb->baddr) {
>> > +                       v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
>> > +                               "buffer address is 0\n");
>> > +                       return -EINVAL;
>> > +               }
>> > +               vb->boff = vpfe_uservirt_to_phys(vpfe_dev, vb->baddr);
>> > +               /* Make sure user addresses are aligned to 32 bytes */
>> > +               if (!ALIGN(vb->boff, 32))
>> > +                       return -EINVAL;
>> > +       }
>> >        vb->state = VIDEOBUF_PREPARED;
>> >        return 0;
>> >  }
>> > @@ -1327,13 +1395,6 @@ static int vpfe_reqbufs(struct file *file, void
>> *priv,
>> >                return -EINVAL;
>> >        }
>> >
>> > -       if (V4L2_MEMORY_USERPTR == req_buf->memory) {
>> > -               /* we don't support user ptr IO */
>> > -               v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
>> > -                        " USERPTR IO not supported\n");
>> > -               return  -EINVAL;
>> > -       }
>> > -
>> >        ret = mutex_lock_interruptible(&vpfe_dev->lock);
>> >        if (ret)
>> >                return ret;
>> > @@ -1541,7 +1602,10 @@ static int vpfe_streamon(struct file *file, void
>> *priv,
>> >        vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
>> >        /* Initialize field_id and started member */
>> >        vpfe_dev->field_id = 0;
>> > -       addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
>> > +       if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
>> > +               addr = vpfe_dev->cur_frm->boff;
>> > +       else
>> > +               addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
>> >
>> >        /* Calculate field offset */
>> >        vpfe_calculate_offsets(vpfe_dev);
>> > --
>> > 1.6.2.4
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >
>>
>>
>>
>> --
>> Murali Karicheri
>> mkaricheri@gmail.com
>
  

Patch

diff --git a/drivers/media/video/ti-media/vpfe_capture.c b/drivers/media/video/ti-media/vpfe_capture.c
index cece265..7d4ab44 100644
--- a/drivers/media/video/ti-media/vpfe_capture.c
+++ b/drivers/media/video/ti-media/vpfe_capture.c
@@ -538,7 +538,24 @@  static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)
 					struct videobuf_buffer, queue);
 	list_del(&vpfe_dev->next_frm->queue);
 	vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
-	addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
+	if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
+		addr = vpfe_dev->cur_frm->boff;
+	else
+		addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
+
+	ccdc_dev->hw_ops.setfbaddr(addr);
+}
+
+static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)
+{
+	unsigned long addr;
+
+	if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
+		addr = vpfe_dev->cur_frm->boff;
+	else
+		addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
+
+	addr += vpfe_dev->field_off;
 	ccdc_dev->hw_ops.setfbaddr(addr);
 }

@@ -559,7 +576,6 @@  static irqreturn_t vpfe_isr(int irq, void *dev_id)
 {
 	struct vpfe_device *vpfe_dev = dev_id;
 	enum v4l2_field field;
-	unsigned long addr;
 	int fid;

 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n");
@@ -604,10 +620,7 @@  static irqreturn_t vpfe_isr(int irq, void *dev_id)
 			 * the CCDC memory address
 			 */
 			if (field == V4L2_FIELD_SEQ_TB) {
-				addr =
-				  videobuf_to_dma_contig(vpfe_dev->cur_frm);
-				addr += vpfe_dev->field_off;
-				ccdc_dev->hw_ops.setfbaddr(addr);
+				vpfe_schedule_bottom_field(vpfe_dev);
 			}
 			goto clear_intr;
 		}
@@ -1234,7 +1247,10 @@  static int vpfe_videobuf_setup(struct videobuf_queue *vq,
 	struct vpfe_device *vpfe_dev = fh->vpfe_dev;

 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
-	*size = config_params.device_bufsize;
+	*size = vpfe_dev->fmt.fmt.pix.sizeimage;
+	if (vpfe_dev->memory == V4L2_MEMORY_MMAP &&
+		vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize)
+		*size = config_params.device_bufsize;

 	if (*count < config_params.min_numbuffers)
 		*count = config_params.min_numbuffers;
@@ -1243,6 +1259,46 @@  static int vpfe_videobuf_setup(struct videobuf_queue *vq,
 	return 0;
 }

+/*
+ * vpfe_uservirt_to_phys: This function is used to convert user
+ * space virtual address to physical address.
+ */
+static u32 vpfe_uservirt_to_phys(struct vpfe_device *vpfe_dev, u32 virtp)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long physp = 0;
+	struct vm_area_struct *vma;
+
+	vma = find_vma(mm, virtp);
+
+	/* For kernel direct-mapped memory, take the easy way */
+	if (virtp >= PAGE_OFFSET)
+		physp = virt_to_phys((void *)virtp);
+	else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff))
+		/* this will catch, kernel-allocated, mmaped-to-usermode addr */
+		physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
+	else {
+		/* otherwise, use get_user_pages() for general userland pages */
+		int res, nr_pages = 1;
+		struct page *pages;
+		down_read(&current->mm->mmap_sem);
+
+		res = get_user_pages(current, current->mm,
+				     virtp, nr_pages, 1, 0, &pages, NULL);
+		up_read(&current->mm->mmap_sem);
+
+		if (res == nr_pages)
+			physp = __pa(page_address(&pages[0]) +
+				     (virtp & ~PAGE_MASK));
+		else {
+			v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+				"get_user_pages failed\n");
+			return 0;
+		}
+	}
+	return physp;
+}
+
 static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
 				struct videobuf_buffer *vb,
 				enum v4l2_field field)
@@ -1259,6 +1315,18 @@  static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
 		vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
 		vb->field = field;
 	}
+
+	if (V4L2_MEMORY_USERPTR == vpfe_dev->memory) {
+		if (!vb->baddr) {
+			v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+				"buffer address is 0\n");
+			return -EINVAL;
+		}
+		vb->boff = vpfe_uservirt_to_phys(vpfe_dev, vb->baddr);
+		/* Make sure user addresses are aligned to 32 bytes */
+		if (!ALIGN(vb->boff, 32))
+			return -EINVAL;
+	}
 	vb->state = VIDEOBUF_PREPARED;
 	return 0;
 }
@@ -1327,13 +1395,6 @@  static int vpfe_reqbufs(struct file *file, void *priv,
 		return -EINVAL;
 	}

-	if (V4L2_MEMORY_USERPTR == req_buf->memory) {
-		/* we don't support user ptr IO */
-		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
-			 " USERPTR IO not supported\n");
-		return  -EINVAL;
-	}
-
 	ret = mutex_lock_interruptible(&vpfe_dev->lock);
 	if (ret)
 		return ret;
@@ -1541,7 +1602,10 @@  static int vpfe_streamon(struct file *file, void *priv,
 	vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
 	/* Initialize field_id and started member */
 	vpfe_dev->field_id = 0;
-	addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
+	if (V4L2_MEMORY_USERPTR == vpfe_dev->memory)
+		addr = vpfe_dev->cur_frm->boff;
+	else
+		addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);

 	/* Calculate field offset */
 	vpfe_calculate_offsets(vpfe_dev);