All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Split CODA driver into multiple files
@ 2014-07-23 15:28 Philipp Zabel
  2014-07-23 15:28 ` [PATCH 1/8] [media] coda: move coda driver into its own directory Philipp Zabel
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

Hi,

Hans suggested to split the CODA driver, so this series moves it into
its own subdirectory and splits it roughly in half by moving the BIT
processor handling and H.264 specific helper function out into their
own files.
The coda-bit.c will get its coda-jpeg.c counterpart in the future
for JPEG encoding and decoding on i.MX6.

regards
Philipp

Philipp Zabel (8):
  [media] coda: move coda driver into its own directory
  [media] coda: move defines, enums, and structs into shared header
  [media] coda: add context ops
  [media] coda: move BIT processor command execution out of pic_run_work
  [media] coda: add coda_bit_stream_set_flag helper
  [media] coda: move per-instance buffer allocation and cleanup
  [media] coda: move H.264 helper function into separate file
  [media] coda: move BIT specific functions into separate file

 drivers/media/platform/Makefile                    |    2 +-
 drivers/media/platform/coda.c                      | 4000 --------------------
 drivers/media/platform/coda/Makefile               |    3 +
 drivers/media/platform/coda/coda-bit.c             | 1810 +++++++++
 drivers/media/platform/coda/coda-common.c          | 2003 ++++++++++
 drivers/media/platform/coda/coda-h264.c            |   36 +
 drivers/media/platform/coda/coda.h                 |  287 ++
 .../media/platform/{coda.h => coda/coda_regs.h}    |    0
 8 files changed, 4140 insertions(+), 4001 deletions(-)
 delete mode 100644 drivers/media/platform/coda.c
 create mode 100644 drivers/media/platform/coda/Makefile
 create mode 100644 drivers/media/platform/coda/coda-bit.c
 create mode 100644 drivers/media/platform/coda/coda-common.c
 create mode 100644 drivers/media/platform/coda/coda-h264.c
 create mode 100644 drivers/media/platform/coda/coda.h
 rename drivers/media/platform/{coda.h => coda/coda_regs.h} (100%)

-- 
2.0.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/8] [media] coda: move coda driver into its own directory
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-07-23 15:28 ` [PATCH 2/8] [media] coda: move defines, enums, and structs into shared header Philipp Zabel
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

The coda driver has grown significantly and will continue to grow.
Move the coda driver into its own directory so it can be split.
Rename coda.h to coda_regs.h as it contains the register defines.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/Makefile                       | 2 +-
 drivers/media/platform/coda/Makefile                  | 3 +++
 drivers/media/platform/{coda.c => coda/coda-common.c} | 2 +-
 drivers/media/platform/{coda.h => coda/coda_regs.h}   | 0
 4 files changed, 5 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/platform/coda/Makefile
 rename drivers/media/platform/{coda.c => coda/coda-common.c} (99%)
 rename drivers/media/platform/{coda.h => coda/coda_regs.h} (100%)

diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index e5269da..4ac4c91 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
 obj-$(CONFIG_VIDEO_TI_VPE)		+= ti-vpe/
 
 obj-$(CONFIG_VIDEO_MX2_EMMAPRP)		+= mx2_emmaprp.o
-obj-$(CONFIG_VIDEO_CODA) 		+= coda.o
+obj-$(CONFIG_VIDEO_CODA) 		+= coda/
 
 obj-$(CONFIG_VIDEO_SH_VEU)		+= sh_veu.o
 
diff --git a/drivers/media/platform/coda/Makefile b/drivers/media/platform/coda/Makefile
new file mode 100644
index 0000000..13d9ad6
--- /dev/null
+++ b/drivers/media/platform/coda/Makefile
@@ -0,0 +1,3 @@
+coda-objs := coda-common.o
+
+obj-$(CONFIG_VIDEO_CODA) += coda.o
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda/coda-common.c
similarity index 99%
rename from drivers/media/platform/coda.c
rename to drivers/media/platform/coda/coda-common.c
index 3edbef6..1f68201 100644
--- a/drivers/media/platform/coda.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -38,7 +38,7 @@
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
 
-#include "coda.h"
+#include "coda_regs.h"
 
 #define CODA_NAME		"coda"
 
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda/coda_regs.h
similarity index 100%
rename from drivers/media/platform/coda.h
rename to drivers/media/platform/coda/coda_regs.h
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/8] [media] coda: move defines, enums, and structs into shared header
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
  2014-07-23 15:28 ` [PATCH 1/8] [media] coda: move coda driver into its own directory Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-07-23 15:28 ` [PATCH 3/8] [media] coda: add context ops Philipp Zabel
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

These will have to be shared between multiple code files.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 193 +-------------------------
 drivers/media/platform/coda/coda.h        | 216 ++++++++++++++++++++++++++++++
 2 files changed, 219 insertions(+), 190 deletions(-)
 create mode 100644 drivers/media/platform/coda/coda.h

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 1f68201..4649395 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -38,6 +38,7 @@
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
 
+#include "coda.h"
 #include "coda_regs.h"
 
 #define CODA_NAME		"coda"
@@ -50,10 +51,6 @@
 #define CODA7_PS_BUF_SIZE	0x28000
 #define CODA9_PS_SAVE_SIZE	(512 * 1024)
 
-#define CODA_MAX_FRAMEBUFFERS	8
-
-#define CODA_MAX_FRAME_SIZE	0x100000
-#define FMO_SLICE_SAVE_BUF_SIZE         (32)
 #define CODA_DEFAULT_GAMMA		4096
 #define CODA9_DEFAULT_GAMMA		24576	/* 0.75 * 32768 */
 
@@ -70,207 +67,23 @@ static int coda_debug;
 module_param(coda_debug, int, 0644);
 MODULE_PARM_DESC(coda_debug, "Debug level (0-1)");
 
