From patchwork Tue Jul 3 09:30:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prabhakar Lad X-Patchwork-Id: 1149831 Return-Path: X-Original-To: patchwork-davinci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by patchwork2.kernel.org (Postfix) with ESMTP id 30171DFF72 for ; Tue, 3 Jul 2012 09:37:46 +0000 (UTC) Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id q639ZqEx024653; Tue, 3 Jul 2012 04:35:59 -0500 Received: from DFLE70.ent.ti.com (dfle70.ent.ti.com [128.247.5.40]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q639Zq0M007940; Tue, 3 Jul 2012 04:35:52 -0500 Received: from dlelxv23.itg.ti.com (172.17.1.198) by dfle70.ent.ti.com (128.247.5.40) with Microsoft SMTP Server id 14.1.323.3; Tue, 3 Jul 2012 04:35:52 -0500 Received: from linux.omap.com (dlelxs01.itg.ti.com [157.170.227.31]) by dlelxv23.itg.ti.com (8.13.8/8.13.8) with ESMTP id q639ZqP5018183; Tue, 3 Jul 2012 04:35:52 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 5545B80626; Tue, 3 Jul 2012 04:35:52 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dbdp20.itg.ti.com (dbdp20.itg.ti.com [172.24.170.38]) by linux.omap.com (Postfix) with ESMTP id 8907D8064C for ; Tue, 3 Jul 2012 04:35:05 -0500 (CDT) Received: from DBDE70.ent.ti.com (localhost [127.0.0.1]) by dbdp20.itg.ti.com (8.13.8/8.13.8) with ESMTP id q639Z4mp024775; Tue, 3 Jul 2012 15:05:04 +0530 (IST) Received: from dbdp32.itg.ti.com (172.24.170.251) by dbde70.ent.ti.com (172.24.170.148) with Microsoft SMTP Server id 14.1.323.3; Tue, 3 Jul 2012 15:05:04 +0530 Received: from psplinux051 (smtpvbd.itg.ti.com [172.24.170.250]) by dbdp32.itg.ti.com (8.13.8/8.13.8) with ESMTP id q639Z41r004971; Tue, 3 Jul 2012 15:05:04 +0530 Received: from x0144960 by psplinux051 with local (Exim 4.74) (envelope-from ) id 1SlzVg-0001Vj-9o; Tue, 03 Jul 2012 15:05:04 +0530 From: Prabhakar Lad To: LMML Subject: [PATCH v4 07/14] davinci: vpif capture: migrate driver to videobuf2 Date: Tue, 3 Jul 2012 15:00:49 +0530 Message-ID: <1341307856-5298-8-git-send-email-prabhakar.lad@ti.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1341307856-5298-1-git-send-email-prabhakar.lad@ti.com> References: <1341307856-5298-1-git-send-email-prabhakar.lad@ti.com> MIME-Version: 1.0 CC: dlos X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com From: Lad, Prabhakar This patch migrates VPIF capture driver to videobuf2 framework. Signed-off-by: Lad, Prabhakar Signed-off-by: Manjunath Hadli --- drivers/media/video/davinci/Kconfig | 2 +- drivers/media/video/davinci/vpif_capture.c | 596 +++++++++++++--------------- drivers/media/video/davinci/vpif_capture.h | 15 +- 3 files changed, 281 insertions(+), 332 deletions(-) diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig index 9337b56..c45739d 100644 --- a/drivers/media/video/davinci/Kconfig +++ b/drivers/media/video/davinci/Kconfig @@ -14,7 +14,7 @@ config DISPLAY_DAVINCI_DM646X_EVM config CAPTURE_DAVINCI_DM646X_EVM tristate "DM646x EVM Video Capture" depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM - select VIDEOBUF_DMA_CONTIG + select VIDEOBUF2_DMA_CONTIG select VIDEO_DAVINCI_VPIF help Support for DM6467 based capture device. diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index d126fb6..3976ff7 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -80,108 +80,45 @@ static struct vpif_config_params config_params = { /* global variables */ static struct vpif_device vpif_obj = { {NULL} }; static struct device *vpif_dev; - -/** - * vpif_uservirt_to_phys : translate user/virtual address to phy address - * @virtp: user/virtual address - * - * This inline function is used to convert user space virtual address to - * physical address. - */ -static inline u32 vpif_uservirt_to_phys(u32 virtp) -{ - unsigned long physp = 0; - struct mm_struct *mm = current->mm; - 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 - * addresses - */ - 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 { - vpif_err("get_user_pages failed\n"); - return 0; - } - } - return physp; -} +static void vpif_calculate_offsets(struct channel_obj *ch); +static void vpif_config_addr(struct channel_obj *ch, int muxmode); /** * buffer_prepare : callback function for buffer prepare - * @q : buffer queue ptr - * @vb: ptr to video buffer - * @field: field info + * @vb: ptr to vb2_buffer * - * This is the callback function for buffer prepare when videobuf_qbuf() + * This is the callback function for buffer prepare when vb2_qbuf() * function is called. The buffer is prepared and user space virtual address * or user address is converted into physical address */ -static int vpif_buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) +static int vpif_buffer_prepare(struct vb2_buffer *vb) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_queue *q = vb->vb2_queue; struct channel_obj *ch = fh->channel; struct common_obj *common; unsigned long addr; - vpif_dbg(2, debug, "vpif_buffer_prepare\n"); common = &ch->common[VPIF_VIDEO_INDEX]; - /* If buffer is not initialized, initialize it */ - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->width = common->width; - vb->height = common->height; - vb->size = vb->width * vb->height; - vb->field = field; - } - vb->state = VIDEOBUF_PREPARED; - /** - * if user pointer memory mechanism is used, get the physical - * address of the buffer - */ - if (V4L2_MEMORY_USERPTR == common->memory) { - if (0 == vb->baddr) { - vpif_dbg(1, debug, "buffer address is 0\n"); - return -EINVAL; - - } - vb->boff = vpif_uservirt_to_phys(vb->baddr); - if (!IS_ALIGNED(vb->boff, 8)) + if (vb->state != VB2_BUF_STATE_ACTIVE && + vb->state != VB2_BUF_STATE_PREPARED) { + vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage); + if (vb2_plane_vaddr(vb, 0) && + vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) goto exit; - } + addr = vb2_dma_contig_plane_dma_addr(vb, 0); - addr = vb->boff; - if (q->streaming) { - if (!IS_ALIGNED((addr + common->ytop_off), 8) || - !IS_ALIGNED((addr + common->ybtm_off), 8) || - !IS_ALIGNED((addr + common->ctop_off), 8) || - !IS_ALIGNED((addr + common->cbtm_off), 8)) - goto exit; + if (q->streaming) { + if (!IS_ALIGNED((addr + common->ytop_off), 8) || + !IS_ALIGNED((addr + common->ybtm_off), 8) || + !IS_ALIGNED((addr + common->ctop_off), 8) || + !IS_ALIGNED((addr + common->cbtm_off), 8)) + goto exit; + } } return 0; exit: @@ -190,66 +127,79 @@ exit: } /** - * vpif_buffer_setup : Callback function for buffer setup. - * @q: buffer queue ptr - * @count: number of buffers - * @size: size of the buffer + * vpif_buffer_queue_setup : Callback function for buffer setup. + * @vq: vb2_queue ptr + * @fmt: v4l2 format + * @nbuffers: ptr to number of buffers requested by application + * @nplanes:: contains number of distinct video planes needed to hold a frame + * @sizes[]: contains the size (in bytes) of each plane. + * @alloc_ctxs: ptr to allocation context * * This callback function is called when reqbuf() is called to adjust * the buffer count and buffer size */ -static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) +static int vpif_buffer_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vq); struct channel_obj *ch = fh->channel; struct common_obj *common; + unsigned long size; common = &ch->common[VPIF_VIDEO_INDEX]; vpif_dbg(2, debug, "vpif_buffer_setup\n"); /* If memory type is not mmap, return */ - if (V4L2_MEMORY_MMAP != common->memory) - return 0; - - /* Calculate the size of the buffer */ - *size = config_params.channel_bufsize[ch->channel_id]; - - /* - * Checking if the buffer size exceeds the available buffer - * ycmux_mode = 0 means 1 channel mode HD and - * ycmux_mode = 1 means 2 channels mode SD - */ - if (ch->vpifparams.std_info.ycmux_mode == 0) { - if (config_params.video_limit[ch->channel_id]) - while (*size * *count > (config_params.video_limit[0] + if (V4L2_MEMORY_MMAP == common->memory) { + /* Calculate the size of the buffer */ + size = config_params.channel_bufsize[ch->channel_id]; + /* + * Checking if the buffer size exceeds the available buffer + * ycmux_mode = 0 means 1 channel mode HD and + * ycmux_mode = 1 means 2 channels mode SD + */ + if (ch->vpifparams.std_info.ycmux_mode == 0) { + if (config_params.video_limit[ch->channel_id]) + while (size * *nbuffers > + (config_params.video_limit[0] + config_params.video_limit[1])) - (*count)--; - } else { - if (config_params.video_limit[ch->channel_id]) - while (*size * *count > + (*nbuffers)--; + } else { + if (config_params.video_limit[ch->channel_id]) + while (size * *nbuffers > config_params.video_limit[ch->channel_id]) - (*count)--; + (*nbuffers)--; + } + + } else { + size = common->fmt.fmt.pix.sizeimage; } - if (*count < config_params.min_numbuffers) - *count = config_params.min_numbuffers; + if (*nbuffers < config_params.min_numbuffers) + *nbuffers = config_params.min_numbuffers; + + *nplanes = 1; + sizes[0] = size; + alloc_ctxs[0] = common->alloc_ctx; + return 0; } /** * vpif_buffer_queue : Callback function to add buffer to DMA queue - * @q: ptr to videobuf_queue - * @vb: ptr to videobuf_buffer + * @vb: ptr to vb2_buffer */ -static void vpif_buffer_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpif_buffer_queue(struct vb2_buffer *vb) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); struct channel_obj *ch = fh->channel; + struct vpif_cap_buffer *buf = container_of(vb, + struct vpif_cap_buffer, vb); struct common_obj *common; common = &ch->common[VPIF_VIDEO_INDEX]; @@ -257,43 +207,189 @@ static void vpif_buffer_queue(struct videobuf_queue *q, vpif_dbg(2, debug, "vpif_buffer_queue\n"); /* add the buffer to the DMA queue */ - list_add_tail(&vb->queue, &common->dma_queue); - /* Change state of the buffer */ - vb->state = VIDEOBUF_QUEUED; + list_add_tail(&buf->list, &common->dma_queue); } /** - * vpif_buffer_release : Callback function to free buffer - * @q: buffer queue ptr - * @vb: ptr to video buffer + * vpif_buf_cleanup : Callback function to free buffer + * @vb: ptr to vb2_buffer * - * This function is called from the videobuf layer to free memory + * This function is called from the videobuf2 layer to free memory * allocated to the buffers */ -static void vpif_buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpif_buf_cleanup(struct vb2_buffer *vb) { /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; + struct vpif_fh *fh = vb2_get_drv_priv(vb->vb2_queue); + struct vpif_cap_buffer *buf = container_of(vb, + struct vpif_cap_buffer, vb); struct channel_obj *ch = fh->channel; struct common_obj *common; + unsigned long flags; common = &ch->common[VPIF_VIDEO_INDEX]; - videobuf_dma_contig_free(q, vb); - vb->state = VIDEOBUF_NEEDS_INIT; + spin_lock_irqsave(&common->irqlock, flags); + if (vb->state == VB2_BUF_STATE_ACTIVE) + list_del_init(&buf->list); + spin_unlock_irqrestore(&common->irqlock, flags); + } -static struct videobuf_queue_ops video_qops = { - .buf_setup = vpif_buffer_setup, - .buf_prepare = vpif_buffer_prepare, - .buf_queue = vpif_buffer_queue, - .buf_release = vpif_buffer_release, -}; +static void vpif_wait_prepare(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_unlock(&common->lock); +} + +static void vpif_wait_finish(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + common = &ch->common[VPIF_VIDEO_INDEX]; + mutex_lock(&common->lock); +} + +static int vpif_buffer_init(struct vb2_buffer *vb) +{ + struct vpif_cap_buffer *buf = container_of(vb, + struct vpif_cap_buffer, vb); + + INIT_LIST_HEAD(&buf->list); + + return 0; +} static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = { {1, 1} }; +static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct vpif_capture_config *vpif_config_data = + vpif_dev->platform_data; + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct vpif_params *vpif = &ch->vpifparams; + unsigned long addr = 0; + int ret; + + /* If buffer queue is empty, return error */ + if (list_empty(&common->dma_queue)) { + vpif_dbg(1, debug, "buffer queue is empty\n"); + return -EIO; + } + + /* Get the next frame from the buffer queue */ + common->cur_frm = common->next_frm = list_entry(common->dma_queue.next, + struct vpif_cap_buffer, list); + /* Remove buffer from the buffer queue */ + list_del(&common->cur_frm->list); + /* Mark state of the current frame to active */ + common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; + /* Initialize field_id and started member */ + ch->field_id = 0; + common->started = 1; + addr = vb2_dma_contig_plane_dma_addr(&common->cur_frm->vb, 0); + + /* Calculate the offset for Y and C data in the buffer */ + vpif_calculate_offsets(ch); + + if ((vpif->std_info.frm_fmt && + ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) && + (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) || + (!vpif->std_info.frm_fmt && + (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { + vpif_dbg(1, debug, "conflict in field format and std format\n"); + return -EINVAL; + } + + /* configure 1 or 2 channel mode */ + ret = vpif_config_data->setup_input_channel_mode + (vpif->std_info.ycmux_mode); + + if (ret < 0) { + vpif_dbg(1, debug, "can't set vpif channel mode\n"); + return ret; + } + + /* Call vpif_set_params function to set the parameters and addresses */ + ret = vpif_set_video_params(vpif, ch->channel_id); + + if (ret < 0) { + vpif_dbg(1, debug, "can't set video params\n"); + return ret; + } + + common->started = ret; + vpif_config_addr(ch, ret); + + common->set_addr(addr + common->ytop_off, + addr + common->ybtm_off, + addr + common->ctop_off, + addr + common->cbtm_off); + + /** + * Set interrupt for both the fields in VPIF Register enable channel in + * VPIF register + */ + if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { + channel0_intr_assert(); + channel0_intr_enable(1); + enable_channel0(1); + } + if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || + (common->started == 2)) { + channel1_intr_assert(); + channel1_intr_enable(1); + enable_channel1(1); + } + channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; + + return 0; +} + +/* abort streaming and wait for last buffer */ +static int vpif_stop_streaming(struct vb2_queue *vq) +{ + struct vpif_fh *fh = vb2_get_drv_priv(vq); + struct channel_obj *ch = fh->channel; + struct common_obj *common; + + if (!vb2_is_streaming(vq)) + return 0; + + common = &ch->common[VPIF_VIDEO_INDEX]; + + /* release all active buffers */ + while (!list_empty(&common->dma_queue)) { + common->next_frm = list_entry(common->dma_queue.next, + struct vpif_cap_buffer, list); + list_del(&common->next_frm->list); + vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); + } + + return 0; +} + +static struct vb2_ops video_qops = { + .queue_setup = vpif_buffer_queue_setup, + .wait_prepare = vpif_wait_prepare, + .wait_finish = vpif_wait_finish, + .buf_init = vpif_buffer_init, + .buf_prepare = vpif_buffer_prepare, + .start_streaming = vpif_start_streaming, + .stop_streaming = vpif_stop_streaming, + .buf_cleanup = vpif_buf_cleanup, + .buf_queue = vpif_buffer_queue, +}; + /** * vpif_process_buffer_complete: process a completed buffer * @common: ptr to common channel object @@ -304,9 +400,9 @@ static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = */ static void vpif_process_buffer_complete(struct common_obj *common) { - do_gettimeofday(&common->cur_frm->ts); - common->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&common->cur_frm->done); + do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp); + vb2_buffer_done(&common->cur_frm->vb, + VB2_BUF_STATE_DONE); /* Make curFrm pointing to nextFrm */ common->cur_frm = common->next_frm; } @@ -324,14 +420,11 @@ static void vpif_schedule_next_buffer(struct common_obj *common) unsigned long addr = 0; common->next_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); + struct vpif_cap_buffer, list); /* Remove that buffer from the buffer queue */ - list_del(&common->next_frm->queue); - common->next_frm->state = VIDEOBUF_ACTIVE; - if (V4L2_MEMORY_USERPTR == common->memory) - addr = common->next_frm->boff; - else - addr = videobuf_to_dma_contig(common->next_frm); + list_del(&common->next_frm->list); + common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE; + addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0); /* Set top and bottom field addresses in VPIF registers */ common->set_addr(addr + common->ytop_off, @@ -505,10 +598,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch) } else vid_ch->buf_field = common->fmt.fmt.pix.field; - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = common->fmt.fmt.pix.sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; + sizeimage = common->fmt.fmt.pix.sizeimage; hpitch = common->fmt.fmt.pix.bytesperline; vpitch = sizeimage / (hpitch * 2); @@ -660,10 +750,7 @@ static int vpif_check_format(struct channel_obj *ch, hpitch = vpif_params->std_info.width; } - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = pixfmt->sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; + sizeimage = pixfmt->sizeimage; vpitch = sizeimage / (hpitch * 2); @@ -736,7 +823,7 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) vpif_dbg(2, debug, "vpif_mmap\n"); - return videobuf_mmap_mapper(&common->buffer_queue, vma); + return vb2_mmap(&common->buffer_queue, vma); } /** @@ -753,7 +840,7 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait) vpif_dbg(2, debug, "vpif_poll\n"); if (common->started) - return videobuf_poll_stream(filep, &common->buffer_queue, wait); + return vb2_poll(&common->buffer_queue, filep, wait); return 0; } @@ -861,8 +948,8 @@ static int vpif_release(struct file *filep) } common->started = 0; /* Free buffers allocated */ - videobuf_queue_cancel(&common->buffer_queue); - videobuf_mmap_free(&common->buffer_queue); + vb2_queue_release(&common->buffer_queue); + vb2_dma_contig_cleanup_ctx(common->alloc_ctx); } /* Decrement channel usrs counter */ @@ -892,6 +979,7 @@ static int vpif_reqbufs(struct file *file, void *priv, struct channel_obj *ch = fh->channel; struct common_obj *common; u8 index = 0; + struct vb2_queue *q; vpif_dbg(2, debug, "vpif_reqbufs\n"); @@ -917,14 +1005,21 @@ static int vpif_reqbufs(struct file *file, void *priv, if (0 != common->io_usrs) return -EBUSY; - /* Initialize videobuf queue as per the buffer type */ - videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, vpif_dev, - &common->irqlock, - reqbuf->type, - common->fmt.fmt.pix.field, - sizeof(struct videobuf_buffer), fh, - &common->lock); + /* Initialize videobuf2 queue as per the buffer type */ + common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev); + if (!common->alloc_ctx) { + vpif_err("Failed to get the context\n"); + return -EINVAL; + } + q = &common->buffer_queue; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = fh; + q->ops = &video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct vb2_buffer); + + vb2_queue_init(q); /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; @@ -935,7 +1030,7 @@ static int vpif_reqbufs(struct file *file, void *priv, INIT_LIST_HEAD(&common->dma_queue); /* Allocate buffers */ - return videobuf_reqbufs(&common->buffer_queue, reqbuf); + return vb2_reqbufs(&common->buffer_queue, reqbuf); } /** @@ -961,7 +1056,7 @@ static int vpif_querybuf(struct file *file, void *priv, return -EINVAL; } - return videobuf_querybuf(&common->buffer_queue, buf); + return vb2_querybuf(&common->buffer_queue, buf); } /** @@ -977,10 +1072,6 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct v4l2_buffer tbuf = *buf; - struct videobuf_buffer *buf1; - unsigned long addr = 0; - unsigned long flags; - int ret = 0; vpif_dbg(2, debug, "vpif_qbuf\n"); @@ -990,76 +1081,11 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) } if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_err("fh io not allowed \n"); + vpif_err("fh io not allowed\n"); return -EACCES; } - if (!(list_empty(&common->dma_queue)) || - (common->cur_frm != common->next_frm) || - !common->started || - (common->started && (0 == ch->field_id))) - return videobuf_qbuf(&common->buffer_queue, buf); - - /* bufferqueue is empty store buffer address in VPIF registers */ - mutex_lock(&common->buffer_queue.vb_lock); - buf1 = common->buffer_queue.bufs[tbuf.index]; - - if ((buf1->state == VIDEOBUF_QUEUED) || - (buf1->state == VIDEOBUF_ACTIVE)) { - vpif_err("invalid state\n"); - goto qbuf_exit; - } - - switch (buf1->memory) { - case V4L2_MEMORY_MMAP: - if (buf1->baddr == 0) - goto qbuf_exit; - break; - - case V4L2_MEMORY_USERPTR: - if (tbuf.length < buf1->bsize) - goto qbuf_exit; - - if ((VIDEOBUF_NEEDS_INIT != buf1->state) - && (buf1->baddr != tbuf.m.userptr)) { - vpif_buffer_release(&common->buffer_queue, buf1); - buf1->baddr = tbuf.m.userptr; - } - break; - - default: - goto qbuf_exit; - } - - local_irq_save(flags); - ret = vpif_buffer_prepare(&common->buffer_queue, buf1, - common->buffer_queue.field); - if (ret < 0) { - local_irq_restore(flags); - goto qbuf_exit; - } - - buf1->state = VIDEOBUF_ACTIVE; - - if (V4L2_MEMORY_USERPTR == common->memory) - addr = buf1->boff; - else - addr = videobuf_to_dma_contig(buf1); - - common->next_frm = buf1; - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); - - local_irq_restore(flags); - list_add_tail(&buf1->stream, &common->buffer_queue.stream); - mutex_unlock(&common->buffer_queue.vb_lock); - return 0; - -qbuf_exit: - mutex_unlock(&common->buffer_queue.vb_lock); - return -EINVAL; + return vb2_qbuf(&common->buffer_queue, buf); } /** @@ -1076,8 +1102,8 @@ static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) vpif_dbg(2, debug, "vpif_dqbuf\n"); - return videobuf_dqbuf(&common->buffer_queue, buf, - file->f_flags & O_NONBLOCK); + return vb2_dqbuf(&common->buffer_queue, buf, + (file->f_flags & O_NONBLOCK)); } /** @@ -1090,13 +1116,11 @@ static int vpif_streamon(struct file *file, void *priv, enum v4l2_buf_type buftype) { - struct vpif_capture_config *config = vpif_dev->platform_data; struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; struct vpif_params *vpif; - unsigned long addr = 0; int ret = 0; vpif_dbg(2, debug, "vpif_streamon\n"); @@ -1142,95 +1166,13 @@ static int vpif_streamon(struct file *file, void *priv, return ret; } - /* Call videobuf_streamon to start streaming in videobuf */ - ret = videobuf_streamon(&common->buffer_queue); + /* Call vb2_streamon to start streaming in videobuf2 */ + ret = vb2_streamon(&common->buffer_queue, buftype); if (ret) { - vpif_dbg(1, debug, "videobuf_streamon\n"); + vpif_dbg(1, debug, "vb2_streamon\n"); return ret; } - /* If buffer queue is empty, return error */ - if (list_empty(&common->dma_queue)) { - vpif_dbg(1, debug, "buffer queue is empty\n"); - ret = -EIO; - goto exit; - } - - /* Get the next frame from the buffer queue */ - common->cur_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - common->next_frm = common->cur_frm; - - /* Remove buffer from the buffer queue */ - list_del(&common->cur_frm->queue); - /* Mark state of the current frame to active */ - common->cur_frm->state = VIDEOBUF_ACTIVE; - /* Initialize field_id and started member */ - ch->field_id = 0; - common->started = 1; - - if (V4L2_MEMORY_USERPTR == common->memory) - addr = common->cur_frm->boff; - else - addr = videobuf_to_dma_contig(common->cur_frm); - - /* Calculate the offset for Y and C data in the buffer */ - vpif_calculate_offsets(ch); - - if ((vpif->std_info.frm_fmt && - ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) && - (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) || - (!vpif->std_info.frm_fmt && - (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { - vpif_dbg(1, debug, "conflict in field format and std format\n"); - ret = -EINVAL; - goto exit; - } - - /* configure 1 or 2 channel mode */ - ret = config->setup_input_channel_mode(vpif->std_info.ycmux_mode); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set vpif channel mode\n"); - goto exit; - } - - /* Call vpif_set_params function to set the parameters and addresses */ - ret = vpif_set_video_params(vpif, ch->channel_id); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set video params\n"); - goto exit; - } - - common->started = ret; - vpif_config_addr(ch, ret); - - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); - - /** - * Set interrupt for both the fields in VPIF Register enable channel in - * VPIF register - */ - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { - channel0_intr_assert(); - channel0_intr_enable(1); - enable_channel0(1); - } - if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || - (common->started == 2)) { - channel1_intr_assert(); - channel1_intr_enable(1); - enable_channel1(1); - } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; - return ret; - -exit: - videobuf_streamoff(&common->buffer_queue); return ret; } @@ -1285,7 +1227,7 @@ static int vpif_streamoff(struct file *file, void *priv, if (ret && (ret != -ENOIOCTLCMD)) vpif_dbg(1, debug, "stream off failed in subdev\n"); - return videobuf_streamoff(&common->buffer_queue); + return vb2_streamoff(&common->buffer_queue, buftype); } /** diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h index 8095910..3511510 100644 --- a/drivers/media/video/davinci/vpif_capture.h +++ b/drivers/media/video/davinci/vpif_capture.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include "vpif.h" @@ -60,11 +60,16 @@ struct video_obj { u32 input_idx; }; +struct vpif_cap_buffer { + struct vb2_buffer vb; + struct list_head list; +}; + struct common_obj { /* Pointer pointing to current v4l2_buffer */ - struct videobuf_buffer *cur_frm; + struct vpif_cap_buffer *cur_frm; /* Pointer pointing to current v4l2_buffer */ - struct videobuf_buffer *next_frm; + struct vpif_cap_buffer *next_frm; /* * This field keeps track of type of buffer exchange mechanism * user has selected @@ -73,7 +78,9 @@ struct common_obj { /* Used to store pixel format */ struct v4l2_format fmt; /* Buffer queue used in video-buf */ - struct videobuf_queue buffer_queue; + struct vb2_queue buffer_queue; + /* allocator-specific contexts for each plane */ + struct vb2_alloc_ctx *alloc_ctx; /* Queue of filled frames */ struct list_head dma_queue; /* Used in video-buf */