Commit f9f715a9 authored by Andrzej Hajda's avatar Andrzej Hajda Committed by Mauro Carvalho Chehab

[media] s5p-mfc: added support for end of stream handling in MFC encoder

s5p-mfc encoder after receiving V4L2_ENC_CMD_STOP command
will instruct MFC device to release all encoded frames.
After dequeuing last encoded frame driver will generate
V4L2_EVENT_EOS event.
Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5565a2ad
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-event.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <media/videobuf2-core.h> #include <media/videobuf2-core.h>
#include "regs-mfc.h" #include "regs-mfc.h"
...@@ -539,6 +540,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx, ...@@ -539,6 +540,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
} }
} }
static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
unsigned int reason, unsigned int err)
{
struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_buf *mb_entry;
mfc_debug(2, "Stream completed");
s5p_mfc_clear_int_flags(dev);
ctx->int_type = reason;
ctx->int_err = err;
ctx->state = MFCINST_FINISHED;
spin_lock(&dev->irqlock);
if (!list_empty(&ctx->dst_queue)) {
mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
list);
list_del(&mb_entry->list);
ctx->dst_queue_cnt--;
vb2_set_plane_payload(mb_entry->b, 0, 0);
vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
}
spin_unlock(&dev->irqlock);
clear_work_bit(ctx);
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
WARN_ON(1);
s5p_mfc_clock_off();
wake_up(&ctx->queue);
s5p_mfc_try_run(dev);
}
/* Interrupt processing */ /* Interrupt processing */
static irqreturn_t s5p_mfc_irq(int irq, void *priv) static irqreturn_t s5p_mfc_irq(int irq, void *priv)
{ {
...@@ -614,6 +649,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) ...@@ -614,6 +649,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
s5p_mfc_handle_init_buffers(ctx, reason, err); s5p_mfc_handle_init_buffers(ctx, reason, err);
break; break;
case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
s5p_mfc_handle_stream_complete(ctx, reason, err);
break;
default: default:
mfc_debug(2, "Unknown int reason\n"); mfc_debug(2, "Unknown int reason\n");
s5p_mfc_clear_int_flags(dev); s5p_mfc_clear_int_flags(dev);
...@@ -889,9 +929,12 @@ static unsigned int s5p_mfc_poll(struct file *file, ...@@ -889,9 +929,12 @@ static unsigned int s5p_mfc_poll(struct file *file,
goto end; goto end;
} }
mutex_unlock(&dev->mfc_mutex); mutex_unlock(&dev->mfc_mutex);
poll_wait(file, &ctx->fh.wait, wait);
poll_wait(file, &src_q->done_wq, wait); poll_wait(file, &src_q->done_wq, wait);
poll_wait(file, &dst_q->done_wq, wait); poll_wait(file, &dst_q->done_wq, wait);
mutex_lock(&dev->mfc_mutex); mutex_lock(&dev->mfc_mutex);
if (v4l2_event_pending(&ctx->fh))
rc |= POLLPRI;
spin_lock_irqsave(&src_q->done_lock, flags); spin_lock_irqsave(&src_q->done_lock, flags);
if (!list_empty(&src_q->done_list)) if (!list_empty(&src_q->done_list))
src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer, src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
......
...@@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg { ...@@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg {
MFC_DEC_RES_CHANGE, MFC_DEC_RES_CHANGE,
}; };
#define MFC_BUF_FLAG_USED (1 << 0)
#define MFC_BUF_FLAG_EOS (1 << 1)
struct s5p_mfc_ctx; struct s5p_mfc_ctx;
/** /**
...@@ -161,7 +164,7 @@ struct s5p_mfc_buf { ...@@ -161,7 +164,7 @@ struct s5p_mfc_buf {
} raw; } raw;
size_t stream; size_t stream;
} cookie; } cookie;
int used; int flags;
}; };
/** /**
......
...@@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev) ...@@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
release_firmware(fw_blob); release_firmware(fw_blob);
return -EIO; return -EIO;
} }
dev->bank2 = bank2_base_phys; /* Valid buffers passed to MFC encoder with LAST_FRAME command
* should not have address of bank2 - MFC will treat it as a null frame.
* To avoid such situation we set bank2 address below the pool address.
*/
dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
wmb(); wmb();
release_firmware(fw_blob); release_firmware(fw_blob);
......
...@@ -936,14 +936,14 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) ...@@ -936,14 +936,14 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
mfc_buf->used = 0; mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
spin_lock_irqsave(&dev->irqlock, flags); spin_lock_irqsave(&dev->irqlock, flags);
list_add_tail(&mfc_buf->list, &ctx->src_queue); list_add_tail(&mfc_buf->list, &ctx->src_queue);
ctx->src_queue_cnt++; ctx->src_queue_cnt++;
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
mfc_buf->used = 0; mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
/* Mark destination as available for use by MFC */ /* Mark destination as available for use by MFC */
spin_lock_irqsave(&dev->irqlock, flags); spin_lock_irqsave(&dev->irqlock, flags);
set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag); set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-event.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/videobuf2-core.h> #include <media/videobuf2-core.h>
...@@ -576,9 +577,9 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) ...@@ -576,9 +577,9 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
if (ctx->state == MFCINST_RUNNING && if (ctx->state == MFCINST_RUNNING &&
ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
return 1; return 1;
/* context is ready to encode remain frames */ /* context is ready to encode remaining frames */
if (ctx->state == MFCINST_FINISHING && if (ctx->state == MFCINST_FINISHING &&
ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) ctx->dst_queue_cnt >= 1)
return 1; return 1;
mfc_debug(2, "ctx is not ready\n"); mfc_debug(2, "ctx is not ready\n");
return 0; return 0;
...@@ -724,7 +725,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx) ...@@ -724,7 +725,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) { if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
list); list);
if (mb_entry->used) { if (mb_entry->flags & MFC_BUF_FLAG_USED) {
list_del(&mb_entry->list); list_del(&mb_entry->list);
ctx->src_queue_cnt--; ctx->src_queue_cnt--;
list_add_tail(&mb_entry->list, &ctx->ref_queue); list_add_tail(&mb_entry->list, &ctx->ref_queue);
...@@ -1119,27 +1120,43 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ...@@ -1119,27 +1120,43 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
mfc_err("Call on QBUF after unrecoverable error\n"); mfc_err("Call on QBUF after unrecoverable error\n");
return -EIO; return -EIO;
} }
if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
if (ctx->state == MFCINST_FINISHING) {
mfc_err("Call on QBUF after EOS command\n");
return -EIO;
}
return vb2_qbuf(&ctx->vq_src, buf); return vb2_qbuf(&ctx->vq_src, buf);
else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
return vb2_qbuf(&ctx->vq_dst, buf); return vb2_qbuf(&ctx->vq_dst, buf);
}
return -EINVAL; return -EINVAL;
} }
/* Dequeue a buffer */ /* Dequeue a buffer */
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
{ {
const struct v4l2_event ev = {
.type = V4L2_EVENT_EOS
};
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
int ret;
if (ctx->state == MFCINST_ERROR) { if (ctx->state == MFCINST_ERROR) {
mfc_err("Call on DQBUF after unrecoverable error\n"); mfc_err("Call on DQBUF after unrecoverable error\n");
return -EIO; return -EIO;
} }
if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
return -EINVAL; if (ret == 0 && ctx->state == MFCINST_FINISHED
&& list_empty(&ctx->vq_dst.done_list))
v4l2_event_queue_fh(&ctx->fh, &ev);
} else {
ret = -EINVAL;
}
return ret;
} }
/* Stream on */ /* Stream on */
...@@ -1471,6 +1488,57 @@ static int vidioc_g_parm(struct file *file, void *priv, ...@@ -1471,6 +1488,57 @@ static int vidioc_g_parm(struct file *file, void *priv,
return 0; return 0;
} }
int vidioc_encoder_cmd(struct file *file, void *priv,
struct v4l2_encoder_cmd *cmd)
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
struct s5p_mfc_dev *dev = ctx->dev;
struct s5p_mfc_buf *buf;
unsigned long flags;
switch (cmd->cmd) {
case V4L2_ENC_CMD_STOP:
if (cmd->flags != 0)
return -EINVAL;
if (!ctx->vq_src.streaming)
return -EINVAL;
spin_lock_irqsave(&dev->irqlock, flags);
if (list_empty(&ctx->src_queue)) {
mfc_debug(2, "EOS: empty src queue, entering finishing state");
ctx->state = MFCINST_FINISHING;
spin_unlock_irqrestore(&dev->irqlock, flags);
s5p_mfc_try_run(dev);
} else {
mfc_debug(2, "EOS: marking last buffer of stream");
buf = list_entry(ctx->src_queue.prev,
struct s5p_mfc_buf, list);
if (buf->flags & MFC_BUF_FLAG_USED)
ctx->state = MFCINST_FINISHING;
else
buf->flags |= MFC_BUF_FLAG_EOS;
spin_unlock_irqrestore(&dev->irqlock, flags);
}
break;
default:
return -EINVAL;
}
return 0;
}
static int vidioc_subscribe_event(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
switch (sub->type) {
case V4L2_EVENT_EOS:
return v4l2_event_subscribe(fh, sub, 2, NULL);
default:
return -EINVAL;
}
}
static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = { static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
.vidioc_querycap = vidioc_querycap, .vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
...@@ -1491,6 +1559,9 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = { ...@@ -1491,6 +1559,9 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
.vidioc_streamoff = vidioc_streamoff, .vidioc_streamoff = vidioc_streamoff,
.vidioc_s_parm = vidioc_s_parm, .vidioc_s_parm = vidioc_s_parm,
.vidioc_g_parm = vidioc_g_parm, .vidioc_g_parm = vidioc_g_parm,
.vidioc_encoder_cmd = vidioc_encoder_cmd,
.vidioc_subscribe_event = vidioc_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
}; };
static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
...@@ -1706,7 +1777,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) ...@@ -1706,7 +1777,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
} }
if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
mfc_buf->used = 0; mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
/* Mark destination as available for use by MFC */ /* Mark destination as available for use by MFC */
spin_lock_irqsave(&dev->irqlock, flags); spin_lock_irqsave(&dev->irqlock, flags);
list_add_tail(&mfc_buf->list, &ctx->dst_queue); list_add_tail(&mfc_buf->list, &ctx->dst_queue);
...@@ -1714,17 +1785,10 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb) ...@@ -1714,17 +1785,10 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
mfc_buf->used = 0; mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
spin_lock_irqsave(&dev->irqlock, flags); spin_lock_irqsave(&dev->irqlock, flags);
if (vb->v4l2_planes[0].bytesused == 0) {
mfc_debug(1, "change state to FINISHING\n");
ctx->state = MFCINST_FINISHING;
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
cleanup_ref_queue(ctx);
} else {
list_add_tail(&mfc_buf->list, &ctx->src_queue); list_add_tail(&mfc_buf->list, &ctx->src_queue);
ctx->src_queue_cnt++; ctx->src_queue_cnt++;
}
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
} else { } else {
mfc_err("unsupported buffer type (%d)\n", vq->type); mfc_err("unsupported buffer type (%d)\n", vq->type);
......
...@@ -1075,14 +1075,21 @@ int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx) ...@@ -1075,14 +1075,21 @@ int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx) int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
{ {
struct s5p_mfc_dev *dev = ctx->dev; struct s5p_mfc_dev *dev = ctx->dev;
int cmd;
/* memory structure cur. frame */ /* memory structure cur. frame */
if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
s5p_mfc_set_shared_buffer(ctx); s5p_mfc_set_shared_buffer(ctx);
mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
(ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); if (ctx->state == MFCINST_FINISHING)
cmd = S5P_FIMV_CH_LAST_FRAME;
else
cmd = S5P_FIMV_CH_FRAME_START;
mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
| (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
return 0; return 0;
} }
...@@ -1133,7 +1140,7 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) ...@@ -1133,7 +1140,7 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
} }
/* Get the next source buffer */ /* Get the next source buffer */
temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
temp_vb->used = 1; temp_vb->flags |= MFC_BUF_FLAG_USED;
s5p_mfc_set_dec_stream_buffer(ctx, s5p_mfc_set_dec_stream_buffer(ctx,
vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream, vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
temp_vb->b->v4l2_planes[0].bytesused); temp_vb->b->v4l2_planes[0].bytesused);
...@@ -1160,7 +1167,7 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) ...@@ -1160,7 +1167,7 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
unsigned int dst_size; unsigned int dst_size;
spin_lock_irqsave(&dev->irqlock, flags); spin_lock_irqsave(&dev->irqlock, flags);
if (list_empty(&ctx->src_queue)) { if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
mfc_debug(2, "no src buffers\n"); mfc_debug(2, "no src buffers\n");
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
return -EAGAIN; return -EAGAIN;
...@@ -1170,19 +1177,40 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx) ...@@ -1170,19 +1177,40 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
return -EAGAIN; return -EAGAIN;
} }
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); if (list_empty(&ctx->src_queue)) {
src_mb->used = 1; /* send null frame */
src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2);
src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); src_mb = NULL;
s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr); } else {
src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
list);
src_mb->flags |= MFC_BUF_FLAG_USED;
if (src_mb->b->v4l2_planes[0].bytesused == 0) {
/* send null frame */
s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2,
dev->bank2);
ctx->state = MFCINST_FINISHING;
} else {
src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
0);
src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
1);
s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr,
src_c_addr);
if (src_mb->flags & MFC_BUF_FLAG_EOS)
ctx->state = MFCINST_FINISHING;
}
}
dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
dst_mb->used = 1; dst_mb->flags |= MFC_BUF_FLAG_USED;
dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
dst_size = vb2_plane_size(dst_mb->b, 0); dst_size = vb2_plane_size(dst_mb->b, 0);
s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_clean_ctx_int_flags(ctx);
mfc_debug(2, "encoding buffer with index=%d state=%d",
src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
s5p_mfc_encode_one_frame(ctx); s5p_mfc_encode_one_frame(ctx);
return 0; return 0;
} }
......
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