-enum {
-	V4L2_M2M_SRC = 0,
-	V4L2_M2M_DST = 1,
-};
-
-enum coda_inst_type {
-	CODA_INST_ENCODER,
-	CODA_INST_DECODER,
-};
-
-enum coda_product {
-	CODA_DX6 = 0xf001,
-	CODA_7541 = 0xf012,
-	CODA_960 = 0xf020,
-};
-
 struct coda_fmt {
 	char *name;
 	u32 fourcc;
 };
 
-struct coda_codec {
-	u32 mode;
-	u32 src_fourcc;
-	u32 dst_fourcc;
-	u32 max_w;
-	u32 max_h;
-};
-
-struct coda_devtype {
-	char			*firmware;
-	enum coda_product	product;
-	const struct coda_codec	*codecs;
-	unsigned int		num_codecs;
-	size_t			workbuf_size;
-	size_t			tempbuf_size;
-	size_t			iram_size;
-};
-
-/* Per-queue, driver-specific private data */
-struct coda_q_data {
-	unsigned int		width;
-	unsigned int		height;
-	unsigned int		bytesperline;
-	unsigned int		sizeimage;
-	unsigned int		fourcc;
-	struct v4l2_rect	rect;
-};
-
-struct coda_aux_buf {
-	void			*vaddr;
-	dma_addr_t		paddr;
-	u32			size;
-	struct debugfs_blob_wrapper blob;
-	struct dentry		*dentry;
-};
-
-struct coda_dev {
-	struct v4l2_device	v4l2_dev;
-	struct video_device	vfd[2];
-	struct platform_device	*plat_dev;
-	const struct coda_devtype *devtype;
-
-	void __iomem		*regs_base;
-	struct clk		*clk_per;
-	struct clk		*clk_ahb;
-	struct reset_control	*rstc;
-
-	struct coda_aux_buf	codebuf;
-	struct coda_aux_buf	tempbuf;
-	struct coda_aux_buf	workbuf;
-	struct gen_pool		*iram_pool;
-	struct coda_aux_buf	iram;
-
-	spinlock_t		irqlock;
-	struct mutex		dev_mutex;
-	struct mutex		coda_mutex;
-	struct workqueue_struct	*workqueue;
-	struct v4l2_m2m_dev	*m2m_dev;
-	struct vb2_alloc_ctx	*alloc_ctx;
-	struct list_head	instances;
-	unsigned long		instance_mask;
-	struct dentry		*debugfs_root;
-};
-
-struct coda_params {
-	u8			rot_mode;
-	u8			h264_intra_qp;
-	u8			h264_inter_qp;
-	u8			h264_min_qp;
-	u8			h264_max_qp;
-	u8			h264_deblk_enabled;
-	u8			h264_deblk_alpha;
-	u8			h264_deblk_beta;
-	u8			mpeg4_intra_qp;
-	u8			mpeg4_inter_qp;
-	u8			gop_size;
-	int			intra_refresh;
-	int			codec_mode;
-	int			codec_mode_aux;
-	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
-	u32			framerate;
-	u16			bitrate;
-	u32			slice_max_bits;
-	u32			slice_max_mb;
-};
-
-struct coda_iram_info {
-	u32		axi_sram_use;
-	phys_addr_t	buf_bit_use;
-	phys_addr_t	buf_ip_ac_dc_use;
-	phys_addr_t	buf_dbk_y_use;
-	phys_addr_t	buf_dbk_c_use;
-	phys_addr_t	buf_ovl_use;
-	phys_addr_t	buf_btp_use;
-	phys_addr_t	search_ram_paddr;
-	int		search_ram_size;
-	int		remaining;
-	phys_addr_t	next_paddr;
-};
-
-struct gdi_tiled_map {
-	int xy2ca_map[16];
-	int xy2ba_map[16];
-	int xy2ra_map[16];
-	int rbc2axi_map[32];
-	int xy2rbc_config;
-	int map_type;
-#define GDI_LINEAR_FRAME_MAP 0
-};
-
-struct coda_timestamp {
-	struct list_head	list;
-	u32			sequence;
-	struct v4l2_timecode	timecode;
-	struct timeval		timestamp;
-};
-
-struct coda_ctx {
-	struct coda_dev			*dev;
-	struct mutex			buffer_mutex;
-	struct list_head		list;
-	struct work_struct		pic_run_work;
-	struct work_struct		seq_end_work;
-	struct completion		completion;
-	int				aborting;
-	int				initialized;
-	int				streamon_out;
-	int				streamon_cap;
-	u32				isequence;
-	u32				qsequence;
-	u32				osequence;
-	u32				sequence_offset;
-	struct coda_q_data		q_data[2];
-	enum coda_inst_type		inst_type;
-	const struct coda_codec		*codec;
-	enum v4l2_colorspace		colorspace;
-	struct coda_params		params;
-	struct v4l2_ctrl_handler	ctrls;
-	struct v4l2_fh			fh;
-	int				gopcounter;
-	int				runcounter;
-	char				vpu_header[3][64];
-	int				vpu_header_size[3];
-	struct kfifo			bitstream_fifo;
-	struct mutex			bitstream_mutex;
-	struct coda_aux_buf		bitstream;
-	bool				hold;
-	struct coda_aux_buf		parabuf;
-	struct coda_aux_buf		psbuf;
-	struct coda_aux_buf		slicebuf;
-	struct coda_aux_buf		internal_frames[CODA_MAX_FRAMEBUFFERS];
-	u32				frame_types[CODA_MAX_FRAMEBUFFERS];
-	struct coda_timestamp		frame_timestamps[CODA_MAX_FRAMEBUFFERS];
-	u32				frame_errors[CODA_MAX_FRAMEBUFFERS];
-	struct list_head		timestamp_list;
-	struct coda_aux_buf		workbuf;
-	int				num_internal_frames;
-	int				idx;
-	int				reg_idx;
-	struct coda_iram_info		iram_info;
-	struct gdi_tiled_map		tiled_map;
-	u32				bit_stream_param;
-	u32				frm_dis_flg;
-	u32				frame_mem_ctrl;
-	int				display_idx;
-	struct dentry			*debugfs_entry;
-};
-
 static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
 static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
 
