summaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorPhilipp Zabel2019-06-18 18:45:21 +0200
committerMauro Carvalho Chehab2019-06-24 20:31:50 +0200
commite7fd95849b3c25ae1604ba2788e63fe6570ba0ff (patch)
treea0025d3e7d49812c57b6b0596976aada1aa056f9 /drivers/media
parentmedia: coda: do not enforce 512-byte initial bitstream payload on CODA960 (diff)
downloadkernel-qcow2-linux-e7fd95849b3c25ae1604ba2788e63fe6570ba0ff.tar.gz
kernel-qcow2-linux-e7fd95849b3c25ae1604ba2788e63fe6570ba0ff.tar.xz
kernel-qcow2-linux-e7fd95849b3c25ae1604ba2788e63fe6570ba0ff.zip
media: coda: flush bitstream ring buffer on decoder restart
The bitstream ringbuffer might be in an underrun state after draining, or it might still contain unread data if the previous decoder stop command was flagged as immediate. Flush the bitstream ring buffer during V4L2_DEC_CMD_START to get into a well defined state. Also fill the bitstream with buffers that have been queued during draining, to resume decoding immediately. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/coda/coda-bit.c20
-rw-r--r--drivers/media/platform/coda/coda-common.c7
-rw-r--r--drivers/media/platform/coda/coda.h1
3 files changed, 28 insertions, 0 deletions
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index 5a1016243032..843f92312f47 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -199,6 +199,26 @@ static int coda_h264_bitstream_pad(struct coda_ctx *ctx, u32 size)
return (n < size) ? -ENOSPC : 0;
}
+int coda_bitstream_flush(struct coda_ctx *ctx)
+{
+ int ret;
+
+ if (ctx->inst_type != CODA_INST_DECODER || !ctx->use_bit)
+ return 0;
+
+ ret = coda_command_sync(ctx, CODA_COMMAND_DEC_BUF_FLUSH);
+ if (ret < 0) {
+ v4l2_err(&ctx->dev->v4l2_dev, "failed to flush bitstream\n");
+ return ret;
+ }
+
+ kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr,
+ ctx->bitstream.size);
+ coda_kfifo_sync_to_device_full(ctx);
+
+ return 0;
+}
+
static int coda_bitstream_queue(struct coda_ctx *ctx, const u8 *buf, u32 size)
{
u32 n = kfifo_in(&ctx->bitstream_fifo, buf, size);
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 1f1eb9685bc4..0f5e6dcded99 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1052,6 +1052,7 @@ static int coda_decoder_cmd(struct file *file, void *fh,
struct v4l2_decoder_cmd *dc)
{
struct coda_ctx *ctx = fh_to_ctx(fh);
+ struct coda_dev *dev = ctx->dev;
struct vb2_queue *dst_vq;
int ret;
@@ -1061,10 +1062,16 @@ static int coda_decoder_cmd(struct file *file, void *fh,
switch (dc->cmd) {
case V4L2_DEC_CMD_START:
+ mutex_lock(&ctx->bitstream_mutex);
+ mutex_lock(&dev->coda_mutex);
+ coda_bitstream_flush(ctx);
+ mutex_unlock(&dev->coda_mutex);
dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
vb2_clear_last_buffer_dequeued(dst_vq);
ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
+ coda_fill_bitstream(ctx, NULL);
+ mutex_unlock(&ctx->bitstream_mutex);
break;
case V4L2_DEC_CMD_STOP:
/* Set the stream-end flag on this context */
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 12bbd3129269..6911c1c811ce 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -322,6 +322,7 @@ static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx,
}
bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos);
+int coda_bitstream_flush(struct coda_ctx *ctx);
void coda_bit_stream_end_flag(struct coda_ctx *ctx);