Commit 60aa38d8 authored by Lad, Prabhakar's avatar Lad, Prabhakar Committed by Mauro Carvalho Chehab

[media] davinci: vpif capture: migrate driver to videobuf2

This patch migrates VPIF capture driver to videobuf2 framework.
Signed-off-by: default avatarLad, Prabhakar <prabhakar.lad@ti.com>
Signed-off-by: default avatarManjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 764af39a
...@@ -14,7 +14,7 @@ config DISPLAY_DAVINCI_DM646X_EVM ...@@ -14,7 +14,7 @@ config DISPLAY_DAVINCI_DM646X_EVM
config CAPTURE_DAVINCI_DM646X_EVM config CAPTURE_DAVINCI_DM646X_EVM
tristate "DM646x EVM Video Capture" tristate "DM646x EVM Video Capture"
depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
select VIDEOBUF_DMA_CONTIG select VIDEOBUF2_DMA_CONTIG
select VIDEO_DAVINCI_VPIF select VIDEO_DAVINCI_VPIF
help help
Support for DM6467 based capture device. Support for DM6467 based capture device.
......
...@@ -80,108 +80,45 @@ static struct vpif_config_params config_params = { ...@@ -80,108 +80,45 @@ static struct vpif_config_params config_params = {
/* global variables */ /* global variables */
static struct vpif_device vpif_obj = { {NULL} }; static struct vpif_device vpif_obj = { {NULL} };
static struct device *vpif_dev; static struct device *vpif_dev;
static void vpif_calculate_offsets(struct channel_obj *ch);
/** static void vpif_config_addr(struct channel_obj *ch, int muxmode);
* 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(&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 {
vpif_err("get_user_pages failed\n");
return 0;
}
}
return physp;
}
/** /**
* buffer_prepare : callback function for buffer prepare * buffer_prepare : callback function for buffer prepare
* @q : buffer queue ptr * @vb: ptr to vb2_buffer
* @vb: ptr to video buffer
* @field: field info
* *
* 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 * function is called. The buffer is prepared and user space virtual address
* or user address is converted into physical address * or user address is converted into physical address
*/ */
static int vpif_buffer_prepare(struct videobuf_queue *q, static int vpif_buffer_prepare(struct vb2_buffer *vb)
struct videobuf_buffer *vb,
enum v4l2_field field)
{ {
/* Get the file handle object and channel object */ /* 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 channel_obj *ch = fh->channel;
struct common_obj *common; struct common_obj *common;
unsigned long addr; unsigned long addr;
vpif_dbg(2, debug, "vpif_buffer_prepare\n"); vpif_dbg(2, debug, "vpif_buffer_prepare\n");
common = &ch->common[VPIF_VIDEO_INDEX]; common = &ch->common[VPIF_VIDEO_INDEX];
/* If buffer is not initialized, initialize it */ if (vb->state != VB2_BUF_STATE_ACTIVE &&
if (VIDEOBUF_NEEDS_INIT == vb->state) { vb->state != VB2_BUF_STATE_PREPARED) {
vb->width = common->width; vb2_set_plane_payload(vb, 0, common->fmt.fmt.pix.sizeimage);
vb->height = common->height; if (vb2_plane_vaddr(vb, 0) &&
vb->size = vb->width * vb->height; vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
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))
goto exit; goto exit;
} addr = vb2_dma_contig_plane_dma_addr(vb, 0);
addr = vb->boff; if (q->streaming) {
if (q->streaming) { if (!IS_ALIGNED((addr + common->ytop_off), 8) ||
if (!IS_ALIGNED((addr + common->ytop_off), 8) || !IS_ALIGNED((addr + common->ybtm_off), 8) ||
!IS_ALIGNED((addr + common->ybtm_off), 8) || !IS_ALIGNED((addr + common->ctop_off), 8) ||
!IS_ALIGNED((addr + common->ctop_off), 8) || !IS_ALIGNED((addr + common->cbtm_off), 8))
!IS_ALIGNED((addr + common->cbtm_off), 8)) goto exit;
goto exit; }
} }
return 0; return 0;
exit: exit:
...@@ -190,66 +127,79 @@ static int vpif_buffer_prepare(struct videobuf_queue *q, ...@@ -190,66 +127,79 @@ static int vpif_buffer_prepare(struct videobuf_queue *q,
} }
/** /**
* vpif_buffer_setup : Callback function for buffer setup. * vpif_buffer_queue_setup : Callback function for buffer setup.
* @q: buffer queue ptr * @vq: vb2_queue ptr
* @count: number of buffers * @fmt: v4l2 format
* @size: size of the buffer * @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 * This callback function is called when reqbuf() is called to adjust
* the buffer count and buffer size * the buffer count and buffer size
*/ */
static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, static int vpif_buffer_queue_setup(struct vb2_queue *vq,
unsigned int *size) 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 */ /* 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 channel_obj *ch = fh->channel;
struct common_obj *common; struct common_obj *common;
unsigned long size;
common = &ch->common[VPIF_VIDEO_INDEX]; common = &ch->common[VPIF_VIDEO_INDEX];
vpif_dbg(2, debug, "vpif_buffer_setup\n"); vpif_dbg(2, debug, "vpif_buffer_setup\n");
/* If memory type is not mmap, return */ /* If memory type is not mmap, return */
if (V4L2_MEMORY_MMAP != common->memory) if (V4L2_MEMORY_MMAP == common->memory) {
return 0; /* Calculate the size of the buffer */
size = config_params.channel_bufsize[ch->channel_id];
/* 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
* Checking if the buffer size exceeds the available buffer */
* ycmux_mode = 0 means 1 channel mode HD and if (ch->vpifparams.std_info.ycmux_mode == 0) {
* ycmux_mode = 1 means 2 channels mode SD if (config_params.video_limit[ch->channel_id])
*/ while (size * *nbuffers >
if (ch->vpifparams.std_info.ycmux_mode == 0) { (config_params.video_limit[0]
if (config_params.video_limit[ch->channel_id])
while (*size * *count > (config_params.video_limit[0]
+ config_params.video_limit[1])) + config_params.video_limit[1]))
(*count)--; (*nbuffers)--;
} else { } else {
if (config_params.video_limit[ch->channel_id]) if (config_params.video_limit[ch->channel_id])
while (*size * *count > while (size * *nbuffers >
config_params.video_limit[ch->channel_id]) config_params.video_limit[ch->channel_id])
(*count)--; (*nbuffers)--;
}
} else {
size = common->fmt.fmt.pix.sizeimage;
} }
if (*count < config_params.min_numbuffers) if (*nbuffers < config_params.min_numbuffers)
*count = config_params.min_numbuffers; *nbuffers = config_params.min_numbuffers;
*nplanes = 1;
sizes[0] = size;
alloc_ctxs[0] = common->alloc_ctx;
return 0; return 0;
} }
/** /**
* vpif_buffer_queue : Callback function to add buffer to DMA queue * vpif_buffer_queue : Callback function to add buffer to DMA queue
* @q: ptr to videobuf_queue * @vb: ptr to vb2_buffer
* @vb: ptr to videobuf_buffer
*/ */
static void vpif_buffer_queue(struct videobuf_queue *q, static void vpif_buffer_queue(struct vb2_buffer *vb)
struct videobuf_buffer *vb)
{ {
/* Get the file handle object and channel object */ /* 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 channel_obj *ch = fh->channel;
struct vpif_cap_buffer *buf = container_of(vb,
struct vpif_cap_buffer, vb);
struct common_obj *common; struct common_obj *common;
common = &ch->common[VPIF_VIDEO_INDEX]; common = &ch->common[VPIF_VIDEO_INDEX];
...@@ -257,43 +207,189 @@ static void vpif_buffer_queue(struct videobuf_queue *q, ...@@ -257,43 +207,189 @@ static void vpif_buffer_queue(struct videobuf_queue *q,
vpif_dbg(2, debug, "vpif_buffer_queue\n"); vpif_dbg(2, debug, "vpif_buffer_queue\n");
/* add the buffer to the DMA queue */ /* add the buffer to the DMA queue */
list_add_tail(&vb->queue, &common->dma_queue); list_add_tail(&buf->list, &common->dma_queue);
/* Change state of the buffer */
vb->state = VIDEOBUF_QUEUED;
} }
/** /**
* vpif_buffer_release : Callback function to free buffer * vpif_buf_cleanup : Callback function to free buffer
* @q: buffer queue ptr * @vb: ptr to vb2_buffer
* @vb: ptr to video 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 * allocated to the buffers
*/ */
static void vpif_buffer_release(struct videobuf_queue *q, static void vpif_buf_cleanup(struct vb2_buffer *vb)
struct videobuf_buffer *vb)
{ {
/* Get the file handle object and channel object */ /* 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 channel_obj *ch = fh->channel;
struct common_obj *common; struct common_obj *common;
unsigned long flags;
common = &ch->common[VPIF_VIDEO_INDEX]; common = &ch->common[VPIF_VIDEO_INDEX];
videobuf_dma_contig_free(q, vb); spin_lock_irqsave(&common->irqlock, flags);
vb->state = VIDEOBUF_NEEDS_INIT; 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 = { static void vpif_wait_prepare(struct vb2_queue *vq)
.buf_setup = vpif_buffer_setup, {
.buf_prepare = vpif_buffer_prepare, struct vpif_fh *fh = vb2_get_drv_priv(vq);
.buf_queue = vpif_buffer_queue, struct channel_obj *ch = fh->channel;
.buf_release = vpif_buffer_release, 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] = static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] =
{ {1, 1} }; { {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 * vpif_process_buffer_complete: process a completed buffer
* @common: ptr to common channel object * @common: ptr to common channel object
...@@ -304,9 +400,9 @@ static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = ...@@ -304,9 +400,9 @@ static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] =
*/ */
static void vpif_process_buffer_complete(struct common_obj *common) static void vpif_process_buffer_complete(struct common_obj *common)
{ {
do_gettimeofday(&common->cur_frm->ts); do_gettimeofday(&common->cur_frm->vb.v4l2_buf.timestamp);
common->cur_frm->state = VIDEOBUF_DONE; vb2_buffer_done(&common->cur_frm->vb,
wake_up_interruptible(&common->cur_frm->done); VB2_BUF_STATE_DONE);
/* Make curFrm pointing to nextFrm */ /* Make curFrm pointing to nextFrm */
common->cur_frm = common->next_frm; common->cur_frm = common->next_frm;
} }
...@@ -324,14 +420,11 @@ static void vpif_schedule_next_buffer(struct common_obj *common) ...@@ -324,14 +420,11 @@ static void vpif_schedule_next_buffer(struct common_obj *common)
unsigned long addr = 0; unsigned long addr = 0;
common->next_frm = list_entry(common->dma_queue.next, 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 */ /* Remove that buffer from the buffer queue */
list_del(&common->next_frm->queue); list_del(&common->next_frm->list);
common->next_frm->state = VIDEOBUF_ACTIVE; common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
if (V4L2_MEMORY_USERPTR == common->memory) addr = vb2_dma_contig_plane_dma_addr(&common->next_frm->vb, 0);
addr = common->next_frm->boff;
else
addr = videobuf_to_dma_contig(common->next_frm);
/* Set top and bottom field addresses in VPIF registers */ /* Set top and bottom field addresses in VPIF registers */
common->set_addr(addr + common->ytop_off, common->set_addr(addr + common->ytop_off,
...@@ -505,10 +598,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch) ...@@ -505,10 +598,7 @@ static void vpif_calculate_offsets(struct channel_obj *ch)
} else } else
vid_ch->buf_field = common->fmt.fmt.pix.field; vid_ch->buf_field = common->fmt.fmt.pix.field;
if (V4L2_MEMORY_USERPTR == common->memory) sizeimage = common->fmt.fmt.pix.sizeimage;
sizeimage = common->fmt.fmt.pix.sizeimage;
else
sizeimage = config_params.channel_bufsize[ch->channel_id];
hpitch = common->fmt.fmt.pix.bytesperline; hpitch = common->fmt.fmt.pix.bytesperline;
vpitch = sizeimage / (hpitch * 2); vpitch = sizeimage / (hpitch * 2);
...@@ -660,10 +750,7 @@ static int vpif_check_format(struct channel_obj *ch, ...@@ -660,10 +750,7 @@ static int vpif_check_format(struct channel_obj *ch,
hpitch = vpif_params->std_info.width; hpitch = vpif_params->std_info.width;
} }
if (V4L2_MEMORY_USERPTR == common->memory) sizeimage = pixfmt->sizeimage;
sizeimage = pixfmt->sizeimage;
else
sizeimage = config_params.channel_bufsize[ch->channel_id];
vpitch = sizeimage / (hpitch * 2); vpitch = sizeimage / (hpitch * 2);
...@@ -736,7 +823,7 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) ...@@ -736,7 +823,7 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
vpif_dbg(2, debug, "vpif_mmap\n"); 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) ...@@ -753,7 +840,7 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait)
vpif_dbg(2, debug, "vpif_poll\n"); vpif_dbg(2, debug, "vpif_poll\n");
if (common->started) if (common->started)
return videobuf_poll_stream(filep, &common->buffer_queue, wait); return vb2_poll(&common->buffer_queue, filep, wait);
return 0; return 0;
} }
...@@ -861,8 +948,8 @@ static int vpif_release(struct file *filep) ...@@ -861,8 +948,8 @@ static int vpif_release(struct file *filep)
} }
common->started = 0; common->started = 0;
/* Free buffers allocated */ /* Free buffers allocated */
videobuf_queue_cancel(&common->buffer_queue); vb2_queue_release(&common->buffer_queue);
videobuf_mmap_free(&common->buffer_queue); vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
} }
/* Decrement channel usrs counter */ /* Decrement channel usrs counter */
...@@ -892,6 +979,7 @@ static int vpif_reqbufs(struct file *file, void *priv, ...@@ -892,6 +979,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
struct channel_obj *ch = fh->channel; struct channel_obj *ch = fh->channel;
struct common_obj *common; struct common_obj *common;
u8 index = 0; u8 index = 0;
struct vb2_queue *q;
vpif_dbg(2, debug, "vpif_reqbufs\n"); vpif_dbg(2, debug, "vpif_reqbufs\n");
...@@ -917,14 +1005,21 @@ static int vpif_reqbufs(struct file *file, void *priv, ...@@ -917,14 +1005,21 @@ static int vpif_reqbufs(struct file *file, void *priv,
if (0 != common->io_usrs) if (0 != common->io_usrs)
return -EBUSY; return -EBUSY;
/* Initialize videobuf queue as per the buffer type */ /* Initialize videobuf2 queue as per the buffer type */
videobuf_queue_dma_contig_init(&common->buffer_queue, common->alloc_ctx = vb2_dma_contig_init_ctx(vpif_dev);
&video_qops, vpif_dev, if (!common->alloc_ctx) {
&common->irqlock, vpif_err("Failed to get the context\n");
reqbuf->type, return -EINVAL;
common->fmt.fmt.pix.field, }
sizeof(struct videobuf_buffer), fh, q = &common->buffer_queue;
&common->lock); 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 vpif_cap_buffer);
vb2_queue_init(q);
/* Set io allowed member of file handle to TRUE */ /* Set io allowed member of file handle to TRUE */
fh->io_allowed[index] = 1; fh->io_allowed[index] = 1;
...@@ -935,7 +1030,7 @@ static int vpif_reqbufs(struct file *file, void *priv, ...@@ -935,7 +1030,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
INIT_LIST_HEAD(&common->dma_queue); INIT_LIST_HEAD(&common->dma_queue);
/* Allocate buffers */ /* 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, ...@@ -961,7 +1056,7 @@ static int vpif_querybuf(struct file *file, void *priv,
return -EINVAL; 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) ...@@ -977,10 +1072,6 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
struct channel_obj *ch = fh->channel; struct channel_obj *ch = fh->channel;
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
struct v4l2_buffer tbuf = *buf; 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"); vpif_dbg(2, debug, "vpif_qbuf\n");
...@@ -990,76 +1081,11 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ...@@ -990,76 +1081,11 @@ static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
} }
if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
vpif_err("fh io not allowed \n"); vpif_err("fh io not allowed\n");
return -EACCES; return -EACCES;
} }
if (!(list_empty(&common->dma_queue)) || return vb2_qbuf(&common->buffer_queue, buf);
(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;
} }
/** /**
...@@ -1076,8 +1102,8 @@ static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *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"); vpif_dbg(2, debug, "vpif_dqbuf\n");
return videobuf_dqbuf(&common->buffer_queue, buf, return vb2_dqbuf(&common->buffer_queue, buf,
file->f_flags & O_NONBLOCK); (file->f_flags & O_NONBLOCK));
} }
/** /**
...@@ -1090,13 +1116,11 @@ static int vpif_streamon(struct file *file, void *priv, ...@@ -1090,13 +1116,11 @@ static int vpif_streamon(struct file *file, void *priv,
enum v4l2_buf_type buftype) enum v4l2_buf_type buftype)
{ {
struct vpif_capture_config *config = vpif_dev->platform_data;
struct vpif_fh *fh = priv; struct vpif_fh *fh = priv;
struct channel_obj *ch = fh->channel; struct channel_obj *ch = fh->channel;
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
struct vpif_params *vpif; struct vpif_params *vpif;
unsigned long addr = 0;
int ret = 0; int ret = 0;
vpif_dbg(2, debug, "vpif_streamon\n"); vpif_dbg(2, debug, "vpif_streamon\n");
...@@ -1142,95 +1166,13 @@ static int vpif_streamon(struct file *file, void *priv, ...@@ -1142,95 +1166,13 @@ static int vpif_streamon(struct file *file, void *priv,
return ret; return ret;
} }
/* Call videobuf_streamon to start streaming in videobuf */ /* Call vb2_streamon to start streaming in videobuf2 */
ret = videobuf_streamon(&common->buffer_queue); ret = vb2_streamon(&common->buffer_queue, buftype);
if (ret) { if (ret) {
vpif_dbg(1, debug, "videobuf_streamon\n"); vpif_dbg(1, debug, "vb2_streamon\n");
return ret; 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; return ret;
} }
...@@ -1285,7 +1227,7 @@ static int vpif_streamoff(struct file *file, void *priv, ...@@ -1285,7 +1227,7 @@ static int vpif_streamoff(struct file *file, void *priv,
if (ret && (ret != -ENOIOCTLCMD)) if (ret && (ret != -ENOIOCTLCMD))
vpif_dbg(1, debug, "stream off failed in subdev\n"); vpif_dbg(1, debug, "stream off failed in subdev\n");
return videobuf_streamoff(&common->buffer_queue); return vb2_streamoff(&common->buffer_queue, buftype);
} }
/** /**
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/videobuf-core.h> #include <media/videobuf-core.h>
#include <media/videobuf-dma-contig.h> #include <media/videobuf2-dma-contig.h>
#include <media/davinci/vpif_types.h> #include <media/davinci/vpif_types.h>
#include "vpif.h" #include "vpif.h"
...@@ -60,11 +60,16 @@ struct video_obj { ...@@ -60,11 +60,16 @@ struct video_obj {
u32 input_idx; u32 input_idx;
}; };
struct vpif_cap_buffer {
struct vb2_buffer vb;
struct list_head list;
};
struct common_obj { struct common_obj {
/* Pointer pointing to current v4l2_buffer */ /* Pointer pointing to current v4l2_buffer */
struct videobuf_buffer *cur_frm; struct vpif_cap_buffer *cur_frm;
/* Pointer pointing to current v4l2_buffer */ /* 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 * This field keeps track of type of buffer exchange mechanism
* user has selected * user has selected
...@@ -73,7 +78,9 @@ struct common_obj { ...@@ -73,7 +78,9 @@ struct common_obj {
/* Used to store pixel format */ /* Used to store pixel format */
struct v4l2_format fmt; struct v4l2_format fmt;
/* Buffer queue used in video-buf */ /* 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 */ /* Queue of filled frames */
struct list_head dma_queue; struct list_head dma_queue;
/* Used in video-buf */ /* Used in video-buf */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment