From 7c3e8de49852cd0269dc84dd605f199f39d3b2c8 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Tue, 31 May 2011 12:35:10 +0200 Subject: rework vpu to videobuf2 --- module/imx-vpu.c | 249 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 132 insertions(+), 117 deletions(-) diff --git a/module/imx-vpu.c b/module/imx-vpu.c index 5970255..e342c5a 100644 --- a/module/imx-vpu.c +++ b/module/imx-vpu.c @@ -32,7 +32,7 @@ #include -#include +#include #include #include #include @@ -225,8 +225,8 @@ static struct vpu_driver_data drvdata_imx53 = { /* buffer for one video frame */ struct vpu_buffer { /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - struct vpu_instance *instance; + struct vb2_buffer vb; + struct list_head list; }; struct vpu; @@ -245,7 +245,7 @@ struct vpu_instance { int width, height; int num_fb; int format; - struct videobuf_queue vidq; + struct vb2_queue vidq; int in_use; int videobuf_init; @@ -291,12 +291,15 @@ struct vpu { void __iomem *base; struct vpu_instance instance[VPU_NUM_INSTANCE]; spinlock_t lock; - struct videobuf_buffer *active; + struct vpu_buffer *active; + struct vb2_alloc_ctx *alloc_ctx; + enum v4l2_field field; struct list_head queued; struct clk *clk; int irq; struct vpu_regs *regs; struct vpu_driver_data *drvdata; + int sequence; dma_addr_t vpu_code_table_phys; void __iomem *vpu_code_table; @@ -304,6 +307,11 @@ struct vpu { void __iomem *vpu_work_buf; }; +static struct vpu_buffer *to_vpu_vb(struct vb2_buffer *vb) +{ + return container_of(vb, struct vpu_buffer, vb); +} + #define ROUND_UP_2(num) (((num) + 1) & ~1) #define ROUND_UP_4(num) (((num) + 3) & ~3) #define ROUND_UP_8(num) (((num) + 7) & ~7) @@ -357,19 +365,16 @@ static ssize_t show_info(struct device *dev, struct device_attribute *attr, char *buf) { struct vpu *vpu = dev_get_drvdata(dev); - struct vpu_buffer *vbuf; - struct videobuf_buffer *vb; int i, len = 0; + struct vpu_buffer *vbuf, *tmp; spin_lock_irq(&vpu->lock); - vb = vpu->active; len += sprintf(buf + len, "VPU Info\n" "--------\n" "active: %p", vpu->active); - if (vb) { - vbuf = container_of(vb, struct vpu_buffer, vb); - len += sprintf(buf + len, " (instance %d)\n", vbuf->instance->idx); + if (vpu->active) { + len += sprintf(buf + len, " (instance %d)\n", vpu->instance->idx); } else len += sprintf(buf + len, "\n"); @@ -406,9 +411,10 @@ static ssize_t show_info(struct device *dev, len += sprintf(buf + len, "queued buffers\n" "--------------\n"); - list_for_each_entry(vb, &vpu->queued, queue) { - vbuf = container_of(vb, struct vpu_buffer, vb); - len += sprintf(buf + len, "%p (instance %d, state %d)\n", vb, vbuf->instance->idx, vb->state); + list_for_each_entry_safe(vbuf, tmp, &vpu->queued, list) { + struct vb2_queue *q = vbuf->vb.vb2_queue; + struct vpu_instance *q_instance = vb2_get_drv_priv(q); + len += sprintf(buf + len, "%p (instance %d, streaming %d)\n", vbuf, q_instance->idx, vb2_is_streaming(q)); } spin_unlock_irq(&vpu->lock); @@ -895,17 +901,15 @@ out: return ret; } -static void noinline vpu_enc_start_frame(struct vpu_instance *instance, struct videobuf_buffer *vb) +static void noinline vpu_enc_start_frame(struct vpu_instance *instance) { struct vpu *vpu = instance->vpu; - dma_addr_t dma = videobuf_to_dma_contig(vb); + dma_addr_t dma = vb2_dma_contig_plane_paddr(&vpu->active->vb, 0); int height = instance->height; int stridey = ROUND_UP_4(instance->width); int ustride; unsigned long u; - vpu->active = vb; - vpu_write(vpu, CMD_ENC_PIC_ROT_MODE, 0x10); vpu_write(vpu, CMD_ENC_PIC_QS, 30); @@ -921,7 +925,7 @@ static void noinline vpu_enc_start_frame(struct vpu_instance *instance, struct v vpu_bit_issue_command(instance, PIC_RUN); } -static void vpu_dec_start_frame(struct vpu_instance *instance, struct videobuf_buffer *vb) +static void vpu_dec_start_frame(struct vpu_instance *instance) { struct vpu *vpu = instance->vpu; struct vpu_regs *regs = vpu->regs; @@ -946,7 +950,7 @@ static void vpu_dec_start_frame(struct vpu_instance *instance, struct videobuf_b height = instance->height; } - dma = videobuf_to_dma_contig(vb); + dma = vb2_dma_contig_plane_paddr(&vpu->active->vb, 0); /* Set rotator output */ vpu_write(vpu, CMD_DEC_PIC_ROT_ADDR_Y, dma); @@ -971,8 +975,7 @@ static void vpu_dec_start_frame(struct vpu_instance *instance, struct videobuf_b */ static int vpu_start_frame(struct vpu *vpu) { - struct videobuf_buffer *vb; - struct vpu_buffer *vbuf; + struct vpu_buffer *vbuf, *tmp; struct vpu_instance *instance; int i, ret; @@ -990,11 +993,11 @@ static int vpu_start_frame(struct vpu *vpu) } } - list_for_each_entry(vb, &vpu->queued, queue) { - vbuf = container_of(vb, struct vpu_buffer, vb); - instance = vbuf->instance; + list_for_each_entry_safe(vbuf, tmp, &vpu->queued, list) { + struct vb2_queue *q = vbuf->vb.vb2_queue; + instance = vb2_get_drv_priv(q); if (!instance->hold) { - vpu->active = vb; + vpu->active = vbuf; break; } } @@ -1008,52 +1011,51 @@ static int vpu_start_frame(struct vpu *vpu) instance->hold = 1; } - vb = vpu->active; - - vb->state = VIDEOBUF_ACTIVE; - if (instance->mode == VPU_MODE_ENCODER) - vpu_enc_start_frame(instance, vb); + vpu_enc_start_frame(instance); else - vpu_dec_start_frame(instance, vb); + vpu_dec_start_frame(instance); return 0; } static void vpu_dec_irq_handler(struct vpu *vpu, struct vpu_instance *instance, - struct videobuf_buffer *vb) + struct vb2_buffer *vb) { struct vpu_regs *regs = vpu->regs; + struct vpu_buffer *buf = to_vpu_vb(vb); + if (!vpu_read(vpu, regs->ret_dec_pic_option)) { if (instance->flushing) { - vb->state = VIDEOBUF_ERROR; + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); } else { - vb->state = VIDEOBUF_QUEUED; + vb2_buffer_done(vb, VB2_BUF_STATE_QUEUED); instance->hold = 1; return; } } else - vb->state = VIDEOBUF_DONE; + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); vpu_write(vpu, BIT_FRM_DIS_FLG(instance->idx), 0); + list_del_init(&buf->list); - list_del_init(&vb->queue); - - vb->ts = ktime_to_timeval(instance->frametime); + vb->v4l2_buf.timestamp = ktime_to_timeval(instance->frametime); instance->frametime = ktime_add(instance->frame_duration, instance->frametime); - vb->field_count++; - wake_up(&vb->done); + vb->v4l2_buf.field = vpu->field; + vb->v4l2_buf.sequence = vpu->sequence++; + wake_up_interruptible(&instance->waitq); } static void vpu_enc_irq_handler(struct vpu *vpu, struct vpu_instance *instance, - struct videobuf_buffer *vb) + struct vb2_buffer *vb) { int size; int ret; + struct vpu_buffer *buf = to_vpu_vb(vb); size = vpu_read(vpu, BIT_WR_PTR(instance->idx)) - vpu_read(vpu, BIT_RD_PTR(instance->idx)); @@ -1071,11 +1073,12 @@ static void vpu_enc_irq_handler(struct vpu *vpu, struct vpu_instance *instance, BUG(); } - list_del_init(&vb->queue); - vb->state = VIDEOBUF_DONE; + list_del_init(&buf->list); + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + + vb->v4l2_buf.field = vpu->field; + vb->v4l2_buf.sequence = vpu->sequence++; - vb->field_count++; - wake_up(&vb->done); wake_up_interruptible(&instance->waitq); } @@ -1083,8 +1086,8 @@ static irqreturn_t vpu_irq_handler(int irq, void *dev_id) { struct vpu *vpu = dev_id; struct vpu_instance *instance; - struct videobuf_buffer *vb = vpu->active; - struct vpu_buffer *vbuf; + struct vpu_buffer *vbuf = vpu->active; + struct vb2_queue *q = vbuf->vb.vb2_queue; unsigned long flags; spin_lock_irqsave(&vpu->lock, flags); @@ -1092,16 +1095,14 @@ static irqreturn_t vpu_irq_handler(int irq, void *dev_id) vpu_write(vpu, BIT_INT_CLEAR, 1); vpu_write(vpu, BIT_INT_REASON, 0); - if (!vb) + if (!&vbuf->vb) goto out; - - vbuf = container_of(vpu->active, struct vpu_buffer, vb); - instance = vbuf->instance; + instance = vb2_get_drv_priv(q); if (instance->mode == VPU_MODE_DECODER) - vpu_dec_irq_handler(vpu, instance, vb); + vpu_dec_irq_handler(vpu, instance, &vbuf->vb); else - vpu_enc_irq_handler(vpu, instance, vb); + vpu_enc_irq_handler(vpu, instance, &vbuf->vb); vpu_start_frame(vpu); @@ -1244,7 +1245,7 @@ static int vpu_release(struct file *file) int i; if (instance->videobuf_init) { - videobuf_stop(&instance->vidq); + vb2_queue_release(&instance->vidq); instance->videobuf_init = 0; } @@ -1276,7 +1277,7 @@ static int vpu_mmap(struct file *file, struct vm_area_struct *vma) { struct vpu_instance *instance = file->private_data; - return videobuf_mmap_mapper(&instance->vidq, vma); + return vb2_mmap(&instance->vidq, vma); } static ssize_t vpu_write_stream(struct file *file, const char __user *ubuf, size_t len, @@ -1467,65 +1468,65 @@ static int frame_calc_size(int width, int height) return (width * height * 3) / 2; } -static int vpu_videobuf_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) +static int vpu_vb2_setup(struct vb2_queue *q, + unsigned int *count, unsigned int *num_planes, + unsigned long sizes[], void *alloc_ctxs[]) { - struct vpu_instance *instance = q->priv_data; + struct vpu_instance *instance = vb2_get_drv_priv(q); + struct vpu *vpu = instance->vpu; - *size = frame_calc_size(instance->width, instance->height); + *num_planes = 1; + vpu->sequence = 0; + alloc_ctxs[0] = vpu->alloc_ctx; + sizes[0] = frame_calc_size(instance->width, instance->height); return 0; } -static int vpu_videobuf_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) +static int vpu_vb2_prepare(struct vb2_buffer *vb) { - struct vpu_instance *instance = q->priv_data; - struct vpu_buffer *vbuf = container_of(vb, struct vpu_buffer, vb); - int ret = 0; - - vbuf->instance = instance; - vb->width = instance->width; - vb->height = instance->height; - vb->size = frame_calc_size(vb->width, vb->height); + struct vb2_queue *q = vb->vb2_queue; + struct vpu_instance *instance = vb2_get_drv_priv(q); - if (vb->state == VIDEOBUF_NEEDS_INIT) { - ret = videobuf_iolock(&instance->vidq, vb, NULL); - if (ret) - goto fail; + size_t new_size = frame_calc_size(instance->width, instance->height); - vb->state = VIDEOBUF_PREPARED; + if (vb2_plane_size(vb, 0) < new_size) { + dev_err(instance->vpu->vdev->dev.parent, "Buffer too small (%lu < %zu)\n", + vb2_plane_size(vb, 0), new_size); + return -ENOBUFS; } -fail: - return ret; + vb2_set_plane_payload(vb, 0, new_size); + return 0; } -static void vpu_videobuf_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpu_vb2_queue(struct vb2_buffer *vb) { - struct vpu_instance *instance = q->priv_data; + struct vb2_queue *q = vb->vb2_queue; + struct vpu_buffer *buf = to_vpu_vb(vb); + struct vpu_instance *instance = q->drv_priv; struct vpu *vpu = instance->vpu; + unsigned long flags; - list_add_tail(&vb->queue, &vpu->queued); - - vb->state = VIDEOBUF_QUEUED; + spin_lock_irqsave(&vpu->lock, flags); + list_add_tail(&buf->list, &vpu->queued); + spin_unlock_irqrestore(&vpu->lock, flags); if (!vpu->active) vpu_start_frame(vpu); } -static void vpu_videobuf_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) +static void vpu_vb2_release(struct vb2_buffer *vb) { - struct vpu_instance *instance = q->priv_data; + struct vpu_buffer *buf = to_vpu_vb(vb); + struct vb2_queue *q = vb->vb2_queue; + struct vpu_instance *instance = q->drv_priv; struct vpu *vpu = instance->vpu; - struct videobuf_buffer *vbtmp; + struct vpu_buffer *vbuf, *tmp; spin_lock_irq(&vpu->lock); - if (vb->state == VIDEOBUF_ACTIVE) { + if (vpu->active == buf) { u32 rdptr; /* @@ -1540,27 +1541,33 @@ static void vpu_videobuf_release(struct videobuf_queue *q, vpu->active = NULL; } - list_for_each_entry(vbtmp, &vpu->queued, queue) { - if (vbtmp == vb) { - dev_dbg(vpu->dev, "%s: buffer %p still queued. This should not happen\n", + list_for_each_entry_safe(vbuf, tmp, &vpu->queued, list) { + if (vbuf == buf) { + printk("%s: buffer %p still queued. This should not happen\n", __func__, vb); - list_del(&vb->queue); + list_del(&buf->list); break; } } spin_unlock_irq(&vpu->lock); +} + +static int vpu_vb2_init(struct vb2_buffer *vb) +{ - videobuf_dma_contig_free(q, vb); + struct vpu_buffer *buf = to_vpu_vb(vb); + INIT_LIST_HEAD(&buf->list); - vb->state = VIDEOBUF_NEEDS_INIT; + return 0; } -static struct videobuf_queue_ops vpu_videobuf_ops = { - .buf_setup = vpu_videobuf_setup, - .buf_prepare = vpu_videobuf_prepare, - .buf_queue = vpu_videobuf_queue, - .buf_release = vpu_videobuf_release, +static struct vb2_ops vpu_videobuf_ops = { + .queue_setup = vpu_vb2_setup, + .buf_prepare = vpu_vb2_prepare, + .buf_queue = vpu_vb2_queue, + .buf_cleanup = vpu_vb2_release, + .buf_init = vpu_vb2_init, }; static int vpu_reqbufs(struct file *file, void *priv, @@ -1568,25 +1575,24 @@ static int vpu_reqbufs(struct file *file, void *priv, { struct vpu_instance *instance = file->private_data; struct vpu *vpu = instance->vpu; + struct vb2_queue *q = &instance->vidq; int ret = 0; vpu->vdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); /* Initialize videobuf queue as per the buffer type */ - videobuf_queue_dma_contig_init(&instance->vidq, - &vpu_videobuf_ops, &vpu->vdev->dev, - &vpu->lock, - reqbuf->type, - V4L2_FIELD_NONE, - sizeof(struct vpu_buffer), - instance, - NULL); + q->type = reqbuf->type; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = instance; + q->ops = &vpu_videobuf_ops; + q->mem_ops = &vb2_dma_contig_memops; + ret = vb2_queue_init(q); instance->videobuf_init = 1; /* Allocate buffers */ - ret = videobuf_reqbufs(&instance->vidq, reqbuf); + ret |= vb2_reqbufs(&instance->vidq, reqbuf); return ret; } @@ -1594,22 +1600,21 @@ static int vpu_reqbufs(struct file *file, void *priv, static int vpu_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) { struct vpu_instance *instance = file->private_data; - - return videobuf_querybuf(&instance->vidq, p); + return vb2_querybuf(&instance->vidq, p); } static int vpu_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) { struct vpu_instance *instance = file->private_data; - return videobuf_qbuf(&instance->vidq, p); + return vb2_qbuf(&instance->vidq, p); } static int vpu_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) { struct vpu_instance *instance = file->private_data; - return videobuf_dqbuf(&instance->vidq, p, file->f_flags & O_NONBLOCK); + return vb2_dqbuf(&instance->vidq, p, file->f_flags & O_NONBLOCK); } static int vpu_g_fmt_vid_cap(struct file *file, void *priv, @@ -1667,14 +1672,14 @@ static int vpu_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (instance->mode == VPU_MODE_ENCODER) instance->hold = 0; - return videobuf_streamon(&instance->vidq); + return vb2_streamon(&instance->vidq, i); } static int vpu_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { struct vpu_instance *instance = file->private_data; - return videobuf_streamoff(&instance->vidq); + return vb2_streamoff(&instance->vidq, i); } static unsigned int vpu_poll(struct file *file, struct poll_table_struct *wait) @@ -1688,10 +1693,10 @@ static unsigned int vpu_poll(struct file *file, struct poll_table_struct *wait) ret |= POLLOUT | POLLWRNORM; if (instance->vidq.streaming) - ret |= videobuf_poll_stream(file, &instance->vidq, wait); + ret |= vb2_poll(&instance->vidq, file, wait); } else { if (instance->vidq.streaming) - ret |= videobuf_poll_stream(file, &instance->vidq, wait); + ret |= vb2_poll(&instance->vidq, file, wait); } return ret; @@ -1785,6 +1790,13 @@ static int vpu_dev_probe(struct platform_device *pdev) goto err_out_ioremap; } + vpu->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(vpu->alloc_ctx)) { + err = PTR_ERR(vpu->alloc_ctx); + goto err_alloc_ctx; + } + + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); vpu->irq = platform_get_irq(pdev, 0); err = request_irq(vpu->irq, vpu_irq_handler, 0, dev_name(&pdev->dev), vpu); @@ -1814,6 +1826,8 @@ static int vpu_dev_probe(struct platform_device *pdev) err_out_register: free_irq(vpu->irq, vpu); err_out_irq: + vb2_dma_contig_cleanup_ctx(vpu->alloc_ctx); +err_alloc_ctx: iounmap(vpu->base); err_out_ioremap: clk_disable(vpu->clk); @@ -1847,6 +1861,7 @@ static int vpu_dev_remove(struct platform_device *pdev) dma_free_coherent(NULL, regs->code_buf_size, vpu->vpu_code_table, vpu->vpu_code_table_phys); + vb2_dma_contig_cleanup_ctx(vpu->alloc_ctx); video_unregister_device(vpu->vdev); device_remove_file(&pdev->dev, &dev_attr_info); -- cgit v1.2.3