-static inline void coda_write(struct coda_dev *dev, u32 data, u32 reg)
+void coda_write(struct coda_dev *dev, u32 data, u32 reg)
 {
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
 		 "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
 	writel(data, dev->regs_base + reg);
 }
 
-static inline unsigned int coda_read(struct coda_dev *dev, u32 reg)
+unsigned int coda_read(struct coda_dev *dev, u32 reg)
 {
 	u32 data;
 	data = readl(dev->regs_base + reg);
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
new file mode 100644
index 0000000..aafd186
--- /dev/null
+++ b/drivers/media/platform/coda/coda.h
@@ -0,0 +1,216 @@
+/*
+ * Coda multi-standard codec IP
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    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/debugfs.h>
+#include <linux/irqreturn.h>
+#include <linux/mutex.h>
+#include <linux/kfifo.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-core.h>
+
+#include "coda_regs.h"
+
+#define CODA_MAX_FRAMEBUFFERS	8
+#define CODA_MAX_FRAME_SIZE	0x100000
+#define FMO_SLICE_SAVE_BUF_SIZE	(32)
+
+enum {
+	V4L2_M2M_SRC = 0,
+	V4L2_M2M_DST = 1,
+};
+
+enum coda_inst_type {
+	CODA_INST_ENCODER,
+	CODA_INST_DECODER,
+};
+
+enum coda_product {
+	CODA_DX6 = 0xf001,
+	CODA_7541 = 0xf012,
+	CODA_960 = 0xf020,
+};
+
+struct coda_devtype {
+	char			*firmware;
+	enum coda_product	product;
+	const struct coda_codec	*codecs;
+	unsigned int		num_codecs;
+	size_t			workbuf_size;
+	size_t			tempbuf_size;
+	size_t			iram_size;
+};
+
+struct coda_aux_buf {
+	void			*vaddr;
+	dma_addr_t		paddr;
+	u32			size;
+	struct debugfs_blob_wrapper blob;
+	struct dentry		*dentry;
+};
+
+struct coda_dev {
+	struct v4l2_device	v4l2_dev;
+	struct video_device	vfd[2];
+	struct platform_device	*plat_dev;
+	const struct coda_devtype *devtype;
+
+	void __iomem		*regs_base;
+	struct clk		*clk_per;
+	struct clk		*clk_ahb;
+	struct reset_control	*rstc;
+
+	struct coda_aux_buf	codebuf;
+	struct coda_aux_buf	tempbuf;
+	struct coda_aux_buf	workbuf;
+	struct gen_pool		*iram_pool;
+	struct coda_aux_buf	iram;
+
+	spinlock_t		irqlock;
+	struct mutex		dev_mutex;
+	struct mutex		coda_mutex;
+	struct workqueue_struct	*workqueue;
+	struct v4l2_m2m_dev	*m2m_dev;
+	struct vb2_alloc_ctx	*alloc_ctx;
+	struct list_head	instances;
+	unsigned long		instance_mask;
+	struct dentry		*debugfs_root;
+};
+
+struct coda_codec {
+	u32 mode;
+	u32 src_fourcc;
+	u32 dst_fourcc;
+	u32 max_w;
+	u32 max_h;
+};
+
+struct coda_huff_tab;
+
+struct coda_params {
+	u8			rot_mode;
+	u8			h264_intra_qp;
+	u8			h264_inter_qp;
+	u8			h264_min_qp;
+	u8			h264_max_qp;
+	u8			h264_deblk_enabled;
+	u8			h264_deblk_alpha;
+	u8			h264_deblk_beta;
+	u8			mpeg4_intra_qp;
+	u8			mpeg4_inter_qp;
+	u8			gop_size;
+	int			intra_refresh;
+	int			codec_mode;
+	int			codec_mode_aux;
+	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+	u32			framerate;
+	u16			bitrate;
+	u32			slice_max_bits;
+	u32			slice_max_mb;
+};
+
+struct coda_timestamp {
+	struct list_head	list;
+	u32			sequence;
+	struct v4l2_timecode	timecode;
+	struct timeval		timestamp;
+};
+
+/* Per-queue, driver-specific private data */
+struct coda_q_data {
+	unsigned int		width;
+	unsigned int		height;
+	unsigned int		bytesperline;
+	unsigned int		sizeimage;
+	unsigned int		fourcc;
+	struct v4l2_rect	rect;
+};
+
+struct coda_iram_info {
+	u32		axi_sram_use;
+	phys_addr_t	buf_bit_use;
+	phys_addr_t	buf_ip_ac_dc_use;
+	phys_addr_t	buf_dbk_y_use;
+	phys_addr_t	buf_dbk_c_use;
+	phys_addr_t	buf_ovl_use;
+	phys_addr_t	buf_btp_use;
+	phys_addr_t	search_ram_paddr;
+	int		search_ram_size;
+	int		remaining;
+	phys_addr_t	next_paddr;
+};
+
+struct gdi_tiled_map {
+	int xy2ca_map[16];
+	int xy2ba_map[16];
+	int xy2ra_map[16];
+	int rbc2axi_map[32];
+	int xy2rbc_config;
+	int map_type;
+#define GDI_LINEAR_FRAME_MAP 0
+};
+
+struct coda_ctx {
+	struct coda_dev			*dev;
+	struct mutex			buffer_mutex;
+	struct list_head		list;
+	struct work_struct		pic_run_work;
+	struct work_struct		seq_end_work;
+	struct completion		completion;
+	int				aborting;
+	int				initialized;
+	int				streamon_out;
+	int				streamon_cap;
+	u32				isequence;
+	u32				qsequence;
+	u32				osequence;
+	u32				sequence_offset;
+	struct coda_q_data		q_data[2];
+	enum coda_inst_type		inst_type;
+	const struct coda_codec		*codec;
+	enum v4l2_colorspace		colorspace;
+	struct coda_params		params;
+	struct v4l2_ctrl_handler	ctrls;
+	struct v4l2_fh			fh;
+	int				gopcounter;
+	int				runcounter;
+	char				vpu_header[3][64];
+	int				vpu_header_size[3];
+	struct kfifo			bitstream_fifo;
+	struct mutex			bitstream_mutex;
+	struct coda_aux_buf		bitstream;
+	bool				hold;
+	struct coda_aux_buf		parabuf;
+	struct coda_aux_buf		psbuf;
+	struct coda_aux_buf		slicebuf;
+	struct coda_aux_buf		internal_frames[CODA_MAX_FRAMEBUFFERS];
+	u32				frame_types[CODA_MAX_FRAMEBUFFERS];
+	struct coda_timestamp		frame_timestamps[CODA_MAX_FRAMEBUFFERS];
+	u32				frame_errors[CODA_MAX_FRAMEBUFFERS];
+	struct list_head		timestamp_list;
+	struct coda_aux_buf		workbuf;
+	int				num_internal_frames;
+	int				idx;
+	int				reg_idx;
+	struct coda_iram_info		iram_info;
+	struct gdi_tiled_map		tiled_map;
+	u32				bit_stream_param;
+	u32				frm_dis_flg;
+	u32				frame_mem_ctrl;
+	int				display_idx;
+	struct dentry			*debugfs_entry;
+};
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/8] [media] coda: add context ops
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
  2014-07-23 15:28 ` [PATCH 1/8] [media] coda: move coda driver into its own directory Philipp Zabel
  2014-07-23 15:28 ` [PATCH 2/8] [media] coda: move defines, enums, and structs into shared header Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-07-23 15:28 ` [PATCH 4/8] [media] coda: move BIT processor command execution out of pic_run_work Philipp Zabel
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

Add a struct coda_context_ops that encapsulates context specific operations.
This will simplify adding JPEG support in the future and helps to avoid
exporting all functions individually when they move out of the main code
file.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 85 ++++++++++++++++++-------------
 drivers/media/platform/coda/coda.h        | 13 +++++
 2 files changed, 63 insertions(+), 35 deletions(-)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 4649395..ecab30a 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -802,7 +802,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 int __coda_start_decoding(struct coda_ctx *ctx);
 
 static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
 {
@@ -978,7 +978,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 
 	/* Run coda_start_decoding (again) if not yet initialized */
 	if (!ctx->initialized) {
-		int ret = coda_start_decoding(ctx);
+		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);
@@ -1043,7 +1043,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 	return 0;
 }
 
-static void coda_prepare_encode(struct coda_ctx *ctx)
+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;
@@ -1185,6 +1185,8 @@ static void coda_prepare_encode(struct coda_ctx *ctx)
 		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
 		coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
 	}
+
+	return 0;
 }
 
 static void coda_device_run(void *m2m_priv)
@@ -1235,16 +1237,12 @@ static void coda_pic_run_work(struct work_struct *work)
 	mutex_lock(&ctx->buffer_mutex);
 	mutex_lock(&dev->coda_mutex);
 
-	if (ctx->inst_type == CODA_INST_DECODER) {
-		ret = coda_prepare_decode(ctx);
-		if (ret < 0) {
-			mutex_unlock(&dev->coda_mutex);
-			mutex_unlock(&ctx->buffer_mutex);
-			/* job_finish scheduled by prepare_decode */
-			return;
-		}
-	} else {
-		coda_prepare_encode(ctx);
+	ret = ctx->ops->prepare_run(ctx);
+	if (ret < 0 && ctx->inst_type == CODA_INST_DECODER) {
+		mutex_unlock(&dev->coda_mutex);
+		mutex_unlock(&ctx->buffer_mutex);
+		/* job_finish scheduled by prepare_decode */
+		return;
 	}
 
 	if (dev->devtype->product != CODA_DX6)
@@ -1262,10 +1260,7 @@ static void coda_pic_run_work(struct work_struct *work)
 
 		coda_hw_reset(ctx);
 	} else if (!ctx->aborting) {
-		if (ctx->inst_type == CODA_INST_DECODER)
-			coda_finish_decode(ctx);
-		else
-			coda_finish_encode(ctx);
+		ctx->ops->finish_run(ctx);
 	}
 
 	if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out))
@@ -1848,7 +1843,7 @@ err:
 	return ret;
 }
 
-static int coda_start_decoding(struct coda_ctx *ctx)
+static int __coda_start_decoding(struct coda_ctx *ctx)
 {
 	struct coda_q_data *q_data_src, *q_data_dst;
 	u32 bitstream_buf, bitstream_size;
@@ -2039,6 +2034,18 @@ static int coda_start_decoding(struct coda_ctx *ctx)
 	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)
 {
@@ -2083,7 +2090,6 @@ 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_dev *dev = ctx->dev;
 	struct coda_q_data *q_data_src, *q_data_dst;
 	u32 dst_fourcc;
 	int ret = 0;
@@ -2135,16 +2141,12 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 	if (ret < 0)
 		return ret;
 
+	ret = ctx->ops->start_streaming(ctx);
 	if (ctx->inst_type == CODA_INST_DECODER) {
-		mutex_lock(&dev->coda_mutex);
-		ret = coda_start_decoding(ctx);
-		mutex_unlock(&dev->coda_mutex);
 		if (ret == -EAGAIN)
 			return 0;
 		else if (ret < 0)
 			return ret;
-	} else {
-		ret = coda_start_encoding(ctx);
 	}
 
 	ctx->initialized = 1;
@@ -2739,10 +2741,9 @@ static int coda_next_free_instance(struct coda_dev *dev)
 	return idx;
 }
 
-static int coda_open(struct file *file, enum coda_inst_type inst_type)
+static int coda_open(struct file *file, enum coda_inst_type inst_type,
+		     const struct coda_context_ops *ctx_ops)
 {
-	int (*queue_init)(void *priv, struct vb2_queue *src_vq,
-			  struct vb2_queue *dst_vq);
 	struct coda_dev *dev = video_drvdata(file);
 	struct coda_ctx *ctx = NULL;
 	char *name;
@@ -2765,9 +2766,10 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type)
 	kfree(name);
 
 	ctx->inst_type = inst_type;
+	ctx->ops = ctx_ops;
 	init_completion(&ctx->completion);
 	INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
-	INIT_WORK(&ctx->seq_end_work, coda_seq_end_work);
+	INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
 	v4l2_fh_init(&ctx->fh, video_devdata(file));
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
@@ -2798,11 +2800,8 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type)
 		goto err_clk_ahb;
 
 	set_default_params(ctx);
-	if (inst_type == CODA_INST_ENCODER)
-		queue_init = coda_encoder_queue_init;
-	else
-		queue_init = coda_decoder_queue_init;
-	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, queue_init);
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+					    ctx->ops->queue_init);
 	if (IS_ERR(ctx->fh.m2m_ctx)) {
 		ret = PTR_ERR(ctx->fh.m2m_ctx);
 
@@ -2873,14 +2872,30 @@ err_coda_max:
 	return ret;
 }
 
+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,
+};
+
+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
+};
+
 static int coda_encoder_open(struct file *file)
 {
-	return coda_open(file, CODA_INST_ENCODER);
+	return coda_open(file, CODA_INST_ENCODER, &coda_encode_ops);
 }
 
 static int coda_decoder_open(struct file *file)
 {
-	return coda_open(file, CODA_INST_DECODER);
+	return coda_open(file, CODA_INST_DECODER, &coda_decode_ops);
 }
 
 static int coda_release(struct file *file)
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index aafd186..c98270c 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -164,6 +164,18 @@ struct gdi_tiled_map {
 #define GDI_LINEAR_FRAME_MAP 0
 };
 
+struct coda_ctx;
+
+struct coda_context_ops {
+	int (*queue_init)(void *priv, struct vb2_queue *src_vq,
+			  struct vb2_queue *dst_vq);
+	int (*start_streaming)(struct coda_ctx *ctx);
+	int (*prepare_run)(struct coda_ctx *ctx);
+	void (*finish_run)(struct coda_ctx *ctx);
+	void (*seq_end_work)(struct work_struct *work);
+	void (*release)(struct coda_ctx *ctx);
+};
+
 struct coda_ctx {
 	struct coda_dev			*dev;
 	struct mutex			buffer_mutex;
@@ -171,6 +183,7 @@ struct coda_ctx {
 	struct work_struct		pic_run_work;
 	struct work_struct		seq_end_work;
 	struct completion		completion;
+	const struct coda_context_ops	*ops;
 	int				aborting;
 	int				initialized;
 	int				streamon_out;
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/8] [media] coda: move BIT processor command execution out of pic_run_work
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
                   ` (2 preceding siblings ...)
  2014-07-23 15:28 ` [PATCH 3/8] [media] coda: add context ops Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-07-23 15:28 ` [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper Philipp Zabel
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

In preparation for the split, move the AXI_SRAM_USE register access and the
PIC_RUN command execution out of pic_run_work into prepare_encode/decode.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index ecab30a..04a7b12 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1040,6 +1040,13 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 	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;
 }
 
