RE: [PATCH 8/8] [media] coda: move BIT specific functions into separate file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Philipp,

I have some errors from checkpatch for this patch. Please fix them.

ERROR: return is not a function, parentheses are not required
#86: FILE: drivers/media/platform/coda/coda-bit.c:40:
+	return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0);

WARNING: quoted string split across lines
#681: FILE: drivers/media/platform/coda/coda-bit.c:635:
+		v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s,"
+			 " Version: %u.%u.%u\n",

WARNING: quoted string split across lines
#695: FILE: drivers/media/platform/coda/coda-bit.c:649:
+		v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: "
+			  "%u.%u.%u\n", major, minor, releas

And many, many following warnings: "WARNING: line over 80 characters".
Please check if these lines *REALLY* need to be such long.

Best wishes,
-- 
Kamil Debski
Samsung R&D Institute Poland


> -----Original Message-----
> From: Philipp Zabel [mailto:p.zabel@xxxxxxxxxxxxxx]
> Sent: Wednesday, July 23, 2014 5:29 PM
> To: linux-media@xxxxxxxxxxxxxxx
> Cc: Mauro Carvalho Chehab; Kamil Debski; Fabio Estevam; Hans Verkuil;
> Nicolas Dufresne; kernel@xxxxxxxxxxxxxx; Philipp Zabel
> Subject: [PATCH 8/8] [media] coda: move BIT specific functions into
> separate file
> 
> This patch moves the BIT processor specific coda_context_ops, the
> firmware
> upload and other related functions from coda-common.c into coda-bit.c.
> 
> Signed-off-by: Philipp Zabel <p.zabel@xxxxxxxxxxxxxx>
> ---
>  drivers/media/platform/coda/Makefile      |    2 +-
>  drivers/media/platform/coda/coda-bit.c    | 1810
> ++++++++++++++++++++++++++++
>  drivers/media/platform/coda/coda-common.c | 1857 +--------------------
> --------
>  drivers/media/platform/coda/coda.h        |   56 +
>  4 files changed, 1893 insertions(+), 1832 deletions(-)
>  create mode 100644 drivers/media/platform/coda/coda-bit.c
> 
> diff --git a/drivers/media/platform/coda/Makefile
> b/drivers/media/platform/coda/Makefile
> index 0e59fbd..3543291 100644
> --- a/drivers/media/platform/coda/Makefile
> +++ b/drivers/media/platform/coda/Makefile
> @@ -1,3 +1,3 @@
> -coda-objs := coda-common.o coda-h264.o
> +coda-objs := coda-common.o coda-bit.o coda-h264.o
> 
>  obj-$(CONFIG_VIDEO_CODA) += coda.o
> diff --git a/drivers/media/platform/coda/coda-bit.c
> b/drivers/media/platform/coda/coda-bit.c
> new file mode 100644
> index 0000000..1d2716d
> --- /dev/null
> +++ b/drivers/media/platform/coda/coda-bit.c
> @@ -0,0 +1,1810 @@
> +/*
> + * Coda multi-standard codec IP - BIT processor functions
> + *
> + * Copyright (C) 2012 Vista Silicon S.L.
> + *    Javier Martin, <javier.martin@xxxxxxxxxxxxxxxxx>
> + *    Xavier Duret
> + * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License as published
> by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/irqreturn.h>
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/videodev2.h>
> +
> +#include <media/v4l2-common.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-fh.h>
> +#include <media/v4l2-mem2mem.h>
> +#include <media/videobuf2-core.h>
> +#include <media/videobuf2-dma-contig.h>
> +#include <media/videobuf2-vmalloc.h>
> +
> +#include "coda.h"
> +
> +#define CODA7_PS_BUF_SIZE	0x28000
> +#define CODA9_PS_SAVE_SIZE	(512 * 1024)
> +
> +#define CODA_DEFAULT_GAMMA	4096
> +#define CODA9_DEFAULT_GAMMA	24576	/* 0.75 * 32768 */
> +
> +static inline int coda_is_initialized(struct coda_dev *dev)
> +{
> +	return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0);
> +}
> +
> +static inline unsigned long coda_isbusy(struct coda_dev *dev)
> +{
> +	return coda_read(dev, CODA_REG_BIT_BUSY);
> +}
> +
> +static int coda_wait_timeout(struct coda_dev *dev)
> +{
> +	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
> +
> +	while (coda_isbusy(dev)) {
> +		if (time_after(jiffies, timeout))
> +			return -ETIMEDOUT;
> +	}
> +	return 0;
> +}
> +
> +static void coda_command_async(struct coda_ctx *ctx, int cmd)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +
> +	if (dev->devtype->product == CODA_960 ||
> +	    dev->devtype->product == CODA_7541) {
> +		/* Restore context related registers to CODA */
> +		coda_write(dev, ctx->bit_stream_param,
> +				CODA_REG_BIT_BIT_STREAM_PARAM);
> +		coda_write(dev, ctx->frm_dis_flg,
> +				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
> +		coda_write(dev, ctx->frame_mem_ctrl,
> +				CODA_REG_BIT_FRAME_MEM_CTRL);
> +		coda_write(dev, ctx->workbuf.paddr,
> CODA_REG_BIT_WORK_BUF_ADDR);
> +	}
> +
> +	if (dev->devtype->product == CODA_960) {
> +		coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
> +		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
> +	}
> +
> +	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
> +
> +	coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
> +	coda_write(dev, ctx->params.codec_mode,
> CODA_REG_BIT_RUN_COD_STD);
> +	coda_write(dev, ctx->params.codec_mode_aux,
> CODA7_REG_BIT_RUN_AUX_STD);
> +
> +	coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
> +}
> +
> +static int coda_command_sync(struct coda_ctx *ctx, int cmd)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +
> +	coda_command_async(ctx, cmd);
> +	return coda_wait_timeout(dev);
> +}
> +
> +int coda_hw_reset(struct coda_ctx *ctx)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	unsigned long timeout;
> +	unsigned int idx;
> +	int ret;
> +
> +	if (!dev->rstc)
> +		return -ENOENT;
> +
> +	idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
> +
> +	if (dev->devtype->product == CODA_960) {
> +		timeout = jiffies + msecs_to_jiffies(100);
> +		coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
> +		while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
> +			if (time_after(jiffies, timeout))
> +				return -ETIME;
> +			cpu_relax();
> +		}
> +	}
> +
> +	ret = reset_control_reset(dev->rstc);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (dev->devtype->product == CODA_960)
> +		coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
> +	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
> +	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
> +	ret = coda_wait_timeout(dev);
> +	coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
> +
> +	return ret;
> +}
> +
> +static void coda_kfifo_sync_from_device(struct coda_ctx *ctx)
> +{
> +	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
> +	struct coda_dev *dev = ctx->dev;
> +	u32 rd_ptr;
> +
> +	rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
> +	kfifo->out = (kfifo->in & ~kfifo->mask) |
> +		      (rd_ptr - ctx->bitstream.paddr);
> +	if (kfifo->out > kfifo->in)
> +		kfifo->out -= kfifo->mask + 1;
> +}
> +
> +static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx)
> +{
> +	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
> +	struct coda_dev *dev = ctx->dev;
> +	u32 rd_ptr, wr_ptr;
> +
> +	rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask);
> +	coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
> +	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
> +	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
> +}
> +
> +static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
> +{
> +	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
> +	struct coda_dev *dev = ctx->dev;
> +	u32 wr_ptr;
> +
> +	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
> +	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
> +}
> +
> +static int coda_bitstream_queue(struct coda_ctx *ctx, struct
> vb2_buffer *src_buf)
> +{
> +	u32 src_size = vb2_get_plane_payload(src_buf, 0);
> +	u32 n;
> +
> +	n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0),
> src_size);
> +	if (n < src_size)
> +		return -ENOSPC;
> +
> +	dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx-
> >bitstream.paddr,
> +				   ctx->bitstream.size, DMA_TO_DEVICE);
> +
> +	src_buf->v4l2_buf.sequence = ctx->qsequence++;
> +
> +	return 0;
> +}
> +
> +static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
> +				     struct vb2_buffer *src_buf)
> +{
> +	int ret;
> +
> +	if (coda_get_bitstream_payload(ctx) +
> +	    vb2_get_plane_payload(src_buf, 0) + 512 >= ctx-
> >bitstream.size)
> +		return false;
> +
> +	if (vb2_plane_vaddr(src_buf, 0) == NULL) {
> +		v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty
> buffer\n");
> +		return true;
> +	}
> +
> +	ret = coda_bitstream_queue(ctx, src_buf);
> +	if (ret < 0) {
> +		v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer
> overflow\n");
> +		return false;
> +	}
> +	/* Sync read pointer to device */
> +	if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
> +		coda_kfifo_sync_to_device_write(ctx);
> +
> +	ctx->hold = false;
> +
> +	return true;
> +}
> +
> +void coda_fill_bitstream(struct coda_ctx *ctx)
> +{
> +	struct vb2_buffer *src_buf;
> +	struct coda_timestamp *ts;
> +
> +	while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
> +		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> +
> +		if (coda_bitstream_try_queue(ctx, src_buf)) {
> +			/*
> +			 * Source buffer is queued in the bitstream
> ringbuffer;
> +			 * queue the timestamp and mark source buffer as
done
> +			 */
> +			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> +
> +			ts = kmalloc(sizeof(*ts), GFP_KERNEL);
> +			if (ts) {
> +				ts->sequence = src_buf->v4l2_buf.sequence;
> +				ts->timecode = src_buf->v4l2_buf.timecode;
> +				ts->timestamp = src_buf->v4l2_buf.timestamp;
> +				list_add_tail(&ts->list,
&ctx->timestamp_list);
> +			}
> +
> +			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
> +		} else {
> +			break;
> +		}
> +	}
> +}
> +
> +void coda_bit_stream_end_flag(struct coda_ctx *ctx)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +
> +	ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
> +
> +	if ((dev->devtype->product == CODA_960) &&
> +	    coda_isbusy(dev) &&
> +	    (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
> +		/* If this context is currently running, update the
> hardware flag */
> +		coda_write(dev, ctx->bit_stream_param,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> +	}
> +}
> +
> +static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32
> value)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	u32 *p = ctx->parabuf.vaddr;
> +
> +	if (dev->devtype->product == CODA_DX6)
> +		p[index] = value;
> +	else
> +		p[index ^ 1] = value;
> +}
> +
> +static void coda_free_framebuffers(struct coda_ctx *ctx)
> +{
> +	int i;
> +
> +	for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++)
> +		coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]);
> +}
> +
> +static int coda_alloc_framebuffers(struct coda_ctx *ctx,
> +				   struct coda_q_data *q_data, u32 fourcc)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	int width, height;
> +	dma_addr_t paddr;
> +	int ysize;
> +	int ret;
> +	int i;
> +
> +	if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
> +	     ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) {
> +		width = round_up(q_data->width, 16);
> +		height = round_up(q_data->height, 16);
> +	} else {
> +		width = round_up(q_data->width, 8);
> +		height = q_data->height;
> +	}
> +	ysize = width * height;
> +
> +	/* Allocate frame buffers */
> +	for (i = 0; i < ctx->num_internal_frames; i++) {
> +		size_t size;
> +		char *name;
> +
> +		size = ysize + ysize / 2;
> +		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
> +		    dev->devtype->product != CODA_DX6)
> +			size += ysize / 4;
> +		name = kasprintf(GFP_KERNEL, "fb%d", i);
> +		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i],
> +					     size, name);
> +		kfree(name);
> +		if (ret < 0) {
> +			coda_free_framebuffers(ctx);
> +			return ret;
> +		}
> +	}
> +
> +	/* Register frame buffers in the parameter buffer */
> +	for (i = 0; i < ctx->num_internal_frames; i++) {
> +		paddr = ctx->internal_frames[i].paddr;
> +		coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */
> +		coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */
> +		coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize +
> ysize/4); /* Cr */
> +
> +		/* mvcol buffer for h.264 */
> +		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
> +		    dev->devtype->product != CODA_DX6)
> +			coda_parabuf_write(ctx, 96 + i,
> +					   ctx->internal_frames[i].paddr +
> +					   ysize + ysize/4 + ysize/4);
> +	}
> +
> +	/* mvcol buffer for mpeg4 */
> +	if ((dev->devtype->product != CODA_DX6) &&
> +	    (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4))
> +		coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr +
> +					    ysize + ysize/4 + ysize/4);
> +
> +	return 0;
> +}
> +
> +static void coda_free_context_buffers(struct coda_ctx *ctx)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +
> +	coda_free_aux_buf(dev, &ctx->slicebuf);
> +	coda_free_aux_buf(dev, &ctx->psbuf);
> +	if (dev->devtype->product != CODA_DX6)
> +		coda_free_aux_buf(dev, &ctx->workbuf);
> +}
> +
> +static int coda_alloc_context_buffers(struct coda_ctx *ctx,
> +				      struct coda_q_data *q_data)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	size_t size;
> +	int ret;
> +
> +	if (dev->devtype->product == CODA_DX6)
> +		return 0;
> +
> +	if (ctx->psbuf.vaddr) {
> +		v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n");
> +		return -EBUSY;
> +	}
> +	if (ctx->slicebuf.vaddr) {
> +		v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n");
> +		return -EBUSY;
> +	}
> +	if (ctx->workbuf.vaddr) {
> +		v4l2_err(&dev->v4l2_dev, "context buffer still
> allocated\n");
> +		ret = -EBUSY;
> +		return -ENOMEM;
> +	}
> +
> +	if (q_data->fourcc == V4L2_PIX_FMT_H264) {
> +		/* worst case slice size */
> +		size = (DIV_ROUND_UP(q_data->width, 16) *
> +			DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
> +		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size,
> "slicebuf");
> +		if (ret < 0) {
> +			v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte
> slice buffer",
> +				 ctx->slicebuf.size);
> +			return ret;
> +		}
> +	}
> +
> +	if (dev->devtype->product == CODA_7541) {
> +		ret = coda_alloc_context_buf(ctx, &ctx->psbuf,
> CODA7_PS_BUF_SIZE, "psbuf");
> +		if (ret < 0) {
> +			v4l2_err(&dev->v4l2_dev, "failed to allocate psmem
> buffer");
> +			goto err;
> +		}
> +	}
> +
> +	size = dev->devtype->workbuf_size;
> +	if (dev->devtype->product == CODA_960 &&
> +	    q_data->fourcc == V4L2_PIX_FMT_H264)
> +		size += CODA9_PS_SAVE_SIZE;
> +	ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size,
> "workbuf");
> +	if (ret < 0) {
> +		v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte
> context buffer",
> +			 ctx->workbuf.size);
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	coda_free_context_buffers(ctx);
> +	return ret;
> +}
> +
> +static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer
> *buf,
> +			      int header_code, u8 *header, int *size)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	size_t bufsize;
> +	int ret;
> +	int i;
> +
> +	if (dev->devtype->product == CODA_960)
> +		memset(vb2_plane_vaddr(buf, 0), 0, 64);
> +
> +	coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0),
> +		   CODA_CMD_ENC_HEADER_BB_START);
> +	bufsize = vb2_plane_size(buf, 0);
> +	if (dev->devtype->product == CODA_960)
> +		bufsize /= 1024;
> +	coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
> +	coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE);
> +	ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER);
> +	if (ret < 0) {
> +		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER
> timeout\n");
> +		return ret;
> +	}
> +
> +	if (dev->devtype->product == CODA_960) {
> +		for (i = 63; i > 0; i--)
> +			if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0)
> +				break;
> +		*size = i + 1;
> +	} else {
> +		*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
> +			coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
> +	}
> +	memcpy(header, vb2_plane_vaddr(buf, 0), *size);
> +
> +	return 0;
> +}
> +
> +static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t
> size)
> +{
> +	phys_addr_t ret;
> +
> +	size = round_up(size, 1024);
> +	if (size > iram->remaining)
> +		return 0;
> +	iram->remaining -= size;
> +
> +	ret = iram->next_paddr;
> +	iram->next_paddr += size;
> +
> +	return ret;
> +}
> +
> +static void coda_setup_iram(struct coda_ctx *ctx)
> +{
> +	struct coda_iram_info *iram_info = &ctx->iram_info;
> +	struct coda_dev *dev = ctx->dev;
> +	int mb_width;
> +	int dbk_bits;
> +	int bit_bits;
> +	int ip_bits;
> +
> +	memset(iram_info, 0, sizeof(*iram_info));
> +	iram_info->next_paddr = dev->iram.paddr;
> +	iram_info->remaining = dev->iram.size;
> +
> +	switch (dev->devtype->product) {
> +	case CODA_7541:
> +		dbk_bits = CODA7_USE_HOST_DBK_ENABLE |
> CODA7_USE_DBK_ENABLE;
> +		bit_bits = CODA7_USE_HOST_BIT_ENABLE |
> CODA7_USE_BIT_ENABLE;
> +		ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
> +		break;
> +	case CODA_960:
> +		dbk_bits = CODA9_USE_HOST_DBK_ENABLE |
> CODA9_USE_DBK_ENABLE;
> +		bit_bits = CODA9_USE_HOST_BIT_ENABLE |
> CODA7_USE_BIT_ENABLE;
> +		ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
> +		break;
> +	default: /* CODA_DX6 */
> +		return;
> +	}
> +
> +	if (ctx->inst_type == CODA_INST_ENCODER) {
> +		struct coda_q_data *q_data_src;
> +
> +		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> +		mb_width = DIV_ROUND_UP(q_data_src->width, 16);
> +
> +		/* Prioritize in case IRAM is too small for everything */
> +		if (dev->devtype->product == CODA_7541) {
> +			iram_info->search_ram_size = round_up(mb_width * 16
*
> +							      36 + 2048,
1024);
> +			iram_info->search_ram_paddr =
> coda_iram_alloc(iram_info,
> +
iram_info->search_ram_size);
> +			if (!iram_info->search_ram_paddr) {
> +				pr_err("IRAM is smaller than the search ram
> size\n");
> +				goto out;
> +			}
> +			iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE
|
> +						   CODA7_USE_ME_ENABLE;
> +		}
> +
> +		/* Only H.264BP and H.263P3 are considered */
> +		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 *
> mb_width);
> +		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 *
> mb_width);
> +		if (!iram_info->buf_dbk_c_use)
> +			goto out;
> +		iram_info->axi_sram_use |= dbk_bits;
> +
> +		iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> +		if (!iram_info->buf_bit_use)
> +			goto out;
> +		iram_info->axi_sram_use |= bit_bits;
> +
> +		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info,
> 128 * mb_width);
> +		if (!iram_info->buf_ip_ac_dc_use)
> +			goto out;
> +		iram_info->axi_sram_use |= ip_bits;
> +
> +		/* OVL and BTP disabled for encoder */
> +	} else if (ctx->inst_type == CODA_INST_DECODER) {
> +		struct coda_q_data *q_data_dst;
> +
> +		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> +		mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
> +
> +		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> +		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> +		if (!iram_info->buf_dbk_c_use)
> +			goto out;
> +		iram_info->axi_sram_use |= dbk_bits;
> +
> +		iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> +		if (!iram_info->buf_bit_use)
> +			goto out;
> +		iram_info->axi_sram_use |= bit_bits;
> +
> +		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info,
> 128 * mb_width);
> +		if (!iram_info->buf_ip_ac_dc_use)
> +			goto out;
> +		iram_info->axi_sram_use |= ip_bits;
> +
> +		/* OVL and BTP unused as there is no VC1 support yet */
> +	}
> +
> +out:
> +	if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
> +		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
> +			 "IRAM smaller than needed\n");
> +
> +	if (dev->devtype->product == CODA_7541) {
> +		/* TODO - Enabling these causes picture errors on CODA7541
> */
> +		if (ctx->inst_type == CODA_INST_DECODER) {
> +			/* fw 1.4.50 */
> +			iram_info->axi_sram_use &=
~(CODA7_USE_HOST_IP_ENABLE
> |
> +						     CODA7_USE_IP_ENABLE);
> +		} else {
> +			/* fw 13.4.29 */
> +			iram_info->axi_sram_use &=
~(CODA7_USE_HOST_IP_ENABLE
> |
> +
CODA7_USE_HOST_DBK_ENABLE |
> +						     CODA7_USE_IP_ENABLE |
> +						     CODA7_USE_DBK_ENABLE);
> +		}
> +	}
> +}
> +
> +static u32 coda_supported_firmwares[] = {
> +	CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
> +	CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
> +	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
> +};
> +
> +static bool coda_firmware_supported(u32 vernum)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++)
> +		if (vernum == coda_supported_firmwares[i])
> +			return true;
> +	return false;
> +}
> +
> +int coda_check_firmware(struct coda_dev *dev)
> +{
> +	u16 product, major, minor, release;
> +	u32 data;
> +	int ret;
> +
> +	ret = clk_prepare_enable(dev->clk_per);
> +	if (ret)
> +		goto err_clk_per;
> +
> +	ret = clk_prepare_enable(dev->clk_ahb);
> +	if (ret)
> +		goto err_clk_ahb;
> +
> +	coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
> +	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
> +	coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
> +	coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
> +	coda_write(dev, CODA_COMMAND_FIRMWARE_GET,
> CODA_REG_BIT_RUN_COMMAND);
> +	if (coda_wait_timeout(dev)) {
> +		v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
> +		ret = -EIO;
> +		goto err_run_cmd;
> +	}
> +
> +	if (dev->devtype->product == CODA_960) {
> +		data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
> +		v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
> +			  data);
> +	}
> +
> +	/* Check we are compatible with the loaded firmware */
> +	data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM);
> +	product = CODA_FIRMWARE_PRODUCT(data);
> +	major = CODA_FIRMWARE_MAJOR(data);
> +	minor = CODA_FIRMWARE_MINOR(data);
> +	release = CODA_FIRMWARE_RELEASE(data);
> +
> +	clk_disable_unprepare(dev->clk_per);
> +	clk_disable_unprepare(dev->clk_ahb);
> +
> +	if (product != dev->devtype->product) {
> +		v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s,"
> +			 " Version: %u.%u.%u\n",
> +			 coda_product_name(dev->devtype->product),
> +			 coda_product_name(product), major, minor, release);
> +		return -EINVAL;
> +	}
> +
> +	v4l2_info(&dev->v4l2_dev, "Initialized %s.\n",
> +		  coda_product_name(product));
> +
> +	if (coda_firmware_supported(data)) {
> +		v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n",
> +			  major, minor, release);
> +	} else {
> +		v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: "
> +			  "%u.%u.%u\n", major, minor, release);
> +	}
> +
> +	return 0;
> +
> +err_run_cmd:
> +	clk_disable_unprepare(dev->clk_ahb);
> +err_clk_ahb:
> +	clk_disable_unprepare(dev->clk_per);
> +err_clk_per:
> +	return ret;
> +}
> +
> +/*
> + * Encoder context operations
> + */
> +
> +static int coda_start_encoding(struct coda_ctx *ctx)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> +	struct coda_q_data *q_data_src, *q_data_dst;
> +	u32 bitstream_buf, bitstream_size;
> +	struct vb2_buffer *buf;
> +	int gamma, ret, value;
> +	u32 dst_fourcc;
> +
> +	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> +	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> +	dst_fourcc = q_data_dst->fourcc;
> +
> +	/* Allocate per-instance buffers */
> +	ret = coda_alloc_context_buffers(ctx, q_data_src);
> +	if (ret < 0)
> +		return ret;
> +
> +	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +	bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
> +	bitstream_size = q_data_dst->sizeimage;
> +
> +	if (!coda_is_initialized(dev)) {
> +		v4l2_err(v4l2_dev, "coda is not initialized.\n");
> +		return -EFAULT;
> +	}
> +
> +	mutex_lock(&dev->coda_mutex);
> +
> +	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
> +	coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx-
> >reg_idx));
> +	coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx-
> >reg_idx));
> +	switch (dev->devtype->product) {
> +	case CODA_DX6:
> +		coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
> +			CODADX6_STREAM_BUF_PIC_RESET,
> CODA_REG_BIT_STREAM_CTRL);
> +		break;
> +	case CODA_960:
> +		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
> +		/* fallthrough */
> +	case CODA_7541:
> +		coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
> +			CODA7_STREAM_BUF_PIC_RESET,
> CODA_REG_BIT_STREAM_CTRL);
> +		break;
> +	}
> +
> +	value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL);
> +	value &= ~(1 << 2 | 0x7 << 9);
> +	ctx->frame_mem_ctrl = value;
> +	coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL);
> +
> +	if (dev->devtype->product == CODA_DX6) {
> +		/* Configure the coda */
> +		coda_write(dev, dev->iram.paddr,
> CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
> +	}
> +
> +	/* Could set rotation here if needed */
> +	switch (dev->devtype->product) {
> +	case CODA_DX6:
> +		value = (q_data_src->width & CODADX6_PICWIDTH_MASK) <<
> CODADX6_PICWIDTH_OFFSET;
> +		value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) <<
> CODA_PICHEIGHT_OFFSET;
> +		break;
> +	case CODA_7541:
> +		if (dst_fourcc == V4L2_PIX_FMT_H264) {
> +			value = (round_up(q_data_src->width, 16) &
> +				 CODA7_PICWIDTH_MASK) <<
CODA7_PICWIDTH_OFFSET;
> +			value |= (round_up(q_data_src->height, 16) &
> +				  CODA7_PICHEIGHT_MASK) <<
> CODA_PICHEIGHT_OFFSET;
> +			break;
> +		}
> +		/* fallthrough */
> +	case CODA_960:
> +		value = (q_data_src->width & CODA7_PICWIDTH_MASK) <<
> CODA7_PICWIDTH_OFFSET;
> +		value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) <<
> CODA_PICHEIGHT_OFFSET;
> +	}
> +	coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
> +	coda_write(dev, ctx->params.framerate,
> +		   CODA_CMD_ENC_SEQ_SRC_F_RATE);
> +
> +	ctx->params.codec_mode = ctx->codec->mode;
> +	switch (dst_fourcc) {
> +	case V4L2_PIX_FMT_MPEG4:
> +		if (dev->devtype->product == CODA_960)
> +			coda_write(dev, CODA9_STD_MPEG4,
> CODA_CMD_ENC_SEQ_COD_STD);
> +		else
> +			coda_write(dev, CODA_STD_MPEG4,
> CODA_CMD_ENC_SEQ_COD_STD);
> +		coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
> +		break;
> +	case V4L2_PIX_FMT_H264:
> +		if (dev->devtype->product == CODA_960)
> +			coda_write(dev, CODA9_STD_H264,
> CODA_CMD_ENC_SEQ_COD_STD);
> +		else
> +			coda_write(dev, CODA_STD_H264,
> CODA_CMD_ENC_SEQ_COD_STD);
> +		if (ctx->params.h264_deblk_enabled) {
> +			value = ((ctx->params.h264_deblk_alpha &
> +				  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK)
<<
> +
CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
> +				((ctx->params.h264_deblk_beta &
> +				  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK)
<<
> +
CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET);
> +		} else {
> +			value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET;
> +		}
> +		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
> +		break;
> +	default:
> +		v4l2_err(v4l2_dev,
> +			 "dst format (0x%08x) invalid.\n", dst_fourcc);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	switch (ctx->params.slice_mode) {
> +	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
> +		value = 0;
> +		break;
> +	case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
> +		value  = (ctx->params.slice_max_mb &
> CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET;
> +		value |= (1 & CODA_SLICING_UNIT_MASK) <<
> CODA_SLICING_UNIT_OFFSET;
> +		value |=  1 & CODA_SLICING_MODE_MASK;
> +		break;
> +	case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
> +		value  = (ctx->params.slice_max_bits &
> CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET;
> +		value |= (0 & CODA_SLICING_UNIT_MASK) <<
> CODA_SLICING_UNIT_OFFSET;
> +		value |=  1 & CODA_SLICING_MODE_MASK;
> +		break;
> +	}
> +	coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
> +	value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
> +	coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
> +
> +	if (ctx->params.bitrate) {
> +		/* Rate control enabled */
> +		value = (ctx->params.bitrate &
> CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET;
> +		value |=  1 & CODA_RATECONTROL_ENABLE_MASK;
> +		if (dev->devtype->product == CODA_960)
> +			value |= BIT(31); /* disable autoskip */
> +	} else {
> +		value = 0;
> +	}
> +	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
> +
> +	coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
> +	coda_write(dev, ctx->params.intra_refresh,
> +		   CODA_CMD_ENC_SEQ_INTRA_REFRESH);
> +
> +	coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
> +	coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
> +
> +
> +	value = 0;
> +	if (dev->devtype->product == CODA_960)
> +		gamma = CODA9_DEFAULT_GAMMA;
> +	else
> +		gamma = CODA_DEFAULT_GAMMA;
> +	if (gamma > 0) {
> +		coda_write(dev, (gamma & CODA_GAMMA_MASK) <<
> CODA_GAMMA_OFFSET,
> +			   CODA_CMD_ENC_SEQ_RC_GAMMA);
> +	}
> +
> +	if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) {
> +		coda_write(dev,
> +			   ctx->params.h264_min_qp << CODA_QPMIN_OFFSET |
> +			   ctx->params.h264_max_qp << CODA_QPMAX_OFFSET,
> +			   CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX);
> +	}
> +	if (dev->devtype->product == CODA_960) {
> +		if (ctx->params.h264_max_qp)
> +			value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET;
> +		if (CODA_DEFAULT_GAMMA > 0)
> +			value |= 1 << CODA9_OPTION_GAMMA_OFFSET;
> +	} else {
> +		if (CODA_DEFAULT_GAMMA > 0) {
> +			if (dev->devtype->product == CODA_DX6)
> +				value |= 1 << CODADX6_OPTION_GAMMA_OFFSET;
> +			else
> +				value |= 1 << CODA7_OPTION_GAMMA_OFFSET;
> +		}
> +		if (ctx->params.h264_min_qp)
> +			value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET;
> +		if (ctx->params.h264_max_qp)
> +			value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET;
> +	}
> +	coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
> +
> +	coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
> +
> +	coda_setup_iram(ctx);
> +
> +	if (dst_fourcc == V4L2_PIX_FMT_H264) {
> +		switch (dev->devtype->product) {
> +		case CODA_DX6:
> +			value = FMO_SLICE_SAVE_BUF_SIZE << 7;
> +			coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
> +			break;
> +		case CODA_7541:
> +			coda_write(dev, ctx->iram_info.search_ram_paddr,
> +					CODA7_CMD_ENC_SEQ_SEARCH_BASE);
> +			coda_write(dev, ctx->iram_info.search_ram_size,
> +					CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
> +			break;
> +		case CODA_960:
> +			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION);
> +			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT);
> +		}
> +	}
> +
> +	ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
> +		goto out;
> +	}
> +
> +	if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) {
> +		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n");
> +		ret = -EFAULT;
> +		goto out;
> +	}
> +
> +	if (dev->devtype->product == CODA_960)
> +		ctx->num_internal_frames = 4;
> +	else
> +		ctx->num_internal_frames = 2;
> +	ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
> +		goto out;
> +	}
> +
> +	coda_write(dev, ctx->num_internal_frames,
> CODA_CMD_SET_FRAME_BUF_NUM);
> +	coda_write(dev, q_data_src->bytesperline,
> +			CODA_CMD_SET_FRAME_BUF_STRIDE);
> +	if (dev->devtype->product == CODA_7541) {
> +		coda_write(dev, q_data_src->bytesperline,
> +				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
> +	}
> +	if (dev->devtype->product != CODA_DX6) {
> +		coda_write(dev, ctx->iram_info.buf_bit_use,
> +				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
> +				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
> +				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
> +				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_ovl_use,
> +				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
> +		if (dev->devtype->product == CODA_960) {
> +			coda_write(dev, ctx->iram_info.buf_btp_use,
> +					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
> +
> +			/* FIXME */
> +			coda_write(dev, ctx->internal_frames[2].paddr,
> CODA9_CMD_SET_FRAME_SUBSAMP_A);
> +			coda_write(dev, ctx->internal_frames[3].paddr,
> CODA9_CMD_SET_FRAME_SUBSAMP_B);
> +		}
> +	}
> +
> +	ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
> +		goto out;
> +	}
> +
> +	/* Save stream headers */
> +	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +	switch (dst_fourcc) {
> +	case V4L2_PIX_FMT_H264:
> +		/*
> +		 * Get SPS in the first frame and copy it to an
> +		 * intermediate buffer.
> +		 */
> +		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS,
> +					 &ctx->vpu_header[0][0],
> +					 &ctx->vpu_header_size[0]);
> +		if (ret < 0)
> +			goto out;
> +
> +		/*
> +		 * Get PPS in the first frame and copy it to an
> +		 * intermediate buffer.
> +		 */
> +		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS,
> +					 &ctx->vpu_header[1][0],
> +					 &ctx->vpu_header_size[1]);
> +		if (ret < 0)
> +			goto out;
> +
> +		/*
> +		 * Length of H.264 headers is variable and thus it might
> not be
> +		 * aligned for the coda to append the encoded frame. In
> that is
> +		 * the case a filler NAL must be added to header 2.
> +		 */
> +		ctx->vpu_header_size[2] = coda_h264_padding(
> +					(ctx->vpu_header_size[0] +
> +					 ctx->vpu_header_size[1]),
> +					 ctx->vpu_header[2]);
> +		break;
> +	case V4L2_PIX_FMT_MPEG4:
> +		/*
> +		 * Get VOS in the first frame and copy it to an
> +		 * intermediate buffer
> +		 */
> +		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS,
> +					 &ctx->vpu_header[0][0],
> +					 &ctx->vpu_header_size[0]);
> +		if (ret < 0)
> +			goto out;
> +
> +		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS,
> +					 &ctx->vpu_header[1][0],
> +					 &ctx->vpu_header_size[1]);
> +		if (ret < 0)
> +			goto out;
> +
> +		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL,
> +					 &ctx->vpu_header[2][0],
> +					 &ctx->vpu_header_size[2]);
> +		if (ret < 0)
> +			goto out;
> +		break;
> +	default:
> +		/* No more formats need to save headers at the moment */
> +		break;
> +	}
> +
> +out:
> +	mutex_unlock(&dev->coda_mutex);
> +	return ret;
> +}
> +
> +static int coda_prepare_encode(struct coda_ctx *ctx)
> +{
> +	struct coda_q_data *q_data_src, *q_data_dst;
> +	struct vb2_buffer *src_buf, *dst_buf;
> +	struct coda_dev *dev = ctx->dev;
> +	int force_ipicture;
> +	int quant_param = 0;
> +	u32 picture_y, picture_cb, picture_cr;
> +	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
> +	u32 dst_fourcc;
> +
> +	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> +	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> +	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> +	dst_fourcc = q_data_dst->fourcc;
> +
> +	src_buf->v4l2_buf.sequence = ctx->osequence;
> +	dst_buf->v4l2_buf.sequence = ctx->osequence;
> +	ctx->osequence++;
> +
> +	/*
> +	 * Workaround coda firmware BUG that only marks the first
> +	 * frame as IDR. This is a problem for some decoders that can't
> +	 * recover when a frame is lost.
> +	 */
> +	if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) {
> +		src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
> +		src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
> +	} else {
> +		src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
> +		src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
> +	}
> +
> +	if (dev->devtype->product == CODA_960)
> +		coda_set_gdi_regs(ctx);
> +
> +	/*
> +	 * Copy headers at the beginning of the first frame for H.264
> only.
> +	 * In MPEG4 they are already copied by the coda.
> +	 */
> +	if (src_buf->v4l2_buf.sequence == 0) {
> +		pic_stream_buffer_addr =
> +			vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
> +			ctx->vpu_header_size[0] +
> +			ctx->vpu_header_size[1] +
> +			ctx->vpu_header_size[2];
> +		pic_stream_buffer_size = CODA_MAX_FRAME_SIZE -
> +			ctx->vpu_header_size[0] -
> +			ctx->vpu_header_size[1] -
> +			ctx->vpu_header_size[2];
> +		memcpy(vb2_plane_vaddr(dst_buf, 0),
> +		       &ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
> +		memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx-
> >vpu_header_size[0],
> +		       &ctx->vpu_header[1][0], ctx->vpu_header_size[1]);
> +		memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx-
> >vpu_header_size[0] +
> +			ctx->vpu_header_size[1], &ctx->vpu_header[2][0],
> +			ctx->vpu_header_size[2]);
> +	} else {
> +		pic_stream_buffer_addr =
> +			vb2_dma_contig_plane_dma_addr(dst_buf, 0);
> +		pic_stream_buffer_size = CODA_MAX_FRAME_SIZE;
> +	}
> +
> +	if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
> +		force_ipicture = 1;
> +		switch (dst_fourcc) {
> +		case V4L2_PIX_FMT_H264:
> +			quant_param = ctx->params.h264_intra_qp;
> +			break;
> +		case V4L2_PIX_FMT_MPEG4:
> +			quant_param = ctx->params.mpeg4_intra_qp;
> +			break;
> +		default:
> +			v4l2_warn(&ctx->dev->v4l2_dev,
> +				"cannot set intra qp, fmt not supported\n");
> +			break;
> +		}
> +	} else {
> +		force_ipicture = 0;
> +		switch (dst_fourcc) {
> +		case V4L2_PIX_FMT_H264:
> +			quant_param = ctx->params.h264_inter_qp;
> +			break;
> +		case V4L2_PIX_FMT_MPEG4:
> +			quant_param = ctx->params.mpeg4_inter_qp;
> +			break;
> +		default:
> +			v4l2_warn(&ctx->dev->v4l2_dev,
> +				"cannot set inter qp, fmt not supported\n");
> +			break;
> +		}
> +	}
> +
> +	/* submit */
> +	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
> CODA_CMD_ENC_PIC_ROT_MODE);
> +	coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
> +
> +
> +	picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0);
> +	switch (q_data_src->fourcc) {
> +	case V4L2_PIX_FMT_YVU420:
> +		/* Switch Cb and Cr for YVU420 format */
> +		picture_cr = picture_y + q_data_src->bytesperline *
> +				q_data_src->height;
> +		picture_cb = picture_cr + q_data_src->bytesperline / 2 *
> +				q_data_src->height / 2;
> +		break;
> +	case V4L2_PIX_FMT_YUV420:
> +	default:
> +		picture_cb = picture_y + q_data_src->bytesperline *
> +				q_data_src->height;
> +		picture_cr = picture_cb + q_data_src->bytesperline / 2 *
> +				q_data_src->height / 2;
> +		break;
> +	}
> +
> +	if (dev->devtype->product == CODA_960) {
> +		coda_write(dev, 4/*FIXME: 0*/,
> CODA9_CMD_ENC_PIC_SRC_INDEX);
> +		coda_write(dev, q_data_src->width,
> CODA9_CMD_ENC_PIC_SRC_STRIDE);
> +		coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
> +
> +		coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y);
> +		coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB);
> +		coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR);
> +	} else {
> +		coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
> +		coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
> +		coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
> +	}
> +	coda_write(dev, force_ipicture << 1 & 0x2,
> +		   CODA_CMD_ENC_PIC_OPTION);
> +
> +	coda_write(dev, pic_stream_buffer_addr,
> CODA_CMD_ENC_PIC_BB_START);
> +	coda_write(dev, pic_stream_buffer_size / 1024,
> +		   CODA_CMD_ENC_PIC_BB_SIZE);
> +
> +	if (!ctx->streamon_out) {
> +		/* After streamoff on the output side, set the stream end
> flag */
> +		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
> +		coda_write(dev, ctx->bit_stream_param,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> +	}
> +
> +	if (dev->devtype->product != CODA_DX6)
> +		coda_write(dev, ctx->iram_info.axi_sram_use,
> +				CODA7_REG_BIT_AXI_SRAM_USE);
> +
> +	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
> +
> +	return 0;
> +}
> +
> +static void coda_finish_encode(struct coda_ctx *ctx)
> +{
> +	struct vb2_buffer *src_buf, *dst_buf;
> +	struct coda_dev *dev = ctx->dev;
> +	u32 wr_ptr, start_ptr;
> +
> +	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> +	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +
> +	/* Get results from the coda */
> +	start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
> +	wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
> +
> +	/* Calculate bytesused field */
> +	if (dst_buf->v4l2_buf.sequence == 0) {
> +		vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr +
> +					ctx->vpu_header_size[0] +
> +					ctx->vpu_header_size[1] +
> +					ctx->vpu_header_size[2]);
> +	} else {
> +		vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr);
> +	}
> +
> +	v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n",
> +		 wr_ptr - start_ptr);
> +
> +	coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM);
> +	coda_read(dev, CODA_RET_ENC_PIC_FLAG);
> +
> +	if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) {
> +		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
> +		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
> +	} else {
> +		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
> +		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
> +	}
> +
> +	dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
> +	dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +	dst_buf->v4l2_buf.flags |=
> +		src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +	dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
> +
> +	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
> +
> +	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> +	v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
> +
> +	ctx->gopcounter--;
> +	if (ctx->gopcounter < 0)
> +		ctx->gopcounter = ctx->params.gop_size - 1;
> +
> +	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +		"job finished: encoding frame (%d) (%s)\n",
> +		dst_buf->v4l2_buf.sequence,
> +		(dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
> +		"KEYFRAME" : "PFRAME");
> +}
> +
> +static void coda_seq_end_work(struct work_struct *work)
> +{
> +	struct coda_ctx *ctx = container_of(work, struct coda_ctx,
> seq_end_work);
> +	struct coda_dev *dev = ctx->dev;
> +
> +	mutex_lock(&ctx->buffer_mutex);
> +	mutex_lock(&dev->coda_mutex);
> +
> +	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +		 "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx,
> __func__);
> +	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
> +		v4l2_err(&dev->v4l2_dev,
> +			 "CODA_COMMAND_SEQ_END failed\n");
> +	}
> +
> +	kfifo_init(&ctx->bitstream_fifo,
> +		ctx->bitstream.vaddr, ctx->bitstream.size);
> +
> +	coda_free_framebuffers(ctx);
> +	coda_free_context_buffers(ctx);
> +
> +	mutex_unlock(&dev->coda_mutex);
> +	mutex_unlock(&ctx->buffer_mutex);
> +}
> +
> +static void coda_bit_release(struct coda_ctx *ctx)
> +{
> +	coda_free_framebuffers(ctx);
> +	coda_free_context_buffers(ctx);
> +}
> +
> +const struct coda_context_ops coda_bit_encode_ops = {
> +	.queue_init = coda_encoder_queue_init,
> +	.start_streaming = coda_start_encoding,
> +	.prepare_run = coda_prepare_encode,
> +	.finish_run = coda_finish_encode,
> +	.seq_end_work = coda_seq_end_work,
> +	.release = coda_bit_release,
> +};
> +
> +/*
> + * Decoder context operations
> + */
> +
> +static int __coda_start_decoding(struct coda_ctx *ctx)
> +{
> +	struct coda_q_data *q_data_src, *q_data_dst;
> +	u32 bitstream_buf, bitstream_size;
> +	struct coda_dev *dev = ctx->dev;
> +	int width, height;
> +	u32 src_fourcc;
> +	u32 val;
> +	int ret;
> +
> +	/* Start decoding */
> +	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> +	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> +	bitstream_buf = ctx->bitstream.paddr;
> +	bitstream_size = ctx->bitstream.size;
> +	src_fourcc = q_data_src->fourcc;
> +
> +	/* Allocate per-instance buffers */
> +	ret = coda_alloc_context_buffers(ctx, q_data_src);
> +	if (ret < 0)
> +		return ret;
> +
> +	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
> +
> +	/* Update coda bitstream read and write pointers from kfifo */
> +	coda_kfifo_sync_to_device_full(ctx);
> +
> +	ctx->display_idx = -1;
> +	ctx->frm_dis_flg = 0;
> +	coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
> +
> +	coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE,
> +			CODA_REG_BIT_BIT_STREAM_PARAM);
> +
> +	coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
> +	coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
> +	val = 0;
> +	if ((dev->devtype->product == CODA_7541) ||
> +	    (dev->devtype->product == CODA_960))
> +		val |= CODA_REORDER_ENABLE;
> +	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
> +
> +	ctx->params.codec_mode = ctx->codec->mode;
> +	if (dev->devtype->product == CODA_960 &&
> +	    src_fourcc == V4L2_PIX_FMT_MPEG4)
> +		ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
> +	else
> +		ctx->params.codec_mode_aux = 0;
> +	if (src_fourcc == V4L2_PIX_FMT_H264) {
> +		if (dev->devtype->product == CODA_7541) {
> +			coda_write(dev, ctx->psbuf.paddr,
> +					CODA_CMD_DEC_SEQ_PS_BB_START);
> +			coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
> +					CODA_CMD_DEC_SEQ_PS_BB_SIZE);
> +		}
> +		if (dev->devtype->product == CODA_960) {
> +			coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN);
> +			coda_write(dev, 512,
> CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE);
> +		}
> +	}
> +	if (dev->devtype->product != CODA_960)
> +		coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
> +
> +	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
> +		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT
> timeout\n");
> +		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* Update kfifo out pointer from coda bitstream read pointer */
> +	coda_kfifo_sync_from_device(ctx);
> +
> +	coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
> +
> +	if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) {
> +		v4l2_err(&dev->v4l2_dev,
> +			"CODA_COMMAND_SEQ_INIT failed, error code = %d\n",
> +			coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON));
> +		return -EAGAIN;
> +	}
> +
> +	val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE);
> +	if (dev->devtype->product == CODA_DX6) {
> +		width = (val >> CODADX6_PICWIDTH_OFFSET) &
> CODADX6_PICWIDTH_MASK;
> +		height = val & CODADX6_PICHEIGHT_MASK;
> +	} else {
> +		width = (val >> CODA7_PICWIDTH_OFFSET) &
> CODA7_PICWIDTH_MASK;
> +		height = val & CODA7_PICHEIGHT_MASK;
> +	}
> +
> +	if (width > q_data_dst->width || height > q_data_dst->height) {
> +		v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n",
> +			 width, height, q_data_dst->width, q_data_dst-
> >height);
> +		return -EINVAL;
> +	}
> +
> +	width = round_up(width, 16);
> +	height = round_up(height, 16);
> +
> +	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now:
> %dx%d\n",
> +		 __func__, ctx->idx, width, height);
> +
> +	ctx->num_internal_frames = coda_read(dev,
> CODA_RET_DEC_SEQ_FRAME_NEED);
> +	if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
> +		v4l2_err(&dev->v4l2_dev,
> +			 "not enough framebuffers to decode (%d < %d)\n",
> +			 CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames);
> +		return -EINVAL;
> +	}
> +
> +	if (src_fourcc == V4L2_PIX_FMT_H264) {
> +		u32 left_right;
> +		u32 top_bottom;
> +
> +		left_right = coda_read(dev,
> CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT);
> +		top_bottom = coda_read(dev,
> CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM);
> +
> +		q_data_dst->rect.left = (left_right >> 10) & 0x3ff;
> +		q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff;
> +		q_data_dst->rect.width = width - q_data_dst->rect.left -
> +					 (left_right & 0x3ff);
> +		q_data_dst->rect.height = height - q_data_dst->rect.top -
> +					  (top_bottom & 0x3ff);
> +	}
> +
> +	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Tell the decoder how many frame buffers we allocated. */
> +	coda_write(dev, ctx->num_internal_frames,
> CODA_CMD_SET_FRAME_BUF_NUM);
> +	coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE);
> +
> +	if (dev->devtype->product != CODA_DX6) {
> +		/* Set secondary AXI IRAM */
> +		coda_setup_iram(ctx);
> +
> +		coda_write(dev, ctx->iram_info.buf_bit_use,
> +				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
> +				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
> +				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
> +				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
> +		coda_write(dev, ctx->iram_info.buf_ovl_use,
> +				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
> +		if (dev->devtype->product == CODA_960)
> +			coda_write(dev, ctx->iram_info.buf_btp_use,
> +					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
> +	}
> +
> +	if (dev->devtype->product == CODA_960) {
> +		coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
> +
> +		coda_write(dev, 0x20262024,
> CODA9_CMD_SET_FRAME_CACHE_SIZE);
> +		coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
> +				32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
> +				8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
> +				8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
> +				CODA9_CMD_SET_FRAME_CACHE_CONFIG);
> +	}
> +
> +	if (src_fourcc == V4L2_PIX_FMT_H264) {
> +		coda_write(dev, ctx->slicebuf.paddr,
> +				CODA_CMD_SET_FRAME_SLICE_BB_START);
> +		coda_write(dev, ctx->slicebuf.size / 1024,
> +				CODA_CMD_SET_FRAME_SLICE_BB_SIZE);
> +	}
> +
> +	if (dev->devtype->product == CODA_7541) {
> +		int max_mb_x = 1920 / 16;
> +		int max_mb_y = 1088 / 16;
> +		int max_mb_num = max_mb_x * max_mb_y;
> +
> +		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 |
> max_mb_y,
> +				CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
> +	} else if (dev->devtype->product == CODA_960) {
> +		int max_mb_x = 1920 / 16;
> +		int max_mb_y = 1088 / 16;
> +		int max_mb_num = max_mb_x * max_mb_y;
> +
> +		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 |
> max_mb_y,
> +				CODA9_CMD_SET_FRAME_MAX_DEC_SIZE);
> +	}
> +
> +	if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
> +		v4l2_err(&ctx->dev->v4l2_dev,
> +			 "CODA_COMMAND_SET_FRAME_BUF timeout\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int coda_start_decoding(struct coda_ctx *ctx)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	int ret;
> +
> +	mutex_lock(&dev->coda_mutex);
> +	ret = __coda_start_decoding(ctx);
> +	mutex_unlock(&dev->coda_mutex);
> +
> +	return ret;
> +}
> +
> +static int coda_prepare_decode(struct coda_ctx *ctx)
> +{
> +	struct vb2_buffer *dst_buf;
> +	struct coda_dev *dev = ctx->dev;
> +	struct coda_q_data *q_data_dst;
> +	u32 stridey, height;
> +	u32 picture_y, picture_cb, picture_cr;
> +
> +	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> +
> +	if (ctx->params.rot_mode & CODA_ROT_90) {
> +		stridey = q_data_dst->height;
> +		height = q_data_dst->width;
> +	} else {
> +		stridey = q_data_dst->width;
> +		height = q_data_dst->height;
> +	}
> +
> +	/* Try to copy source buffer contents into the bitstream
> ringbuffer */
> +	mutex_lock(&ctx->bitstream_mutex);
> +	coda_fill_bitstream(ctx);
> +	mutex_unlock(&ctx->bitstream_mutex);
> +
> +	if (coda_get_bitstream_payload(ctx) < 512 &&
> +	    (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
> +		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +			 "bitstream payload: %d, skipping\n",
> +			 coda_get_bitstream_payload(ctx));
> +		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> +		return -EAGAIN;
> +	}
> +
> +	/* Run coda_start_decoding (again) if not yet initialized */
> +	if (!ctx->initialized) {
> +		int ret = __coda_start_decoding(ctx);
> +
> +		if (ret < 0) {
> +			v4l2_err(&dev->v4l2_dev, "failed to start
> decoding\n");
> +			v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx-
> >fh.m2m_ctx);
> +			return -EAGAIN;
> +		} else {
> +			ctx->initialized = 1;
> +		}
> +	}
> +
> +	if (dev->devtype->product == CODA_960)
> +		coda_set_gdi_regs(ctx);
> +
> +	/* Set rotator output */
> +	picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
> +	if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
> +		/* Switch Cr and Cb for YVU420 format */
> +		picture_cr = picture_y + stridey * height;
> +		picture_cb = picture_cr + stridey / 2 * height / 2;
> +	} else {
> +		picture_cb = picture_y + stridey * height;
> +		picture_cr = picture_cb + stridey / 2 * height / 2;
> +	}
> +
> +	if (dev->devtype->product == CODA_960) {
> +		/*
> +		 * The CODA960 seems to have an internal list of buffers
> with
> +		 * 64 entries that includes the registered frame buffers as
> +		 * well as the rotator buffer output.
> +		 * ROT_INDEX needs to be < 0x40, but > ctx-
> >num_internal_frames.
> +		 */
> +		coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf-
> >v4l2_buf.index,
> +				CODA9_CMD_DEC_PIC_ROT_INDEX);
> +		coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y);
> +		coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB);
> +		coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR);
> +		coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE);
> +	} else {
> +		coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
> +		coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
> +		coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
> +		coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
> +	}
> +	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
> +			CODA_CMD_DEC_PIC_ROT_MODE);
> +
> +	switch (dev->devtype->product) {
> +	case CODA_DX6:
> +		/* TBD */
> +	case CODA_7541:
> +		coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
> +		break;
> +	case CODA_960:
> +		coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /*
> 'hardcode to use interrupt disable mode'? */
> +		break;
> +	}
> +
> +	coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
> +
> +	coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START);
> +	coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE);
> +
> +	if (dev->devtype->product != CODA_DX6)
> +		coda_write(dev, ctx->iram_info.axi_sram_use,
> +				CODA7_REG_BIT_AXI_SRAM_USE);
> +
> +	coda_kfifo_sync_to_device_full(ctx);
> +
> +	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
> +
> +	return 0;
> +}
> +
> +static void coda_finish_decode(struct coda_ctx *ctx)
> +{
> +	struct coda_dev *dev = ctx->dev;
> +	struct coda_q_data *q_data_src;
> +	struct coda_q_data *q_data_dst;
> +	struct vb2_buffer *dst_buf;
> +	struct coda_timestamp *ts;
> +	int width, height;
> +	int decoded_idx;
> +	int display_idx;
> +	u32 src_fourcc;
> +	int success;
> +	u32 err_mb;
> +	u32 val;
> +
> +	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +
> +	/* Update kfifo out pointer from coda bitstream read pointer */
> +	coda_kfifo_sync_from_device(ctx);
> +
> +	/*
> +	 * in stream-end mode, the read pointer can overshoot the write
> pointer
> +	 * by up to 512 bytes
> +	 */
> +	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) {
> +		if (coda_get_bitstream_payload(ctx) >= CODA_MAX_FRAME_SIZE
> - 512)
> +			kfifo_init(&ctx->bitstream_fifo,
> +				ctx->bitstream.vaddr, ctx->bitstream.size);
> +	}
> +
> +	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> +	src_fourcc = q_data_src->fourcc;
> +
> +	val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS);
> +	if (val != 1)
> +		pr_err("DEC_PIC_SUCCESS = %d\n", val);
> +
> +	success = val & 0x1;
> +	if (!success)
> +		v4l2_err(&dev->v4l2_dev, "decode failed\n");
> +
> +	if (src_fourcc == V4L2_PIX_FMT_H264) {
> +		if (val & (1 << 3))
> +			v4l2_err(&dev->v4l2_dev,
> +				 "insufficient PS buffer space (%d
bytes)\n",
> +				 ctx->psbuf.size);
> +		if (val & (1 << 2))
> +			v4l2_err(&dev->v4l2_dev,
> +				 "insufficient slice buffer space (%d
> bytes)\n",
> +				 ctx->slicebuf.size);
> +	}
> +
> +	val = coda_read(dev, CODA_RET_DEC_PIC_SIZE);
> +	width = (val >> 16) & 0xffff;
> +	height = val & 0xffff;
> +
> +	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> +
> +	/* frame crop information */
> +	if (src_fourcc == V4L2_PIX_FMT_H264) {
> +		u32 left_right;
> +		u32 top_bottom;
> +
> +		left_right = coda_read(dev,
> CODA_RET_DEC_PIC_CROP_LEFT_RIGHT);
> +		top_bottom = coda_read(dev,
> CODA_RET_DEC_PIC_CROP_TOP_BOTTOM);
> +
> +		if (left_right == 0xffffffff && top_bottom == 0xffffffff) {
> +			/* Keep current crop information */
> +		} else {
> +			struct v4l2_rect *rect = &q_data_dst->rect;
> +
> +			rect->left = left_right >> 16 & 0xffff;
> +			rect->top = top_bottom >> 16 & 0xffff;
> +			rect->width = width - rect->left -
> +				      (left_right & 0xffff);
> +			rect->height = height - rect->top -
> +				       (top_bottom & 0xffff);
> +		}
> +	} else {
> +		/* no cropping */
> +	}
> +
> +	err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
> +	if (err_mb > 0)
> +		v4l2_err(&dev->v4l2_dev,
> +			 "errors in %d macroblocks\n", err_mb);
> +
> +	if (dev->devtype->product == CODA_7541) {
> +		val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
> +		if (val == 0) {
> +			/* not enough bitstream data */
> +			v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +				 "prescan failed: %d\n", val);
> +			ctx->hold = true;
> +			return;
> +		}
> +	}
> +
> +	ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx-
> >reg_idx));
> +
> +	/*
> +	 * The previous display frame was copied out by the rotator,
> +	 * now it can be overwritten again
> +	 */
> +	if (ctx->display_idx >= 0 &&
> +	    ctx->display_idx < ctx->num_internal_frames) {
> +		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
> +		coda_write(dev, ctx->frm_dis_flg,
> +				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
> +	}
> +
> +	/*
> +	 * The index of the last decoded frame, not necessarily in
> +	 * display order, and the index of the next display frame.
> +	 * The latter could have been decoded in a previous run.
> +	 */
> +	decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX);
> +	display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX);
> +
> +	if (decoded_idx == -1) {
> +		/* no frame was decoded, but we might have a display frame
> */
> +		if (display_idx >= 0 && display_idx < ctx-
> >num_internal_frames)
> +			ctx->sequence_offset++;
> +		else if (ctx->display_idx < 0)
> +			ctx->hold = true;
> +	} else if (decoded_idx == -2) {
> +		/* no frame was decoded, we still return the remaining
> buffers */
> +	} else if (decoded_idx < 0 || decoded_idx >= ctx-
> >num_internal_frames) {
> +		v4l2_err(&dev->v4l2_dev,
> +			 "decoded frame index out of range: %d\n",
> decoded_idx);
> +	} else {
> +		ts = list_first_entry(&ctx->timestamp_list,
> +				      struct coda_timestamp, list);
> +		list_del(&ts->list);
> +		val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
> +		val -= ctx->sequence_offset;
> +		if (val != (ts->sequence & 0xffff)) {
> +			v4l2_err(&dev->v4l2_dev,
> +				 "sequence number mismatch (%d(%d) !=
%d)\n",
> +				 val, ctx->sequence_offset, ts->sequence);
> +		}
> +		ctx->frame_timestamps[decoded_idx] = *ts;
> +		kfree(ts);
> +
> +		val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
> +		if (val == 0)
> +			ctx->frame_types[decoded_idx] =
> V4L2_BUF_FLAG_KEYFRAME;
> +		else if (val == 1)
> +			ctx->frame_types[decoded_idx] =
V4L2_BUF_FLAG_PFRAME;
> +		else
> +			ctx->frame_types[decoded_idx] =
V4L2_BUF_FLAG_BFRAME;
> +
> +		ctx->frame_errors[decoded_idx] = err_mb;
> +	}
> +
> +	if (display_idx == -1) {
> +		/*
> +		 * no more frames to be decoded, but there could still
> +		 * be rotator output to dequeue
> +		 */
> +		ctx->hold = true;
> +	} else if (display_idx == -3) {
> +		/* possibly prescan failure */
> +	} else if (display_idx < 0 || display_idx >= ctx-
> >num_internal_frames) {
> +		v4l2_err(&dev->v4l2_dev,
> +			 "presentation frame index out of range: %d\n",
> +			 display_idx);
> +	}
> +
> +	/* If a frame was copied out, return it */
> +	if (ctx->display_idx >= 0 &&
> +	    ctx->display_idx < ctx->num_internal_frames) {
> +		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> +		dst_buf->v4l2_buf.sequence = ctx->osequence++;
> +
> +		dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
> +					     V4L2_BUF_FLAG_PFRAME |
> +					     V4L2_BUF_FLAG_BFRAME);
> +		dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx-
> >display_idx];
> +		ts = &ctx->frame_timestamps[ctx->display_idx];
> +		dst_buf->v4l2_buf.timecode = ts->timecode;
> +		dst_buf->v4l2_buf.timestamp = ts->timestamp;
> +
> +		vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
> +
> +		v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ?
> +				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> +
> +		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +			"job finished: decoding frame (%d) (%s)\n",
> +			dst_buf->v4l2_buf.sequence,
> +			(dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
> +			"KEYFRAME" : "PFRAME");
> +	} else {
> +		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> +			"job finished: no frame decoded\n");
> +	}
> +
> +	/* The rotator will copy the current display frame next time */
> +	ctx->display_idx = display_idx;
> +}
> +
> +const struct coda_context_ops coda_bit_decode_ops = {
> +	.queue_init = coda_decoder_queue_init,
> +	.start_streaming = coda_start_decoding,
> +	.prepare_run = coda_prepare_decode,
> +	.finish_run = coda_finish_decode,
> +	.seq_end_work = coda_seq_end_work,
> +	.release = coda_bit_release,
> +};
> +
> +irqreturn_t coda_irq_handler(int irq, void *data)
> +{
> +	struct coda_dev *dev = data;
> +	struct coda_ctx *ctx;
> +
> +	/* read status register to attend the IRQ */
> +	coda_read(dev, CODA_REG_BIT_INT_STATUS);
> +	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
> +		      CODA_REG_BIT_INT_CLEAR);
> +
> +	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
> +	if (ctx == NULL) {
> +		v4l2_err(&dev->v4l2_dev, "Instance released before the end
> of transaction\n");
> +		mutex_unlock(&dev->coda_mutex);
> +		return IRQ_HANDLED;
> +	}
> +
> +	if (ctx->aborting) {
> +		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
> +			 "task has been aborted\n");
> +	}
> +
> +	if (coda_isbusy(ctx->dev)) {
> +		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
> +			 "coda is still busy!!!!\n");
> +		return IRQ_NONE;
> +	}
> +
> +	complete(&ctx->completion);
> +
> +	return IRQ_HANDLED;
> +}
> diff --git a/drivers/media/platform/coda/coda-common.c
> b/drivers/media/platform/coda/coda-common.c
> index 5226dea..3b3a980 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -48,12 +48,6 @@
>  #define CODA_PARA_BUF_SIZE	(10 * 1024)
>  #define CODA_ISRAM_SIZE	(2048 * 2)
> 
> -#define CODA7_PS_BUF_SIZE	0x28000
> -#define CODA9_PS_SAVE_SIZE	(512 * 1024)
> -
> -#define CODA_DEFAULT_GAMMA		4096
> -#define CODA9_DEFAULT_GAMMA		24576	/* 0.75 * 32768 */
> -
>  #define MIN_W 176
>  #define MIN_H 144
> 
> @@ -63,7 +57,7 @@
> 
>  #define fh_to_ctx(__fh)	container_of(__fh, struct coda_ctx, fh)
> 
> -static int coda_debug;
> +int coda_debug;
>  module_param(coda_debug, int, 0644);
>  MODULE_PARM_DESC(coda_debug, "Debug level (0-1)");
> 
> @@ -88,128 +82,6 @@ unsigned int coda_read(struct coda_dev *dev, u32
> reg)
>  	return data;
>  }
> 
> -static inline unsigned long coda_isbusy(struct coda_dev *dev)
> -{
> -	return coda_read(dev, CODA_REG_BIT_BUSY);
> -}
> -
> -static inline int coda_is_initialized(struct coda_dev *dev)
> -{
> -	return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0);
> -}
> -
> -static int coda_wait_timeout(struct coda_dev *dev)
> -{
> -	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
> -
> -	while (coda_isbusy(dev)) {
> -		if (time_after(jiffies, timeout))
> -			return -ETIMEDOUT;
> -	}
> -	return 0;
> -}
> -
> -static void coda_command_async(struct coda_ctx *ctx, int cmd)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -
> -	if (dev->devtype->product == CODA_960 ||
> -	    dev->devtype->product == CODA_7541) {
> -		/* Restore context related registers to CODA */
> -		coda_write(dev, ctx->bit_stream_param,
> -				CODA_REG_BIT_BIT_STREAM_PARAM);
> -		coda_write(dev, ctx->frm_dis_flg,
> -				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
> -		coda_write(dev, ctx->frame_mem_ctrl,
> -				CODA_REG_BIT_FRAME_MEM_CTRL);
> -		coda_write(dev, ctx->workbuf.paddr,
> CODA_REG_BIT_WORK_BUF_ADDR);
> -	}
> -
> -	if (dev->devtype->product == CODA_960) {
> -		coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
> -		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
> -	}
> -
> -	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
> -
> -	coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
> -	coda_write(dev, ctx->params.codec_mode,
> CODA_REG_BIT_RUN_COD_STD);
> -	coda_write(dev, ctx->params.codec_mode_aux,
> CODA7_REG_BIT_RUN_AUX_STD);
> -
> -	coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
> -}
> -
> -static int coda_command_sync(struct coda_ctx *ctx, int cmd)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -
> -	coda_command_async(ctx, cmd);
> -	return coda_wait_timeout(dev);
> -}
> -
> -static int coda_hw_reset(struct coda_ctx *ctx)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	unsigned long timeout;
> -	unsigned int idx;
> -	int ret;
> -
> -	if (!dev->rstc)
> -		return -ENOENT;
> -
> -	idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
> -
> -	if (dev->devtype->product == CODA_960) {
> -		timeout = jiffies + msecs_to_jiffies(100);
> -		coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
> -		while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
> -			if (time_after(jiffies, timeout))
> -				return -ETIME;
> -			cpu_relax();
> -		}
> -	}
> -
> -	ret = reset_control_reset(dev->rstc);
> -	if (ret < 0)
> -		return ret;
> -
> -	if (dev->devtype->product == CODA_960)
> -		coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
> -	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
> -	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
> -	ret = coda_wait_timeout(dev);
> -	coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
> -
> -	return ret;
> -}
> -
> -static void coda_bit_stream_end_flag(struct coda_ctx *ctx)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -
> -	ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
> -
> -	if ((dev->devtype->product == CODA_960) &&
> -	    coda_isbusy(dev) &&
> -	    (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
> -		/* If this context is currently running, update the
> hardware flag */
> -		coda_write(dev, ctx->bit_stream_param,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> -	}
> -}
> -
> -static struct coda_q_data *get_q_data(struct coda_ctx *ctx,
> -					 enum v4l2_buf_type type)
> -{
> -	switch (type) {
> -	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
> -		return &(ctx->q_data[V4L2_M2M_SRC]);
> -	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> -		return &(ctx->q_data[V4L2_M2M_DST]);
> -	default:
> -		return NULL;
> -	}
> -}
> -
>  /*
>   * Array of all formats supported by any version of Coda:
>   */
> @@ -330,7 +202,7 @@ static void coda_get_max_dimensions(struct coda_dev
> *dev,
>  		*max_h = h;
>  }
> 
> -static char *coda_product_name(int product)
> +const char *coda_product_name(int product)
>  {
>  	static char buf[9];
> 
> @@ -804,124 +676,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops
> = {
>  	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>  };
> 
> -static int __coda_start_decoding(struct coda_ctx *ctx);
> -
> -static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
> -{
> -	return kfifo_len(&ctx->bitstream_fifo);
> -}
> -
> -static void coda_kfifo_sync_from_device(struct coda_ctx *ctx)
> -{
> -	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
> -	struct coda_dev *dev = ctx->dev;
> -	u32 rd_ptr;
> -
> -	rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
> -	kfifo->out = (kfifo->in & ~kfifo->mask) |
> -		      (rd_ptr - ctx->bitstream.paddr);
> -	if (kfifo->out > kfifo->in)
> -		kfifo->out -= kfifo->mask + 1;
> -}
> -
> -static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx)
> -{
> -	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
> -	struct coda_dev *dev = ctx->dev;
> -	u32 rd_ptr, wr_ptr;
> -
> -	rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask);
> -	coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
> -	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
> -	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
> -}
> -
> -static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
> -{
> -	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
> -	struct coda_dev *dev = ctx->dev;
> -	u32 wr_ptr;
> -
> -	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
> -	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
> -}
> -
> -static int coda_bitstream_queue(struct coda_ctx *ctx, struct
> vb2_buffer *src_buf)
> -{
> -	u32 src_size = vb2_get_plane_payload(src_buf, 0);
> -	u32 n;
> -
> -	n = kfifo_in(&ctx->bitstream_fifo, vb2_plane_vaddr(src_buf, 0),
> src_size);
> -	if (n < src_size)
> -		return -ENOSPC;
> -
> -	dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx-
> >bitstream.paddr,
> -				   ctx->bitstream.size, DMA_TO_DEVICE);
> -
> -	src_buf->v4l2_buf.sequence = ctx->qsequence++;
> -
> -	return 0;
> -}
> -
> -static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
> -				     struct vb2_buffer *src_buf)
> -{
> -	int ret;
> -
> -	if (coda_get_bitstream_payload(ctx) +
> -	    vb2_get_plane_payload(src_buf, 0) + 512 >= ctx-
> >bitstream.size)
> -		return false;
> -
> -	if (vb2_plane_vaddr(src_buf, 0) == NULL) {
> -		v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty
> buffer\n");
> -		return true;
> -	}
> -
> -	ret = coda_bitstream_queue(ctx, src_buf);
> -	if (ret < 0) {
> -		v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer
> overflow\n");
> -		return false;
> -	}
> -	/* Sync read pointer to device */
> -	if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
> -		coda_kfifo_sync_to_device_write(ctx);
> -
> -	ctx->hold = false;
> -
> -	return true;
> -}
> -
> -static void coda_fill_bitstream(struct coda_ctx *ctx)
> -{
> -	struct vb2_buffer *src_buf;
> -	struct coda_timestamp *ts;
> -
> -	while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
> -		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> -
> -		if (coda_bitstream_try_queue(ctx, src_buf)) {
> -			/*
> -			 * Source buffer is queued in the bitstream
> ringbuffer;
> -			 * queue the timestamp and mark source buffer as
done
> -			 */
> -			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> -
> -			ts = kmalloc(sizeof(*ts), GFP_KERNEL);
> -			if (ts) {
> -				ts->sequence = src_buf->v4l2_buf.sequence;
> -				ts->timecode = src_buf->v4l2_buf.timecode;
> -				ts->timestamp = src_buf->v4l2_buf.timestamp;
> -				list_add_tail(&ts->list,
&ctx->timestamp_list);
> -			}
> -
> -			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
> -		} else {
> -			break;
> -		}
> -	}
> -}
> -
> -static void coda_set_gdi_regs(struct coda_ctx *ctx)
> +void coda_set_gdi_regs(struct coda_ctx *ctx)
>  {
>  	struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
>  	struct coda_dev *dev = ctx->dev;
> @@ -945,264 +700,6 @@ static void coda_set_gdi_regs(struct coda_ctx
> *ctx)
>  /*
>   * Mem-to-mem operations.
>   */
> -static int coda_prepare_decode(struct coda_ctx *ctx)
> -{
> -	struct vb2_buffer *dst_buf;
> -	struct coda_dev *dev = ctx->dev;
> -	struct coda_q_data *q_data_dst;
> -	u32 stridey, height;
> -	u32 picture_y, picture_cb, picture_cr;
> -
> -	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> -	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -
> -	if (ctx->params.rot_mode & CODA_ROT_90) {
> -		stridey = q_data_dst->height;
> -		height = q_data_dst->width;
> -	} else {
> -		stridey = q_data_dst->width;
> -		height = q_data_dst->height;
> -	}
> -
> -	/* Try to copy source buffer contents into the bitstream
> ringbuffer */
> -	mutex_lock(&ctx->bitstream_mutex);
> -	coda_fill_bitstream(ctx);
> -	mutex_unlock(&ctx->bitstream_mutex);
> -
> -	if (coda_get_bitstream_payload(ctx) < 512 &&
> -	    (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
> -		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> -			 "bitstream payload: %d, skipping\n",
> -			 coda_get_bitstream_payload(ctx));
> -		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> -		return -EAGAIN;
> -	}
> -
> -	/* Run coda_start_decoding (again) if not yet initialized */
> -	if (!ctx->initialized) {
> -		int ret = __coda_start_decoding(ctx);
> -		if (ret < 0) {
> -			v4l2_err(&dev->v4l2_dev, "failed to start
> decoding\n");
> -			v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx-
> >fh.m2m_ctx);
> -			return -EAGAIN;
> -		} else {
> -			ctx->initialized = 1;
> -		}
> -	}
> -
> -	if (dev->devtype->product == CODA_960)
> -		coda_set_gdi_regs(ctx);
> -
> -	/* Set rotator output */
> -	picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
> -	if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
> -		/* Switch Cr and Cb for YVU420 format */
> -		picture_cr = picture_y + stridey * height;
> -		picture_cb = picture_cr + stridey / 2 * height / 2;
> -	} else {
> -		picture_cb = picture_y + stridey * height;
> -		picture_cr = picture_cb + stridey / 2 * height / 2;
> -	}
> -
> -	if (dev->devtype->product == CODA_960) {
> -		/*
> -		 * The CODA960 seems to have an internal list of buffers
> with
> -		 * 64 entries that includes the registered frame buffers as
> -		 * well as the rotator buffer output.
> -		 * ROT_INDEX needs to be < 0x40, but > ctx-
> >num_internal_frames.
> -		 */
> -		coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf-
> >v4l2_buf.index,
> -				CODA9_CMD_DEC_PIC_ROT_INDEX);
> -		coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y);
> -		coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB);
> -		coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR);
> -		coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE);
> -	} else {
> -		coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
> -		coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
> -		coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
> -		coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
> -	}
> -	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
> -			CODA_CMD_DEC_PIC_ROT_MODE);
> -
> -	switch (dev->devtype->product) {
> -	case CODA_DX6:
> -		/* TBD */
> -	case CODA_7541:
> -		coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
> -		break;
> -	case CODA_960:
> -		coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /*
> 'hardcode to use interrupt disable mode'? */
> -		break;
> -	}
> -
> -	coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
> -
> -	coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START);
> -	coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE);
> -
> -	if (dev->devtype->product != CODA_DX6)
> -		coda_write(dev, ctx->iram_info.axi_sram_use,
> -				CODA7_REG_BIT_AXI_SRAM_USE);
> -
> -	coda_kfifo_sync_to_device_full(ctx);
> -	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
> -
> -	return 0;
> -}
> -
> -static int coda_prepare_encode(struct coda_ctx *ctx)
> -{
> -	struct coda_q_data *q_data_src, *q_data_dst;
> -	struct vb2_buffer *src_buf, *dst_buf;
> -	struct coda_dev *dev = ctx->dev;
> -	int force_ipicture;
> -	int quant_param = 0;
> -	u32 picture_y, picture_cb, picture_cr;
> -	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
> -	u32 dst_fourcc;
> -
> -	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> -	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> -	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> -	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -	dst_fourcc = q_data_dst->fourcc;
> -
> -	src_buf->v4l2_buf.sequence = ctx->osequence;
> -	dst_buf->v4l2_buf.sequence = ctx->osequence;
> -	ctx->osequence++;
> -
> -	/*
> -	 * Workaround coda firmware BUG that only marks the first
> -	 * frame as IDR. This is a problem for some decoders that can't
> -	 * recover when a frame is lost.
> -	 */
> -	if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) {
> -		src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
> -		src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
> -	} else {
> -		src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
> -		src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
> -	}
> -
> -	if (dev->devtype->product == CODA_960)
> -		coda_set_gdi_regs(ctx);
> -
> -	/*
> -	 * Copy headers at the beginning of the first frame for H.264
> only.
> -	 * In MPEG4 they are already copied by the coda.
> -	 */
> -	if (src_buf->v4l2_buf.sequence == 0) {
> -		pic_stream_buffer_addr =
> -			vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
> -			ctx->vpu_header_size[0] +
> -			ctx->vpu_header_size[1] +
> -			ctx->vpu_header_size[2];
> -		pic_stream_buffer_size = CODA_MAX_FRAME_SIZE -
> -			ctx->vpu_header_size[0] -
> -			ctx->vpu_header_size[1] -
> -			ctx->vpu_header_size[2];
> -		memcpy(vb2_plane_vaddr(dst_buf, 0),
> -		       &ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
> -		memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx-
> >vpu_header_size[0],
> -		       &ctx->vpu_header[1][0], ctx->vpu_header_size[1]);
> -		memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx-
> >vpu_header_size[0] +
> -			ctx->vpu_header_size[1], &ctx->vpu_header[2][0],
> -			ctx->vpu_header_size[2]);
> -	} else {
> -		pic_stream_buffer_addr =
> -			vb2_dma_contig_plane_dma_addr(dst_buf, 0);
> -		pic_stream_buffer_size = CODA_MAX_FRAME_SIZE;
> -	}
> -
> -	if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
> -		force_ipicture = 1;
> -		switch (dst_fourcc) {
> -		case V4L2_PIX_FMT_H264:
> -			quant_param = ctx->params.h264_intra_qp;
> -			break;
> -		case V4L2_PIX_FMT_MPEG4:
> -			quant_param = ctx->params.mpeg4_intra_qp;
> -			break;
> -		default:
> -			v4l2_warn(&ctx->dev->v4l2_dev,
> -				"cannot set intra qp, fmt not supported\n");
> -			break;
> -		}
> -	} else {
> -		force_ipicture = 0;
> -		switch (dst_fourcc) {
> -		case V4L2_PIX_FMT_H264:
> -			quant_param = ctx->params.h264_inter_qp;
> -			break;
> -		case V4L2_PIX_FMT_MPEG4:
> -			quant_param = ctx->params.mpeg4_inter_qp;
> -			break;
> -		default:
> -			v4l2_warn(&ctx->dev->v4l2_dev,
> -				"cannot set inter qp, fmt not supported\n");
> -			break;
> -		}
> -	}
> -
> -	/* submit */
> -	coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
> CODA_CMD_ENC_PIC_ROT_MODE);
> -	coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
> -
> -
> -	picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0);
> -	switch (q_data_src->fourcc) {
> -	case V4L2_PIX_FMT_YVU420:
> -		/* Switch Cb and Cr for YVU420 format */
> -		picture_cr = picture_y + q_data_src->bytesperline *
> -				q_data_src->height;
> -		picture_cb = picture_cr + q_data_src->bytesperline / 2 *
> -				q_data_src->height / 2;
> -		break;
> -	case V4L2_PIX_FMT_YUV420:
> -	default:
> -		picture_cb = picture_y + q_data_src->bytesperline *
> -				q_data_src->height;
> -		picture_cr = picture_cb + q_data_src->bytesperline / 2 *
> -				q_data_src->height / 2;
> -		break;
> -	}
> -
> -	if (dev->devtype->product == CODA_960) {
> -		coda_write(dev, 4/*FIXME: 0*/,
> CODA9_CMD_ENC_PIC_SRC_INDEX);
> -		coda_write(dev, q_data_src->width,
> CODA9_CMD_ENC_PIC_SRC_STRIDE);
> -		coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
> -
> -		coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y);
> -		coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB);
> -		coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR);
> -	} else {
> -		coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
> -		coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
> -		coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
> -	}
> -	coda_write(dev, force_ipicture << 1 & 0x2,
> -		   CODA_CMD_ENC_PIC_OPTION);
> -
> -	coda_write(dev, pic_stream_buffer_addr,
> CODA_CMD_ENC_PIC_BB_START);
> -	coda_write(dev, pic_stream_buffer_size / 1024,
> -		   CODA_CMD_ENC_PIC_BB_SIZE);
> -
> -	if (!ctx->streamon_out) {
> -		/* After streamoff on the output side, set the stream end
> flag */
> -		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
> -		coda_write(dev, ctx->bit_stream_param,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> -	}
> -
> -	if (dev->devtype->product != CODA_DX6)
> -		coda_write(dev, ctx->iram_info.axi_sram_use,
> -				CODA7_REG_BIT_AXI_SRAM_USE);
> -
> -	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
> -
> -	return 0;
> -}
> 
>  static void coda_device_run(void *m2m_priv)
>  {
> @@ -1212,37 +709,6 @@ static void coda_device_run(void *m2m_priv)
>  	queue_work(dev->workqueue, &ctx->pic_run_work);
>  }
> 
> -static void coda_free_framebuffers(struct coda_ctx *ctx);
> -static void coda_free_context_buffers(struct coda_ctx *ctx);
> -
> -static void coda_seq_end_work(struct work_struct *work)
> -{
> -	struct coda_ctx *ctx = container_of(work, struct coda_ctx,
> seq_end_work);
> -	struct coda_dev *dev = ctx->dev;
> -
> -	mutex_lock(&ctx->buffer_mutex);
> -	mutex_lock(&dev->coda_mutex);
> -
> -	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> -		 "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx,
> __func__);
> -	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
> -		v4l2_err(&dev->v4l2_dev,
> -			 "CODA_COMMAND_SEQ_END failed\n");
> -	}
> -
> -	kfifo_init(&ctx->bitstream_fifo,
> -		ctx->bitstream.vaddr, ctx->bitstream.size);
> -
> -	coda_free_framebuffers(ctx);
> -	coda_free_context_buffers(ctx);
> -
> -	mutex_unlock(&dev->coda_mutex);
> -	mutex_unlock(&ctx->buffer_mutex);
> -}
> -
> -static void coda_finish_decode(struct coda_ctx *ctx);
> -static void coda_finish_encode(struct coda_ctx *ctx);
> -
>  static void coda_pic_run_work(struct work_struct *work)
>  {
>  	struct coda_ctx *ctx = container_of(work, struct coda_ctx,
> pic_run_work);
> @@ -1502,20 +968,8 @@ static void coda_buf_queue(struct vb2_buffer *vb)
>  	}
>  }
> 
> -static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32
> value)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	u32 *p = ctx->parabuf.vaddr;
> -
> -	if (dev->devtype->product == CODA_DX6)
> -		p[index] = value;
> -	else
> -		p[index ^ 1] = value;
> -}
> -
> -static int coda_alloc_aux_buf(struct coda_dev *dev,
> -			      struct coda_aux_buf *buf, size_t size,
> -			      const char *name, struct dentry *parent)
> +int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
> +		       size_t size, const char *name, struct dentry
> *parent)
>  {
>  	buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf-
> >paddr,
>  					GFP_KERNEL);
> @@ -1536,15 +990,8 @@ static int coda_alloc_aux_buf(struct coda_dev
> *dev,
>  	return 0;
>  }
> 
> -static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
> -					 struct coda_aux_buf *buf, size_t
size,
> -					 const char *name)
> -{
> -	return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx-
> >debugfs_entry);
> -}
> -
> -static void coda_free_aux_buf(struct coda_dev *dev,
> -			      struct coda_aux_buf *buf)
> +void coda_free_aux_buf(struct coda_dev *dev,
> +		       struct coda_aux_buf *buf)
>  {
>  	if (buf->vaddr) {
>  		dma_free_coherent(&dev->plat_dev->dev, buf->size,
> @@ -1555,538 +1002,21 @@ static void coda_free_aux_buf(struct coda_dev
> *dev,
>  	debugfs_remove(buf->dentry);
>  }
> 
> -static void coda_free_framebuffers(struct coda_ctx *ctx)
> +static int coda_start_streaming(struct vb2_queue *q, unsigned int
> count)
>  {
> -	int i;
> +	struct coda_ctx *ctx = vb2_get_drv_priv(q);
> +	struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
> +	struct coda_q_data *q_data_src, *q_data_dst;
> +	u32 dst_fourcc;
> +	int ret = 0;
> 
> -	for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++)
> -		coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i]);
> -}
> -
> -static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct
> coda_q_data *q_data, u32 fourcc)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	int width, height;
> -	dma_addr_t paddr;
> -	int ysize;
> -	int ret;
> -	int i;
> -
> -	if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
> -	     ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) {
> -		width = round_up(q_data->width, 16);
> -		height = round_up(q_data->height, 16);
> -	} else {
> -		width = round_up(q_data->width, 8);
> -		height = q_data->height;
> -	}
> -	ysize = width * height;
> -
> -	/* Allocate frame buffers */
> -	for (i = 0; i < ctx->num_internal_frames; i++) {
> -		size_t size;
> -		char *name;
> -
> -		size = ysize + ysize / 2;
> -		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
> -		    dev->devtype->product != CODA_DX6)
> -			size += ysize / 4;
> -		name = kasprintf(GFP_KERNEL, "fb%d", i);
> -		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i],
> -					     size, name);
> -		kfree(name);
> -		if (ret < 0) {
> -			coda_free_framebuffers(ctx);
> -			return ret;
> -		}
> -	}
> -
> -	/* Register frame buffers in the parameter buffer */
> -	for (i = 0; i < ctx->num_internal_frames; i++) {
> -		paddr = ctx->internal_frames[i].paddr;
> -		coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */
> -		coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */
> -		coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize +
> ysize/4); /* Cr */
> -
> -		/* mvcol buffer for h.264 */
> -		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
> -		    dev->devtype->product != CODA_DX6)
> -			coda_parabuf_write(ctx, 96 + i,
> -					   ctx->internal_frames[i].paddr +
> -					   ysize + ysize/4 + ysize/4);
> -	}
> -
> -	/* mvcol buffer for mpeg4 */
> -	if ((dev->devtype->product != CODA_DX6) &&
> -	    (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4))
> -		coda_parabuf_write(ctx, 97, ctx->internal_frames[i].paddr +
> -					    ysize + ysize/4 + ysize/4);
> -
> -	return 0;
> -}
> -
> -static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t
> size)
> -{
> -	phys_addr_t ret;
> -
> -	size = round_up(size, 1024);
> -	if (size > iram->remaining)
> -		return 0;
> -	iram->remaining -= size;
> -
> -	ret = iram->next_paddr;
> -	iram->next_paddr += size;
> -
> -	return ret;
> -}
> -
> -static void coda_setup_iram(struct coda_ctx *ctx)
> -{
> -	struct coda_iram_info *iram_info = &ctx->iram_info;
> -	struct coda_dev *dev = ctx->dev;
> -	int mb_width;
> -	int dbk_bits;
> -	int bit_bits;
> -	int ip_bits;
> -
> -	memset(iram_info, 0, sizeof(*iram_info));
> -	iram_info->next_paddr = dev->iram.paddr;
> -	iram_info->remaining = dev->iram.size;
> -
> -	switch (dev->devtype->product) {
> -	case CODA_7541:
> -		dbk_bits = CODA7_USE_HOST_DBK_ENABLE |
> CODA7_USE_DBK_ENABLE;
> -		bit_bits = CODA7_USE_HOST_BIT_ENABLE |
> CODA7_USE_BIT_ENABLE;
> -		ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
> -		break;
> -	case CODA_960:
> -		dbk_bits = CODA9_USE_HOST_DBK_ENABLE |
> CODA9_USE_DBK_ENABLE;
> -		bit_bits = CODA9_USE_HOST_BIT_ENABLE |
> CODA7_USE_BIT_ENABLE;
> -		ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
> -		break;
> -	default: /* CODA_DX6 */
> -		return;
> -	}
> -
> -	if (ctx->inst_type == CODA_INST_ENCODER) {
> -		struct coda_q_data *q_data_src;
> -
> -		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> -		mb_width = DIV_ROUND_UP(q_data_src->width, 16);
> -
> -		/* Prioritize in case IRAM is too small for everything */
> -		if (dev->devtype->product == CODA_7541) {
> -			iram_info->search_ram_size = round_up(mb_width * 16
*
> -							      36 + 2048,
1024);
> -			iram_info->search_ram_paddr =
> coda_iram_alloc(iram_info,
> -
iram_info->search_ram_size);
> -			if (!iram_info->search_ram_paddr) {
> -				pr_err("IRAM is smaller than the search ram
> size\n");
> -				goto out;
> -			}
> -			iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE
|
> -						   CODA7_USE_ME_ENABLE;
> -		}
> -
> -		/* Only H.264BP and H.263P3 are considered */
> -		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 *
> mb_width);
> -		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 *
> mb_width);
> -		if (!iram_info->buf_dbk_c_use)
> -			goto out;
> -		iram_info->axi_sram_use |= dbk_bits;
> -
> -		iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> -		if (!iram_info->buf_bit_use)
> -			goto out;
> -		iram_info->axi_sram_use |= bit_bits;
> -
> -		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info,
> 128 * mb_width);
> -		if (!iram_info->buf_ip_ac_dc_use)
> -			goto out;
> -		iram_info->axi_sram_use |= ip_bits;
> -
> -		/* OVL and BTP disabled for encoder */
> -	} else if (ctx->inst_type == CODA_INST_DECODER) {
> -		struct coda_q_data *q_data_dst;
> -
> -		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -		mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
> -
> -		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> -		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> -		if (!iram_info->buf_dbk_c_use)
> -			goto out;
> -		iram_info->axi_sram_use |= dbk_bits;
> -
> -		iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 *
> mb_width);
> -		if (!iram_info->buf_bit_use)
> -			goto out;
> -		iram_info->axi_sram_use |= bit_bits;
> -
> -		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info,
> 128 * mb_width);
> -		if (!iram_info->buf_ip_ac_dc_use)
> -			goto out;
> -		iram_info->axi_sram_use |= ip_bits;
> -
> -		/* OVL and BTP unused as there is no VC1 support yet */
> -	}
> -
> -out:
> -	if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
> -		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
> -			 "IRAM smaller than needed\n");
> -
> -	if (dev->devtype->product == CODA_7541) {
> -		/* TODO - Enabling these causes picture errors on CODA7541
> */
> -		if (ctx->inst_type == CODA_INST_DECODER) {
> -			/* fw 1.4.50 */
> -			iram_info->axi_sram_use &=
~(CODA7_USE_HOST_IP_ENABLE
> |
> -						     CODA7_USE_IP_ENABLE);
> -		} else {
> -			/* fw 13.4.29 */
> -			iram_info->axi_sram_use &=
~(CODA7_USE_HOST_IP_ENABLE
> |
> -
CODA7_USE_HOST_DBK_ENABLE |
> -						     CODA7_USE_IP_ENABLE |
> -						     CODA7_USE_DBK_ENABLE);
> -		}
> -	}
> -}
> -
> -static void coda_free_context_buffers(struct coda_ctx *ctx)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -
> -	coda_free_aux_buf(dev, &ctx->slicebuf);
> -	coda_free_aux_buf(dev, &ctx->psbuf);
> -	if (dev->devtype->product != CODA_DX6)
> -		coda_free_aux_buf(dev, &ctx->workbuf);
> -}
> -
> -static int coda_alloc_context_buffers(struct coda_ctx *ctx,
> -				      struct coda_q_data *q_data)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	size_t size;
> -	int ret;
> -
> -	if (dev->devtype->product == CODA_DX6)
> -		return 0;
> -
> -	if (ctx->psbuf.vaddr) {
> -		v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n");
> -		return -EBUSY;
> -	}
> -	if (ctx->slicebuf.vaddr) {
> -		v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n");
> -		return -EBUSY;
> -	}
> -	if (ctx->workbuf.vaddr) {
> -		v4l2_err(&dev->v4l2_dev, "context buffer still
> allocated\n");
> -		ret = -EBUSY;
> -		return -ENOMEM;
> -	}
> -
> -	if (q_data->fourcc == V4L2_PIX_FMT_H264) {
> -		/* worst case slice size */
> -		size = (DIV_ROUND_UP(q_data->width, 16) *
> -			DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
> -		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size,
> "slicebuf");
> -		if (ret < 0) {
> -			v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte
> slice buffer",
> -				 ctx->slicebuf.size);
> -			return ret;
> -		}
> -	}
> -
> -	if (dev->devtype->product == CODA_7541) {
> -		ret = coda_alloc_context_buf(ctx, &ctx->psbuf,
> CODA7_PS_BUF_SIZE, "psbuf");
> -		if (ret < 0) {
> -			v4l2_err(&dev->v4l2_dev, "failed to allocate psmem
> buffer");
> -			goto err;
> -		}
> -	}
> -
> -	size = dev->devtype->workbuf_size;
> -	if (dev->devtype->product == CODA_960 &&
> -	    q_data->fourcc == V4L2_PIX_FMT_H264)
> -		size += CODA9_PS_SAVE_SIZE;
> -	ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size,
> "workbuf");
> -	if (ret < 0) {
> -		v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte
> context buffer",
> -			 ctx->workbuf.size);
> -		goto err;
> -	}
> -
> -	return 0;
> -
> -err:
> -	coda_free_context_buffers(ctx);
> -	return ret;
> -}
> -
> -static int __coda_start_decoding(struct coda_ctx *ctx)
> -{
> -	struct coda_q_data *q_data_src, *q_data_dst;
> -	u32 bitstream_buf, bitstream_size;
> -	struct coda_dev *dev = ctx->dev;
> -	int width, height;
> -	u32 src_fourcc;
> -	u32 val;
> -	int ret;
> -
> -	/* Start decoding */
> -	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> -	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -	bitstream_buf = ctx->bitstream.paddr;
> -	bitstream_size = ctx->bitstream.size;
> -	src_fourcc = q_data_src->fourcc;
> -
> -	/* Allocate per-instance buffers */
> -	ret = coda_alloc_context_buffers(ctx, q_data_src);
> -	if (ret < 0)
> -		return ret;
> -
> -	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
> -
> -	/* Update coda bitstream read and write pointers from kfifo */
> -	coda_kfifo_sync_to_device_full(ctx);
> -
> -	ctx->display_idx = -1;
> -	ctx->frm_dis_flg = 0;
> -	coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
> -
> -	coda_write(dev, CODA_BIT_DEC_SEQ_INIT_ESCAPE,
> -			CODA_REG_BIT_BIT_STREAM_PARAM);
> -
> -	coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
> -	coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
> -	val = 0;
> -	if ((dev->devtype->product == CODA_7541) ||
> -	    (dev->devtype->product == CODA_960))
> -		val |= CODA_REORDER_ENABLE;
> -	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
> -
> -	ctx->params.codec_mode = ctx->codec->mode;
> -	if (dev->devtype->product == CODA_960 &&
> -	    src_fourcc == V4L2_PIX_FMT_MPEG4)
> -		ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
> -	else
> -		ctx->params.codec_mode_aux = 0;
> -	if (src_fourcc == V4L2_PIX_FMT_H264) {
> -		if (dev->devtype->product == CODA_7541) {
> -			coda_write(dev, ctx->psbuf.paddr,
> -					CODA_CMD_DEC_SEQ_PS_BB_START);
> -			coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
> -					CODA_CMD_DEC_SEQ_PS_BB_SIZE);
> -		}
> -		if (dev->devtype->product == CODA_960) {
> -			coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN);
> -			coda_write(dev, 512,
> CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE);
> -		}
> -	}
> -	if (dev->devtype->product != CODA_960) {
> -		coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
> -	}
> -
> -	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
> -		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT
> timeout\n");
> -		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
> -		return -ETIMEDOUT;
> -	}
> -
> -	/* Update kfifo out pointer from coda bitstream read pointer */
> -	coda_kfifo_sync_from_device(ctx);
> -
> -	coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
> -
> -	if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) {
> -		v4l2_err(&dev->v4l2_dev,
> -			"CODA_COMMAND_SEQ_INIT failed, error code = %d\n",
> -			coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON));
> -		return -EAGAIN;
> -	}
> -
> -	val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE);
> -	if (dev->devtype->product == CODA_DX6) {
> -		width = (val >> CODADX6_PICWIDTH_OFFSET) &
> CODADX6_PICWIDTH_MASK;
> -		height = val & CODADX6_PICHEIGHT_MASK;
> -	} else {
> -		width = (val >> CODA7_PICWIDTH_OFFSET) &
> CODA7_PICWIDTH_MASK;
> -		height = val & CODA7_PICHEIGHT_MASK;
> -	}
> -
> -	if (width > q_data_dst->width || height > q_data_dst->height) {
> -		v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n",
> -			 width, height, q_data_dst->width, q_data_dst-
> >height);
> -		return -EINVAL;
> -	}
> -
> -	width = round_up(width, 16);
> -	height = round_up(height, 16);
> -
> -	v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now:
> %dx%d\n",
> -		 __func__, ctx->idx, width, height);
> -
> -	ctx->num_internal_frames = coda_read(dev,
> CODA_RET_DEC_SEQ_FRAME_NEED);
> -	if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
> -		v4l2_err(&dev->v4l2_dev,
> -			 "not enough framebuffers to decode (%d < %d)\n",
> -			 CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames);
> -		return -EINVAL;
> -	}
> -
> -	if (src_fourcc == V4L2_PIX_FMT_H264) {
> -		u32 left_right;
> -		u32 top_bottom;
> -
> -		left_right = coda_read(dev,
> CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT);
> -		top_bottom = coda_read(dev,
> CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM);
> -
> -		q_data_dst->rect.left = (left_right >> 10) & 0x3ff;
> -		q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff;
> -		q_data_dst->rect.width = width - q_data_dst->rect.left -
> -					 (left_right & 0x3ff);
> -		q_data_dst->rect.height = height - q_data_dst->rect.top -
> -					  (top_bottom & 0x3ff);
> -	}
> -
> -	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Tell the decoder how many frame buffers we allocated. */
> -	coda_write(dev, ctx->num_internal_frames,
> CODA_CMD_SET_FRAME_BUF_NUM);
> -	coda_write(dev, width, CODA_CMD_SET_FRAME_BUF_STRIDE);
> -
> -	if (dev->devtype->product != CODA_DX6) {
> -		/* Set secondary AXI IRAM */
> -		coda_setup_iram(ctx);
> -
> -		coda_write(dev, ctx->iram_info.buf_bit_use,
> -				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
> -				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
> -				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
> -				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_ovl_use,
> -				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
> -		if (dev->devtype->product == CODA_960)
> -			coda_write(dev, ctx->iram_info.buf_btp_use,
> -					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
> -	}
> -
> -	if (dev->devtype->product == CODA_960) {
> -		coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
> -
> -		coda_write(dev, 0x20262024,
> CODA9_CMD_SET_FRAME_CACHE_SIZE);
> -		coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
> -				32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
> -				8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
> -				8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
> -				CODA9_CMD_SET_FRAME_CACHE_CONFIG);
> -	}
> -
> -	if (src_fourcc == V4L2_PIX_FMT_H264) {
> -		coda_write(dev, ctx->slicebuf.paddr,
> -				CODA_CMD_SET_FRAME_SLICE_BB_START);
> -		coda_write(dev, ctx->slicebuf.size / 1024,
> -				CODA_CMD_SET_FRAME_SLICE_BB_SIZE);
> -	}
> -
> -	if (dev->devtype->product == CODA_7541) {
> -		int max_mb_x = 1920 / 16;
> -		int max_mb_y = 1088 / 16;
> -		int max_mb_num = max_mb_x * max_mb_y;
> -
> -		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 |
> max_mb_y,
> -				CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
> -	} else if (dev->devtype->product == CODA_960) {
> -		int max_mb_x = 1920 / 16;
> -		int max_mb_y = 1088 / 16;
> -		int max_mb_num = max_mb_x * max_mb_y;
> -
> -		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 |
> max_mb_y,
> -				CODA9_CMD_SET_FRAME_MAX_DEC_SIZE);
> -	}
> -
> -	if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
> -		v4l2_err(&ctx->dev->v4l2_dev,
> -			 "CODA_COMMAND_SET_FRAME_BUF timeout\n");
> -		return -ETIMEDOUT;
> -	}
> -
> -	return 0;
> -}
> -
> -static int coda_start_decoding(struct coda_ctx *ctx)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	int ret;
> -
> -	mutex_lock(&dev->coda_mutex);
> -	ret = __coda_start_decoding(ctx);
> -	mutex_unlock(&dev->coda_mutex);
> -
> -	return ret;
> -}
> -
> -static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer
> *buf,
> -			      int header_code, u8 *header, int *size)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	size_t bufsize;
> -	int ret;
> -	int i;
> -
> -	if (dev->devtype->product == CODA_960)
> -		memset(vb2_plane_vaddr(buf, 0), 0, 64);
> -
> -	coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0),
> -		   CODA_CMD_ENC_HEADER_BB_START);
> -	bufsize = vb2_plane_size(buf, 0);
> -	if (dev->devtype->product == CODA_960)
> -		bufsize /= 1024;
> -	coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
> -	coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE);
> -	ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER);
> -	if (ret < 0) {
> -		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER
> timeout\n");
> -		return ret;
> -	}
> -
> -	if (dev->devtype->product == CODA_960) {
> -		for (i = 63; i > 0; i--)
> -			if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0)
> -				break;
> -		*size = i + 1;
> -	} else {
> -		*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
> -			coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
> -	}
> -	memcpy(header, vb2_plane_vaddr(buf, 0), *size);
> -
> -	return 0;
> -}
> -
> -static int coda_start_encoding(struct coda_ctx *ctx);
> -
> -static int coda_start_streaming(struct vb2_queue *q, unsigned int
> count)
> -{
> -	struct coda_ctx *ctx = vb2_get_drv_priv(q);
> -	struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
> -	struct coda_q_data *q_data_src, *q_data_dst;
> -	u32 dst_fourcc;
> -	int ret = 0;
> -
> -	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> -	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> -		if (q_data_src->fourcc == V4L2_PIX_FMT_H264) {
> -			/* copy the buffers that where queued before
streamon
> */
> -			mutex_lock(&ctx->bitstream_mutex);
> -			coda_fill_bitstream(ctx);
> -			mutex_unlock(&ctx->bitstream_mutex);
> +	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> +	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
> +		if (q_data_src->fourcc == V4L2_PIX_FMT_H264) {
> +			/* copy the buffers that where queued before
streamon
> */
> +			mutex_lock(&ctx->bitstream_mutex);
> +			coda_fill_bitstream(ctx);
> +			mutex_unlock(&ctx->bitstream_mutex);
> 
>  			if (coda_get_bitstream_payload(ctx) < 512)
>  				return -EINVAL;
> @@ -2134,337 +1064,6 @@ static int coda_start_streaming(struct
> vb2_queue *q, unsigned int count)
>  	return ret;
>  }
> 
> -static int coda_start_encoding(struct coda_ctx *ctx)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
> -	struct coda_q_data *q_data_src, *q_data_dst;
> -	u32 bitstream_buf, bitstream_size;
> -	struct vb2_buffer *buf;
> -	int gamma, ret, value;
> -	u32 dst_fourcc;
> -
> -	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> -	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -	dst_fourcc = q_data_dst->fourcc;
> -
> -	/* Allocate per-instance buffers */
> -	ret = coda_alloc_context_buffers(ctx, q_data_src);
> -	if (ret < 0)
> -		return ret;
> -
> -	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> -	bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
> -	bitstream_size = q_data_dst->sizeimage;
> -
> -	if (!coda_is_initialized(dev)) {
> -		v4l2_err(v4l2_dev, "coda is not initialized.\n");
> -		return -EFAULT;
> -	}
> -
> -	mutex_lock(&dev->coda_mutex);
> -
> -	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
> -	coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx-
> >reg_idx));
> -	coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx-
> >reg_idx));
> -	switch (dev->devtype->product) {
> -	case CODA_DX6:
> -		coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
> -			CODADX6_STREAM_BUF_PIC_RESET,
> CODA_REG_BIT_STREAM_CTRL);
> -		break;
> -	case CODA_960:
> -		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
> -		/* fallthrough */
> -	case CODA_7541:
> -		coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
> -			CODA7_STREAM_BUF_PIC_RESET,
> CODA_REG_BIT_STREAM_CTRL);
> -		break;
> -	}
> -
> -	value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL);
> -	value &= ~(1 << 2 | 0x7 << 9);
> -	ctx->frame_mem_ctrl = value;
> -	coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL);
> -
> -	if (dev->devtype->product == CODA_DX6) {
> -		/* Configure the coda */
> -		coda_write(dev, dev->iram.paddr,
> CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
> -	}
> -
> -	/* Could set rotation here if needed */
> -	switch (dev->devtype->product) {
> -	case CODA_DX6:
> -		value = (q_data_src->width & CODADX6_PICWIDTH_MASK) <<
> CODADX6_PICWIDTH_OFFSET;
> -		value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) <<
> CODA_PICHEIGHT_OFFSET;
> -		break;
> -	case CODA_7541:
> -		if (dst_fourcc == V4L2_PIX_FMT_H264) {
> -			value = (round_up(q_data_src->width, 16) &
> -				 CODA7_PICWIDTH_MASK) <<
CODA7_PICWIDTH_OFFSET;
> -			value |= (round_up(q_data_src->height, 16) &
> -				  CODA7_PICHEIGHT_MASK) <<
> CODA_PICHEIGHT_OFFSET;
> -			break;
> -		}
> -		/* fallthrough */
> -	case CODA_960:
> -		value = (q_data_src->width & CODA7_PICWIDTH_MASK) <<
> CODA7_PICWIDTH_OFFSET;
> -		value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) <<
> CODA_PICHEIGHT_OFFSET;
> -	}
> -	coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
> -	coda_write(dev, ctx->params.framerate,
> -		   CODA_CMD_ENC_SEQ_SRC_F_RATE);
> -
> -	ctx->params.codec_mode = ctx->codec->mode;
> -	switch (dst_fourcc) {
> -	case V4L2_PIX_FMT_MPEG4:
> -		if (dev->devtype->product == CODA_960)
> -			coda_write(dev, CODA9_STD_MPEG4,
> CODA_CMD_ENC_SEQ_COD_STD);
> -		else
> -			coda_write(dev, CODA_STD_MPEG4,
> CODA_CMD_ENC_SEQ_COD_STD);
> -		coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
> -		break;
> -	case V4L2_PIX_FMT_H264:
> -		if (dev->devtype->product == CODA_960)
> -			coda_write(dev, CODA9_STD_H264,
> CODA_CMD_ENC_SEQ_COD_STD);
> -		else
> -			coda_write(dev, CODA_STD_H264,
> CODA_CMD_ENC_SEQ_COD_STD);
> -		if (ctx->params.h264_deblk_enabled) {
> -			value = ((ctx->params.h264_deblk_alpha &
> -				  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK)
<<
> -
CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
> -				((ctx->params.h264_deblk_beta &
> -				  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK)
<<
> -
CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET);
> -		} else {
> -			value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET;
> -		}
> -		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
> -		break;
> -	default:
> -		v4l2_err(v4l2_dev,
> -			 "dst format (0x%08x) invalid.\n", dst_fourcc);
> -		ret = -EINVAL;
> -		goto out;
> -	}
> -
> -	switch (ctx->params.slice_mode) {
> -	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
> -		value = 0;
> -		break;
> -	case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
> -		value  = (ctx->params.slice_max_mb &
> CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET;
> -		value |= (1 & CODA_SLICING_UNIT_MASK) <<
> CODA_SLICING_UNIT_OFFSET;
> -		value |=  1 & CODA_SLICING_MODE_MASK;
> -		break;
> -	case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
> -		value  = (ctx->params.slice_max_bits &
> CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET;
> -		value |= (0 & CODA_SLICING_UNIT_MASK) <<
> CODA_SLICING_UNIT_OFFSET;
> -		value |=  1 & CODA_SLICING_MODE_MASK;
> -		break;
> -	}
> -	coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
> -	value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
> -	coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
> -
> -	if (ctx->params.bitrate) {
> -		/* Rate control enabled */
> -		value = (ctx->params.bitrate &
> CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET;
> -		value |=  1 & CODA_RATECONTROL_ENABLE_MASK;
> -		if (dev->devtype->product == CODA_960)
> -			value |= BIT(31); /* disable autoskip */
> -	} else {
> -		value = 0;
> -	}
> -	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
> -
> -	coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
> -	coda_write(dev, ctx->params.intra_refresh,
> -		   CODA_CMD_ENC_SEQ_INTRA_REFRESH);
> -
> -	coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
> -	coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
> -
> -
> -	value = 0;
> -	if (dev->devtype->product == CODA_960)
> -		gamma = CODA9_DEFAULT_GAMMA;
> -	else
> -		gamma = CODA_DEFAULT_GAMMA;
> -	if (gamma > 0) {
> -		coda_write(dev, (gamma & CODA_GAMMA_MASK) <<
> CODA_GAMMA_OFFSET,
> -			   CODA_CMD_ENC_SEQ_RC_GAMMA);
> -	}
> -
> -	if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) {
> -		coda_write(dev,
> -			   ctx->params.h264_min_qp << CODA_QPMIN_OFFSET |
> -			   ctx->params.h264_max_qp << CODA_QPMAX_OFFSET,
> -			   CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX);
> -	}
> -	if (dev->devtype->product == CODA_960) {
> -		if (ctx->params.h264_max_qp)
> -			value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET;
> -		if (CODA_DEFAULT_GAMMA > 0)
> -			value |= 1 << CODA9_OPTION_GAMMA_OFFSET;
> -	} else {
> -		if (CODA_DEFAULT_GAMMA > 0) {
> -			if (dev->devtype->product == CODA_DX6)
> -				value |= 1 << CODADX6_OPTION_GAMMA_OFFSET;
> -			else
> -				value |= 1 << CODA7_OPTION_GAMMA_OFFSET;
> -		}
> -		if (ctx->params.h264_min_qp)
> -			value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET;
> -		if (ctx->params.h264_max_qp)
> -			value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET;
> -	}
> -	coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
> -
> -	coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
> -
> -	coda_setup_iram(ctx);
> -
> -	if (dst_fourcc == V4L2_PIX_FMT_H264) {
> -		switch (dev->devtype->product) {
> -		case CODA_DX6:
> -			value = FMO_SLICE_SAVE_BUF_SIZE << 7;
> -			coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
> -			break;
> -		case CODA_7541:
> -			coda_write(dev, ctx->iram_info.search_ram_paddr,
> -					CODA7_CMD_ENC_SEQ_SEARCH_BASE);
> -			coda_write(dev, ctx->iram_info.search_ram_size,
> -					CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
> -			break;
> -		case CODA_960:
> -			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION);
> -			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT);
> -		}
> -	}
> -
> -	ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
> -	if (ret < 0) {
> -		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
> -		goto out;
> -	}
> -
> -	if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) {
> -		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n");
> -		ret = -EFAULT;
> -		goto out;
> -	}
> -
> -	if (dev->devtype->product == CODA_960)
> -		ctx->num_internal_frames = 4;
> -	else
> -		ctx->num_internal_frames = 2;
> -	ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
> -	if (ret < 0) {
> -		v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
> -		goto out;
> -	}
> -
> -	coda_write(dev, ctx->num_internal_frames,
> CODA_CMD_SET_FRAME_BUF_NUM);
> -	coda_write(dev, q_data_src->bytesperline,
> -			CODA_CMD_SET_FRAME_BUF_STRIDE);
> -	if (dev->devtype->product == CODA_7541) {
> -		coda_write(dev, q_data_src->bytesperline,
> -				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
> -	}
> -	if (dev->devtype->product != CODA_DX6) {
> -		coda_write(dev, ctx->iram_info.buf_bit_use,
> -				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
> -				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
> -				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
> -				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
> -		coda_write(dev, ctx->iram_info.buf_ovl_use,
> -				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
> -		if (dev->devtype->product == CODA_960) {
> -			coda_write(dev, ctx->iram_info.buf_btp_use,
> -					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
> -
> -			/* FIXME */
> -			coda_write(dev, ctx->internal_frames[2].paddr,
> CODA9_CMD_SET_FRAME_SUBSAMP_A);
> -			coda_write(dev, ctx->internal_frames[3].paddr,
> CODA9_CMD_SET_FRAME_SUBSAMP_B);
> -		}
> -	}
> -
> -	ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
> -	if (ret < 0) {
> -		v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
> -		goto out;
> -	}
> -
> -	/* Save stream headers */
> -	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> -	switch (dst_fourcc) {
> -	case V4L2_PIX_FMT_H264:
> -		/*
> -		 * Get SPS in the first frame and copy it to an
> -		 * intermediate buffer.
> -		 */
> -		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS,
> -					 &ctx->vpu_header[0][0],
> -					 &ctx->vpu_header_size[0]);
> -		if (ret < 0)
> -			goto out;
> -
> -		/*
> -		 * Get PPS in the first frame and copy it to an
> -		 * intermediate buffer.
> -		 */
> -		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS,
> -					 &ctx->vpu_header[1][0],
> -					 &ctx->vpu_header_size[1]);
> -		if (ret < 0)
> -			goto out;
> -
> -		/*
> -		 * Length of H.264 headers is variable and thus it might
> not be
> -		 * aligned for the coda to append the encoded frame. In
> that is
> -		 * the case a filler NAL must be added to header 2.
> -		 */
> -		ctx->vpu_header_size[2] = coda_h264_padding(
> -					(ctx->vpu_header_size[0] +
> -					 ctx->vpu_header_size[1]),
> -					 ctx->vpu_header[2]);
> -		break;
> -	case V4L2_PIX_FMT_MPEG4:
> -		/*
> -		 * Get VOS in the first frame and copy it to an
> -		 * intermediate buffer
> -		 */
> -		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS,
> -					 &ctx->vpu_header[0][0],
> -					 &ctx->vpu_header_size[0]);
> -		if (ret < 0)
> -			goto out;
> -
> -		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS,
> -					 &ctx->vpu_header[1][0],
> -					 &ctx->vpu_header_size[1]);
> -		if (ret < 0)
> -			goto out;
> -
> -		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL,
> -					 &ctx->vpu_header[2][0],
> -					 &ctx->vpu_header_size[2]);
> -		if (ret < 0)
> -			goto out;
> -		break;
> -	default:
> -		/* No more formats need to save headers at the moment */
> -		break;
> -	}
> -
> -out:
> -	mutex_unlock(&dev->coda_mutex);
> -	return ret;
> -}
> -
>  static void coda_stop_streaming(struct vb2_queue *q)
>  {
>  	struct coda_ctx *ctx = vb2_get_drv_priv(q);
> @@ -2664,8 +1263,8 @@ static int coda_queue_init(struct coda_ctx *ctx,
> struct vb2_queue *vq)
>  	return vb2_queue_init(vq);
>  }
> 
> -static int coda_encoder_queue_init(void *priv, struct vb2_queue
> *src_vq,
> -				   struct vb2_queue *dst_vq)
> +int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq)
>  {
>  	int ret;
> 
> @@ -2684,8 +1283,8 @@ static int coda_encoder_queue_init(void *priv,
> struct vb2_queue *src_vq,
>  	return coda_queue_init(priv, dst_vq);
>  }
> 
> -static int coda_decoder_queue_init(void *priv, struct vb2_queue
> *src_vq,
> -				   struct vb2_queue *dst_vq)
> +int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq)
>  {
>  	int ret;
> 
> @@ -2845,38 +1444,14 @@ err_coda_max:
>  	return ret;
>  }
> 
> -static void coda_bit_release(struct coda_ctx *ctx)
> -{
> -	coda_free_framebuffers(ctx);
> -	coda_free_context_buffers(ctx);
> -}
> -
> -struct coda_context_ops coda_encode_ops = {
> -	.queue_init = coda_encoder_queue_init,
> -	.start_streaming = coda_start_encoding,
> -	.prepare_run = coda_prepare_encode,
> -	.finish_run = coda_finish_encode,
> -	.seq_end_work = coda_seq_end_work,
> -	.release = coda_bit_release,
> -};
> -
> -struct coda_context_ops coda_decode_ops = {
> -	.queue_init = coda_decoder_queue_init,
> -	.start_streaming = coda_start_decoding,
> -	.prepare_run = coda_prepare_decode,
> -	.finish_run = coda_finish_decode,
> -	.seq_end_work = coda_seq_end_work,
> -	.release = coda_bit_release,
> -};
> -
>  static int coda_encoder_open(struct file *file)
>  {
> -	return coda_open(file, CODA_INST_ENCODER, &coda_encode_ops);
> +	return coda_open(file, CODA_INST_ENCODER, &coda_bit_encode_ops);
>  }
> 
>  static int coda_decoder_open(struct file *file)
>  {
> -	return coda_open(file, CODA_INST_DECODER, &coda_decode_ops);
> +	return coda_open(file, CODA_INST_DECODER, &coda_bit_decode_ops);
>  }
> 
>  static int coda_release(struct file *file)
> @@ -2940,316 +1515,6 @@ static const struct v4l2_file_operations
> coda_decoder_fops = {
>  	.mmap		= v4l2_m2m_fop_mmap,
>  };
> 
> -static void coda_finish_decode(struct coda_ctx *ctx)
> -{
> -	struct coda_dev *dev = ctx->dev;
> -	struct coda_q_data *q_data_src;
> -	struct coda_q_data *q_data_dst;
> -	struct vb2_buffer *dst_buf;
> -	struct coda_timestamp *ts;
> -	int width, height;
> -	int decoded_idx;
> -	int display_idx;
> -	u32 src_fourcc;
> -	int success;
> -	u32 err_mb;
> -	u32 val;
> -
> -	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> -
> -	/* Update kfifo out pointer from coda bitstream read pointer */
> -	coda_kfifo_sync_from_device(ctx);
> -
> -	/*
> -	 * in stream-end mode, the read pointer can overshoot the write
> pointer
> -	 * by up to 512 bytes
> -	 */
> -	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) {
> -		if (coda_get_bitstream_payload(ctx) >= CODA_MAX_FRAME_SIZE
> - 512)
> -			kfifo_init(&ctx->bitstream_fifo,
> -				ctx->bitstream.vaddr, ctx->bitstream.size);
> -	}
> -
> -	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
> -	src_fourcc = q_data_src->fourcc;
> -
> -	val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS);
> -	if (val != 1)
> -		pr_err("DEC_PIC_SUCCESS = %d\n", val);
> -
> -	success = val & 0x1;
> -	if (!success)
> -		v4l2_err(&dev->v4l2_dev, "decode failed\n");
> -
> -	if (src_fourcc == V4L2_PIX_FMT_H264) {
> -		if (val & (1 << 3))
> -			v4l2_err(&dev->v4l2_dev,
> -				 "insufficient PS buffer space (%d
bytes)\n",
> -				 ctx->psbuf.size);
> -		if (val & (1 << 2))
> -			v4l2_err(&dev->v4l2_dev,
> -				 "insufficient slice buffer space (%d
> bytes)\n",
> -				 ctx->slicebuf.size);
> -	}
> -
> -	val = coda_read(dev, CODA_RET_DEC_PIC_SIZE);
> -	width = (val >> 16) & 0xffff;
> -	height = val & 0xffff;
> -
> -	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
> -
> -	/* frame crop information */
> -	if (src_fourcc == V4L2_PIX_FMT_H264) {
> -		u32 left_right;
> -		u32 top_bottom;
> -
> -		left_right = coda_read(dev,
> CODA_RET_DEC_PIC_CROP_LEFT_RIGHT);
> -		top_bottom = coda_read(dev,
> CODA_RET_DEC_PIC_CROP_TOP_BOTTOM);
> -
> -		if (left_right == 0xffffffff && top_bottom == 0xffffffff) {
> -			/* Keep current crop information */
> -		} else {
> -			struct v4l2_rect *rect = &q_data_dst->rect;
> -
> -			rect->left = left_right >> 16 & 0xffff;
> -			rect->top = top_bottom >> 16 & 0xffff;
> -			rect->width = width - rect->left -
> -				      (left_right & 0xffff);
> -			rect->height = height - rect->top -
> -				       (top_bottom & 0xffff);
> -		}
> -	} else {
> -		/* no cropping */
> -	}
> -
> -	err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
> -	if (err_mb > 0)
> -		v4l2_err(&dev->v4l2_dev,
> -			 "errors in %d macroblocks\n", err_mb);
> -
> -	if (dev->devtype->product == CODA_7541) {
> -		val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
> -		if (val == 0) {
> -			/* not enough bitstream data */
> -			v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> -				 "prescan failed: %d\n", val);
> -			ctx->hold = true;
> -			return;
> -		}
> -	}
> -
> -	ctx->frm_dis_flg = coda_read(dev, CODA_REG_BIT_FRM_DIS_FLG(ctx-
> >reg_idx));
> -
> -	/*
> -	 * The previous display frame was copied out by the rotator,
> -	 * now it can be overwritten again
> -	 */
> -	if (ctx->display_idx >= 0 &&
> -	    ctx->display_idx < ctx->num_internal_frames) {
> -		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
> -		coda_write(dev, ctx->frm_dis_flg,
> -				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
> -	}
> -
> -	/*
> -	 * The index of the last decoded frame, not necessarily in
> -	 * display order, and the index of the next display frame.
> -	 * The latter could have been decoded in a previous run.
> -	 */
> -	decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX);
> -	display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX);
> -
> -	if (decoded_idx == -1) {
> -		/* no frame was decoded, but we might have a display frame
> */
> -		if (display_idx >= 0 && display_idx < ctx-
> >num_internal_frames)
> -			ctx->sequence_offset++;
> -		else if (ctx->display_idx < 0)
> -			ctx->hold = true;
> -	} else if (decoded_idx == -2) {
> -		/* no frame was decoded, we still return the remaining
> buffers */
> -	} else if (decoded_idx < 0 || decoded_idx >= ctx-
> >num_internal_frames) {
> -		v4l2_err(&dev->v4l2_dev,
> -			 "decoded frame index out of range: %d\n",
> decoded_idx);
> -	} else {
> -		ts = list_first_entry(&ctx->timestamp_list,
> -				      struct coda_timestamp, list);
> -		list_del(&ts->list);
> -		val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
> -		val -= ctx->sequence_offset;
> -		if (val != (ts->sequence & 0xffff)) {
> -			v4l2_err(&dev->v4l2_dev,
> -				 "sequence number mismatch (%d(%d) !=
%d)\n",
> -				 val, ctx->sequence_offset, ts->sequence);
> -		}
> -		ctx->frame_timestamps[decoded_idx] = *ts;
> -		kfree(ts);
> -
> -		val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
> -		if (val == 0)
> -			ctx->frame_types[decoded_idx] =
> V4L2_BUF_FLAG_KEYFRAME;
> -		else if (val == 1)
> -			ctx->frame_types[decoded_idx] =
V4L2_BUF_FLAG_PFRAME;
> -		else
> -			ctx->frame_types[decoded_idx] =
V4L2_BUF_FLAG_BFRAME;
> -
> -		ctx->frame_errors[decoded_idx] = err_mb;
> -	}
> -
> -	if (display_idx == -1) {
> -		/*
> -		 * no more frames to be decoded, but there could still
> -		 * be rotator output to dequeue
> -		 */
> -		ctx->hold = true;
> -	} else if (display_idx == -3) {
> -		/* possibly prescan failure */
> -	} else if (display_idx < 0 || display_idx >= ctx-
> >num_internal_frames) {
> -		v4l2_err(&dev->v4l2_dev,
> -			 "presentation frame index out of range: %d\n",
> -			 display_idx);
> -	}
> -
> -	/* If a frame was copied out, return it */
> -	if (ctx->display_idx >= 0 &&
> -	    ctx->display_idx < ctx->num_internal_frames) {
> -		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> -		dst_buf->v4l2_buf.sequence = ctx->osequence++;
> -
> -		dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
> -					     V4L2_BUF_FLAG_PFRAME |
> -					     V4L2_BUF_FLAG_BFRAME);
> -		dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx-
> >display_idx];
> -		ts = &ctx->frame_timestamps[ctx->display_idx];
> -		dst_buf->v4l2_buf.timecode = ts->timecode;
> -		dst_buf->v4l2_buf.timestamp = ts->timestamp;
> -
> -		vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
> -
> -		v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ?
> -				  VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
> -
> -		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> -			"job finished: decoding frame (%d) (%s)\n",
> -			dst_buf->v4l2_buf.sequence,
> -			(dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
> -			"KEYFRAME" : "PFRAME");
> -	} else {
> -		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> -			"job finished: no frame decoded\n");
> -	}
> -
> -	/* The rotator will copy the current display frame next time */
> -	ctx->display_idx = display_idx;
> -}
> -
> -static void coda_finish_encode(struct coda_ctx *ctx)
> -{
> -	struct vb2_buffer *src_buf, *dst_buf;
> -	struct coda_dev *dev = ctx->dev;
> -	u32 wr_ptr, start_ptr;
> -
> -	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> -	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> -
> -	/* Get results from the coda */
> -	start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
> -	wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
> -
> -	/* Calculate bytesused field */
> -	if (dst_buf->v4l2_buf.sequence == 0) {
> -		vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr +
> -					ctx->vpu_header_size[0] +
> -					ctx->vpu_header_size[1] +
> -					ctx->vpu_header_size[2]);
> -	} else {
> -		vb2_set_plane_payload(dst_buf, 0, wr_ptr - start_ptr);
> -	}
> -
> -	v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n",
> -		 wr_ptr - start_ptr);
> -
> -	coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM);
> -	coda_read(dev, CODA_RET_ENC_PIC_FLAG);
> -
> -	if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) {
> -		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
> -		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
> -	} else {
> -		dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
> -		dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
> -	}
> -
> -	dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
> -	dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -	dst_buf->v4l2_buf.flags |=
> -		src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -	dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
> -
> -	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
> -
> -	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> -	v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
> -
> -	ctx->gopcounter--;
> -	if (ctx->gopcounter < 0)
> -		ctx->gopcounter = ctx->params.gop_size - 1;
> -
> -	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> -		"job finished: encoding frame (%d) (%s)\n",
> -		dst_buf->v4l2_buf.sequence,
> -		(dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
> -		"KEYFRAME" : "PFRAME");
> -}
> -
> -static irqreturn_t coda_irq_handler(int irq, void *data)
> -{
> -	struct coda_dev *dev = data;
> -	struct coda_ctx *ctx;
> -
> -	/* read status register to attend the IRQ */
> -	coda_read(dev, CODA_REG_BIT_INT_STATUS);
> -	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
> -		      CODA_REG_BIT_INT_CLEAR);
> -
> -	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
> -	if (ctx == NULL) {
> -		v4l2_err(&dev->v4l2_dev, "Instance released before the end
> of transaction\n");
> -		mutex_unlock(&dev->coda_mutex);
> -		return IRQ_HANDLED;
> -	}
> -
> -	if (ctx->aborting) {
> -		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
> -			 "task has been aborted\n");
> -	}
> -
> -	if (coda_isbusy(ctx->dev)) {
> -		v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
> -			 "coda is still busy!!!!\n");
> -		return IRQ_NONE;
> -	}
> -
> -	complete(&ctx->completion);
> -
> -	return IRQ_HANDLED;
> -}
> -
> -static u32 coda_supported_firmwares[] = {
> -	CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
> -	CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
> -	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
> -};
> -
> -static bool coda_firmware_supported(u32 vernum)
> -{
> -	int i;
> -
> -	for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++)
> -		if (vernum == coda_supported_firmwares[i])
> -			return true;
> -	return false;
> -}
> -
>  static int coda_hw_init(struct coda_dev *dev)
>  {
>  	u32 data;
> @@ -3346,76 +1611,6 @@ err_clk_per:
>  	return ret;
>  }
> 
> -static int coda_check_firmware(struct coda_dev *dev)
> -{
> -	u16 product, major, minor, release;
> -	u32 data;
> -	int ret;
> -
> -	ret = clk_prepare_enable(dev->clk_per);
> -	if (ret)
> -		goto err_clk_per;
> -
> -	ret = clk_prepare_enable(dev->clk_ahb);
> -	if (ret)
> -		goto err_clk_ahb;
> -
> -	coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
> -	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
> -	coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
> -	coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
> -	coda_write(dev, CODA_COMMAND_FIRMWARE_GET,
> CODA_REG_BIT_RUN_COMMAND);
> -	if (coda_wait_timeout(dev)) {
> -		v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
> -		ret = -EIO;
> -		goto err_run_cmd;
> -	}
> -
> -	if (dev->devtype->product == CODA_960) {
> -		data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
> -		v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
> -			  data);
> -	}
> -
> -	/* Check we are compatible with the loaded firmware */
> -	data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM);
> -	product = CODA_FIRMWARE_PRODUCT(data);
> -	major = CODA_FIRMWARE_MAJOR(data);
> -	minor = CODA_FIRMWARE_MINOR(data);
> -	release = CODA_FIRMWARE_RELEASE(data);
> -
> -	clk_disable_unprepare(dev->clk_per);
> -	clk_disable_unprepare(dev->clk_ahb);
> -
> -	if (product != dev->devtype->product) {
> -		v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s,"
> -			 " Version: %u.%u.%u\n",
> -			 coda_product_name(dev->devtype->product),
> -			 coda_product_name(product), major, minor, release);
> -		return -EINVAL;
> -	}
> -
> -	v4l2_info(&dev->v4l2_dev, "Initialized %s.\n",
> -		  coda_product_name(product));
> -
> -	if (coda_firmware_supported(data)) {
> -		v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n",
> -			  major, minor, release);
> -	} else {
> -		v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: "
> -			  "%u.%u.%u\n", major, minor, release);
> -	}
> -
> -	return 0;
> -
> -err_run_cmd:
> -	clk_disable_unprepare(dev->clk_ahb);
> -err_clk_ahb:
> -	clk_disable_unprepare(dev->clk_per);
> -err_clk_per:
> -	return ret;
> -}
> -
>  static int coda_register_device(struct coda_dev *dev, struct
> video_device *vfd)
>  {
>  	vfd->release	= video_device_release_empty,
> diff --git a/drivers/media/platform/coda/coda.h
> b/drivers/media/platform/coda/coda.h
> index 84e0829..bbc18c0 100644
> --- a/drivers/media/platform/coda/coda.h
> +++ b/drivers/media/platform/coda/coda.h
> @@ -228,4 +228,60 @@ struct coda_ctx {
>  	struct dentry			*debugfs_entry;
>  };
> 
> +extern int coda_debug;
> +
> +void coda_write(struct coda_dev *dev, u32 data, u32 reg);
> +unsigned int coda_read(struct coda_dev *dev, u32 reg);
> +
> +int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
> +		       size_t size, const char *name, struct dentry
> *parent);
> +void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf
> *buf);
> +
> +static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
> +					 struct coda_aux_buf *buf, size_t
size,
> +					 const char *name)
> +{
> +	return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx-
> >debugfs_entry);
> +}
> +
> +int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq);
> +int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq);
> +
> +int coda_hw_reset(struct coda_ctx *ctx);
> +
> +void coda_fill_bitstream(struct coda_ctx *ctx);
> +
> +void coda_set_gdi_regs(struct coda_ctx *ctx);
> +
> +static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx,
> +					     enum v4l2_buf_type type)
> +{
> +	switch (type) {
> +	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
> +		return &(ctx->q_data[V4L2_M2M_SRC]);
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> +		return &(ctx->q_data[V4L2_M2M_DST]);
> +	default:
> +		return NULL;
> +	}
> +}
> +
> +const char *coda_product_name(int product);
> +
> +int coda_check_firmware(struct coda_dev *dev);
> +
> +static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
> +{
> +	return kfifo_len(&ctx->bitstream_fifo);
> +}
> +
> +void coda_bit_stream_end_flag(struct coda_ctx *ctx);
> +
>  int coda_h264_padding(int size, char *p);
> +
> +extern const struct coda_context_ops coda_bit_encode_ops;
> +extern const struct coda_context_ops coda_bit_decode_ops;
> +
> +irqreturn_t coda_irq_handler(int irq, void *data);
> --
> 2.0.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux