diff options
author | Seung-Woo Kim <sw0312.kim@samsung.com> | 2013-11-29 16:57:34 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2015-06-09 23:16:41 -0700 |
commit | ad533b7c467aa4117cde97bdd9b86e98e35c8741 (patch) | |
tree | c385bf2746cc677da0a8d84f671e4195e983c119 /drivers | |
parent | 3a787d8f31f201ba75781174f9066d705f342470 (diff) | |
download | linux-exynos-tizen_3.0.2015.q2_common.tar.gz linux-exynos-tizen_3.0.2015.q2_common.tar.bz2 linux-exynos-tizen_3.0.2015.q2_common.zip |
media: s5p-mfc: Add support for V4L2_MEMORY_DMABUF typesubmit/tizen_3.0.2015.q2_common/20150615.075539submit/tizen/20150610.113634accepted/tizen/wearable/20150611.004643accepted/tizen/tv/20150611.004627accepted/tizen/mobile/20150611.004618accepted/tizen/common/20150610.144553accepted/tizen/3.0.2015.q2/common/20150615.160122tizen_3.0.2015.q2_commonaccepted/tizen_3.0.2015.q2_common
There is memory constraint that it should be within 128MB from
firmware address. But if IOMMU is supported, then this constraint
is meaningless and DMABUF importing can be used.
So this patch adds V4L2_MEMORY_DMABUF type support for both decoder
and encoder.
Change-Id: I2c893da31f906fcd3f26edeed67ad1e4667e6081
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc.c | 12 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 4 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 68 | ||||
-rw-r--r-- | drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 10 |
4 files changed, 82 insertions, 12 deletions
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 61e4540283c6..fa680cd9c6e9 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -813,9 +813,15 @@ static int s5p_mfc_open(struct file *file) q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; +#ifdef CONFIG_EXYNOS_IOMMU + q->io_modes = q->io_modes | VB2_USERPTR | VB2_DMABUF; +#endif q->ops = get_dec_queue_ops(); } else if (vdev == dev->vfd_enc) { q->io_modes = VB2_MMAP | VB2_USERPTR; +#ifdef CONFIG_EXYNOS_IOMMU + q->io_modes = q->io_modes | VB2_DMABUF; +#endif q->ops = get_enc_queue_ops(); } else { ret = -ENOENT; @@ -836,9 +842,15 @@ static int s5p_mfc_open(struct file *file) q->lock = &dev->mfc_mutex; if (vdev == dev->vfd_dec) { q->io_modes = VB2_MMAP; +#ifdef CONFIG_EXYNOS_IOMMU + q->io_modes = q->io_modes | VB2_USERPTR | VB2_DMABUF; +#endif q->ops = get_dec_queue_ops(); } else if (vdev == dev->vfd_enc) { q->io_modes = VB2_MMAP | VB2_USERPTR; +#ifdef CONFIG_EXYNOS_IOMMU + q->io_modes = q->io_modes | VB2_DMABUF; +#endif q->ops = get_enc_queue_ops(); } else { ret = -ENOENT; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h index 24262bbb1a35..c296edfae8b6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h @@ -723,5 +723,9 @@ void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx); #define MFC_V7_BIT BIT(2) #define MFC_V8_BIT BIT(3) +#define s5p_mfc_supported_mem_type(mem) \ + ((mem == V4L2_MEMORY_MMAP || \ + mem == V4L2_MEMORY_USERPTR || \ + mem == V4L2_MEMORY_DMABUF) ? 1 : 0) #endif /* S5P_MFC_COMMON_H_ */ diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index aebe4fd7f03a..00e6047e2db2 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -546,14 +546,27 @@ static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, goto out; } - WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count); - ctx->capture_state = QUEUE_BUFS_MMAPED; + if (reqbufs->memory == V4L2_MEMORY_MMAP) { + if (ctx->dst_bufs_cnt == ctx->total_dpb_count) { + ctx->capture_state = QUEUE_BUFS_MMAPED; + } else { + mfc_err("Not all buffers passed to buf_init\n"); + reqbufs->count = 0; + ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); + s5p_mfc_hw_call(dev->mfc_ops, + release_codec_buffers, ctx); + ret = -ENOMEM; + goto out; + } + } if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); - s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, - 0); + if (reqbufs->memory == V4L2_MEMORY_MMAP) { + s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); + } } else { mfc_err("Buffers have already been requested\n"); ret = -EINVAL; @@ -572,11 +585,17 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); +#ifdef CONFIG_EXYNOS_IOMMU + if (!s5p_mfc_supported_mem_type(reqbufs->memory)) { + mfc_err("Memory type %d is not supported\n", reqbufs->memory); + return -EINVAL; + } +#else if (reqbufs->memory != V4L2_MEMORY_MMAP) { mfc_err("Only V4L2_MEMORY_MAP is supported\n"); return -EINVAL; } - +#endif if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { return reqbufs_output(dev, ctx, reqbufs); } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { @@ -994,6 +1013,28 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb) return 0; } +static int s5p_mfc_buf_prepare(struct vb2_buffer *vb) +{ + struct vb2_queue *vq = vb->vb2_queue; + struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); + unsigned int index = vb->v4l2_buf.index; + + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + if (vb2_plane_size(vb, 0) < ctx->luma_size || + vb2_plane_size(vb, 1) < ctx->chroma_size) { + mfc_err("Plane buffer (CAPTURE) is too small.\n"); + return -EINVAL; + } + } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) { + mfc_err("Plane buffer (OUTPUT) is too small.\n"); + return -EINVAL; + } + } + + return 0; +} + static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) { struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); @@ -1063,6 +1104,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) struct s5p_mfc_dev *dev = ctx->dev; unsigned long flags; struct s5p_mfc_buf *mfc_buf; + int wait_flag = 0; if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; @@ -1080,12 +1122,25 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) list_add_tail(&mfc_buf->list, &ctx->dst_queue); ctx->dst_queue_cnt++; spin_unlock_irqrestore(&dev->irqlock, flags); + if ((vq->memory == V4L2_MEMORY_USERPTR || + vq->memory == V4L2_MEMORY_DMABUF) && + ctx->dst_queue_cnt == ctx->total_dpb_count) + ctx->capture_state = QUEUE_BUFS_MMAPED; } else { mfc_err("Unsupported buffer type (%d)\n", vq->type); } - if (s5p_mfc_ctx_ready(ctx)) + if (s5p_mfc_ctx_ready(ctx)) { set_work_bit_irqsave(ctx); + if ((vq->memory == V4L2_MEMORY_USERPTR || + vq->memory == V4L2_MEMORY_DMABUF) && + ctx->state == MFCINST_HEAD_PARSED && + ctx->capture_state == QUEUE_BUFS_MMAPED) + wait_flag = 1; + } s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); + if (wait_flag) + s5p_mfc_wait_for_done_ctx(ctx, + S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); } static struct vb2_ops s5p_mfc_dec_qops = { @@ -1093,6 +1148,7 @@ static struct vb2_ops s5p_mfc_dec_qops = { .wait_prepare = vb2_ops_wait_prepare, .wait_finish = vb2_ops_wait_finish, .buf_init = s5p_mfc_buf_init, + .buf_prepare = s5p_mfc_buf_prepare, .start_streaming = s5p_mfc_start_streaming, .stop_streaming = s5p_mfc_stop_streaming, .buf_queue = s5p_mfc_buf_queue, diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 2e57e9f45b85..adccaeb5a917 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1138,9 +1138,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - /* if memory is not mmp or userptr return error */ - if ((reqbufs->memory != V4L2_MEMORY_MMAP) && - (reqbufs->memory != V4L2_MEMORY_USERPTR)) + /* if memory is not mmp, userptr or dmabuf return error */ + if (!s5p_mfc_supported_mem_type(reqbufs->memory)) return -EINVAL; if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (reqbufs->count == 0) { @@ -1214,9 +1213,8 @@ static int vidioc_querybuf(struct file *file, void *priv, struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - /* if memory is not mmp or userptr return error */ - if ((buf->memory != V4L2_MEMORY_MMAP) && - (buf->memory != V4L2_MEMORY_USERPTR)) + /* if memory is not mmp, userptr or dmabuf return error */ + if (!s5p_mfc_supported_mem_type(buf->memory)) return -EINVAL; if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (ctx->state != MFCINST_GOT_INST) { |