@@ -1186,6 +1193,12 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
 		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;
 }
 
@@ -1245,14 +1258,6 @@ static void coda_pic_run_work(struct work_struct *work)
 		return;
 	}
 
-	if (dev->devtype->product != CODA_DX6)
-		coda_write(dev, ctx->iram_info.axi_sram_use,
-				CODA7_REG_BIT_AXI_SRAM_USE);
-
-	if (ctx->inst_type == CODA_INST_DECODER)
-		coda_kfifo_sync_to_device_full(ctx);
-	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
-
 	if (!wait_for_completion_timeout(&ctx->completion, msecs_to_jiffies(1000))) {
 		dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout\n");
 
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
                   ` (3 preceding siblings ...)
  2014-07-23 15:28 ` [PATCH 4/8] [media] coda: move BIT processor command execution out of pic_run_work Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-08-05 15:39   ` Kamil Debski
  2014-07-23 15:28 ` [PATCH 6/8] [media] coda: move per-instance buffer allocation and cleanup Philipp Zabel
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

This adds a helper function to consolidate three occurences where
the bitstream parameter stream end flag is set during operation.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 52 +++++++++++--------------------
 1 file changed, 19 insertions(+), 33 deletions(-)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 04a7b12..547744a 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -187,6 +187,20 @@ static int coda_hw_reset(struct coda_ctx *ctx)
 	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)
 {
@@ -732,7 +746,6 @@ static int coda_decoder_cmd(struct file *file, void *fh,
 			    struct v4l2_decoder_cmd *dc)
 {
 	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct coda_dev *dev = ctx->dev;
 	int ret;
 
 	ret = coda_try_decoder_cmd(file, fh, dc);
@@ -743,15 +756,8 @@ static int coda_decoder_cmd(struct file *file, void *fh,
 	if (ctx->inst_type != CODA_INST_DECODER)
 		return 0;
 
-	/* Set the strem-end flag on this context */
-	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);
-	}
+	/* Set the stream-end flag on this context */
+	coda_bit_stream_end_flag(ctx);
 	ctx->hold = false;
 	v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
 
@@ -1474,7 +1480,6 @@ static int coda_buf_prepare(struct vb2_buffer *vb)
 static void coda_buf_queue(struct vb2_buffer *vb)
 {
 	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct coda_dev *dev = ctx->dev;
 	struct coda_q_data *q_data;
 
 	q_data = get_q_data(ctx, vb->vb2_queue->type);
@@ -1489,15 +1494,8 @@ static void coda_buf_queue(struct vb2_buffer *vb)
 		 * For backwards compatibility, queuing an empty buffer marks
 		 * the stream end
 		 */
-		if (vb2_get_plane_payload(vb, 0) == 0) {
-			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 decoder instance is running, set the stream end flag */
-				coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
-			}
-		}
+		if (vb2_get_plane_payload(vb, 0) == 0)
+			coda_bit_stream_end_flag(ctx);
 		mutex_lock(&ctx->bitstream_mutex);
 		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 		if (vb2_is_streaming(vb->vb2_queue))
@@ -2494,19 +2492,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
 			 "%s: output\n", __func__);
 		ctx->streamon_out = 0;
 
