summaryrefslogtreecommitdiff
path: root/drivers/media/platform/coda
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/coda')
-rw-r--r--drivers/media/platform/coda/coda-bit.c4
-rw-r--r--drivers/media/platform/coda/coda-common.c44
-rw-r--r--drivers/media/platform/coda/coda.h1
3 files changed, 42 insertions, 7 deletions
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 44085e3d43d5..1157454e3bc8 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -402,6 +402,9 @@ void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
meta->timestamp = src_buf->vb2_buf.timestamp;
meta->start = start;
meta->end = ctx->bitstream_fifo.kfifo.in;
+ meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST;
+ if (meta->last)
+ coda_dbg(1, ctx, "marking last meta");
spin_lock(&ctx->buffer_meta_lock);
list_add_tail(&meta->list,
&ctx->buffer_meta_list);
@@ -2334,6 +2337,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
memset(&decoded_frame->meta, 0,
sizeof(struct coda_buffer_meta));
decoded_frame->meta.sequence = val;
+ decoded_frame->meta.last = false;
ctx->sequence_offset++;
}
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 95c233b2cbf8..11baa5b1eed8 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1077,6 +1077,8 @@ static int coda_decoder_cmd(struct file *file, void *fh,
struct coda_dev *dev = ctx->dev;
struct vb2_v4l2_buffer *buf;
struct vb2_queue *dst_vq;
+ bool stream_end;
+ bool wakeup;
int ret;
ret = coda_try_decoder_cmd(file, fh, dc);
@@ -1097,23 +1099,51 @@ static int coda_decoder_cmd(struct file *file, void *fh,
mutex_unlock(&ctx->bitstream_mutex);
break;
case V4L2_DEC_CMD_STOP:
+ stream_end = false;
+ wakeup = false;
+
buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
- if (buf)
+ if (buf) {
+ coda_dbg(1, ctx, "marking last pending buffer\n");
+
/* Mark last buffer */
buf->flags |= V4L2_BUF_FLAG_LAST;
- if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) {
+ if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) {
+ coda_dbg(1, ctx, "all remaining buffers queued\n");
+ stream_end = true;
+ }
+ } else {
+ coda_dbg(1, ctx, "marking last meta\n");
+
+ /* Mark last meta */
+ spin_lock(&ctx->buffer_meta_lock);
+ if (!list_empty(&ctx->buffer_meta_list)) {
+ struct coda_buffer_meta *meta;
+
+ meta = list_last_entry(&ctx->buffer_meta_list,
+ struct coda_buffer_meta,
+ list);
+ meta->last = true;
+ stream_end = true;
+ } else {
+ wakeup = true;
+ }
+ spin_unlock(&ctx->buffer_meta_lock);
+ }
+
+ if (stream_end) {
+ coda_dbg(1, ctx, "all remaining buffers queued\n");
+
/* Set the stream-end flag on this context */
coda_bit_stream_end_flag(ctx);
ctx->hold = false;
v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
+ }
- flush_work(&ctx->pic_run_work);
-
+ if (wakeup) {
/* If there is no buffer in flight, wake up */
- if (!ctx->streamon_out ||
- ctx->qsequence == ctx->osequence)
- coda_wake_up_capture_queue(ctx);
+ coda_wake_up_capture_queue(ctx);
}
break;
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 97845e58fb8b..5c183c1944fe 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -146,6 +146,7 @@ struct coda_buffer_meta {
u64 timestamp;
unsigned int start;
unsigned int end;
+ bool last;
};
/* Per-queue, driver-specific private data */