q->drv_priv = &ctx->fh;
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;
q->drv_priv = &ctx->fh;
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;
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
int ret = 0;
+#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) {
/* Can only request buffers after an instance has been opened.*/
if (ctx->state == MFCINST_INIT) {
s5p_mfc_clock_off();
return -ENOMEM;
}
- 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;
- s5p_mfc_clock_on();
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
- ctx);
- s5p_mfc_clock_off();
- return -ENOMEM;
+ 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;
+ s5p_mfc_clock_on();
+ ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+ s5p_mfc_hw_call(dev->mfc_ops,
+ release_codec_buffers, ctx);
+ s5p_mfc_clock_off();
+ return -ENOMEM;
+ }
}
if (s5p_mfc_ctx_ready(ctx))
set_work_bit_irqsave(ctx);
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
- s5p_mfc_wait_for_done_ctx(ctx,
+ if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+ s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0);
+ }
}
return ret;
}
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);
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];
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(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 = {
.wait_prepare = s5p_mfc_unlock,
.wait_finish = s5p_mfc_lock,
.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,
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 (ctx->capture_state != QUEUE_FREE) {
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) {