-		if (ctx->inst_type == CODA_INST_DECODER &&
-		    coda_isbusy(dev) && ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX)) {
-			/* if this decoder instance is running, set the stream end flag */
-			if (dev->devtype->product == CODA_960) {
-				u32 val = coda_read(dev, CODA_REG_BIT_BIT_STREAM_PARAM);
-
-				val |= CODA_BIT_STREAM_END_FLAG;
-				coda_write(dev, val, CODA_REG_BIT_BIT_STREAM_PARAM);
-				ctx->bit_stream_param = val;
-			}
-		}
-		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
-
+		coda_bit_stream_end_flag(ctx);
 		ctx->isequence = 0;
 	} else {
 		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/8] [media] coda: move per-instance buffer allocation and cleanup
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
                   ` (4 preceding siblings ...)
  2014-07-23 15:28 ` [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-07-23 15:28 ` [PATCH 7/8] [media] coda: move H.264 helper function into separate file Philipp Zabel
  2014-07-23 15:28 ` [PATCH 8/8] [media] coda: move BIT specific functions " Philipp Zabel
  7 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

This patch moves the context buffer allocation into the context start_streaming
callbacks. The context buffer and internal framebuffer cleanup is moved into
the context release callback.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/coda/coda-common.c | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 547744a..df0470e 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1863,6 +1863,11 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
 	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 */
@@ -2139,11 +2144,6 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
 		return -EINVAL;
 	}
 
