From patchwork Tue Feb 23 08:34:32 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Hiremath X-Patchwork-Id: 81415 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1N8YldS003041 for ; Tue, 23 Feb 2010 08:34:47 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752178Ab0BWIep (ORCPT ); Tue, 23 Feb 2010 03:34:45 -0500 Received: from bear.ext.ti.com ([192.94.94.41]:49925 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752132Ab0BWIeo (ORCPT ); Tue, 23 Feb 2010 03:34:44 -0500 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id o1N8YeX3003303 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 23 Feb 2010 02:34:43 -0600 Received: from localhost.localdomain (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id o1N8YXE7017447; Tue, 23 Feb 2010 14:04:38 +0530 (IST) From: hvaibhav@ti.com To: linux-media@vger.kernel.org Cc: linux-omap@vger.kernel.org, hverkuil@xs4all.nl, Vaibhav Hiremath , Muralidharan Karicheri Subject: [PATCH-V1 09/10] VPFE Capture: Add support for USERPTR mode of operation Date: Tue, 23 Feb 2010 14:04:32 +0530 Message-Id: <1266914073-30135-10-git-send-email-hvaibhav@ti.com> X-Mailer: git-send-email 1.6.2.4 In-Reply-To: References: Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Tue, 23 Feb 2010 08:34:47 +0000 (UTC) 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(¤t->mm->mmap_sem); + + res = get_user_pages(current, current->mm, + virtp, nr_pages, 1, 0, &pages, NULL); + up_read(¤t->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);