aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAndrzej Hajda <a.hajda@samsung.com>2012-08-21 07:05:32 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-10-02 12:58:04 -0400
commitf9f715a95d07d3868bb30aeb20252b6b05d35d8f (patch)
tree53a684372a77a28412e06ad66855a6f9c747f000 /drivers/media
parent5565a2ad47cdd8e697a28137bd8379455667bc1c (diff)
[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: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c43
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_common.h5
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c6
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c4
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_enc.c106
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr.c48
6 files changed, 177 insertions, 35 deletions
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 9360d5771823..776e6bc241fc 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -19,6 +19,7 @@
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/videodev2.h> 21#include <linux/videodev2.h>
22#include <media/v4l2-event.h>
22#include <linux/workqueue.h> 23#include <linux/workqueue.h>
23#include <media/videobuf2-core.h> 24#include <media/videobuf2-core.h>
24#include "regs-mfc.h" 25#include "regs-mfc.h"
@@ -539,6 +540,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
539 } 540 }
540} 541}
541 542
543static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
544 unsigned int reason, unsigned int err)
545{
546 struct s5p_mfc_dev *dev = ctx->dev;
547 struct s5p_mfc_buf *mb_entry;
548
549 mfc_debug(2, "Stream completed");
550
551 s5p_mfc_clear_int_flags(dev);
552 ctx->int_type = reason;
553 ctx->int_err = err;
554 ctx->state = MFCINST_FINISHED;
555
556 spin_lock(&dev->irqlock);
557 if (!list_empty(&ctx->dst_queue)) {
558 mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
559 list);
560 list_del(&mb_entry->list);
561 ctx->dst_queue_cnt--;
562 vb2_set_plane_payload(mb_entry->b, 0, 0);
563 vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
564 }
565 spin_unlock(&dev->irqlock);
566
567 clear_work_bit(ctx);
568
569 if (test_and_clear_bit(0, &dev->hw_lock) == 0)
570 WARN_ON(1);
571
572 s5p_mfc_clock_off();
573 wake_up(&ctx->queue);
574 s5p_mfc_try_run(dev);
575}
576
542/* Interrupt processing */ 577/* Interrupt processing */
543static irqreturn_t s5p_mfc_irq(int irq, void *priv) 578static irqreturn_t s5p_mfc_irq(int irq, void *priv)
544{ 579{
@@ -614,6 +649,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
614 case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET: 649 case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
615 s5p_mfc_handle_init_buffers(ctx, reason, err); 650 s5p_mfc_handle_init_buffers(ctx, reason, err);
616 break; 651 break;
652
653 case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
654 s5p_mfc_handle_stream_complete(ctx, reason, err);
655 break;
656
617 default: 657 default:
618 mfc_debug(2, "Unknown int reason\n"); 658 mfc_debug(2, "Unknown int reason\n");
619 s5p_mfc_clear_int_flags(dev); 659 s5p_mfc_clear_int_flags(dev);
@@ -889,9 +929,12 @@ static unsigned int s5p_mfc_poll(struct file *file,
889 goto end; 929 goto end;
890 } 930 }
891 mutex_unlock(&dev->mfc_mutex); 931 mutex_unlock(&dev->mfc_mutex);
932 poll_wait(file, &ctx->fh.wait, wait);
892 poll_wait(file, &src_q->done_wq, wait); 933 poll_wait(file, &src_q->done_wq, wait);
893 poll_wait(file, &dst_q->done_wq, wait); 934 poll_wait(file, &dst_q->done_wq, wait);
894 mutex_lock(&dev->mfc_mutex); 935 mutex_lock(&dev->mfc_mutex);
936 if (v4l2_event_pending(&ctx->fh))
937 rc |= POLLPRI;
895 spin_lock_irqsave(&src_q->done_lock, flags); 938 spin_lock_irqsave(&src_q->done_lock, flags);
896 if (!list_empty(&src_q->done_list)) 939 if (!list_empty(&src_q->done_list))
897 src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer, 940 src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index bd5706a6bad1..8871f0de6efd 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg {
146 MFC_DEC_RES_CHANGE, 146 MFC_DEC_RES_CHANGE,
147}; 147};
148 148
149#define MFC_BUF_FLAG_USED (1 << 0)
150#define MFC_BUF_FLAG_EOS (1 << 1)
151
149struct s5p_mfc_ctx; 152struct s5p_mfc_ctx;
150 153
151/** 154/**
@@ -161,7 +164,7 @@ struct s5p_mfc_buf {
161 } raw; 164 } raw;
162 size_t stream; 165 size_t stream;
163 } cookie; 166 } cookie;
164 int used; 167 int flags;
165}; 168};
166 169
167/** 170/**
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 992303d76b11..0deba6bc687c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
98 release_firmware(fw_blob); 98 release_firmware(fw_blob);
99 return -EIO; 99 return -EIO;
100 } 100 }
101 dev->bank2 = bank2_base_phys; 101 /* Valid buffers passed to MFC encoder with LAST_FRAME command
102 * should not have address of bank2 - MFC will treat it as a null frame.
103 * To avoid such situation we set bank2 address below the pool address.
104 */
105 dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
102 memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); 106 memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
103 wmb(); 107 wmb();
104 release_firmware(fw_blob); 108 release_firmware(fw_blob);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 456f5df6b179..aef83d13182c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -936,14 +936,14 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
936 936
937 if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 937 if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
938 mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; 938 mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
939 mfc_buf->used = 0; 939 mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
940 spin_lock_irqsave(&dev->irqlock, flags); 940 spin_lock_irqsave(&dev->irqlock, flags);
941 list_add_tail(&mfc_buf->list, &ctx->src_queue); 941 list_add_tail(&mfc_buf->list, &ctx->src_queue);
942 ctx->src_queue_cnt++; 942 ctx->src_queue_cnt++;
943 spin_unlock_irqrestore(&dev->irqlock, flags); 943 spin_unlock_irqrestore(&dev->irqlock, flags);
944 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 944 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
945 mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; 945 mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
946 mfc_buf->used = 0; 946 mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
947 /* Mark destination as available for use by MFC */ 947 /* Mark destination as available for use by MFC */
948 spin_lock_irqsave(&dev->irqlock, flags); 948 spin_lock_irqsave(&dev->irqlock, flags);
949 set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag); 949 set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index fdeebb031b45..075cc5c5f9bc 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -21,6 +21,7 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/version.h> 22#include <linux/version.h>
23#include <linux/videodev2.h> 23#include <linux/videodev2.h>
24#include <media/v4l2-event.h>
24#include <linux/workqueue.h> 25#include <linux/workqueue.h>
25#include <media/v4l2-ctrls.h> 26#include <media/v4l2-ctrls.h>
26#include <media/videobuf2-core.h> 27#include <media/videobuf2-core.h>
@@ -576,9 +577,9 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
576 if (ctx->state == MFCINST_RUNNING && 577 if (ctx->state == MFCINST_RUNNING &&
577 ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) 578 ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
578 return 1; 579 return 1;
579 /* context is ready to encode remain frames */ 580 /* context is ready to encode remaining frames */
580 if (ctx->state == MFCINST_FINISHING && 581 if (ctx->state == MFCINST_FINISHING &&
581 ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1) 582 ctx->dst_queue_cnt >= 1)
582 return 1; 583 return 1;
583 mfc_debug(2, "ctx is not ready\n"); 584 mfc_debug(2, "ctx is not ready\n");
584 return 0; 585 return 0;
@@ -724,7 +725,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
724 if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) { 725 if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
725 mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, 726 mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
726 list); 727 list);
727 if (mb_entry->used) { 728 if (mb_entry->flags & MFC_BUF_FLAG_USED) {
728 list_del(&mb_entry->list); 729 list_del(&mb_entry->list);
729 ctx->src_queue_cnt--; 730 ctx->src_queue_cnt--;
730 list_add_tail(&mb_entry->list, &ctx->ref_queue); 731 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 mfc_err("Call on QBUF after unrecoverable error\n"); 1120 mfc_err("Call on QBUF after unrecoverable error\n");
1120 return -EIO; 1121 return -EIO;
1121 } 1122 }
1122 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 1123 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1124 if (ctx->state == MFCINST_FINISHING) {
1125 mfc_err("Call on QBUF after EOS command\n");
1126 return -EIO;
1127 }
1123 return vb2_qbuf(&ctx->vq_src, buf); 1128 return vb2_qbuf(&ctx->vq_src, buf);
1124 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 1129 } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1125 return vb2_qbuf(&ctx->vq_dst, buf); 1130 return vb2_qbuf(&ctx->vq_dst, buf);
1131 }
1126 return -EINVAL; 1132 return -EINVAL;
1127} 1133}
1128 1134
1129/* Dequeue a buffer */ 1135/* Dequeue a buffer */
1130static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) 1136static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1131{ 1137{
1138 const struct v4l2_event ev = {
1139 .type = V4L2_EVENT_EOS
1140 };
1132 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); 1141 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1142 int ret;
1133 1143
1134 if (ctx->state == MFCINST_ERROR) { 1144 if (ctx->state == MFCINST_ERROR) {
1135 mfc_err("Call on DQBUF after unrecoverable error\n"); 1145 mfc_err("Call on DQBUF after unrecoverable error\n");
1136 return -EIO; 1146 return -EIO;
1137 } 1147 }
1138 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 1148 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1139 return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); 1149 ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
1140 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 1150 } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1141 return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); 1151 ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
1142 return -EINVAL; 1152 if (ret == 0 && ctx->state == MFCINST_FINISHED
1153 && list_empty(&ctx->vq_dst.done_list))
1154 v4l2_event_queue_fh(&ctx->fh, &ev);
1155 } else {
1156 ret = -EINVAL;
1157 }
1158
1159 return ret;
1143} 1160}
1144 1161
1145/* Stream on */ 1162/* Stream on */
@@ -1471,6 +1488,57 @@ static int vidioc_g_parm(struct file *file, void *priv,
1471 return 0; 1488 return 0;
1472} 1489}
1473 1490
1491int vidioc_encoder_cmd(struct file *file, void *priv,
1492 struct v4l2_encoder_cmd *cmd)
1493{
1494 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
1495 struct s5p_mfc_dev *dev = ctx->dev;
1496 struct s5p_mfc_buf *buf;
1497 unsigned long flags;
1498
1499 switch (cmd->cmd) {
1500 case V4L2_ENC_CMD_STOP:
1501 if (cmd->flags != 0)
1502 return -EINVAL;
1503
1504 if (!ctx->vq_src.streaming)
1505 return -EINVAL;
1506
1507 spin_lock_irqsave(&dev->irqlock, flags);
1508 if (list_empty(&ctx->src_queue)) {
1509 mfc_debug(2, "EOS: empty src queue, entering finishing state");
1510 ctx->state = MFCINST_FINISHING;
1511 spin_unlock_irqrestore(&dev->irqlock, flags);
1512 s5p_mfc_try_run(dev);
1513 } else {
1514 mfc_debug(2, "EOS: marking last buffer of stream");
1515 buf = list_entry(ctx->src_queue.prev,
1516 struct s5p_mfc_buf, list);
1517 if (buf->flags & MFC_BUF_FLAG_USED)
1518 ctx->state = MFCINST_FINISHING;
1519 else
1520 buf->flags |= MFC_BUF_FLAG_EOS;
1521 spin_unlock_irqrestore(&dev->irqlock, flags);
1522 }
1523 break;
1524 default:
1525 return -EINVAL;
1526
1527 }
1528 return 0;
1529}
1530
1531static int vidioc_subscribe_event(struct v4l2_fh *fh,
1532 struct v4l2_event_subscription *sub)
1533{
1534 switch (sub->type) {
1535 case V4L2_EVENT_EOS:
1536 return v4l2_event_subscribe(fh, sub, 2, NULL);
1537 default:
1538 return -EINVAL;
1539 }
1540}
1541
1474static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = { 1542static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
1475 .vidioc_querycap = vidioc_querycap, 1543 .vidioc_querycap = vidioc_querycap,
1476 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, 1544 .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 .vidioc_streamoff = vidioc_streamoff, 1559 .vidioc_streamoff = vidioc_streamoff,
1492 .vidioc_s_parm = vidioc_s_parm, 1560 .vidioc_s_parm = vidioc_s_parm,
1493 .vidioc_g_parm = vidioc_g_parm, 1561 .vidioc_g_parm = vidioc_g_parm,
1562 .vidioc_encoder_cmd = vidioc_encoder_cmd,
1563 .vidioc_subscribe_event = vidioc_subscribe_event,
1564 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1494}; 1565};
1495 1566
1496static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb) 1567static 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 } 1777 }
1707 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 1778 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1708 mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; 1779 mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
1709 mfc_buf->used = 0; 1780 mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
1710 /* Mark destination as available for use by MFC */ 1781 /* Mark destination as available for use by MFC */
1711 spin_lock_irqsave(&dev->irqlock, flags); 1782 spin_lock_irqsave(&dev->irqlock, flags);
1712 list_add_tail(&mfc_buf->list, &ctx->dst_queue); 1783 list_add_tail(&mfc_buf->list, &ctx->dst_queue);
@@ -1714,17 +1785,10 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
1714 spin_unlock_irqrestore(&dev->irqlock, flags); 1785 spin_unlock_irqrestore(&dev->irqlock, flags);
1715 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 1786 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1716 mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; 1787 mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
1717 mfc_buf->used = 0; 1788 mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
1718 spin_lock_irqsave(&dev->irqlock, flags); 1789 spin_lock_irqsave(&dev->irqlock, flags);
1719 if (vb->v4l2_planes[0].bytesused == 0) { 1790 list_add_tail(&mfc_buf->list, &ctx->src_queue);
1720 mfc_debug(1, "change state to FINISHING\n"); 1791 ctx->src_queue_cnt++;
1721 ctx->state = MFCINST_FINISHING;
1722 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
1723 cleanup_ref_queue(ctx);
1724 } else {
1725 list_add_tail(&mfc_buf->list, &ctx->src_queue);
1726 ctx->src_queue_cnt++;
1727 }
1728 spin_unlock_irqrestore(&dev->irqlock, flags); 1792 spin_unlock_irqrestore(&dev->irqlock, flags);
1729 } else { 1793 } else {
1730 mfc_err("unsupported buffer type (%d)\n", vq->type); 1794 mfc_err("unsupported buffer type (%d)\n", vq->type);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index b5fd3d4d5a7b..767a51271dc2 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -1075,14 +1075,21 @@ int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
1075int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx) 1075int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
1076{ 1076{
1077 struct s5p_mfc_dev *dev = ctx->dev; 1077 struct s5p_mfc_dev *dev = ctx->dev;
1078 int cmd;
1078 /* memory structure cur. frame */ 1079 /* memory structure cur. frame */
1079 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) 1080 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
1080 mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR); 1081 mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
1081 else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) 1082 else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
1082 mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR); 1083 mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
1083 s5p_mfc_set_shared_buffer(ctx); 1084 s5p_mfc_set_shared_buffer(ctx);
1084 mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) | 1085
1085 (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID); 1086 if (ctx->state == MFCINST_FINISHING)
1087 cmd = S5P_FIMV_CH_LAST_FRAME;
1088 else
1089 cmd = S5P_FIMV_CH_FRAME_START;
1090 mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
1091 | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
1092
1086 return 0; 1093 return 0;
1087} 1094}
1088 1095
@@ -1133,7 +1140,7 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
1133 } 1140 }
1134 /* Get the next source buffer */ 1141 /* Get the next source buffer */
1135 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); 1142 temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
1136 temp_vb->used = 1; 1143 temp_vb->flags |= MFC_BUF_FLAG_USED;
1137 s5p_mfc_set_dec_stream_buffer(ctx, 1144 s5p_mfc_set_dec_stream_buffer(ctx,
1138 vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream, 1145 vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
1139 temp_vb->b->v4l2_planes[0].bytesused); 1146 temp_vb->b->v4l2_planes[0].bytesused);
@@ -1160,7 +1167,7 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
1160 unsigned int dst_size; 1167 unsigned int dst_size;
1161 1168
1162 spin_lock_irqsave(&dev->irqlock, flags); 1169 spin_lock_irqsave(&dev->irqlock, flags);
1163 if (list_empty(&ctx->src_queue)) { 1170 if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
1164 mfc_debug(2, "no src buffers\n"); 1171 mfc_debug(2, "no src buffers\n");
1165 spin_unlock_irqrestore(&dev->irqlock, flags); 1172 spin_unlock_irqrestore(&dev->irqlock, flags);
1166 return -EAGAIN; 1173 return -EAGAIN;
@@ -1170,19 +1177,40 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
1170 spin_unlock_irqrestore(&dev->irqlock, flags); 1177 spin_unlock_irqrestore(&dev->irqlock, flags);
1171 return -EAGAIN; 1178 return -EAGAIN;
1172 } 1179 }
1173 src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list); 1180 if (list_empty(&ctx->src_queue)) {
1174 src_mb->used = 1; 1181 /* send null frame */
1175 src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0); 1182 s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2);
1176 src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1); 1183 src_mb = NULL;
1177 s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr); 1184 } else {
1185 src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
1186 list);
1187 src_mb->flags |= MFC_BUF_FLAG_USED;
1188 if (src_mb->b->v4l2_planes[0].bytesused == 0) {
1189 /* send null frame */
1190 s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2,
1191 dev->bank2);
1192 ctx->state = MFCINST_FINISHING;
1193 } else {
1194 src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
1195 0);
1196 src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
1197 1);
1198 s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr,
1199 src_c_addr);
1200 if (src_mb->flags & MFC_BUF_FLAG_EOS)
1201 ctx->state = MFCINST_FINISHING;
1202 }
1203 }
1178 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list); 1204 dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
1179 dst_mb->used = 1; 1205 dst_mb->flags |= MFC_BUF_FLAG_USED;
1180 dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0); 1206 dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
1181 dst_size = vb2_plane_size(dst_mb->b, 0); 1207 dst_size = vb2_plane_size(dst_mb->b, 0);
1182 s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size); 1208 s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
1183 spin_unlock_irqrestore(&dev->irqlock, flags); 1209 spin_unlock_irqrestore(&dev->irqlock, flags);
1184 dev->curr_ctx = ctx->num; 1210 dev->curr_ctx = ctx->num;
1185 s5p_mfc_clean_ctx_int_flags(ctx); 1211 s5p_mfc_clean_ctx_int_flags(ctx);
1212 mfc_debug(2, "encoding buffer with index=%d state=%d",
1213 src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
1186 s5p_mfc_encode_one_frame(ctx); 1214 s5p_mfc_encode_one_frame(ctx);
1187 return 0; 1215 return 0;
1188} 1216}