-	/* Allocate per-instance buffers */
-	ret = coda_alloc_context_buffers(ctx, q_data_src);
-	if (ret < 0)
-		return ret;
-
 	ret = ctx->ops->start_streaming(ctx);
 	if (ctx->inst_type == CODA_INST_DECODER) {
 		if (ret == -EAGAIN)
@@ -2170,6 +2170,11 @@ static int coda_start_encoding(struct coda_ctx *ctx)
 	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;
@@ -2840,7 +2845,6 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type,
 	return 0;
 
 err_dma_writecombine:
-	coda_free_context_buffers(ctx);
 	if (ctx->dev->devtype->product == CODA_DX6)
 		coda_free_aux_buf(dev, &ctx->workbuf);
 	coda_free_aux_buf(dev, &ctx->parabuf);
@@ -2863,12 +2867,19 @@ 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 = {
@@ -2876,7 +2887,8 @@ struct coda_context_ops coda_decode_ops = {
 	.start_streaming = coda_start_decoding,
 	.prepare_run = coda_prepare_decode,
 	.finish_run = coda_finish_decode,
-	.seq_end_work = coda_seq_end_work
+	.seq_end_work = coda_seq_end_work,
+	.release = coda_bit_release,
 };
 
 static int coda_encoder_open(struct file *file)
@@ -2908,15 +2920,12 @@ static int coda_release(struct file *file)
 		flush_work(&ctx->seq_end_work);
 	}
 
-	coda_free_framebuffers(ctx);
-
 	coda_lock(ctx);
 	list_del(&ctx->list);
 	coda_unlock(ctx);
 
 	dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
 		ctx->bitstream.vaddr, ctx->bitstream.paddr);
-	coda_free_context_buffers(ctx);
 	if (ctx->dev->devtype->product == CODA_DX6)
 		coda_free_aux_buf(dev, &ctx->workbuf);
 
