Commit 38beac65 authored by Pawel Osciak's avatar Pawel Osciak Committed by Mauro Carvalho Chehab

[media] s5p-mfc: Fixes for decode REQBUFS

- Honor return values from vb2_reqbufs on REQBUFS(0).

- Do not set the number of allocated buffers to 0 if userspace tries
  to request buffers again without freeing them.

- There is no need to verify correct instance state on reqbufs, as we will
  verify this in queue_setup().

- There is also no need to verify that vb2_reqbufs() was able to allocate enough
  buffers (pb_count) and call buf_init on that many buffers (i.e. dst_buf_count
  is at least pb_count), because this will be verified by second queue_setup()
  call as well and vb2_reqbufs() will fail otherwise.

- Only verify state is MFCINST_INIT when allocating, not when freeing.

- Refactor and simplify code.
Signed-off-by: default avatarPawel Osciak <posciak@chromium.org>
Signed-off-by: default avatarArun Kumar K <arun.kk@samsung.com>
Signed-off-by: default avatarKamil Debski <k.debski@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent a0517f5d
...@@ -462,104 +462,124 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) ...@@ -462,104 +462,124 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
return ret; return ret;
} }
/* Reqeust buffers */ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs)
struct v4l2_requestbuffers *reqbufs)
{ {
struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
int ret = 0; int ret = 0;
if (reqbufs->memory != V4L2_MEMORY_MMAP) { s5p_mfc_clock_on();
mfc_err("Only V4L2_MEMORY_MAP is supported\n");
return -EINVAL; if (reqbufs->count == 0) {
} mfc_debug(2, "Freeing buffers\n");
if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
/* Can only request buffers after an instance has been opened.*/ if (ret)
if (ctx->state == MFCINST_INIT) { goto out;
ctx->src_bufs_cnt = 0; ctx->src_bufs_cnt = 0;
if (reqbufs->count == 0) { } else if (ctx->output_state == QUEUE_FREE) {
mfc_debug(2, "Freeing buffers\n"); /* Can only request buffers after the instance
s5p_mfc_clock_on(); * has been opened.
ret = vb2_reqbufs(&ctx->vq_src, reqbufs); */
s5p_mfc_clock_off(); WARN_ON(ctx->src_bufs_cnt != 0);
return ret; if (ctx->state != MFCINST_INIT) {
} mfc_err("Reqbufs called in an invalid state\n");
/* Decoding */ ret = -EINVAL;
if (ctx->output_state != QUEUE_FREE) { goto out;
mfc_err("Bufs have already been requested\n");
return -EINVAL;
}
s5p_mfc_clock_on();
ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
s5p_mfc_clock_off();
if (ret) {
mfc_err("vb2_reqbufs on output failed\n");
return ret;
}
mfc_debug(2, "vb2_reqbufs: %d\n", ret);
ctx->output_state = QUEUE_BUFS_REQUESTED;
} }
} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n",
reqbufs->count);
ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
if (ret)
goto out;
ctx->output_state = QUEUE_BUFS_REQUESTED;
} else {
mfc_err("Buffers have already been requested\n");
ret = -EINVAL;
}
out:
s5p_mfc_clock_off();
if (ret)
mfc_err("Failed allocating buffers for OUTPUT queue\n");
return ret;
}
static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
struct v4l2_requestbuffers *reqbufs)
{
int ret = 0;
s5p_mfc_clock_on();
if (reqbufs->count == 0) {
mfc_debug(2, "Freeing buffers\n");
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
if (ret)
goto out;
s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
ctx->dst_bufs_cnt = 0; ctx->dst_bufs_cnt = 0;
if (reqbufs->count == 0) { } else if (ctx->capture_state == QUEUE_FREE) {
mfc_debug(2, "Freeing buffers\n"); WARN_ON(ctx->dst_bufs_cnt != 0);
s5p_mfc_clock_on(); mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n",
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); reqbufs->count);
s5p_mfc_clock_off();
return ret;
}
if (ctx->capture_state != QUEUE_FREE) {
mfc_err("Bufs have already been requested\n");
return -EINVAL;
}
ctx->capture_state = QUEUE_BUFS_REQUESTED;
s5p_mfc_clock_on();
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
s5p_mfc_clock_off(); if (ret)
if (ret) { goto out;
mfc_err("vb2_reqbufs on capture failed\n");
return ret; ctx->capture_state = QUEUE_BUFS_REQUESTED;
}
if (reqbufs->count < ctx->pb_count) {
mfc_err("Not enough buffers allocated\n");
reqbufs->count = 0;
s5p_mfc_clock_on();
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
s5p_mfc_clock_off();
return -ENOMEM;
}
ctx->total_dpb_count = reqbufs->count; ctx->total_dpb_count = reqbufs->count;
ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
if (ret) { if (ret) {
mfc_err("Failed to allocate decoding buffers\n"); mfc_err("Failed to allocate decoding buffers\n");
reqbufs->count = 0; reqbufs->count = 0;
s5p_mfc_clock_on(); vb2_reqbufs(&ctx->vq_dst, reqbufs);
ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); ret = -ENOMEM;
s5p_mfc_clock_off(); ctx->capture_state = QUEUE_FREE;
return -ENOMEM; goto out;
}
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;
} }
WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count);
ctx->capture_state = QUEUE_BUFS_MMAPED;
if (s5p_mfc_ctx_ready(ctx)) if (s5p_mfc_ctx_ready(ctx))
set_work_bit_irqsave(ctx); set_work_bit_irqsave(ctx);
s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
s5p_mfc_wait_for_done_ctx(ctx, s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,
S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); 0);
} else {
mfc_err("Buffers have already been requested\n");
ret = -EINVAL;
} }
out:
s5p_mfc_clock_off();
if (ret)
mfc_err("Failed allocating buffers for CAPTURE queue\n");
return ret; return ret;
} }
/* Reqeust buffers */
static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *reqbufs)
{
struct s5p_mfc_dev *dev = video_drvdata(file);
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
if (reqbufs->memory != V4L2_MEMORY_MMAP) {
mfc_err("Only V4L2_MEMORY_MAP is supported\n");
return -EINVAL;
}
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) {
return reqbufs_capture(dev, ctx, reqbufs);
} else {
mfc_err("Invalid type requested\n");
return -EINVAL;
}
}
/* Query buffer */ /* Query buffer */
static int vidioc_querybuf(struct file *file, void *priv, static int vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *buf) struct v4l2_buffer *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