@@ -2928,6 +2937,8 @@ static int coda_release(struct file *file)
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	clear_bit(ctx->idx, &dev->instance_mask);
+	if (ctx->ops->release)
+		ctx->ops->release(ctx);
 	kfree(ctx);
 
 	return 0;
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/8] [media] coda: move H.264 helper function into separate file
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
                   ` (5 preceding siblings ...)
  2014-07-23 15:28 ` [PATCH 6/8] [media] coda: move per-instance buffer allocation and cleanup Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-07-23 15:28 ` [PATCH 8/8] [media] coda: move BIT specific functions " Philipp Zabel
  7 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

Currently there is only the coda_h264_padding function, but
we will have to add more H.264 specific helpers later.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 drivers/media/platform/coda/Makefile      |  2 +-
 drivers/media/platform/coda/coda-common.c | 22 -------------------
 drivers/media/platform/coda/coda-h264.c   | 36 +++++++++++++++++++++++++++++++
 drivers/media/platform/coda/coda.h        |  2 ++
 4 files changed, 39 insertions(+), 23 deletions(-)
 create mode 100644 drivers/media/platform/coda/coda-h264.c

diff --git a/drivers/media/platform/coda/Makefile b/drivers/media/platform/coda/Makefile
index 13d9ad6..0e59fbd 100644
--- a/drivers/media/platform/coda/Makefile
+++ b/drivers/media/platform/coda/Makefile
@@ -1,3 +1,3 @@
-coda-objs := coda-common.o
+coda-objs := coda-common.o coda-h264.o
 
 obj-$(CONFIG_VIDEO_CODA) += coda.o
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index df0470e..5226dea 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -72,10 +72,6 @@ struct coda_fmt {
 	u32 fourcc;
 };
 
-static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
-			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
-static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
-
 void coda_write(struct coda_dev *dev, u32 data, u32 reg)
 {
 	v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
@@ -1629,24 +1625,6 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d
 	return 0;
 }
 
-static int coda_h264_padding(int size, char *p)
-{
-	int nal_size;
-	int diff;
-
-	diff = size - (size & ~0x7);
-	if (diff == 0)
-		return 0;
-
-	nal_size = coda_filler_size[diff];
-	memcpy(p, coda_filler_nal, nal_size);
-
-	/* Add rbsp stop bit and trailing at the end */
-	*(p + nal_size - 1) = 0x80;
-
-	return nal_size;
-}
-
 static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size)
 {
 	phys_addr_t ret;
diff --git a/drivers/media/platform/coda/coda-h264.c b/drivers/media/platform/coda/coda-h264.c
new file mode 100644
index 0000000..0b2fdbe
--- /dev/null
+++ b/drivers/media/platform/coda/coda-h264.c
@@ -0,0 +1,36 @@
+/*
+ * Coda multi-standard codec IP - H.264 helper functions
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ *
+ * 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/kernel.h>
+
+static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
+static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
+
+int coda_h264_padding(int size, char *p)
+{
+	int nal_size;
+	int diff;
+
+	diff = size - (size & ~0x7);
+	if (diff == 0)
+		return 0;
+
+	nal_size = coda_filler_size[diff];
+	memcpy(p, coda_filler_nal, nal_size);
+
+	/* Add rbsp stop bit and trailing at the end */
+	*(p + nal_size - 1) = 0x80;
+
+	return nal_size;
+}
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index c98270c..84e0829 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -227,3 +227,5 @@ struct coda_ctx {
 	int				display_idx;
 	struct dentry			*debugfs_entry;
 };
+
+int coda_h264_padding(int size, char *p);
-- 
2.0.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 8/8] [media] coda: move BIT specific functions into separate file
  2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
                   ` (6 preceding siblings ...)
  2014-07-23 15:28 ` [PATCH 7/8] [media] coda: move H.264 helper function into separate file Philipp Zabel
@ 2014-07-23 15:28 ` Philipp Zabel
  2014-08-05 15:36   ` Kamil Debski
  7 siblings, 1 reply; 12+ messages in thread
From: Philipp Zabel @ 2014-07-23 15:28 UTC (permalink / raw)
  To: linux-media
  Cc: Mauro Carvalho Chehab, Kamil Debski, Fabio Estevam, Hans Verkuil,
	Nicolas Dufresne, kernel, Philipp Zabel

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@pengutronix.de>
---
 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@vista-silicon.com>
+ *    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


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* RE: [PATCH 8/8] [media] coda: move BIT specific functions into separate file
  2014-07-23 15:28 ` [PATCH 8/8] [media] coda: move BIT specific functions " Philipp Zabel
@ 2014-08-05 15:36   ` Kamil Debski
  2014-08-05 16:30     ` Philipp Zabel
  0 siblings, 1 reply; 12+ messages in thread
From: Kamil Debski @ 2014-08-05 15:36 UTC (permalink / raw)
  To: 'Philipp Zabel', linux-media
  Cc: 'Mauro Carvalho Chehab', 'Fabio Estevam',
	'Hans Verkuil', 'Nicolas Dufresne',
	kernel

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@pengutronix.de]
> Sent: Wednesday, July 23, 2014 5:29 PM
> To: linux-media@vger.kernel.org
> Cc: Mauro Carvalho Chehab; Kamil Debski; Fabio Estevam; Hans Verkuil;
> Nicolas Dufresne; kernel@pengutronix.de; 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@pengutronix.de>
> ---
>  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@vista-silicon.com>
> + *    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


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper
  2014-07-23 15:28 ` [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper Philipp Zabel
@ 2014-08-05 15:39   ` Kamil Debski
  0 siblings, 0 replies; 12+ messages in thread
From: Kamil Debski @ 2014-08-05 15:39 UTC (permalink / raw)
  To: 'Philipp Zabel', linux-media
  Cc: 'Mauro Carvalho Chehab', 'Fabio Estevam',
	'Hans Verkuil', 'Nicolas Dufresne',
	kernel

Checkpatch:
------------------------------
WARNING: line over 80 characters
#45: FILE: drivers/media/platform/coda/coda-common.c:199:
+		/* If this context is currently running, update the hardware
flag */

WARNING: line over 80 characters
#46: FILE: drivers/media/platform/coda/coda-common.c:200:
+		coda_write(dev, ctx->bit_stream_param,
CODA_REG_BIT_BIT_STREAM_PARAM);

-- 
Kamil Debski
Samsung R&D Institute Poland


> -----Original Message-----
> From: Philipp Zabel [mailto:p.zabel@pengutronix.de]
> Sent: Wednesday, July 23, 2014 5:29 PM
> To: linux-media@vger.kernel.org
> Cc: Mauro Carvalho Chehab; Kamil Debski; Fabio Estevam; Hans Verkuil;
> Nicolas Dufresne; kernel@pengutronix.de; Philipp Zabel
> Subject: [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper
> 
> This adds a helper function to consolidate three occurences where the
> bitstream parameter stream end flag is set during operation.
> 
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
>  drivers/media/platform/coda/coda-common.c | 52 +++++++++++------------
> --------
>  1 file changed, 19 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/media/platform/coda/coda-common.c
> b/drivers/media/platform/coda/coda-common.c
> index 04a7b12..547744a 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -187,6 +187,20 @@ static int coda_hw_reset(struct coda_ctx *ctx)
>  	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)
>  {
> @@ -732,7 +746,6 @@ static int coda_decoder_cmd(struct file *file, void
> *fh,
>  			    struct v4l2_decoder_cmd *dc)
>  {
>  	struct coda_ctx *ctx = fh_to_ctx(fh);
> -	struct coda_dev *dev = ctx->dev;
>  	int ret;
> 
>  	ret = coda_try_decoder_cmd(file, fh, dc); @@ -743,15 +756,8 @@
> static int coda_decoder_cmd(struct file *file, void *fh,
>  	if (ctx->inst_type != CODA_INST_DECODER)
>  		return 0;
> 
> -	/* Set the strem-end flag on this context */
> -	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);
> -	}
> +	/* Set the stream-end flag on this context */
> +	coda_bit_stream_end_flag(ctx);
>  	ctx->hold = false;
>  	v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
> 
> @@ -1474,7 +1480,6 @@ static int coda_buf_prepare(struct vb2_buffer
> *vb)  static void coda_buf_queue(struct vb2_buffer *vb)  {
>  	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> -	struct coda_dev *dev = ctx->dev;
>  	struct coda_q_data *q_data;
> 
>  	q_data = get_q_data(ctx, vb->vb2_queue->type); @@ -1489,15
> +1494,8 @@ static void coda_buf_queue(struct vb2_buffer *vb)
>  		 * For backwards compatibility, queuing an empty buffer
> marks
>  		 * the stream end
>  		 */
> -		if (vb2_get_plane_payload(vb, 0) == 0) {
> -			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 decoder instance is running, set
the
> stream end flag */
> -				coda_write(dev, ctx->bit_stream_param,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> -			}
> -		}
> +		if (vb2_get_plane_payload(vb, 0) == 0)
> +			coda_bit_stream_end_flag(ctx);
>  		mutex_lock(&ctx->bitstream_mutex);
>  		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
>  		if (vb2_is_streaming(vb->vb2_queue))
> @@ -2494,19 +2492,7 @@ static void coda_stop_streaming(struct vb2_queue
> *q)
>  			 "%s: output\n", __func__);
>  		ctx->streamon_out = 0;
> 
> -		if (ctx->inst_type == CODA_INST_DECODER &&
> -		    coda_isbusy(dev) && ctx->idx == coda_read(dev,
> CODA_REG_BIT_RUN_INDEX)) {
> -			/* if this decoder instance is running, set the
> stream end flag */
> -			if (dev->devtype->product == CODA_960) {
> -				u32 val = coda_read(dev,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> -
> -				val |= CODA_BIT_STREAM_END_FLAG;
> -				coda_write(dev, val,
> CODA_REG_BIT_BIT_STREAM_PARAM);
> -				ctx->bit_stream_param = val;
> -			}
> -		}
> -		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
> -
> +		coda_bit_stream_end_flag(ctx);
>  		ctx->isequence = 0;
>  	} else {
>  		v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
> --
> 2.0.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 8/8] [media] coda: move BIT specific functions into separate file
  2014-08-05 15:36   ` Kamil Debski
@ 2014-08-05 16:30     ` Philipp Zabel
  0 siblings, 0 replies; 12+ messages in thread
From: Philipp Zabel @ 2014-08-05 16:30 UTC (permalink / raw)
  To: Kamil Debski
  Cc: linux-media, 'Mauro Carvalho Chehab',
	'Fabio Estevam', 'Hans Verkuil',
	'Nicolas Dufresne',
	kernel

Hi Kamil,

Am Dienstag, den 05.08.2014, 17:36 +0200 schrieb Kamil Debski:
> 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

In my opinion this is not a problem. It is quite clear that the version
number(s) are generated, and the rest of the string is greppable.

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

This patch only moves code around. I strongly prefer not to make
formatting changes at the same time.

If you insist, I'll prepend a checkpatch cleanup series, but I'd be
happier if you'd let me do this after the move.

regards
Philipp


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-08-05 16:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-23 15:28 [PATCH 0/8] Split CODA driver into multiple files Philipp Zabel
2014-07-23 15:28 ` [PATCH 1/8] [media] coda: move coda driver into its own directory Philipp Zabel
2014-07-23 15:28 ` [PATCH 2/8] [media] coda: move defines, enums, and structs into shared header Philipp Zabel
2014-07-23 15:28 ` [PATCH 3/8] [media] coda: add context ops Philipp Zabel
2014-07-23 15:28 ` [PATCH 4/8] [media] coda: move BIT processor command execution out of pic_run_work Philipp Zabel
2014-07-23 15:28 ` [PATCH 5/8] [media] coda: add coda_bit_stream_set_flag helper Philipp Zabel
2014-08-05 15:39   ` Kamil Debski
2014-07-23 15:28 ` [PATCH 6/8] [media] coda: move per-instance buffer allocation and cleanup Philipp Zabel
2014-07-23 15:28 ` [PATCH 7/8] [media] coda: move H.264 helper function into separate file Philipp Zabel
2014-07-23 15:28 ` [PATCH 8/8] [media] coda: move BIT specific functions " Philipp Zabel
2014-08-05 15:36   ` Kamil Debski
2014-08-05 16:30     ` Philipp Zabel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.